scikit-learn:有没有办法提供一个对象作为预测分类器功能的输入?

时间:2016-08-23 13:55:32

标签: scikit-learn

我计划在制作中使用SGDClassifier。我们的想法是在一些训练数据上训练分类器,使用cPickle将其转储到.pkl文件,然后在脚本中重复使用。然而,存在某些高基数字段,这些字段本质上是分类的并且被转换为一个热矩阵表示,其创建大约5000个特征。现在我获得的预测输入只有这些功能中的一个,其余的都是零。它还将包括除此之外的其他数字特征。从文档中可以看出,predict函数需要一个数组数组作为输入。有没有什么方法可以将我的输入转换为predict函数所期望的格式,而不必每次训练模型时都存储字段?

更新

所以,我们说我的输入包含3个字段:

{
  rate: 10, // numeric
  flagged: 0, //binary 
  host: 'somehost.com' // keeping this categorical
}

主机可以有大约5000个不同的值。现在我将文件加载到pandas数据帧,使用get_dummies函数将主机字段转换为大约5000个新字段,这些字段是二进制字段。

然后我按模型训练并使用cPickle存储它。

现在,当我需要使用predict函数时,对于输入,我只有3个字段(如上所示)。然而,根据我的理解,预测端点将期望一组向量,并且每个向量应该具有那5000个字段。

对于我需要预测的条目,我只知道该条目的一个字段,它将是主机本身的值。

例如,如果我的输入是

{
  rate: 5,
  flagged: 1
  host: 'new_host.com'
}

我知道预测所期望的字段应为:

{
  rate: 5,
  flagged: 1
  new_host: 1
}

但是如果我把它翻译成矢量格式,我就不知道放置new_host字段的索引。此外,我事先并不知道其他主机是什么(除非我在培训阶段将其存储在某处)

我希望我有所作为。如果我做错了,请告诉我。

2 个答案:

答案 0 :(得分:2)

  

我不知道放置new_host字段的索引

一个对我有用的好方法是构建一个pipeline,然后将其用于训练和预测。这样,您就不必关心转换产生的输出的列索引:

# in training 
pipl = Pipeline(steps=[('binarizer', LabelBinarizer(),
                ('clf', SGDClassifier())])
model = pipl.train(X, Y)
pickle.dump(mf, model)

# in production
model = pickle.load(mf)
y = model.predict(X)

作为X,Y输入,您需要传递类似数组的对象。确保输入与训练和测试的结构相同,例如

X = [[data.get('rate'), data.get('flagged'), data.get('host')]] 
Y = [[y-cols]] # your example doesn't specify what is Y in your data

更灵活:Pandas DataFrame + Pipeline

还可以很好地使用Pandas DataFramesklearn-pandas结合使用,因为它允许您对不同的列名称使用不同的转换。 E.g。

df = pd.DataFrame.from_dict(data)
mapper = DataFrameMapper([
        ('host', sklearn.preprocessing.LabelBinarizer()),
        ('rate', sklearn.preprocessing.StandardScaler())
])
pipl = Pipeline(steps=[('mapper', mapper), 
                       ('clf', SGDClassifier())])
X = df[x-cols]
y = df[y-col(s)]
pipl.fit()

请注意,x-colsy-col(s)分别是功能列和目标列的列表。

答案 1 :(得分:1)

你应该使用scikit-learn变换器而不是get_dummies。在这种情况下,LabelBinarizer是有道理的。看上去LabelBinarizer并没有在管道中工作,这是一种做你想做的事情的方法:

binarizer = LabelBinarizer()
# fitting LabelBinarizer means it remembers all the columns it's seen
one_hot_data = binarizer.fit_transform(X_train[:, categorical_col])
# replace string column with one-hot representation
X_train = np.concatenate([np.delete(X_train, categorical_col, axis=1),
                          one_hot_data], axis=1)

model = SGDClassifier()
clf.fit(X_train, y)

pickle.dump(f, {'clf': clf, 'binarizer': binarizer})

然后在预测时间:

estimators = pickle.load(f)
clf = estimators['clf']
binarizer = estimators['binarizer']

one_hot_data = binarizer.transform(X_test[:, categorical_col])
X_test = np.concatenate([np.delete(X_test, categorical_col, axis=1),
                         one_hot_data], axis=1)
clf.predict(X_test)