在scikit-learn中保存新数据的特征向量
为了创建一个机器学习算法,我列出了一个字典的列表,并使用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'。这样可以强制新数据符合正确的向量大小,并且只计算新数据中存在的项目。
我觉得我可能没有充分描述这个问题,所以如果有什么不清楚的地方,我会尽量解释得更好。谢谢大家!
编辑:感谢larsman的回答,解决方案其实很简单:
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中内置了特征向量化器。
1 个回答
我怎么才能让新的数据符合训练向量的维度呢?
你可以使用 transform
方法,而不是 fit_transform
。后者会从你提供的数据集中学习新的词汇。
有没有办法用 pickle 来保存特征向量?
你可以把训练好的向量化器进行 pickle(序列化)。更好的做法是,把向量化器和支持向量机(SVM)放在一个 Pipeline
中,然后一起进行 pickle。你可以使用 sklearn.externals.joblib.dump
来高效地进行 pickle。
(顺便说一下,如果你传给向量化器布尔值 True
而不是字符串 "True"
,它的速度会更快。)