如何在scikit-learn中对支持向量机(SVM)应用标准化?

26

我正在使用scikit-learn的当前稳定版本0.13。 我正在使用类sklearn.svm.LinearSVC将线性支持向量分类器应用于一些数据。

在scikit-learn文档的预处理章节中,我读到了以下内容:

  

许多学习算法目标函数中使用的元素(例如支持向量机的RBF核或线性模型的l1和l2正则化器)都假设所有特征都以零为中心并且方差相同。 如果某个特征的方差比其他特征高出几个数量级,它可能会支配目标函数,并使估计器无法从其他特征中正确学习。

问题1:标准化对于SVM通常是有用的,也适用于像我这种具有线性核函数的情况吗?

问题2:据我所理解,我必须在训练数据上计算均值和标准差,并使用类sklearn.preprocessing.StandardScaler将同样的转换应用于测试数据。 但是,我不明白是否必须在馈送给SVM分类器之前转换训练数据以及测试数据。

也就是说,我是否需要执行以下操作:

scaler = StandardScaler()
scaler.fit(X_train)                # only compute mean and std here
X_test = scaler.transform(X_test)  # perform standardization by centering and scaling

clf = LinearSVC()
clf.fit(X_train, y_train)
clf.predict(X_test)

还是我必须做这个:

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # compute mean, std and transform training data as well
X_test = scaler.transform(X_test)  # same as above

clf = LinearSVC()
clf.fit(X_train, y_train)
clf.predict(X_test)

简而言之,为了在使用LinearSVC时获得合理的结果,我是否必须在训练数据上使用scaler.fit(X_train)scaler.fit_transform(X_train)

2个回答

38

没有。

scaler.transform(X_train)没有任何效果。 transform操作不是原地执行的。你必须这样做

<code>X_train = scaler.fit_transform(X_train)

X_test = scaler.transform(X_test)
</code>
或者
X_train = scaler.fit(X_train).transform(X_train)

在训练数据和测试数据上始终需要进行相同的预处理。如果标准化反映了您对数据的信念,那么标准化始终是有益的。

特别是对于核支持向量机来说,这通常非常重要。


当然,我知道这个。只是我太懒了,没发帖(我真惭愧)。关键是要确定在X_train上是否使用fit()fit_transform() - pemistahl
1
添加了一条评论。重新表述你的问题,它不是关于“fit”或“fit_transform”,而是关于是否要转换测试和训练数据。答案是:肯定要转换。如果只转换一个,你怎么能指望学到任何东西呢?它们将不再来自相同的分布。 - Andreas Mueller
好的,这就是我想知道的。我对支持向量机还比较陌生,所以有点困惑。不管怎样,感谢您的快速回复。 :) - pemistahl
@AndreasMueller,如果我使用梯度提升分类算法,是否需要对我的特征进行缩放? - john doe
如果您使用树作为弱学习器,则不需要缩放。所有基于树的模型都对缩放不敏感。 - Andreas Mueller
显示剩余3条评论

8

为什么不使用一个 Pipeline 来一次性链接(或组合)转换器和评估器?这样可以省去单独拟合和转换数据,然后再使用评估器的麻烦。这还会节省一些空间。

from sklearn.pipeline import Pipeline

pipe_lrSVC = Pipeline([('scaler', StandardScaler()), ('clf', LinearSVC())])
pipe_lrSVC.fit(X_train, y_train)
y_pred = pipe_lrSVC.predict(X_test)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接