2. softmax回归

适用场景:分类问题,预测离散值,输出属于各类别的概率。如,预测图像类别等。
对比线性回归:相当于在线性回归的基础上,将加权和经softmax函数变换,转化为[0,1]的概率;且为输出多个类别的概率值,各类别概率总和为1。



2.1 模型定义

以图像分类问题为例:
假设输入图像的高和宽均为2像素,且色彩为灰度,图像中的4像素分别记为 离散数据线性回归_数据集
假设训练数据集中,图像的真实标签为狗、猫、鸡,分别记为离散值 离散数据线性回归_数据集_02

相当于共有4种特征和3种输出类别。权重包含12个标量(带下标的离散数据线性回归_数据集_03)、偏差包含3个标量(带下标的离散数据线性回归_线性回归_04),针对输入可计算3个输出离散数据线性回归_离散数据线性回归_05
离散数据线性回归_线性回归_06

离散数据线性回归_线性回归_07

离散数据线性回归_标量_08

该过程可用神经网络图表示:



离散数据线性回归_离散数据线性回归_09

softmax回归


同线性回归一样,softmax回归也是一个单层神经网络,其输出层也是一个全连接层。

值得注意的是,实际的输出值,需要将 离散数据线性回归_离散数据线性回归_05

离散数据线性回归_数据集_11

其中,
离散数据线性回归_离散数据线性回归_12

离散数据线性回归_数据集_13离散数据线性回归_离散数据线性回归_14




2.2 小批量样本的矢量计算表达式

为提升计算效率,通常对小批量数据做矢量计算。

给定一个小批量样本,其批量大小为离散数据线性回归_离散数据线性回归_15,输入个数(特征数)为离散数据线性回归_标量_16,输出个数(类别数)为离散数据线性回归_数据集_17。设批量特征为离散数据线性回归_标量_18,权重和偏差分别为离散数据线性回归_数据集_19离散数据线性回归_标量_20,则softmax回归的矢量计算表达式为:

离散数据线性回归_标量_21

离散数据线性回归_数据集_22

其中,离散数据线性回归_离散数据线性回归_23,且这两个矩阵的第离散数据线性回归_线性回归_24行分别为样本离散数据线性回归_线性回归_24的输出离散数据线性回归_数据集_26和概率分布离散数据线性回归_标量_27




2.3 交叉熵损失函数

softmax回归预测输出各类别的概率分布,而真实标签离散数据线性回归_数据集_28也可以用类别分布表达:
对于样本离散数据线性回归_线性回归_24,构造向量 离散数据线性回归_标量_30 ,使其第离散数据线性回归_线性回归_31(样本离散数据线性回归_线性回归_24类别的离散数值)个元素为1,其余为0。
由此,训练目标可以设为使预测概率分布离散数据线性回归_标量_33尽可能接近真实的标签概率分布离散数据线性回归_数据集_34

实现方法:利用交叉熵(cross entropy)衡量两个概率分布的差异。
离散数据线性回归_离散数据线性回归_35

其中,带下标的离散数据线性回归_标量_36是向量离散数据线性回归_数据集_37中非0即1的元素。

假设训练数据集的样本数为离散数据线性回归_离散数据线性回归_15,交叉熵损失函数定义为:
离散数据线性回归_数据集_39

其中,离散数据线性回归_标量_40代表模型参数。

若每个样本只有一个标签,那么,交叉熵损失函数可简写成离散数据线性回归_标量_41




2.4 模型预测及评价

对于训练好的softmax回归模型,给定任一样本特征,预测每个输出类别的概率。
通常将预测概率最大的类别作为输出类别,若与真实类别(标签)一致,则预测结果正确。




2.5 代码实现

2.5.1 读取数据

图像分类数据集:Fashion-MNIST

包含10个类别的图像数据:t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)、ankle boot(短靴)。

图像的高和宽均为28像素,每个像素的数值为0到255之间8位无符号整数(uint8)。
均为灰度图像(仅两个维度),使用二维的numpy.ndarray存储。

import tensorflow as tf
from tensorflow import keras

fashion_mnist = keras.datasets.fashion_mnist
(x_train,y_train),(x_test,y_test) = fashion_mnist.load_data()

# 图像归一化
x_train = x_train / 255.0
x_test = x_test / 255.0

注:图像归一化,采用 Min-Max Normalization。

离散数据线性回归_线性回归_42

其中,max为样本数据的最大值,min为样本数据的最小值。
上述场景中,每个像素的数值为0到255之间。



2.5.2 定义模型及初始化参数

输入层:Flatten,将28 * 28的像素值,压缩为一行 (784, ) 。
输出层:输出个数为10的全连接层,激活函数使用softmax。

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28,28)),
    keras.layers.Dense(10,activation=tf.nn.softmax)])



2.5.3 定义损失函数

# Tensorflow2.0 的keras API的loss参数
loss = 'sparse_categorical_crossentropy'

问题:为何不按原始公式,先进行softmax运算再构造交叉熵损失函数。
回答:softmax函数会出现数值不稳定问题。
原因:上溢和下溢,使结果为NaN。

上溢:大量级的数被近似为无穷时发生上溢。
下溢:当接近零的数被四舍五入为零时发生下溢。
离散数据线性回归_标量_43

假设所有的离散数据线性回归_标量_44都等于某个常数离散数据线性回归_标量_45,理论上对所有离散数据线性回归_标量_44上式结果为1/n。
离散数据线性回归_标量_45是很小的负数,离散数据线性回归_数据集_48下溢,softmax分母为0,最后的结果为NaN;
离散数据线性回归_标量_45量级很大,离散数据线性回归_数据集_48上溢,最后的结果为NaN。



2.5.4 定义优化算法

# 小批量随机梯度下降(学习率=0.1)
optimizer = tf.keras.optimizers.SGD(0.1)



2.5.5 训练模型

model.compile(optimizer=optimizer,
              loss = loss,
              metrics=['accuracy'])
model.fit(x_train,y_train,epochs=5,batch_size=256)

输出:

Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 1s 23us/sample - loss: 0.7893 - accuracy: 0.7424
Epoch 2/5
60000/60000 [==============================] - 0s 7us/sample - loss: 0.5702 - accuracy: 0.8109
Epoch 3/5
60000/60000 [==============================] - 0s 6us/sample - loss: 0.5256 - accuracy: 0.8251
Epoch 4/5
60000/60000 [==============================] - 0s 7us/sample - loss: 0.5018 - accuracy: 0.8316
Epoch 5/5
60000/60000 [==============================] - 0s 7us/sample - loss: 0.4860 - accuracy: 0.8359



2.5.6 效果评估

test_loss, test_acc = model.evaluate(x_test, y_test)
print('Test Acc:',test_acc)

输出:

- 0s 21us/sample - loss: 0.4309 - accuracy: 0.8245
Test Acc: 0.8245




参考

《动手学深度学习》(TF2.0版)