我正在尝试制作一个简单的概念验证,以便我可以看到给定预测的不同类的概率。
然而,我尝试的所有方法似乎都只输出预测的类,尽管我使用了softmax激活函数。我是机器学习的新手,所以我不确定我是否犯了简单的错误,还是Keras中没有这个功能。
我使用的是Keras + TensorFlow。我改编了Keras提供的用于分类MNIST数据集的基本示例之一。
我的代码与示例完全相同,除了几行(已注释)额外的代码,用于将模型导出到本地文件。
'''在MNIST数据集上训练一个简单的深度神经网络。经过20个epochs后,测试准确率达到98.40%(参数调整的空间很大)。在K520 GPU上,每个epoch需要2秒。'''from __future__ import print_functionimport kerasfrom keras.datasets import mnistfrom keras.models import Sequentialfrom keras.layers import Dense, Dropoutfrom keras.optimizers import RMSpropimport h5py # 添加导入,因为model.save需要model_filepath = 'test_model.h5' # 添加文件路径配置batch_size = 128num_classes = 10epochs = 20# 数据已打乱并在训练集和测试集之间拆分(x_train, y_train), (x_test, y_test) = mnist.load_data()x_train = x_train.reshape(60000, 784)x_test = x_test.reshape(10000, 784)x_train = x_train.astype('float32')x_test = x_test.astype('float32')x_train /= 255x_test /= 255print(x_train.shape[0], 'train samples')print(x_test.shape[0], 'test samples')# 将类向量转换为二进制类矩阵y_train = keras.utils.to_categorical(y_train, num_classes)y_test = keras.utils.to_categorical(y_test, num_classes)model = Sequential()model.add(Dense(512, activation='relu', input_shape=(784,)))model.add(Dropout(0.2))model.add(Dense(512, activation='relu'))model.add(Dropout(0.2))model.add(Dense(num_classes, activation='softmax'))model.summary()model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))score = model.evaluate(x_test, y_test, verbose=0)print('Test loss:', score[0])print('Test accuracy:', score[1])model.save(model_filepath) # 添加保存模型print('Model saved') # 添加日志
然后,第二部分是一个简单的脚本,应该导入模型,预测给定数据的类别,并打印出每个类的概率。(我使用了Keras代码库中包含的相同mnist类,以便尽可能简单地制作示例)。
import kerasfrom keras.datasets import mnistfrom keras.models import Sequentialimport keras.backend as Kimport numpy# 加载保存在本地test_model.h5中的模型model_filepath = 'test_model.h5'prev_model = keras.models.load_model(model_filepath)# 这些行是从示例中复制,用于加载MNIST数据(x_train, y_train), (x_test, y_test) = mnist.load_data()x_train = x_train.reshape(60000, 784)# 对于这个示例,我只取前10张图片x_slice = x_train[slice(1, 11, 1)]# 进行预测prediction = prev_model.predict(x_slice)# 每行记录一个预测for single_prediction in prediction: print(single_prediction)
如果我运行第一个脚本导出模型,然后运行第二个脚本对一些示例进行分类,我会得到以下输出:
[ 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.][ 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.][ 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.][ 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.][ 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.][ 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.][ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.][ 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.][ 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.][ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
这对于查看每个预测的类别很好,但如果我想查看每个示例的每个类的相对概率呢?我想要的是类似这样的结果:
[ 0.94 0.01 0.02 0. 0. 0.01 0. 0.01 0.01 0.][ 0. 0. 0. 0. 0.51 0. 0. 0. 0.49 0.]...
换句话说,我需要知道每个预测的确定性,而不仅仅是预测本身。我以为使用模型中的softmax激活函数可以看到相对概率,但我在Keras文档中找不到任何可以给我概率而不是预测答案的内容。我是否犯了某种愚蠢的错误,还是这个功能在Keras中不可用?
回答:
事实证明,问题是我在预测脚本中没有完全规范化数据。
我的预测脚本应该包含以下几行:
# 这些行是从示例中复制,用于加载MNIST数据(x_train, y_train), (x_test, y_test) = mnist.load_data()x_train = x_train.reshape(60000, 784)x_train = x_train.astype('float32') # 这行之前缺失x_train /= 255 # 这行之前也缺失
因为数据没有转换为浮点数,并且没有除以255(以便其在0和1之间),所以它只显示为1和0。