在 sklearn 模型中丢失随机性
Lossing randomness in sklearn model
我遇到了一个很奇怪的情况。
我正在尝试在 sklearn 中使用 SVM 进行二进制 classification 任务。这是我的代码:
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
svc = SVC(kernel='rbf', class_weight='balanced', gamma='auto',probability=True)
c_range = np.logspace(-5, 15, 11, base=2)
gamma_range = np.logspace(-9, 3, 13, base=2)
param_grid = [{'kernel': ['rbf'], 'C': c_range, 'gamma': gamma_range}]
grid = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
clf = grid.fit(x_train, y_train)
predictions = grid.predict(x_test)
如您所见,这是一个非常简单的模型,其中 x_train
是训练数据的输入,x_test
是测试数据的输入,y_train
是训练数据。
我的问题是,既然我没有设置任何种子,为什么这段代码总是重现相同的结果?以我的理解,随机性应该存在于我的模型中,并且至少应该有一些变异结果。
让我说清楚一点,我并不是在抱怨我的模型只对所有测试数据预测相同的 class。我抱怨即使我设置了不同的种子,我的模型仍然产生一致的结果。
比如假设我有3个测试数据。当我将种子设置为 1 或 2 或其他时,测试数据的预测始终为 [1,0,1]。
我尝试设置不同的种子,在模型中更改 random_state。什么都不管用。
我的训练数据很小,只有几百个。测试数据比较大,有几千条数据。
下面的代码将为 SVC 中 random_state
的不同值 return 不同的 class 概率。预测的 classes 在不同的运行中是相同的这一事实仅仅意味着关于数据点所属的 classes 没有太多歧义。换句话说,如果您的数据点看起来像 this,它们很容易分离,并且具有不同种子的模型会将相同的 classes 分配给相同的点。
实际上,如果第一个模型为数据点分配概率 {A: 0.942, B: 0.042, C: 0.016} 而另一个具有不同种子的模型分配概率 {A: 0.917, B : 0.048, C: 0.035},那么两个模型都将预测相同的 class A 对于这一点。
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, GridSearchCV
data = load_wine()
X = data.data
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
x_train = scaler.fit_transform(X_train)
x_test = scaler.transform(X_test)
svc = SVC(kernel='rbf', class_weight='balanced', gamma='auto', probability=True, random_state=50)
c_range = np.logspace(-5, 15, 11, base=2)
gamma_range = np.logspace(-9, 3, 13, base=2)
param_grid = [{'kernel': ['rbf'], 'C': c_range, 'gamma': gamma_range}]
grid = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
clf = grid.fit(x_train, y_train)
predictions = grid.predict_proba(x_test)
print(predictions)
此外,您的大部分数据应该用于训练,而不是用于测试。
我遇到了一个很奇怪的情况。
我正在尝试在 sklearn 中使用 SVM 进行二进制 classification 任务。这是我的代码:
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
svc = SVC(kernel='rbf', class_weight='balanced', gamma='auto',probability=True)
c_range = np.logspace(-5, 15, 11, base=2)
gamma_range = np.logspace(-9, 3, 13, base=2)
param_grid = [{'kernel': ['rbf'], 'C': c_range, 'gamma': gamma_range}]
grid = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
clf = grid.fit(x_train, y_train)
predictions = grid.predict(x_test)
如您所见,这是一个非常简单的模型,其中 x_train
是训练数据的输入,x_test
是测试数据的输入,y_train
是训练数据。
我的问题是,既然我没有设置任何种子,为什么这段代码总是重现相同的结果?以我的理解,随机性应该存在于我的模型中,并且至少应该有一些变异结果。
让我说清楚一点,我并不是在抱怨我的模型只对所有测试数据预测相同的 class。我抱怨即使我设置了不同的种子,我的模型仍然产生一致的结果。
比如假设我有3个测试数据。当我将种子设置为 1 或 2 或其他时,测试数据的预测始终为 [1,0,1]。
我尝试设置不同的种子,在模型中更改 random_state。什么都不管用。 我的训练数据很小,只有几百个。测试数据比较大,有几千条数据。
下面的代码将为 SVC 中 random_state
的不同值 return 不同的 class 概率。预测的 classes 在不同的运行中是相同的这一事实仅仅意味着关于数据点所属的 classes 没有太多歧义。换句话说,如果您的数据点看起来像 this,它们很容易分离,并且具有不同种子的模型会将相同的 classes 分配给相同的点。
实际上,如果第一个模型为数据点分配概率 {A: 0.942, B: 0.042, C: 0.016} 而另一个具有不同种子的模型分配概率 {A: 0.917, B : 0.048, C: 0.035},那么两个模型都将预测相同的 class A 对于这一点。
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, GridSearchCV
data = load_wine()
X = data.data
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
x_train = scaler.fit_transform(X_train)
x_test = scaler.transform(X_test)
svc = SVC(kernel='rbf', class_weight='balanced', gamma='auto', probability=True, random_state=50)
c_range = np.logspace(-5, 15, 11, base=2)
gamma_range = np.logspace(-9, 3, 13, base=2)
param_grid = [{'kernel': ['rbf'], 'C': c_range, 'gamma': gamma_range}]
grid = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
clf = grid.fit(x_train, y_train)
predictions = grid.predict_proba(x_test)
print(predictions)
此外,您的大部分数据应该用于训练,而不是用于测试。