• softmax和分类模型


    softmax和分类模型

    softmax的基本概念

    • 分类问题
      一个简单的图像分类问题,输入图像的高和宽均为2像素,色彩为灰度。
      图像中的4像素分别记为 (x_1, x_2, x_3, x_4)
      假设真实标签为狗、猫或者鸡,这些标签对应的离散值为 (y_1, y_2, y_3)
      我们通常使用离散的数值来表示类别,例如(y_1=1, y_2=2, y_3=3)

    • 权重矢量

      [ egin{aligned} o_1 &= x_1 w_{11} + x_2 w_{21} + x_3 w_{31} + x_4 w_{41} + b_1 end{aligned} ]

      [ egin{aligned} o_2 &= x_1 w_{12} + x_2 w_{22} + x_3 w_{32} + x_4 w_{42} + b_2 end{aligned} ]

      [ egin{aligned} o_3 &= x_1 w_{13} + x_2 w_{23} + x_3 w_{33} + x_4 w_{43} + b_3 end{aligned} ]

    • 神经网络图
      下图用神经网络图描绘了上面的计算。softmax回归同线性回归一样,也是一个单层神经网络。由于每个输出(o_1, o_2, o_3)的计算都要依赖于所有的输入(x_1, x_2, x_3, x_4),softmax回归的输出层也是一个全连接层。

    softmax回归是一个单层神经网络

    既然分类问题需要得到离散的预测输出,一个简单的办法是将输出值(o_i)当作预测类别是(i)的置信度,并将值最大的输出所对应的类作为预测输出,即输出 (underset{i}{argmax} o_i)。例如,如果(o_1,o_2,o_3)分别为(0.1,10,0.1),由于(o_2)最大,那么预测类别为2,其代表猫。

    • 输出问题
      直接使用输出层的输出有两个问题:
      1. 一方面,由于输出层的输出值的范围不确定,我们难以直观上判断这些值的意义。例如,刚才举的例子中的输出值10表示“很置信”图像类别为猫,因为该输出值是其他两类的输出值的100倍。但如果(o_1=o_3=10^3),那么输出值10却又表示图像类别为猫的概率很低。
      2. 另一方面,由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量。

    softmax运算符(softmax operator)解决了以上两个问题。

    Softmax运算,即数值归一化得到0-1概率,通过exp函数,从直接线性化的hard max变为e指数化的soft max,能够使原有的差异倍数变得更加明显

    它通过下式将输出值变换成值为正且和为1的概率分布:

    [ hat{y}_1, hat{y}_2, hat{y}_3 = ext{softmax}(o_1, o_2, o_3) ]

    其中

    [ hat{y}1 = frac{ exp(o_1)}{sum_{i=1}^3 exp(o_i)},quad hat{y}2 = frac{ exp(o_2)}{sum_{i=1}^3 exp(o_i)},quad hat{y}3 = frac{ exp(o_3)}{sum_{i=1}^3 exp(o_i)}. ]

    容易看出(hat{y}_1 + hat{y}_2 + hat{y}_3 = 1)(0 leq hat{y}_1, hat{y}_2, hat{y}_3 leq 1),因此(hat{y}_1, hat{y}_2, hat{y}_3)是一个合法的概率分布。这时候,如果(hat{y}_2=0.8),不管(hat{y}_1)(hat{y}_3)的值是多少,我们都知道图像类别为猫的概率是80%。此外,我们注意到

    [ underset{i}{argmax} o_i = underset{i}{argmax} hat{y}_i ]

    因此softmax运算不改变预测类别输出。

    • 计算效率
      • 单样本矢量计算表达式
        为了提高计算效率,我们可以将单样本分类通过矢量计算来表达。在上面的图像分类问题中,假设softmax回归的权重和偏差参数分别为

    [ oldsymbol{W} = egin{bmatrix} w_{11} & w_{12} & w_{13} \ w_{21} & w_{22} & w_{23} \ w_{31} & w_{32} & w_{33} \ w_{41} & w_{42} & w_{43} end{bmatrix},quad oldsymbol{b} = egin{bmatrix} b_1 & b_2 & b_3 end{bmatrix}, ]

    设高和宽分别为2个像素的图像样本(i)的特征为

    [oldsymbol{x}^{(i)} = egin{bmatrix}x_1^{(i)} & x_2^{(i)} & x_3^{(i)} & x_4^{(i)}end{bmatrix}, ]

    输出层的输出为

    [oldsymbol{o}^{(i)} = egin{bmatrix}o_1^{(i)} & o_2^{(i)} & o_3^{(i)}end{bmatrix}, ]

    预测为狗、猫或鸡的概率分布为

    [oldsymbol{hat{y}}^{(i)} = egin{bmatrix}hat{y}_1^{(i)} & hat{y}_2^{(i)} & hat{y}_3^{(i)}end{bmatrix}. ]

    softmax回归对样本(i)分类的矢量计算表达式为

    [ egin{aligned} oldsymbol{o}^{(i)} &= oldsymbol{x}^{(i)} oldsymbol{W} + oldsymbol{b},\ oldsymbol{hat{y}}^{(i)} &= ext{softmax}(oldsymbol{o}^{(i)}). end{aligned} ]

    • 小批量矢量计算表达式
      为了进一步提升计算效率,我们通常对小批量数据做矢量计算。广义上讲,给定一个小批量样本,其批量大小为(n),输入个数(特征数)为(d),输出个数(类别数)为(q)。设批量特征为(oldsymbol{X} in mathbb{R}^{n imes d})。假设softmax回归的权重和偏差参数分别为(oldsymbol{W} in mathbb{R}^{d imes q})(oldsymbol{b} in mathbb{R}^{1 imes q})。softmax回归的矢量计算表达式为

    [ egin{aligned} oldsymbol{O} &= oldsymbol{X} oldsymbol{W} + oldsymbol{b},\ oldsymbol{hat{Y}} &= ext{softmax}(oldsymbol{O}), end{aligned} ]

    其中的加法运算使用了广播机制,(oldsymbol{O}, oldsymbol{hat{Y}} in mathbb{R}^{n imes q})且这两个矩阵的第(i)行分别为样本(i)的输出(oldsymbol{o}^{(i)})和概率分布(oldsymbol{hat{y}}^{(i)})

    softmax公式的得出方法大概解释可以解释为:
    首先假设样本与理论标准函数的误差(类似于线性回归那一章中生成数据时叠加上的高斯误差)服从正态分布(高斯分布),并且不同样本之间独立同分布,
    通过贝叶斯公式计算各个分类的概率,将高斯分布的公式带入公式之后化简得到。
    在一些地方softmax函数又被称为归一化指数(normalized exponential)

    softmax函数的常数不变性,即softmax(x)=softmax(x+c),推导如下:

    [(softmax(x+c))_i=frac{exp(x_i+c)}{sum_j exp(x_j+c)}=frac{exp(c)exp(x_i)}{exp(c)sum_jexp(x_j)}=frac{exp(x_i)}{sum_jexp(x_j)}=(softmax(x))_i ]

    交叉熵损失函数

    对于样本(i),我们构造向量(oldsymbol{y}^{(i)}in mathbb{R}^{q}) ,使其第(y^{(i)})(样本(i)类别的离散数值)个元素为1,其余为0。这样我们的训练目标可以设为使预测概率分布(oldsymbol{hat y}^{(i)})尽可能接近真实的标签概率分布(oldsymbol{y}^{(i)})

    • 平方损失估计

    [egin{aligned}Loss = |oldsymbol{hat y}^{(i)}-oldsymbol{y}^{(i)}|^2/2end{aligned} ]

    然而,想要预测分类结果正确,我们其实并不需要预测概率完全等于标签概率。例如,在图像分类的例子里,如果(y^{(i)}=3),那么我们只需要(hat{y}^{(i)}_3)比其他两个预测值(hat{y}^{(i)}_1)(hat{y}^{(i)}_2)大就行了。即使(hat{y}^{(i)}_3)值为0.6,不管其他两个预测值为多少,类别预测均正确。而平方损失则过于严格,例如(hat y^{(i)}_1=hat y^{(i)}_2=0.2)(hat y^{(i)}_1=0, hat y^{(i)}_2=0.4)的损失要小很多,虽然两者都有同样正确的分类预测结果。

    改善上述问题的一个方法是使用更适合衡量两个概率分布差异的测量函数。其中,交叉熵(cross entropy)是一个常用的衡量方法:

    [Hleft(oldsymbol y^{(i)}, oldsymbol {hat y}^{(i)} ight ) = -sum_{j=1}^q y_j^{(i)} log hat y_j^{(i)}, ]

    其中带下标的(y_j^{(i)})是向量(oldsymbol y^{(i)})中非0即1的元素,需要注意将它与样本(i)类别的离散数值,即不带下标的(y^{(i)})区分。在上式中,我们知道向量(oldsymbol y^{(i)})中只有第(y^{(i)})个元素(y^{(i)}{y^{(i)}})为1,其余全为0,于是(H(oldsymbol y^{(i)}, oldsymbol {hat y}^{(i)}) = -log hat y_{y^{(i)}}^{(i)})。也就是说,交叉熵只关心对正确类别的预测概率,因为只要其值足够大,就可以确保分类结果正确。当然,遇到一个样本有多个标签时,例如图像里含有不止一个物体时,我们并不能做这一步简化。但即便对于这种情况,交叉熵同样只关心对图像中出现的物体类别的预测概率。

    假设训练数据集的样本数为(n),交叉熵损失函数定义为

    [ell(oldsymbol{Theta}) = frac{1}{n} sum_{i=1}^n Hleft(oldsymbol y^{(i)}, oldsymbol {hat y}^{(i)} ight ), ]

    其中(oldsymbol{Theta})代表模型参数。同样地,如果每个样本只有一个标签,那么交叉熵损失可以简写成(ell(oldsymbol{Theta}) = -(1/n) sum_{i=1}^n log hat y_{y^{(i)}}^{(i)})。从另一个角度来看,我们知道最小化(ell(oldsymbol{Theta}))等价于最大化(exp(-nell(oldsymbol{Theta}))=prod_{i=1}^n hat y_{y^{(i)}}^{(i)}),即最小化交叉熵损失函数等价于最大化训练数据集所有标签类别的联合预测概率。

    获取Fashion-MNIST训练集和读取数据

    在介绍softmax回归的实现前我们先引入一个多类图像分类数据集。它将在后面的章节中被多次使用,以方便我们观察比较算法之间在模型精度和计算效率上的区别。图像分类数据集中最常用的是手写数字识别数据集MNIST[1]。但大部分模型在MNIST上的分类精度都超过了95%。为了更直观地观察算法之间的差异,我们将使用一个图像内容更加复杂的数据集Fashion-MNIST[2]。

    我这里我们会使用torchvision包,它是服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。torchvision主要由以下几部分构成:

    1. torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
    2. torchvision.models: 包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
    3. torchvision.transforms: 常用的图片变换,例如裁剪、旋转等;
    4. torchvision.utils: 其他的一些有用的方法。

    class torchvision.datasets.FashionMNIST(root, train=True, transform=None, target_transform=None, download=False)

    • root(string)– 数据集的根目录,其中存放processed/training.pt和processed/test.pt文件。
    • train(bool, 可选)– 如果设置为True,从training.pt创建数据集,否则从test.pt创建。
    • download(bool, 可选)– 如果设置为True,从互联网下载数据并放到root文件夹下。如果root目录下已经存在数据,不会再次下载。
    • transform(可被调用 , 可选)– 一种函数或变换,输入PIL图片,返回变换之后的数据。如:transforms.RandomCrop。
    • target_transform(可被调用 , 可选)– 一种函数或变换,输入目标,进行变换。
  • 相关阅读:
    简单了解一下:var 、let、const
    C# FlagAttriute 的 小妙招
    项目经验面试题
    linux面试题详解
    jvm面试题详解
    数据库面试详解
    微服务框架面试题
    框架面试题(maven、ZooKeeper、Dubbo、Nginx、Redis、Lucene、Solr、ActiveMQ、JMS
    设计模式面试题详解
    WEB方面面试题详解
  • 原文地址:https://www.cnblogs.com/yu212223/p/12309730.html
Copyright © 2020-2023  润新知