使用带有 sklearn 的 pickle 文件时准确度大幅提高

数据挖掘 机器学习 分类 训练 准确性 泡菜
2022-02-14 04:20:14

我训练了一个 xgboost 分类器,它给出了 49.99% 的准确率,我将该模型保存到一个 pickle 文件中。当我使用 pickle 文件 (.pkl) 运行相同的数据时,它的准确率为 88.99%。我不知道为什么会这样。请帮助我摆脱这种情况。

bank_dataset = pd.read_csv(r"dataset.csv")

missing_val = pd.DataFrame(bank_dataset.isnull().sum())

bank_dataset[' Balance'] = bank_dataset[' Balance'].fillna(bank_dataset[' Balance'].mean())

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

objList = bank_dataset.select_dtypes(include = "object").columns

for feat in objList:
    bank_dataset[feat] = le.fit_transform(bank_dataset[feat].astype(str))

correlation = bank_dataset.corr()
print(correlation['Outcome'].sort_values(ascending = False), '\n')

k = 10
cols = correlation.nlargest(k, 'Outcome')['Outcome'].index
print(cols)
cm = np.corrcoef(bank_dataset[cols].values.T)
f, ax = plt.subplots(figsize=(14,14))
sns.heatmap(cm, vmax = .8, linewidths = 0.01, square = True, annot = True, cmap = "coolwarm", linecolor = "white", 
           annot_kws = {'size':12}, xticklabels = cols.values, yticklabels = cols.values)

X = bank_dataset.iloc[:, [7,8,12,24,11,16,4,18,20]].values
y = bank_dataset.iloc[:, -4].values

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 1)
  
from xgboost import XGBClassifier

xg = XGBClassifier()
xg.fit(X_train, y_train)

y_pred = xg.predict(X_test)

from sklearn.metrics import confusion_matrix
from sklearn import metrics
print(metrics.accuracy_score(y_test, y_pred))
cm = confusion_matrix(y_test, y_pred)

import pickle

filename = 'xg.pkl'
pickle.dump(xg, open(filename, 'wb'))

上面用于训练模型并将模型保存到 .pkl 中的代码

bank_dataset = pd.read_csv(r"dataset.csv")

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

objList = bank_dataset.select_dtypes(include = "object").columns

for feat in objList:
    bank_dataset[feat] = le.fit_transform(bank_dataset[feat].astype(str))

X = bank_dataset.iloc[:, [7,8,12,24,11,16,4,18,20]].values
y = bank_dataset.iloc[:, -4].values

file = open('xg.pkl', 'rb')

data = pickle.load(file)

X_ = data.predict(X)

第二个代码是运行带有用于训练的相同数据的 pkl 文件的代码。

1个回答

在第一个代码中,您X使用以下行随机拆分数据:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 1)

然后在训练模型后,您正确地将其应用到测试集,即 20% 的实例:

y_pred = xg.predict(X_test)

而在第二个代码中,您将模型应用于完整数据X而不是仅应用于测试集:

X_ = data.predict(X)

因此,在第二个代码中,您正在测试整个数据集,其中包括 80% 的训练集。在训练集上进行测试当然是不正确的,这就是你获得人为高性能的原因:模型“作弊”,因为它在训练期间已经看到了 80% 的实例。


[回复评论]

至少有两种可能性可以正确拆分数据并仅在测试数据上使用保存的模型:

  • 选项 1:在运行训练代码之前将数据拆分为两个不同的文件,一个用于训练集,一个用于测试集。训练代码应该只提供训练数据作为输入,它不执行任何拆分,只输出模型。测试代码将模型和测试数据作为输入并输出预测(或性能)。
  • 选项 2:在测试代码中应用与在训练代码中完全相同的拆分。这可以通过random_state调用中的参数来完成train_test_split:通过为此参数使用相同的值,函数将始终以完全相同的方式分离数据。然后当然只使用测试集进行预测和评估(忽略数据的训练集部分)。

鉴于您当前的代码(您只需复制train_test_split调用),选项 2 更容易实现。选项 1 更通用,使 ML 设计更简洁,但不太方便。