我使用NLTK NaiveBayesClassifier进行情感分析。整件事情非常缓慢。我甚至试过保存我的训练师数据,所以我不必每次都重新训练,我注意到速度/时间没有差别。
保存:
import cPickle
f = open('my_classifier.pickle', 'wb')
pickle.dump(classifier, f)
f.close()
稍后加载:
import cPickle
f = open('my_classifier.pickle')
classifier = pickle.load(f)
f.close()
我还能做些什么才能提高速度?分析一个句子需要6秒钟。我希望< 1秒(我在网站上运行这个)。
*现在我已经改为使用cPickle而不是pickle来保存/加载,性能已降至3秒!
答案 0 :(得分:3)
NLTK是一个教学工具包;它并没有真正优化速度。如果你想要一个快速朴素的贝叶斯分类器,请使用scikit-learn中的分类器。在NLTK中有wrapper这个(虽然直接scikit-learn仍然会更快)。
此外,如果使用内存映射,可以快速加载scikit-learn模型。首先,训练模型并用
存储它# Let "clf" be your classifier, usually a Pipeline of CountVectorizer
# and MultinomialNB
from sklearn.externals import joblib
joblib.dump(clf, SOME_PATH, compress=0) # turn off compression
并加载
clf = joblib.load(SOME_PATH, mmap_mode='r')
这也允许廉价地在工作进程之间共享模型。
如果它仍然太慢,请确保您一次处理批量文档而不是一批文档。这可能会快几个数量级。
免责声明:我在scikit-learn和NLTK scikit-learn包装代码中写了许多天真的贝叶斯。
答案 1 :(得分:0)
我想pickle save格式只保存训练数据,并且每次加载时都会重新计算模型。
每次对句子进行分类时,都不应重新加载分类器。您能否以一种可以一次处理多个请求的方式编写Web服务?
我从未使用过Asp.net和IIS。我环顾四周,似乎可以通过安装this extension(here配置说明)来配置IIS以使用FastCGI。如何编写python脚本以使其与FastCGI兼容,解释here。
答案 2 :(得分:0)
如果您真的要使用 400万 15,000 功能来分析可能的十几个单词,那么大多数功能都不会被使用。这表明使用某种基于磁盘的数据库来代替这些功能,并且仅提供您需要的数据库。即使对于长句和低效率的数据库,4寻求x 50个单词仍然比你现在看到的少 - 在最坏的情况下可能是几百毫秒,但肯定不是多秒。
使用NDBM或GDBM后端查看anydbm作为开始,然后根据熟悉程度和可用性考虑其他后端。
您的后续评论似乎暗示了对您正在做的事情和/或事情应该如何运作的基本误解。让我们在词典中用五个单词做一个简单的例子。
# training
d = { 'good': 1, 'bad': -1, 'excellent': 1, 'poor': -1, 'great': 1 }
c = classifier(d)
with open(f, "classifier.pickle", "w") as f:
pickle.dump(c, f)
sentences = ['I took a good look', 'Even his bad examples were stunning']
# classifying, stupid version
for sentence in sentences:
with open(f, "classifier.pickle", "r") as f:
c = pickle.load(f)
sentiment = c(sentence)
# basically, for word in sentence.split(): if word in d: sentiment += d[word]
print sentiment, sentence
# classifying, slightly less stupid version
with open(f, "classifier.pickle", "r") as f:
c = pickle.load(f)
# FastCGI init_end here
for sentence in sentences:
sentiment = c(sentence)
print sentiment, sentence
愚蠢的版本似乎是您目前正在经历的。稍微不那么愚蠢的版本加载分类器一次,然后在每个输入句子上运行它。这就是FastCGI将为您做的事情:您可以在流程启动时执行一次加载部分,然后运行一个服务,在输入句子输入时运行它。这是资源有效但有点工作,因为将脚本转换为FastCGI并设置服务器基础结构是一件麻烦事。如果你期望大量使用,那肯定是要走的路。
但请注意,实际上只需要模型中五个中的两个特征。句子中的大多数单词没有情感分数,并且情感数据库中的大多数单词不需要计算这些输入的分数。因此,数据库实现看起来就像(DBM部分的粗略伪代码)
with opendbm("sentiments.db") as d:
for sentence in sentences:
sentiment = 0
for word in sentence.split():
try:
sentiment += d[word]
except KeyError:
pass
print sentiment, sentence
每笔交易的成本更高,因此它不如FastCGI版本更优化,FastCGI版本仅在启动时将整个模型加载到内存中;但它并不要求你保持状态或设置FastCGI基础设施,而且它比为每个句子加载整个模型的愚蠢版本更有效。
(实际上,对于没有FastCGI的网络服务,您可以在opendbm
内有效地使用for
,而不是相反。)