文章目录
导入模型所用包
示例来源链接:使用TensorFlow2.0实现卷积神经网络CNN对MNIST数字分类
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from sklearn import metrics
import numpy as np
import matplotlib.pyplot as plt
加载数据
加载fashion_mnist
# fashion_mnist
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
加载mnist
# mnist
train_data = pd.read_csv('./mnist/mnist_train.csv')
test_data = pd.read_csv('./mnist/mnist_test.csv')
train_images = train_data.iloc[:,1:]
train_labels = train_data.iloc[:,:1]
test_images = test_data.iloc[:,1:]
test_labels = test_data.iloc[:,:1]
print (train_images.shape)
print (train_labels.shape)
print (test_images.shape)
print (test_labels.shape)
train_images = train_images.values.reshape(-1,28,28)
test_images = test_images.values.reshape(-1,28,28)
train_labels = train_labels.values
test_labels = test_labels.values
(59999, 784)
(59999, 1)
(9999, 784)
(9999, 1)
train_labels[:5]
array([9, 0, 0, 3, 0], dtype=uint8)
plt.imshow(train_images[0], cmap=plt.cm.binary);
数据预处理
train_images = train_images / 255.0
test_images = test_images / 255.0
# 拓展一个维度,添加通道数
train_images = np.expand_dims(train_images,-1)
test_images = np.expand_dims(test_images,-1)
建立模型
model = keras.Sequential()
model.add(keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.summary() # 显示模型的架构
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 32) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 11, 11, 64) 18496
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64) 0
_________________________________________________________________
conv2d_5 (Conv2D) (None, 3, 3, 64) 36928
=================================================================
Total params: 55,744
Trainable params: 55,744
Non-trainable params: 0
_________________________________________________________________
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(64, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
model.summary() # 显示模型的架构
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 32) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 11, 11, 64) 18496
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64) 0
_________________________________________________________________
conv2d_5 (Conv2D) (None, 3, 3, 64) 36928
_________________________________________________________________
flatten_1 (Flatten) (None, 576) 0
_________________________________________________________________
dense_2 (Dense) (None, 64) 36928
_________________________________________________________________
dense_3 (Dense) (None, 10) 650
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________
模型编译
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
模型训练
train_images.shape
(60000, 28, 28, 1)
model.fit(train_images, train_labels, epochs=10)
Epoch 1/10
1875/1875 [==============================] - 23s 12ms/step - loss: 0.7008 - accuracy: 0.7446
Epoch 2/10
1875/1875 [==============================] - 28s 15ms/step - loss: 0.3416 - accuracy: 0.8753
Epoch 3/10
1875/1875 [==============================] - 26s 14ms/step - loss: 0.2820 - accuracy: 0.8962
Epoch 4/10
1875/1875 [==============================] - 26s 14ms/step - loss: 0.2523 - accuracy: 0.9066
Epoch 5/10
1875/1875 [==============================] - 27s 15ms/step - loss: 0.2252 - accuracy: 0.9169
Epoch 6/10
1875/1875 [==============================] - 25s 14ms/step - loss: 0.1981 - accuracy: 0.9281
Epoch 7/10
1875/1875 [==============================] - 24s 13ms/step - loss: 0.1823 - accuracy: 0.9331
Epoch 8/10
1875/1875 [==============================] - 24s 13ms/step - loss: 0.1672 - accuracy: 0.9375
Epoch 9/10
1875/1875 [==============================] - 24s 13ms/step - loss: 0.1514 - accuracy: 0.9420
Epoch 10/10
1875/1875 [==============================] - 25s 13ms/step - loss: 0.1422 - accuracy: 0.9462
<tensorflow.python.keras.callbacks.History at 0x1e49c541bc8>
评估准确性
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
# accuracy: 0.9783
313/313 - 1s - loss: 0.2890 - accuracy: 0.9074
Test accuracy: 0.9074000120162964
做出预测
probability_model = tf.keras.Sequential([model,
tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)
predictions[0]
array([0.08533674, 0.08533674, 0.08533674, 0.08533674, 0.08533674,
0.08533674, 0.08533674, 0.08533678, 0.08533674, 0.23196921],
dtype=float32)
np.argmax(predictions[0])
9
plt.imshow(test_images[0], cmap=plt.cm.binary);
验证预测
class_names_test = [1,1,2,3,2]
def plot_image(i, predictions_array, true_label, img):
# if use mnist dataset,use this code
# predictions_array, true_label, img = predictions_array, true_label[i][0], img[i]
# if use fashion_mnist dataset,use this code
predictions_array, true_label, img = predictions_array, true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
# if use fashion_mnist dataset,use this code
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
# if use mnist dataset,use this code
# plt.xlabel("predicted_label is {},probability is {:2.0f}%,\n,true_label is {}".format(predicted_label,
# 100*np.max(predictions_array),
# true_label),
# color=color)
def plot_value_array(i, predictions_array, true_label):
# if use mnist dataset,use this code
# predictions_array, true_label = predictions_array, true_label[i][0]
# if use fashion_mnist dataset,use this code
predictions_array, true_label = predictions_array, true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
# print (predicted_label,true_label)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], test_labels)
plt.show()
多分类评估
多分类混淆矩阵
二分类混淆矩阵
true_label_test = [0,1,1,1,1,0,0,0,1,1]
pred_label_test = [0,0,1,0,1,0,1,0,1,1]
cfm_test = metrics.confusion_matrix(true_label_test, pred_label_test)
display (cfm_test)
tn, fp, fn, tp = cfm_test.ravel()
print ('matrix predict0 predict1')
print ('label0 {:<6d} {:<6d}'.format(int(tn),int(fp)))
print ('label1 {:<6d} {:<6d}'.format(int(fn),int(tp)))
array([[3, 1],
[2, 4]], dtype=int64)
matrix predict0 predict1
label0 3 1
label1 2 4
# 混淆矩阵行表示实际类别,列表示预测类别
cfm = metrics.confusion_matrix(test_labels, np.argmax(predictions,axis=1))
display (cfm)
array([[874, 1, 25, 23, 2, 1, 65, 0, 9, 0],
[ 3, 981, 2, 14, 0, 0, 0, 0, 0, 0],
[ 15, 2, 920, 7, 19, 0, 35, 0, 2, 0],
[ 14, 7, 12, 932, 14, 0, 18, 0, 3, 0],
[ 0, 3, 104, 30, 801, 0, 58, 0, 4, 0],
[ 0, 0, 0, 0, 0, 978, 0, 10, 1, 11],
[136, 1, 92, 34, 47, 0, 679, 0, 11, 0],
[ 0, 0, 0, 0, 0, 9, 0, 964, 0, 27],
[ 1, 1, 7, 3, 2, 3, 1, 1, 981, 0],
[ 1, 0, 0, 0, 0, 3, 0, 32, 0, 964]], dtype=int64)
多分类召回率
# 混淆矩阵行表示实际类别,列表示预测类别
# 召回率计算时,就是对角线上的值(预测对的)除以该行的求和
for i in range(len(cfm)):
print ('Number %d recall is '%i,cfm[i,i]/np.sum(cfm[i,:]))
Number 0 recall is 0.874
Number 1 recall is 0.981
Number 2 recall is 0.92
Number 3 recall is 0.932
Number 4 recall is 0.801
Number 5 recall is 0.978
Number 6 recall is 0.679
Number 7 recall is 0.964
Number 8 recall is 0.981
Number 9 recall is 0.964
多分类准确率
# 混淆矩阵行表示实际类别,列表示预测类别
# 召回率计算时,就是对角线上的值(预测对的)除以该列的求和
for i in range(len(cfm)):
print ('Number %d precision is '%i,cfm[i,i]/np.sum(cfm[:,i]))
Number 0 precision is 0.8371647509578544
Number 1 precision is 0.9849397590361446
Number 2 precision is 0.7917383820998278
Number 3 precision is 0.8935762224352828
Number 4 precision is 0.9050847457627119
Number 5 precision is 0.9839034205231388
Number 6 precision is 0.7932242990654206
Number 7 precision is 0.9572989076464746
Number 8 precision is 0.9703264094955489
Number 9 precision is 0.9620758483033932
多分类正确率
print (np.sum(np.diagonal(cfm)))
print (np.sum(cfm))
print('Test accuracy:', round(np.sum(np.diagonal(cfm))/np.sum(cfm),4))
9074
10000
Test accuracy: 0.9074
将数据与灰度值对应起来
# cmap为颜色映射,gray为像素灰度值
plt.matshow(cfm,cmap=plt.cm.gray);
去除预测正确的对角线数据,查看混淆矩阵中的其他值
下图不仅可以看出哪个地方犯的错误多,还可以看出是什么样的错误,例如:真实数字9,容易被预测为4,真实数字6,容易被预测为5.
row_sum = np.sum(cfm,axis=1)
err_matrix = cfm / row_sum
np.fill_diagonal(err_matrix,0) # 矩阵对角线填充0
plt.matshow(err_matrix,cmap=plt.cm.gray);