学习目标:
tf.keras softmax 多分类
对数几率回归解决的是二分类的问题,对于多个选项的问题,我们可以使用softmax函数。它是对数几率回归在 N 个可能不同的值上的推广。
学习过程:
神经网络的原始输出不是一个概率值,实质上只是输入的数值做了复杂的加权和与非线性处理之后的一个值而已,那么如何将这个输出变为概率分布?这就是Softmax层的作用。
softmax要求每个样本必须属于某个类别,且所有可能的样本均被覆盖。
softmax分类
softmax个样本分量之和为 1,当只有两个类别时,与对数几率回归完全相同。
tf.keras交叉熵
在tf.keras里,对于多分类问题我们使用categorical_crossentropy 和sparse_categorical_crossentropy来计算softmax交叉熵。
# 学习案例:
Fashion MNIST数据集。我们将使用 60000 张图像训练网络,并使用 10000 张图像评估经过学习的网络分类图像的准确率。可以从 TensorFlow 直接访问 Fashion MNIST,只需导入和加载数据即可。
代码:
标签是一列数值进行训练
import tensorflow as tf
import pandas as pd
import numpy as np
import matplot.pyplot as plt
#导入数据
(train_image, train_label), (test_image, test_label)= tf.keras.datasets.fashion_mnist.load_data()
train_label.shape
#(60000,)
train_iamge.shape
#(60000, 28, 28)
test_image.shape, test_label.shape
#((10000, 28, 28), (10000,))
plt.imshow(train_image[0])
np.max(train_image[0])
#255
train_lable
# array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
#建立模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 28*28
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
#模型概述
model.summary()
#模型编译
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
#模型训练
history = model.fit(train_image, train_lable, epochs=5)
#绘制图表
plt.plot(history.epoch, history.history.get('acc'), label='acc')
plt.plot(history.epoch, history.history.get('val_acc'), label='val_acc')
plt.legend()
plt.show()
#模型测试
model.evaluate(test_image, test_label)
便签转化成one_hot 编码重新建模训练
train_label_onehot = tf.keras.utils.to_categorical(train_label)
train_label_onehot[-1]
#array([0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], dtype=float32)
test_label_onehot = tf.keras.utils.to_categorical(test_label)
test_label_onehot
#array([[0., 0., 0., ..., 0., 0., 1.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 1., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 1., 0.],
[0., 1., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
#建立模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 28*28
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
#模型概述
model.summary()
#模型编译
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['acc']
)
#模型训练
history = model.fit(train_image, train_lable, epochs=5)
#绘制图表
plt.plot(history.epoch, history.history.get('acc'), label='acc')
plt.plot(history.epoch, history.history.get('val_acc'), label='val_acc')
plt.legend()
plt.show()
#预测模型
predict = model.predict(test_image)
test_image.shape
#(10000, 28, 28)
predict.shape
#(10000, 10)
predict[0]
#array([7.7417062e-05, 1.2555851e-07, 5.2015298e-06, 3.9063170e-06,
6.1778355e-06, 1.3308496e-02, 5.2028918e-05, 1.2039219e-02,
6.5957895e-05, 9.7444147e-01], dtype=float32)
np.argmax(predict[0])
#9
test_label[0]
#9
模型优化,增加网络的深度
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
抑制过拟合,最好的办法是增加数据,也可用正则化,图像增强,下面是在网络中增加dropout层
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation='softmax')
])
总结:两种训练方式的损失函数不一样,分别用了categorical_crossentropy 和sparse_categorical_crossentropy来计算softmax交叉熵。
参考文献:
https://study.163.com/course/introduction/1004573006.htm