keras 多类别分类问题-识别手写数字

“识别手写数字”被称为“人工智能”中的“hello world”。

前置知识

  1. 图片数据形式

shape()查看数据形状。

第一个数字为数据项数。一项数据代表一张图片,称为一个样本。

第2、3个数字表示数据形式,是一个什么形状的矩阵。矩阵中的数字值代表了这张正方形图片中对应位置的像素值,像素值为 0~255 之间的数字,这块区域的颜色也随像素值的增大而变黑,从白色到黑色增强。

例如,像素值为 0,表示图片中这一块区域为白色,像素值为 255,表示图片中这一块区域为黑色,像素值为 125,表示图片中这一块区域为灰色

  1. reshape() 方法

第一个参数规定变形后的数据共有多少项,第二个参数是每一项数据的形状

  1. to_categorical 函数

将数据集中“1,2,3,4,5,6……”形式的标签值化为一个向量标签,便于计算机识别

  1. softmax 激活函数

用于处理多分类问题。输出是一个数组,其中元素索引代表一种类别、元素为样本属于该类别的可能性,该可能性用0-1来描述

  1. predict_classes 函数

参考:Get Class Labels from predict method in Keras

TensorFlow 2.6 版本中删除了 predict_classes 函数,需要用代替品

classes = model.predict_classes(x_test)

改为:

  • 多分类问题(最后一层激活层是 softmax)

    predict = model.predict(x_test) # 得到概率
    classes = np.argmax(predict, axis=-1)
    

    也就是np.argmax(model.predict(x_test), axis=-1)

  • 二分类问题(最后一层激活层是 sigmoid)

    predict = model.predict(x_test)
    classes = np.where(y_pred > threshold, 1,0)
    
  • 多标签分类问题(最后一层激活层是 softmax)

    y_predict = model.predict(y_test)
    class_labels = [labels[i] for i, prob in enumerate(y_predict) if prob > 0.5]
    

代码

from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras import optimizers
from tensorflow.keras.datasets import mnist
from tensorflow.python.keras.utils.np_utils import to_categorical

(x_train, y_train), (x_test, y_test) = mnist.load_data('mnist.pkl.gz') # 从 keras 官方下载数据集

print(x_train.shape) # 查看训练集x坐标形状

结果表明 x_train 中一共有60000项数据。一项数据代表一张图片,称为一个样本。这张图片的数据形式是一个28*28的数字矩阵,矩阵中的数字值代表了这张正方形图片中对应位置的像素值,取值范围为0~255之间的数字

# 可以先查看一下数据构成
print(x_train)
print(y_train)
print(y_test)

从结果可以看出,y 代表的标签值并不能代表分类。因为对计算机来说,0,1值才能代表分类

# 转变训练数据的形状:把数字矩阵平铺,即 将28*28二维矩阵变成长度为784(=28*28)的一维数组,便于神经网络接收和处理数据
# 为了方便处理数据,将数组中数字的类型转换为 float32
x_train = x_train.reshape(x_train.shape[0], x_train.shape[1]*x_train.shape[2]).astype('float32') # 第一个参数规定变形后的数据共有多少项。第二个参数为每一项数据的形状,即 一个由原矩阵展开的数组28*28
x_test = x_test.reshape(x_test.shape[0], x_test.shape[1]*x_test.shape[2]).astype('float32')
#  归一化:把矩阵中的每项数字都除以255,将里面的数字转换成0-1之间的数。这样神经网络更好地处理这些数据
x_train /= 255
x_test /= 255

# 将标签值转化成标签
y_train = to_categorical(y_train, num_classes=10)
y_test = to_categorical(y_test, num_classes=10)

# 构建模型
model = Sequential()
model.add(Dense(64, input_shape=(784,))) # 注意:输入层一定要传入input_shape参数
model.add(Activation('relu')) # 激活层,给上一层的输出叠加一个非线性激活函数relu。作用:给模型增加非线性,如果只使用线性函数模型对这种复杂问题的拟合性会不好
model.add(Dense(32))
model.add(Activation('relu'))
model.add(Dense(10)) # 将之前的结果汇总为10个输出,以此对应10个类别
model.add(Activation('softmax')) # 用于处理多分类问题的函数,它的输出是一个数组,其中元素索引代表一种类别、元素为样本属于该类别的可能性

# 编译训练
model.compile(optimizer='adadelta', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=20, epochs=10)

# 测试
score = model.evaluate(x_test, y_test, batch_size=500)
 # 测试对 x_test[5] 的分类。x_test[5]所代表的图片中数字为1,则分类应该为分类为class[1]
predict = model.predict(x_test[5].reshape(1,-1), batch_size=1)
classes = np.argmax(predict, axis=-1)
print(r'loss: ', score[0], r'   accuracy: ', score[1])
print(r'class: ', classes)

结果为

Epoch 1/10
3000/3000 [==============================] - 10s 3ms/step - loss: 2.3030 - accuracy: 0.1228
Epoch 2/10
3000/3000 [==============================] - 8s 3ms/step - loss: 2.1898 - accuracy: 0.1626
Epoch 3/10
3000/3000 [==============================] - 9s 3ms/step - loss: 2.1019 - accuracy: 0.2089
Epoch 4/10
3000/3000 [==============================] - 8s 3ms/step - loss: 2.0175 - accuracy: 0.2681
Epoch 5/10
3000/3000 [==============================] - 8s 3ms/step - loss: 1.9330 - accuracy: 0.3305
Epoch 6/10
3000/3000 [==============================] - 8s 3ms/step - loss: 1.8498 - accuracy: 0.3933
Epoch 7/10
3000/3000 [==============================] - 8s 3ms/step - loss: 1.7689 - accuracy: 0.4483
Epoch 8/10
3000/3000 [==============================] - 8s 3ms/step - loss: 1.6909 - accuracy: 0.4982
Epoch 9/10
3000/3000 [==============================] - 9s 3ms/step - loss: 1.6162 - accuracy: 0.5396
Epoch 10/10
3000/3000 [==============================] - 10s 3ms/step - loss: 1.5444 - accuracy: 0.5770
---
20/20 [==============================] - 1s 7ms/step - loss: 1.4999 - accuracy: 0.6000
1/1 [==============================] - 1s 884ms/step
loss:  1.4999303817749023    accuracy:  0.6000000238418579
class:  [1]
posted @ 2022-08-03 16:58  Vonos  阅读(239)  评论(0)    收藏  举报