簡體   English   中英

如何使用 model.predict() 在 Keras 中重現 model.evaluate() 輸出

[英]How to use model.predict() to reproduce model.evaluate() output in Keras

我有一個 Keras 模型,最后一行是:

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

訓練過程結束后,我想在另一個代碼中加載評估模型。 我正在使用以下方法生成預測和基本事實:

y_predict = model.predict_generator(generator = testing_generator, steps=steps,verbose=0)
y_true = np.asarray(feature_extractor.classes, dtype='float32')
print('predicted {} samples with {} classes'.format(y_predict.shape[0],y_predict.shape[1]))            
        #Calculate score and error
acc = keras.metrics.binary_accuracy(y_true, y_predict)
err = keras.losses.categorical_crossentropy(tf.convert_to_tensor(y_true, np.float32), tf.convert_to_tensor(y_predict, np.float32))
sess = tf.InteractiveSession() 
acc_now = np.mean(acc.eval())
err_now = np.mean(err.eval())
sess.close()
print('Acc and Err from model.predict: {},{}'.format(acc_now,err_now))
print('Model.evaluate output: {}'.format(model.evaluate_generator(generator = testing_generator, steps=steps,verbose=0)))

然后我想評估准確性、錯誤率和混淆矩陣。 我使用predict而不是evaluate的原因是我將能夠產生混淆矩陣。 否則,我將不得不同時使用計算成本很高的兩者。

問題是,我得到了不同的值:

來自模型預測的 Acc 和 Err:0.8237550854682922,12.75771713256836

Model.evaluate 輸出:[13.05123828162994, 0.10646823157343649]

准確率從我的方法中的 0.82 下降到模型評估輸出中的 0.1。 我是否根據需要轉換了model.predict()輸出? 如何使用model.predict()的結果進行模型評估?

我也關注了這個 github issue並嘗試了設置m=Model(x,x)的解決方案。 我對y_predicty_true具有相同的形狀和類型。 這種方法仍然產生:

m.evaluate 的分數:[12.757719990861846, 0.11333714980412431]

使用示例代碼:

        x = Input(y_predict.shape[1:])
        m = Model(x, x)
        m.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
        scores = m.evaluate(y_predict, y_true, batch_size=256, verbose=0) 
        print('Scores from m.evaluate: {}'.format(scores))

在這里,准確度很低,但仍然與evaluate()輸出不同,錯誤與predict()部分相同。


添加模型定義:

num_rows = data_in[-2]
num_columns = data_in[-1]
num_channels = data_in[-3]
num_labels = data_out[-1]


# Construct model     
model = Sequential()
for i in range(cnn_size):
    model.add(Conv2D(filters=2**(i)*16, kernel_size=kernel_size, input_shape=(num_channels, num_rows, num_columns), activation='relu'))
    model.add(MaxPooling2D(pool_size=pool_size))
    model.add(Dropout(dropout_rate))
model.add(GlobalAveragePooling2D())
model.add(Dense(num_labels, activation='softmax'))
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')

其中data_in = (1, 40, 180)data_out = (1, 10)

順便說一句,我知道我可以為這些統計數據實現我自己的 numpy 解決方案,但我想使用與 Keras 相同的功能來避免實現變化。

我建議看看這篇文章。 它是用德文寫的,但是代碼中的所有注釋和隨附的說明都是英文的,所以應該沒有問題。 他有一種類似的方法,有明確的指示。 只需向下滾動到“Fehleranalysis”部分。

https://www.mt-ag.com/so-entwirft-man-ein-top-cnn/

如果您使用帶有'softmax''categorical_crossentropy'的經典分類問題,您可能需要計算分類准確度,而不是二元准確度。

對於y_true是單熱編碼的情況(這似乎是您的情況,因為您使用'categorical_crossentropy''categorical_crossentropy' ):

keras.metrics.categorical_accuracy(y_true, y_pred)

對於y_true是數字標簽(整數)的情況:

keras.metrics.sparse_categorical_accuracy(y_true, y_pred)    

您還可以使用以下方法自行計算准確度:

trueLabels = np.argmax(y_true_numpy, axis=-1) #this line only if y_true is one-hot
predLabels = np.argmax(y_pred_numpy, axis=-1)    
acc = np.mean(trueLabels == predLabels)

關於損失,我認為您正在向后看結果。 評估損失應該是13.05... 您計算出的損失接近於它: 12.75...

現在,如果兩種看似正確的不同方法產生相同的結果,我懷疑evaluate給出的更大結果可能來自模型中的額外損失。 Keras 評估總結了模型中的所有損失,包括權重正則化,可能是損失權重,手動添加的損失等。

我們需要查看您的整個模型以檢測此處為何存在差異。


關於給定模型定義的損失:

它似乎沒有任何會影響損失的東西,結果應該確實是正確的。

在這種情況下,還有另外兩件事可能會導致差異:

  • testing_generatorfeature_extractor工作方式可能不完全相同
    • 除了一個可能的錯誤,你可能會重復同一個生成器兩次,如果生成器是一個yield類型,Keras 隊列可能讓它在你第二次使用生成器時不在同一點開始
  • 您的 Keras 版本有問題(或此處代碼中未包含的某些配置已更改)並且 Dropouts 在評估期間生效的可能性非常小。
    • 快速檢查是多次執行evaluate以查看結果是否完全相同

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM