如何在scikit-learn中对SVM应用标准化?

27 投票
2 回答
25160 浏览
提问于 2025-04-17 14:42

我正在使用当前稳定版本的 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)

简而言之,我是否需要在训练数据上使用 scaler.fit(X_train)scaler.fit_transform(X_train) 才能在 LinearSVC 中获得合理的结果?

2 个回答

9

为什么不使用一个 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)
39

都不是。

scaler.transform(X_train) 这个操作不会直接改变原来的数据。这个 transform 操作是不会在原地进行的。

你需要这样做:

X_train = scaler.fit_transform(X_train)

X_test = scaler.transform(X_test)

或者这样:

X_train = scaler.fit(X_train).transform(X_train)

你在处理训练数据和测试数据时,必须保持相同的预处理步骤。而且,是的,如果标准化符合你对数据的理解,那通常是个好主意。特别是对于核支持向量机(kernel-svms),这点尤其重要。

撰写回答