Machine learning Keras ROC与Scikit ROC不同?

Machine learning Keras ROC与Scikit ROC不同?,machine-learning,keras,scikit-learn,nlp,roc,Machine Learning,Keras,Scikit Learn,Nlp,Roc,从下面的代码来看,使用keras和scikit评估roc实际上会有所不同。有人知道解释吗 将tensorflow导入为tf 从keras.layers导入、输入、退出 从keras导入顺序 进口干酪 从keras.constraints导入maxnorm 从sklearn.metrics导入roc_auc_分数 #培训数据:X_列车、y_列车 #验证数据:X_有效,y_有效 #定义我们将用于使用scikit评估roc的自定义回调 类MyCustomCallback(tf.keras.callba

从下面的代码来看,使用keras和scikit评估roc实际上会有所不同。有人知道解释吗

将tensorflow导入为tf
从keras.layers导入、输入、退出
从keras导入顺序
进口干酪
从keras.constraints导入maxnorm
从sklearn.metrics导入roc_auc_分数
#培训数据:X_列车、y_列车
#验证数据:X_有效,y_有效
#定义我们将用于使用scikit评估roc的自定义回调
类MyCustomCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self、epoch、logs=None):
y_pred=模型预测(X_有效)
打印(“使用scikit=“,roc\U auc\U分数(y\U有效,y\U pred)”评估的roc”)
返回
#定义模型。
def模型():
指标=[
tf.keras.metrics.binaryAccurance(name='Accurance'),
tf.keras.metrics.AUC(name='AUC'),
]
优化器=“亚当”
辍学率=0.1
init='uniform'
nbr#U特征=vocab#U尺寸-1#2500
密集图=256
模型=顺序()
添加(稠密的(稠密的\u nParms,activation='relu',input\u shape=(nbr\u特性,),kernel\u initializer=init,kernel\u constraint=maxnorm(3)))
型号.添加(辍学(辍学))
model.add(密集型(1,激活='sigmoid'))
compile(loss='binary\u crossentropy',optimizer=optimizer,metrics=metrics)
回归模型
#实例化模型
模型=模型()
#符合模型
history=model.fit(x=x\u train,y=y\u train,batch\u size=8,epochs=8,verbose=1,validation\u data=(x\u valid,y\u valid),callbacks=[MyCustomCallback()],shuffle=True,validation\u freq=1,max\u queue\u size=10,workers=4,use\u multiprocessing=True)
输出:

Train on 4000 samples, validate on 1000 samples
Epoch 1/8
4000/4000 [==============================] - 15s 4ms/step - loss: 0.7950 - accuracy: 0.7149 - auc: 0.7213 - val_loss: 0.7551 - val_accuracy: 0.7608 - val_auc: 0.7770
roc evaluated with scikit =  0.78766515781747
Epoch 2/8
4000/4000 [==============================] - 15s 4ms/step - loss: 0.0771 - accuracy: 0.8235 - auc: 0.8571 - val_loss: 1.0803 - val_accuracy: 0.8574 - val_auc: 0.8954
roc evaluated with scikit =  0.7795984218252997
Epoch 3/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0085 - accuracy: 0.8762 - auc: 0.9162 - val_loss: 1.2084 - val_accuracy: 0.8894 - val_auc: 0.9284
roc evaluated with scikit =  0.7705172905961992
Epoch 4/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0025 - accuracy: 0.8982 - auc: 0.9361 - val_loss: 1.1700 - val_accuracy: 0.9054 - val_auc: 0.9424
roc evaluated with scikit =  0.7808804338960933
Epoch 5/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0020 - accuracy: 0.9107 - auc: 0.9469 - val_loss: 1.1887 - val_accuracy: 0.9150 - val_auc: 0.9501
roc evaluated with scikit =  0.7811174659489438
Epoch 6/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0018 - accuracy: 0.9184 - auc: 0.9529 - val_loss: 1.2036 - val_accuracy: 0.9213 - val_auc: 0.9548
roc evaluated with scikit =  0.7822898825544409
Epoch 7/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0017 - accuracy: 0.9238 - auc: 0.9566 - val_loss: 1.2231 - val_accuracy: 0.9258 - val_auc: 0.9579
roc evaluated with scikit =  0.7817036742516923
Epoch 8/8
4000/4000 [==============================] - 14s 4ms/step - loss: 0.0016 - accuracy: 0.9278 - auc: 0.9592 - val_loss: 1.2426 - val_accuracy: 0.9293 - val_auc: 0.9600
roc evaluated with scikit =  0.7817419052279585
正如你所看到的,从第二纪元开始,keras和scikit的验证ROC开始分化。如果我拟合模型,然后使用keras'
model.evaluate(X\u-valid,y\u-valid)
,也会发生同样的情况。非常感谢您的帮助

编辑:在一个单独的测试集上测试模型,我得到roc=0.76,因此scikit似乎给出了正确的答案(顺便说一句,X_train有4000个条目,X_valid有1000个条目,test有15000个条目,这是一个非常非常规的拆分,但它是由外部因素强制执行的)。
此外,关于如何提高绩效的建议也同样受到赞赏

EDIT2:为了回答@arpitrathi的回复,我修改了callbak,但不幸的是没有成功:

class MyCustomCallback(tf.keras.callbacks.Callback):

    def on_epoch_end(self,epoch, logs=None):
        y_pred = model.predict_proba(X_valid)
        print("roc evaluated with scikit = ",roc_auc_score(y_valid, y_pred))
        return

model = model()

history = model.fit(x=X_trainl, y=y_train, batch_size = 8, epochs = 3, verbose=1,validation_data = (X_valid,y_valid), callbacks=[MyCustomCallback()], shuffle=True, validation_freq=1, max_queue_size=10, workers=4, use_multiprocessing=True)


Train on 4000 samples, validate on 1000 samples
Epoch 1/3
4000/4000 [==============================] - 20s 5ms/step - loss: 0.8266 - accuracy: 0.7261 - auc: 0.7409 - val_loss: 0.7547 - val_accuracy: 0.7627 - val_auc: 0.7881
roc evaluated with scikit =  0.7921764130168828
Epoch 2/3
4000/4000 [==============================] - 15s 4ms/step - loss: 0.0482 - accuracy: 0.8270 - auc: 0.8657 - val_loss: 1.0831 - val_accuracy: 0.8620 - val_auc: 0.9054
roc evaluated with scikit =  0.78525915504445
Epoch 3/3
4000/4000 [==============================] - 15s 4ms/step - loss: 0.0092 - accuracy: 0.8794 - auc: 0.9224 - val_loss: 1.2226 - val_accuracy: 0.8928 - val_auc: 0.9340
roc evaluated with scikit =  0.7705555215724655

此外,如果我绘制训练和验证精度图,我看到它们都迅速收敛到1。这很奇怪吗?

问题在于传递给
sklearn
函数的参数,用于
roc\u auc\u score()
计算。你应该使用
model.predict\u proba()
而不是
model.predict()


谢谢你的回答,@arpitrathi!!。我在问题的第二版中回答了这个问题。然后我怀疑这可能是由于sklearn和keras在离散roc曲线时使用的一组阈值造成的。sklearn中的阈值根据
y_得分
值最佳确定(您可以使用
fpr、tpr、阈值=roc_曲线(y_真,y_得分)
进行检查),而keras使用线性间隔的阈值集计算AUC得分。尝试将
tf.keras.metrics.AUC()
中的
num\u thresholds
参数增加到任意大的值,然后查看分数是否收敛。
def on_epoch_end(self,epoch, logs=None):
        y_pred = model.predict_proba(X_valid)
        print("roc evaluated with scikit = ",roc_auc_score(y_valid, y_pred))
        return