我为假新闻检测制作了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上阅读了很多有关此内容的信息,但是找不到答案?
答案 0 :(得分:1)
没有您的实际数据很难回答。但是有一支吸烟枪,令人怀疑您的验证数据可能(与)训练和测试数据完全不同;它来自您的previous question:
如果我在[验证集]功能上使用
fit_transform
,则不会出现错误,但是我的准确度是52%,这太糟糕了(因为我有89.1%)。
虽然在验证数据上使用fit_transform
确实是错误的方法(正确的方法就是您在此处所做的事情),但实际上,它应该不如此高的精度差异。
换句话说,我实际上已经看到很多情况,人们错误地将这样的fit_transform
方法应用于他们的验证/部署数据,却从来没有意识到任何错误,只是因为他们没有任何性能差异-因此它们不会被警告。如果确实所有这些数据在质量上都相似,那么这种情况是可以预期的。
但是在这里,诸如您这样的差异导致强烈怀疑您的验证数据实际上(非常)不同于您的培训和测试数据。如果是这种情况,那么这种性能差异是可以预期的:整个ML实践都是基于(通常是隐式的)假设,即我们的数据(培训,验证,测试,实际部署的数据等)不会发生变化()定性地,它们都来自相同的统计分布。
因此,此处的下一步是对您的训练和验证数据都进行探索性分析,以对此进行调查(实际上,在任何预测性任务中,始终假定这是第0步)。我猜想,即使是基本度量(均值和最大值/最小值等)也将显示它们之间是否存在强烈差异。
尤其是scikit-learn的StandardScaler
使用
z = (x - u) / s
用于转换,其中u
是平均值,s
是数据的标准偏差。如果您的训练和验证集之间的这些值明显不同,那么性能差异就不会出乎意料。