我有一个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()
的结果进行模型评估?
我还遵循了this github issue,并尝试了设置m=Model(x,x)
的解决方案。 y_predict
和y_true
的形状和类型相同。而且这种方法仍然产生:
来自m.e的分数评估:[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)
B.T.W我知道我可以为这些统计信息实现自己的numpy解决方案,但我想使用与Keras相同的功能来避免实现方面的变化。
答案 0 :(得分:1)
如果您使用的是'softmax'
和'categorical_crossentropy'
的经典分类问题,则可能需要计算分类精度,而不是二进制精度。
对于这种情况,y_true
是一键编码的(这似乎是您的情况,因为您使用的是'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_generator
和feature_extractor
可能无法完全相同
yield
类型,则Keras队列可能会使它第二次不在同一点启动您使用生成器evaluate
以查看结果是否完全相同答案 1 :(得分:0)
我建议您看一下这篇文章。它是用德语编写的,但是代码中的所有注释及其随附的说明都是英语,因此应该没有问题。他也有类似的方法,但指令清晰。只需向下滚动到“ Fehleranalyse”部分。