使用 train_test_split 与手动拆分数据时的不同结果
Different results when using train_test_split vs manually splitting the data
我有一个 pandas 数据框,我想对其进行预测并获取每个特征的均方根误差。我正在遵循手动拆分数据集的在线指南,但我认为使用 sklearn.model_selection
中的 train_test_split
会更方便。不幸的是,在手动拆分数据与使用 train_test_split
.
后查看 rmse 值时,我得到了不同的结果
一个(希望)可重现的例子:
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=['feature_1','feature_2','feature_3','feature_4'])
df['target'] = np.random.randint(2,size=100)
df2 = df.copy()
这是一个函数,knn_train_test
,它手动拆分数据、拟合模型、进行预测等:
def knn_train_test(train_col, target_col, df):
knn = KNeighborsRegressor()
np.random.seed(0)
# Randomize order of rows in data frame.
shuffled_index = np.random.permutation(df.index)
rand_df = df.reindex(shuffled_index)
# Divide number of rows in half and round.
last_train_row = int(len(rand_df) / 2)
# Select the first half and set as training set.
# Select the second half and set as test set.
train_df = rand_df.iloc[0:last_train_row]
test_df = rand_df.iloc[last_train_row:]
# Fit a KNN model using default k value.
knn.fit(train_df[[train_col]], train_df[target_col])
# Make predictions using model.
predicted_labels = knn.predict(test_df[[train_col]])
# Calculate and return RMSE.
mse = mean_squared_error(test_df[target_col], predicted_labels)
rmse = np.sqrt(mse)
return rmse
rmse_results = {}
train_cols = df.columns.drop('target')
# For each column (minus `target`), train a model, return RMSE value
# and add to the dictionary `rmse_results`.
for col in train_cols:
rmse_val = knn_train_test(col, 'target', df)
rmse_results[col] = rmse_val
# Create a Series object from the dictionary so
# we can easily view the results, sort, etc
rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()
#Output
feature_3 0.541110
feature_2 0.548452
feature_4 0.559285
feature_1 0.569912
dtype: float64
现在,这里有一个函数 knn_train_test2,它使用 train_test_split
:
拆分数据
def knn_train_test2(train_col, target_col, df2):
knn = KNeighborsRegressor()
np.random.seed(0)
X_train, X_test, y_train, y_test = train_test_split(df2[[train_col]],df2[[target_col]], test_size=0.5)
knn.fit(X_train,y_train)
predictions = knn.predict(X_test)
mse = mean_squared_error(y_test,predictions)
rmse = np.sqrt(mse)
return rmse
rmse_results = {}
train_cols = df2.columns.drop('target')
for col in train_cols:
rmse_val = knn_train_test2(col, 'target', df2)
rmse_results[col] = rmse_val
rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()
# Output
feature_4 0.522303
feature_3 0.556417
feature_1 0.569210
feature_2 0.572713
dtype: float64
为什么我得到不同的结果?我想我误解了一般的 split > train > test 过程,或者 misunderstanding/mis-specifying train_test_split
。提前谢谢你
手动拆分数据只是切片,但train_test_split
也会随机化切片数据。尝试修复随机数种子,看看每次使用 train_test_split
.
时是否都能得到相同的结果
这是机器学习的基本性质。当您手动拆分数据时,您将拥有不同版本的训练和测试集。当你使用 sklearn 函数时,你会得到不同的训练和测试集。您的模型将根据它收到的训练数据进行预测,因此两者的最终结果不同。
如果要重现结果,请使用 train_test_split 通过设置种子值来创建多个训练集。种子值用于在 train_test_split 函数中重现相同的结果。然后当 运行 你的 ml 函数时,也在那里设置一个种子,因为即使是 ML 函数也开始使用随机权重进行训练。在这些具有相同种子的数据集上尝试您的模型,您将获得结果。
您的自定义 train_test_split
实施与 scikit-learn 的实施不同,这就是您对同一种子获得不同结果的原因。
Here你可以找到官方实现。值得注意的第一件事是,scikit-learn 默认执行 10 次 re-shuffeling 迭代和拆分。 (检查 n_splits
参数)
仅 如果您的方法与 scitkit-learn 方法完全相同,那么您可以期待相同种子的相同结果。
我有一个 pandas 数据框,我想对其进行预测并获取每个特征的均方根误差。我正在遵循手动拆分数据集的在线指南,但我认为使用 sklearn.model_selection
中的 train_test_split
会更方便。不幸的是,在手动拆分数据与使用 train_test_split
.
一个(希望)可重现的例子:
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=['feature_1','feature_2','feature_3','feature_4'])
df['target'] = np.random.randint(2,size=100)
df2 = df.copy()
这是一个函数,knn_train_test
,它手动拆分数据、拟合模型、进行预测等:
def knn_train_test(train_col, target_col, df):
knn = KNeighborsRegressor()
np.random.seed(0)
# Randomize order of rows in data frame.
shuffled_index = np.random.permutation(df.index)
rand_df = df.reindex(shuffled_index)
# Divide number of rows in half and round.
last_train_row = int(len(rand_df) / 2)
# Select the first half and set as training set.
# Select the second half and set as test set.
train_df = rand_df.iloc[0:last_train_row]
test_df = rand_df.iloc[last_train_row:]
# Fit a KNN model using default k value.
knn.fit(train_df[[train_col]], train_df[target_col])
# Make predictions using model.
predicted_labels = knn.predict(test_df[[train_col]])
# Calculate and return RMSE.
mse = mean_squared_error(test_df[target_col], predicted_labels)
rmse = np.sqrt(mse)
return rmse
rmse_results = {}
train_cols = df.columns.drop('target')
# For each column (minus `target`), train a model, return RMSE value
# and add to the dictionary `rmse_results`.
for col in train_cols:
rmse_val = knn_train_test(col, 'target', df)
rmse_results[col] = rmse_val
# Create a Series object from the dictionary so
# we can easily view the results, sort, etc
rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()
#Output
feature_3 0.541110
feature_2 0.548452
feature_4 0.559285
feature_1 0.569912
dtype: float64
现在,这里有一个函数 knn_train_test2,它使用 train_test_split
:
def knn_train_test2(train_col, target_col, df2):
knn = KNeighborsRegressor()
np.random.seed(0)
X_train, X_test, y_train, y_test = train_test_split(df2[[train_col]],df2[[target_col]], test_size=0.5)
knn.fit(X_train,y_train)
predictions = knn.predict(X_test)
mse = mean_squared_error(y_test,predictions)
rmse = np.sqrt(mse)
return rmse
rmse_results = {}
train_cols = df2.columns.drop('target')
for col in train_cols:
rmse_val = knn_train_test2(col, 'target', df2)
rmse_results[col] = rmse_val
rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()
# Output
feature_4 0.522303
feature_3 0.556417
feature_1 0.569210
feature_2 0.572713
dtype: float64
为什么我得到不同的结果?我想我误解了一般的 split > train > test 过程,或者 misunderstanding/mis-specifying train_test_split
。提前谢谢你
手动拆分数据只是切片,但train_test_split
也会随机化切片数据。尝试修复随机数种子,看看每次使用 train_test_split
.
这是机器学习的基本性质。当您手动拆分数据时,您将拥有不同版本的训练和测试集。当你使用 sklearn 函数时,你会得到不同的训练和测试集。您的模型将根据它收到的训练数据进行预测,因此两者的最终结果不同。
如果要重现结果,请使用 train_test_split 通过设置种子值来创建多个训练集。种子值用于在 train_test_split 函数中重现相同的结果。然后当 运行 你的 ml 函数时,也在那里设置一个种子,因为即使是 ML 函数也开始使用随机权重进行训练。在这些具有相同种子的数据集上尝试您的模型,您将获得结果。
您的自定义 train_test_split
实施与 scikit-learn 的实施不同,这就是您对同一种子获得不同结果的原因。
Here你可以找到官方实现。值得注意的第一件事是,scikit-learn 默认执行 10 次 re-shuffeling 迭代和拆分。 (检查 n_splits
参数)
仅 如果您的方法与 scitkit-learn 方法完全相同,那么您可以期待相同种子的相同结果。