为啥缩放训练和测试数据后我的 SVM 的性能会下降?

Posted

技术标签:

【中文标题】为啥缩放训练和测试数据后我的 SVM 的性能会下降?【英文标题】:Why does my SVM's performance drop after scaling the training and test data?为什么缩放训练和测试数据后我的 SVM 的性能会下降? 【发布时间】:2014-11-28 01:30:16 【问题描述】:

我正在使用 scikit-learn 对文本进行情感分析。我现在的功能只是词频计数。

当我执行以下操作时,平均 F 值约为 59%:

from sklearn import svm
clf = svm.LinearSVC(class_weight='auto');
clf.fit(Xfeatures, YLabels);
......
predictedLabels = clf.predict(XTestFeatures);

但是当我使用 StandardScalar() 来缩放我的特征向量时,平均 F-measure 下降到 49%:

from sklearn import svm
clf = svm.LinearSVC(class_weight='auto');
Xfeatures = scaler.fit_transform(Xfeatures);
clf.fit(Xfeatures, YLabels);
......
XTestFeatures = scaler.transform(XTestFeatures);
predictedLabels = clf.predict(XTestFeatures);

缩放应该可以提高我的 SVM 的性能,但在这里,它似乎会降低性能。为什么会这样?我怎样才能使它正确?

【问题讨论】:

【参考方案1】:

按均值和方差进行缩放并不是词频的好策略。假设您有两个包含三个术语的术语直方图(我们就称它们为0, 1, 2):

>>> X = array([[100, 10, 50], [1, 0, 2]], dtype=np.float64)

然后你缩放它们;然后你得到

>>> from sklearn.preprocessing import scale
>>> scale(X)
array([[ 1.,  1.,  1.],
       [-1., -1., -1.]])

缩放只是让我们无法判断第 2 项在 X[1] 中出现的频率高于第 0 项。事实上,术语 1 没有出现在 X[1] 中的事实已经无法区分。

当然,这是一个非常极端的例子,但在更大的集合中也会出现类似的效果。你应该做的是标准化直方图:

>>> from sklearn.preprocessing import normalize
>>> normalize(X)
array([[ 0.89087081,  0.08908708,  0.4454354 ],
       [ 0.4472136 ,  0.        ,  0.89442719]])

这会保留您感兴趣的术语的相对频率; 更多积极词比消极词是线性情感分类器关心的,而不是实际频率或它的缩放变体。

(对于单个特征的比例实际上并不重要的领域,建议使用比例缩放,通常是因为特征以不同的单位测量。)

【讨论】:

【参考方案2】:

至少有几件事需要考虑:

缩放数据可能降低准确性。不应该,但可以 准确度是不平衡问题的错误度量,您使用“class_weight='auto'”,所以这是您的情况。请改用一些平衡的度量,例如平均准确度或 MCC。 你似乎使用线性SVM的默认超参数,意思是C=1和;它可能会带来任何几乎随机的结果,您必须通过某种优化技术(至少是网格搜索)来拟合最佳超参数,以便比较两种不同的数据处理(例如您的缩放)

【讨论】:

- 我使用平均 F 度量来比较这两种方法。 - 我正在使用带有默认参数的 LinearSVC。我会研究网格搜索,但你能告诉我为什么默认参数会产生随机结果吗? LinearSVC 不使用内核。

以上是关于为啥缩放训练和测试数据后我的 SVM 的性能会下降?的主要内容,如果未能解决你的问题,请参考以下文章

归一化会降低分类器的性能

缩放 LIBSVM 的测试数据:MATLAB 实现

如何通过 LIBSVM 使用 platt 缩放和交叉验证?

为啥每次单元测试后我的数据库都没有被清除?

提高 SVM 的准确度性能

SVM 训练性能