为了创建一个机器学习算法,我制作了一个字典列表,并使用Scikit的DictVectorzer为每个项目制作了一个特征向量。然后,我从数据集中创建了一个SVM模型,使用部分数据进行训练,然后在测试集上测试模型(你知道,典型的方法)。一切都很好,现在我想把模型部署到野外,看看它是如何在新的、未标记的、看不见的数据上工作的。如何保存特征向量,以便新数据具有相同的大小/特征,并与SVM模型一起工作?例如,如果我想训练单词的存在:
[{
'contains(the)': 'True',
'contains(cat)': 'True',
'contains(is)': 'True',
'contains(hungry)': 'True'
}...
]
我用一个列表来训练,这个列表中有成千上万种动物变体的同一句话。当我对列表进行向量化时,它会考虑所有提到的不同动物,并在向量中为每种动物创建一个索引(“the”、“is”和“hunger”不会改变)。现在,当我尝试在一个新句子上使用该模型时,我想预测一个项目:
[{
'contains(the)': 'True',
'contains(emu)': 'True',
'contains(is)': 'True',
'contains(hungry)': 'True'
}]
在没有原始训练集的情况下,当我使用DictVectorizer时,它会生成:(1,1,1,1)。这比用于训练我的模型的原始向量少了几千个索引,因此SVM模型将无法使用它。或者,即使向量的长度是正确的,因为它是在一个庞大的句子上训练的,特征也可能与原始值不一致。如何获取新数据以符合训练向量的维度?永远不会有比训练集更多的功能,但并非所有功能都保证出现在新数据中。
有没有办法使用pickle保存特征向量?或者,我考虑过的一种方法是生成一个字典,其中包含值为“False”的所有可能特性。这将强制新数据进入适当的向量大小,并仅统计新数据中存在的项。
我觉得我可能没有充分描述这个问题,所以如果有什么不清楚的地方,我会尝试更好地解释。提前谢谢你!
编辑:多亏了拉斯曼的回答,解决方案非常简单:
from sklearn.pipeline import Pipeline
from sklearn import svm
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer(sparse=False)
svm_clf = svm.SVC(kernel='linear')
vec_clf = Pipeline([('vectorizer', vec), ('svm', svm_clf)])
vec_clf.fit(X_Train,Y_Train)
joblib.dump(vec_clf, 'vectorizer_and_SVM.pkl')
利用流水线和支持向量机对数据进行训练。现在,所有未来的模型都可以解开管道,并在SVM中内置一个特征向量器。
如何获取新数据以符合训练向量的维度?
使用transform
方法代替fit\u transform
。后者从您提供给它的数据集中学习一个新词汇表。
有没有办法使用pickle保存特征向量?
对经过训练的矢量器进行Pickle。更好的方法是,将矢量器和SVM进行管道
,并将其pickle。您可以使用
sklearn。外部的。乔布里。倾倒
,以实现高效酸洗。
(旁白:如果将布尔值True
而不是字符串“True”
传递给矢量器,则矢量器会更快)