我正在尝试使用Sci Kit Learn对单字进行一些分析。我创建了svmlight格式的文件,并尝试运行MultinomialNB() KNeighborsClassifier() 和 SVC()
。当我第一次尝试使用单字时,我遇到了X训练维度错误,可能是因为在给定的示例中只包含了在训练拟合中出现的单字。我尝试创建svmlight格式的训练文件,这些文件包括语料库中所有见过的单字的占位符,即使这些单字不在给定的示例中。
问题是这使得训练文件从3 MB膨胀到了300 MB。这导致了sklearn加载文件时的内存错误。有没有办法解决维度不匹配或内存溢出的问题。
X_train, y_train= load_svmlight_file(trainFile)x_test, y_test = load_svmlight_file(testFile)try: clf = MultinomialNB() clf.fit(X_train, y_train) preds = clf.predict(x_test) print('Input data: ' + trainFile.split('.')[0]) print('naive_bayes') print('accuracy: ' + str(accuracy_score(y_test, preds))) if 1 in preds: print('precision: ' + str(precision_score(y_test, preds))) print('recall: ' + str(recall_score(y_test, preds)))except Exception as inst: print 'fail in NB ' + 'Input data: ' + trainFile.split('.')[0] print str(inst) pass
2828个测试示例和1212个测试示例,包含18000个不同的单字
编辑:我尝试使用sklearn CountVectorizer
,但仍然遇到内存问题。这是做这件事的最佳方式吗?
def fileLoadForPipeline(trainSetFile, valSetFile): with open(trainSetFile) as json_file: tdata = json.load(json_file)with open(valSetFile) as json_file: vdata = json.load(json_file)x_train = []x_val = []y_train = []y_val = []for t in tdata: x_train.append(t['request_text']) y_train.append(t['requester_received_pizza'])for v in vdata: x_val.append(t['request_text']) y_val.append(t['requester_received_pizza'])return x_train, y_train, x_val, y_valdef buildPipeline(trainset, valset, norm):x_train, y_train, x_val, y_val = fileLoadForPipeline(trainset, valset)bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=ur'\b\w+\b', min_df=1)xT = bigram_vectorizer.fit_transform(x_train).toarray()xV = bigram_vectorizer.fit_transform(x_val).toarray()if norm: transformer = TfidfTransformer() xT = transformer.fit_transform(xT) xV = transformer.fit_transform(xV)results = []for clf, name in ((Perceptron(n_iter=50), "Perceptron"), (KNeighborsClassifier(n_neighbors=40), "kNN"), (MultinomialNB), (MultinomialNB(alpha=.01),'MultinomialNB'), (BernoulliNB(alpha=.1),'BernoulliNB'),(svm.SVC(class_weight='auto'),'svc')): print 80 * '=' print name results.append(benchmark(clf))
回答:
尝试使用scikit-learn的CountVectorizer
,它会为你对原始文本进行特征提取。最重要的是,对一组训练示例调用fit_transform
方法会自动执行单字的词袋转换,它会跟踪在训练语料库中发现的所有n
个独特词,并将每个文档转换为长度为n
的数组,其特征可以是离散的词计数或二进制存在特征(取决于binary
选项)。CountVectorizer
的优点是它以numpy稀疏矩阵格式存储数据,这使得它非常节省内存,应该能够解决你遇到的任何内存问题。
然后你可以对未来的测试示例调用transform
,它会像正常一样进行转换。
这也应该有助于解决任何维度问题,因为CountVectorizer
的工作是规范化一切。这里有关于使用方法的具体信息:
http://scikit-learn.org/stable/modules/feature_extraction.html#common-vectorizer-usage
这样做的额外好处是,你可以将这个向量化器与分类器结合使用Pipeline
,使拟合和测试更加方便。