训练模型和加载模型后,准确性差异很大

时间:2020-04-02 10:54:27

标签: python machine-learning keras

我为假新闻检测制作了Keras NN模型。我的特征是单词的平均长度,句子的平均长度,标点符号的数量,大写字母的数量,问题的数量等。我有34个特征。我有一个输出,0和1(0为假,1为真实新闻)。 我已经使用了50000个样本进行培训,使用10000个进行测试,并使用2000个进行了验证。我的数据值从-1到10,所以值之间没有太大差异。我曾经这样使用Standard Scaler:

x_train, x_test, y_train, y_test = train_test_split(features, results, test_size=0.20, random_state=0)

scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

validation_features = scaler.transform(validation_features)

我的NN:

model = Sequential()
model.add(Dense(34, input_dim = x_train.shape[1], activation = 'relu')) # input layer requires input_dim param
model.add(Dense(150, activation = 'relu'))
model.add(Dense(150, activation = 'relu'))
model.add(Dense(150, activation = 'relu'))
model.add(Dense(150, activation = 'relu'))
model.add(Dense(150, activation = 'relu'))
model.add(Dense(1, activation='sigmoid')) # sigmoid instead of relu for final probability between 0 and 1

model.compile(loss="binary_crossentropy", optimizer= "adam", metrics=['accuracy'])

es = EarlyStopping(monitor='val_loss', min_delta=0.0, patience=0, verbose=0, mode='auto')
model.fit(x_train, y_train, epochs = 15, shuffle = True, batch_size=64, validation_data=(validation_features, validation_results), verbose=2, callbacks=[es])

scores = model.evaluate(x_test, y_test)
print(model.metrics_names[0], round(scores[0]*100,2), model.metrics_names[1], round(scores[1]*100,2))

结果:

Train on 50407 samples, validate on 2000 samples
Epoch 1/15
 - 3s - loss: 0.3293 - acc: 0.8587 - val_loss: 0.2826 - val_acc: 0.8725
Epoch 2/15
 - 1s - loss: 0.2647 - acc: 0.8807 - val_loss: 0.2629 - val_acc: 0.8745
Epoch 3/15
 - 1s - loss: 0.2459 - acc: 0.8885 - val_loss: 0.2602 - val_acc: 0.8825
Epoch 4/15
 - 1s - loss: 0.2375 - acc: 0.8930 - val_loss: 0.2524 - val_acc: 0.8870
Epoch 5/15
 - 1s - loss: 0.2291 - acc: 0.8960 - val_loss: 0.2423 - val_acc: 0.8905
Epoch 6/15
 - 1s - loss: 0.2229 - acc: 0.8976 - val_loss: 0.2495 - val_acc: 0.8870
12602/12602 [==============================] - 0s 21us/step
loss 23.95 acc 88.81

准确性检查:

prediction = model.predict(validation_features , batch_size=64)

res = []
for p in prediction:
    res.append(p[0].round(0))

# Accuracy with sklearn
acc_score = accuracy_score(validation_results, res)
print("Sklearn acc", acc_score)  # 0.887

保存模型:

model.save("new keras fake news acc 88.7.h5")
scaler_filename = "keras nn scaler.save"
joblib.dump(scaler, scaler_filename)

我已经保存了该模型和该缩放器。 当我加载该模型和该缩放器时,以及当我要进行预测时,我得到的准确度为52%,这很低,因为在训练该模型时我的准确度为88.7%。 我在新数据上应用了.transform进行测试。

validation_df = pd.read_csv("validation.csv")
validation_features = validation_df.iloc[:,:-1]
validation_results = validation_df.iloc[:,-1].tolist()

scaler = joblib.load("keras nn scaler.save") 
validation_features = scaler.transform(validation_features)


my_model_1 = load_model("new keras fake news acc 88.7.h5")
prediction = my_model_1.predict(validation_features , batch_size=64)

res = []
for p in prediction:
    res.append(p[0].round(0))

# Accuracy with sklearn - much lower 
acc_score = accuracy_score(validation_results, res)
print("Sklearn acc", round(acc_score,2))  # 0.52

您能告诉我我在做什么错吗,我已经在github和stackoverflow上阅读了很多有关此内容的信息,但是找不到答案?

1 个答案:

答案 0 :(得分:1)

没有您的实际数据很难回答。但是有一支吸烟枪,令人怀疑您的验证数据可能(与)训练和测试数据完全不同;它来自您的previous question

如果我在[验证集]功能上使用fit_transform,则不会出现错误,但是我的准确度是52%,这太糟糕了(因为我有89.1%)。

虽然在验证数据上使用fit_transform确实是错误的方法(正确的方法就是您在此处所做的事情),但实际上,它应该如此高的精度差异。

换句话说,我实际上已经看到很多情况,人们错误地将这样的fit_transform方法应用于他们的验证/部署数据,却从来没有意识到任何错误,只是因为他们没有任何性能差异-因此它们不会被警告。如果确实所有这些数据在质量上都相似,那么这种情况是可以预期的。

但是在这里,诸如您这样的差异导致强烈怀疑您的验证数据实际上(非常)不同于您的培训和测试数据。如果是这种情况,那么这种性能差异是可以预期的:整个ML实践都是基于(通常是隐式的)假设,即我们的数据(培训,验证,测试,实际部署的数据等)不会发生变化()定性地,它们都来自相同的统计分布。

因此,此处的下一步是对您的训练和验证数据都进行探索性分析,以对此进行调查(实际上,在任何预测性任务中,始终假定这是第0步)。我猜想,即使是基本度量(均值和最大值/最小值等)也将显示它们之间是否存在强烈差异。

尤其是scikit-learn的StandardScaler使用

z = (x - u) / s

用于转换,其中u是平均值,s是数据的标准偏差。如果您的训练和验证集之间的这些值明显不同,那么性能差异就不会出乎意料。