我正在尝试使用scikit-learn构建一个简单的SVM文档分类器,我使用以下代码:
import os
import numpy as np
import scipy.sparse as sp
from sklearn.metrics import accuracy_score
from sklearn import svm
from sklearn.metrics import classification_report
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import cross_validation
from sklearn.datasets import load_svmlight_file
clf=svm.SVC()
path="C:\\Python27"
f1=[]
f2=[]
data2=['omg this is not a ship lol']
f=open(path+'\\mydata\\ACQ\\acqtot','r')
f=f.read()
f1=f.split(';',1085)
for i in range(0,1086):
f2.append('acq')
f1.append('shipping ship')
f2.append('crude')
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(min_df=1)
counter = CountVectorizer(min_df=1)
x_train=vectorizer.fit_transform(f1)
x_test=vectorizer.fit_transform(data2)
num_sample,num_features=x_train.shape
test_sample,test_features=x_test.shape
print("#samples: %d, #features: %d" % (num_sample, num_features)) #samples: 5, #features: 25
print("#samples: %d, #features: %d" % (test_sample, test_features))#samples: 2, #features: 37
y=['acq','crude']
#print x_test.n_features
clf.fit(x_train,f2)
#den= clf.score(x_test,y)
clf.predict(x_test)
它出现以下错误:
(n_features, self.shape_fit_[1]))
ValueError: X.shape[1] = 6 should be equal to 9451, the number of features at training time
但我不理解的是为什么它会期待不。功能是一样的吗?如果我向机器输入一个绝对新的文本数据,它需要预测,那么每个文档显然不可能具有与用于训练它的数据相同数量的特征。在这种情况下,我们是否必须明确地将测试数据的特征数设置为9451?
答案 0 :(得分:14)
为了确保您具有相同的要素表示,您不应该fit_transform您的测试数据,而只是转换它。
x_train=vectorizer.fit_transform(f1)
x_test=vectorizer.transform(data2)
应在标签上应用类似的均匀特征转换。
答案 1 :(得分:3)
SVM的工作原理是假设您的所有训练数据都存在于n
维空间中,然后对该集进行几何优化。为了实现这一目标,如果n=2
,则SVM会选择一条最佳地将(+)
示例与(-)
示例分开的行。
这意味着训练SVM的结果与它所训练的维度有关。这个维度正好是你的特征集的大小(模数内核和其他转换,但无论如何所有这些信息都在一起)唯一设置问题空间)。因此,您不能仅将此训练模型应用于存在于不同维度空间中的新数据。
(您可能会建议我们将训练空间投射或嵌入测试空间 - 这在某些情况下甚至可能有效 - 但它通常无效。)
但是,当你真正分析它时,这种情况变得更加棘手。测试数据维度不仅需要与训练数据维度相对应,而且每个维度的含义需要保持不变。例如,回到我们的n=2
示例中,假设我们正在对人们的情绪进行分类(快乐/悲伤),x
维度就是"享受生活&#34 ;并且y
维度是"花在听悲伤音乐上的时间"。我们期望更高的x
和更小的y
值可以提高幸福的可能性,因此SVM可以找到的良好歧视边界将是y=x
线,因为人们更接近x
轴往往很高兴,靠近y
轴往往很难过。
但接下来让我们说当有人放弃测试数据时,有人会发现x
和y
尺寸的混淆并混淆。轰隆声,突然间你有一个非常不准确的预测器。
因此,特别是,测试数据的观察空间必须匹配训练数据的观察空间。维度是这方面的重要一步,但匹配实际上必须是完美的。
这是一个很长的路要说你需要做一些特征工程或找到没有这种依赖的算法(这也涉及一些特征工程)。
答案 2 :(得分:0)
在这种情况下,我们是否必须明确将测试数据的特征数设置为9451?
是的,你这样做。 SVM需要管理与训练集相同的维度。人们在处理文档时往往会使用一个单词方法或选择前x个不太常用的单词。