为了创建一个机器学习算法,我制作了一个字典列表,并使用scikit的DictVectorizer为每个项目创建了一个特征向量。然后,我从数据集中创建了一个SVM模型,使用部分数据进行训练,并在测试集上测试模型(你知道的,典型的方法)。一切运作良好,现在我想将模型部署到实际环境中,看看它在新的、未标记的、未见过的数据上的表现。我该如何保存特征向量,以便新数据具有相同的大小/特征,并能与SVM模型一起使用?例如,如果我想根据单词的存在进行训练:
[{ 'contains(the)': 'True', 'contains(cat)': 'True', 'contains(is)': 'True', 'contains(hungry)': 'True' }...]
我用包含数千种动物变体的相同句子的列表进行训练。当我对列表进行向量化时,它会考虑到提到的所有不同动物,并为每种动物在向量中创建一个索引(’the’、’is’ 和 ‘hungry’ 不会改变)。现在,当我尝试在新句子上使用模型时,我想预测一个项目:
[{ 'contains(the)': 'True', 'contains(emu)': 'True', 'contains(is)': 'True', 'contains(hungry)': 'True' }]
如果没有原始训练集,当我使用DictVectorizer时,它会生成:(1,1,1,1)。这比用于训练我的模型的原始向量少了几千个索引,因此SVM模型将无法与之配合使用。即使向量的长度是正确的,因为它是在一个巨大的句子上训练的,特征也可能不对应于原始值。我如何让新数据符合训练向量的维度?新数据的特征永远不会超过训练集,但不能保证新数据中会出现所有特征。
有没有办法使用pickle来保存特征向量?或者我考虑过的一种方法是生成一个包含所有可能特征的字典,其值为’False’。这会强制新数据进入适当的向量大小,并且只计算新数据中存在的项目。
我觉得我可能没有充分描述这个问题,所以如果有什么不清楚的地方,我会尝试更好地解释。提前感谢!
编辑:感谢@的回答,解决方案非常简单:
from sklearn.pipeline import Pipelinefrom sklearn import svmfrom sklearn.feature_extraction import DictVectorizervec = 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_transform
。后者会从你提供的数据集中学习一个新的词汇表。
有没有办法使用pickle来保存特征向量?
封装训练好的向量化器。更好的是,创建一个包含向量化器和SVM的Pipeline
,然后封装它。你可以使用sklearn.externals.joblib.dump
进行高效的封装。
(顺便说一句,如果你传递布尔值True
而不是字符串"True"
,向量化器会更快。)