机器学习——softmax计算

全文共 3723 个字

概念与应用

Softmax是机器学习中一个非常重要的工具,他可以兼容 logistics 算法、可以独立作为机器学习的模型进行建模训练、还可以作为深度学习的激励函数。
softmax的作用简单的说就计算一组数值中每个值的占比,公式一般性描述为:
设一共有机器学习——softmax计算个用数值表示的分类机器学习——softmax计算,其中机器学习——softmax计算表示分类的个数。那么softmax计算公式为:
机器学习——softmax计算

在机器学习中经常用它来解决MECE原则的分类——每一个分类相互独立,所有的分类被完全穷尽。比如男人和女人就是负责MECE原则的。

softmax的例子

看一个例子能更好的理解softmax
设有三个数值机器学习——softmax计算,那么他们的softmax占比为:
机器学习——softmax计算
机器学习——softmax计算
机器学习——softmax计算
计算结果为:
机器学习——softmax计算
机器学习——softmax计算

基本特性

从上面的计算结果可以看出softmax的一些特性:

  1. 归一化:最后的合计为1,每一个分类都是一个小于1的数值。
  2. 放大效果:上面的例子中单纯从数值来看,5和1的差距并不大,但是通过指数运算有明显的放大效果,5的占比能到98%以上。
  3. 散列性质,每一个比率虽然最后都会进行归一,但是他们放大之前的数值是可以相互不干扰的。

softmax的损失函数

softmax的损失函数可以用交叉熵来表述,也可以用极大似然评估来描述,后续的数学推导结论会发现2个算法的结果都是一样的。

熵与交叉熵

这里所说的熵来源于信息论,他表示“为了确保完整的信息被描述所需要的编码长度”。看起来是一个很拗口的概念,下面看一个例子。

假设26个英文字母每个字母出现概率都是相同的机器学习——softmax计算(即机器学习——softmax计算),那么记录26个英文字母所需要的信息量是机器学习——softmax计算,这个公式就是表述26个字符的熵。如果取机器学习——softmax计算表示用一个信息位表示2个信息(也就是我们用来衡量数据大小最小计算单位bit:0/1),那么计算出机器学习——softmax计算说明表述所有的英文字符需要5bit的信息量。

交叉熵

在实际使用中大部分事物都不是均匀分布的,比如一篇英文文章中'e'出现出现的频率明显多于其他字符,而且有时也无法知道真实分布的情况。这时计算信息量就可以使用交叉熵,它是在非均匀分布下信息量的一种表述表示:
机器学习——softmax计算。这里机器学习——softmax计算表示每一个事物的真实概率,机器学习——softmax计算表示对应的预估概率。
关于交叉熵的详细说明可以看本人这篇MNIST介绍的文章关于熵与交叉熵的解释说明

极大似然评估

softmax算法可以看做是一个概率问题,设机器学习——softmax计算表示不同的分类,每个分类的概率表示为机器学习——softmax计算,其中机器学习——softmax计算表示分类的个数。机器学习——softmax计算 机器学习——softmax计算表示特征数。设机器学习——softmax计算,那么在softmax中机器学习——softmax计算。用机器学习——softmax计算表示分类的真实分布,由于事物分类遵守MECE原则,所以所有的机器学习——softmax计算组合在一起实际上是个由1和0组成的数组,只有一个元素为1值。可以参照logistics回归算法:机器学习——softmax计算,softmax也可以使用类似的结构:机器学习——softmax计算 。用对数最大似然评估作为损失函数:
机器学习——softmax计算
可以看出极大似然评估和交叉熵最后得到的是一模一样的表达式。
将公式扩展为机器学习——softmax计算个样本的情况:
机器学习——softmax计算

损失函数的含义

前面已经提到softmax分类应该遵守MECE原则,所以一个样本属于某个分类会用“占位”的方法来标注。例如现在有三个分类,样本A属于第二个分类表示为[0,1,0]、样本B属于第三个分类表示为[0,0,1]、C属于第一个分类——[1,0,0]。每个数组可以看做是的样本分类的真实概率分布——属于某个分类该分类对应的概率就是1,其他分类概率是0。
特征和权重参数通过softmax计算之后得到的是一个概率分布。假设样本A的特征通过softmax计算后分类的概率是[0.2,0.6,0.2],这个时候对于损失函数的计算结果是:机器学习——softmax计算
我们放大真实分布的比重为[0.1,0.8,0.1]后,计算结果:机器学习——softmax计算,放大到[0.05,0.9,0.05]得:机器学习——softmax计算。所以一个很直观的感受是:损失函数是从负数无限接近0。

下面通过大量的数据来模拟这个过程。假设所有的样本属于2个分类,样本分类的标注固定为[1,0],随机生成100个样本模拟分类的概率为:
机器学习——softmax计算
那么这100组数据和损失函数计算结果构成的关系如下图:

机器学习——softmax计算

交叉熵与分类的概率的关系


由于所有样本的标注都是[1,0],所以机器学习——softmax计算的概率越接近1、机器学习——softmax计算越接近0越符合真实分布。可以看到当机器学习——softmax计算接近1机器学习——softmax计算接近0时,交叉熵的计算结果从负数方向接近0。可以执行模拟过程的源码用matplotlib看到更清晰的结果。

再使用一个过程来确认这个结果。softmax是体现一组数值的占比,被标记的那个分类占比越高越接近真实分布。现在假设有5000组样本,每个样本对应20个分类,每个分类的特征值在0~10之间随机产生,每个样本的标记在0~20之间随机设定。现在看看标记项的概率值与损失函数的关系:

机器学习——softmax计算

标注项占比与交叉熵关系趋势


图中softmax highest表示标注项的概率(占比),corss entropy就是损失函数的计算结果。可以看到当标记项概率越接近1,损失的计算结果越接近0。如果有兴趣可以使用生成图像的代码了解分析过程。

建模

softmax计算

上面的内容介绍了softmax的公式以及损失函数。下面说明其如何运算。
在实际应用中一个样本的特征是一个的向量:机器学习——softmax计算,每一个特征在计算过程中都有一个权重,所以引入权重参数建立权重结构(直线结构):
机器学习——softmax计算机器学习——softmax计算
所以softmax更加完整的代数表达式是:
机器学习——softmax计算
其中机器学习——softmax计算表示计算结果有多少个分类机器学习——softmax计算,j表示特征的个数机器学习——softmax计算
机器学习——softmax计算个样本时就扩展为一个2阶张量,那么用矩阵形式表述更加简洁:
机器学习——softmax计算
用下标机器学习——softmax计算表示当前的特征属于第几个样本,例如机器学习——softmax计算表示第1个样本的第3个特征。矩阵的计算过程如下:

1.计算权重指数

机器学习——softmax计算
矩阵中机器学习——softmax计算
机器学习——softmax计算表示矩阵每一个元素求e指数。所以得到:

机器学习——softmax计算

机器学习——softmax计算,有:

机器学习——softmax计算

2.计算分母

现在机器学习——softmax计算
机器学习——softmax计算是一个形状为机器学习——softmax计算元素全为1的矩阵:
机器学习——softmax计算

分母:机器学习——softmax计算
所以:机器学习——softmax计算

3.归一化

现在机器学习——softmax计算
所以最终机器学习——softmax计算

交叉熵(极大似然评估)计算

根据交叉熵的公式机器学习——softmax计算,这里机器学习——softmax计算是样本的真实分类(标签label),机器学习——softmax计算是softmax计算的结果。用矩阵结构表示:
机器学习——softmax计算,矩阵机器学习——softmax计算表示取对角线元素形成一个机器学习——softmax计算的矩阵。

1.对数及矩阵乘积

机器学习——softmax计算
对数机器学习——softmax计算表示对每个元素进行对数运算,他仅改变每个元素的值,对矩阵结构没任何影响,所以下面用机器学习——softmax计算继续表示:
机器学习——softmax计算

2.交叉熵计算

机器学习——softmax计算
机器学习——softmax计算符号带入公式得到最终的损失函数矩阵计算结果:
机器学习——softmax计算
把矩阵符号去掉,这里的结果和前面最大似然评估推导的结果一致。

参数优化

通过前文的介绍我们知道,损失函数的目标是获得“最大值”,这个最大值的含义是从负无穷方向接近0的一个极限过程。所以经常会看到很多文章会在指标函数前面添加一个负号,如下面这样:
机器学习——softmax计算
这样就可以把这个过程转变为求“最小值”——从正无穷方向接近0,本质并没有多大区别。

既然这是一个极限过程,自然就可以用积分原理逐渐计算合理的参数。现在的目标是通过导数和找到递增量可以逐步求解机器学习——softmax计算值:
机器学习——softmax计算表示机器学习——softmax计算的偏导函数:机器学习——softmax计算机器学习——softmax计算的更新公式为:机器学习——softmax计算机器学习——softmax计算表示每一步更新的步长。
如果损失函数前携带了负号,那么更新公式应该修改为机器学习——softmax计算,即越来越小。

1.求偏导函数

目的已经明确,那么接下来就是数学运算了:
设softmax计算结果一共有M个分类,输入模型的一个样本一共有N个特征。
机器学习——softmax计算表示权重计算的结果,下标机器学习——softmax计算表示所属的分类,用数组可以表示为:
机器学习——softmax计算
机器学习——softmax计算表示每一个分类softmax计算的结果:机器学习——softmax计算,k表示分类迭代求和的下标:用数组表示为:
机器学习——softmax计算
Loss是最终的损失函数:机器学习——softmax计算机器学习——softmax计算表示每一个softmax分类对应的真实概率,取值0或1。
优化参数是不断的调优权重参数,所以把机器学习——softmax计算看做自变量求导:
机器学习——softmax计算
按照前面给出的公式将损失函数的计算分为3步:1)计算权重模型,2)计算softmax,3)计算交叉熵。现在把求导过程分为这3步对机器学习——softmax计算机器学习——softmax计算以及机器学习——softmax计算复合求导:
机器学习——softmax计算

计算到这里需要注意一个问题。因为目标是对机器学习——softmax计算求导,所以在求和公式中包含机器学习——softmax计算的项(即包含机器学习——softmax计算的项)和不包含的项求导的结果是不一样的,所以需要将机器学习——softmax计算项单独拿出来求导。所以有:
机器学习——softmax计算
机器学习——softmax计算是一个结构为[0,0,0,1,0,0......]的只有一个元素是1其余元素为0的数组,所以它的合计为1,因此得:

机器学习——softmax计算

虽然推导这个求偏导的过程要花费一些功夫,但是这个结果却非常简单——真实分布与预测分布的差值乘权重参数对应的特征值。如果交叉熵函数中使用了负号,那么导函数为机器学习——softmax计算,很多文章更喜欢用这种求最小值的方式。
观察机器学习——softmax计算的表达式,机器学习——softmax计算机器学习——softmax计算都是已知的数值,在优化的过程中只有机器学习——softmax计算会发生改变。所以当预测分布越接近真实分布时增量会越来越接近0。

2.多个样本与矩阵运算

上面求导的过程并没有考虑多个样本的情况,设现在有O个样本。那么求导公式变成:
机器学习——softmax计算
因为每一个子项的求导结果都是向0接近,所以求和再平分之后也是靠近0的。
现在模型参数的更新公式用矩阵表示为:
机器学习——softmax计算。其中机器学习——softmax计算机器学习——softmax计算的矩阵形,机器学习——softmax计算是一个常量,机器学习——softmax计算机器学习——softmax计算的矩阵形。
设P表示样本真实分布的矩阵(即标记矩阵),Q是文章前面介绍的softmax矩阵计算的结果,X表示样本矩阵。那么D的矩阵表示为:机器学习——softmax计算

计算法则总结与编码实现

算法总结

经过前面推导分析,softmax机器学习算法建模分为以下几项内容。

1.定义

机器学习——softmax计算个样本、机器学习——softmax计算个特征、机器学习——softmax计算个分类,。
机器学习——softmax计算是样本(feature)矩阵,形状为机器学习——softmax计算
机器学习——softmax计算是权重矩阵,形状为机器学习——softmax计算
机器学习——softmax计算是标签(label)矩阵,形状为机器学习——softmax计算
机器学习——softmax计算是softmax计算后得到的矩阵,形状为机器学习——softmax计算
机器学习——softmax计算是两个用于合并计算的单位矩阵,形状为(M,1)和(O,1),机器学习——softmax计算
矩阵机器学习——softmax计算表示转置矩阵,机器学习——softmax计算表示取矩阵的对角线元素(类似于特征)。

2.softmax计算

权重指数:机器学习——softmax计算
归一化:机器学习——softmax计算

3.损失函数

机器学习——softmax计算

4.参数训练

机器学习——softmax计算,训练会重复这个计算,直到变化率“接近”0。

编码实现

以下代码在https://github.com/chkui/ml-math-softmax
如下图,sample.softmax_train.softmax_modual.Softmax类模拟了一个softmax机器学习的过程。

import numpy as np

class Softmax:
    def __init__(self, features, labels):
        self.__features = features
        self.__labels = labels
        self.__weight = np.zeros((labels.shape[1], features.shape[1]))
        # 用于 softmax 归一化计算分布的标量矩阵
        self.__e_softmax = np.ones((labels.shape[1], 1))
        # 用于 损失函数计算的标量矩阵
        self.__e_loss = np.ones((features.shape[0], 1))
        # flag用于标记运算符号
        # flag如果是-1,那么损失函数就是求最小值,那么优化器求差值。
        # flag如果是+1损失函数就是求最大值,那么优化器求和
        self.__flag = 1

    def __softmax(self):
        liner = self.__features * self.__weight.T
        exp = np.exp(liner)
        den = exp * self.__e_softmax
        q = exp / den
        return q

    def __loss(self, q):
        h = self.__labels * np.log(q.T)
        h = h.diagonal()
        loss = self.__flag * h * self.__e_loss / self.__e_loss.shape[0]
        return loss

    def __optimizer(self, q, step):
        d = ((self.__flag * self.__labels - self.__flag * q).getT() * self.__features) / self.__features.shape[0]
        self.__weight = self.__weight + (self.__flag * step) * d

    def train(self, handle, repeat=2000, step=0.1):
        """
        训练
        :param handle: 单轮训练的回调,用于输出各项数据 (count, loss, )
        :param repeat: 重复的轮次,每轮会执行一次存储 2000
        :param step: 优化器步近量
        :return:
        """
        print("Weight shape={}".format(self.__weight.shape))
        count = 0
        while count < repeat:
            q = self.__softmax()
            loss = self.__loss(q)
            self.__optimizer(q, step)
            count = count + 1
            handle(count, loss)

类中的__softmax__loss__optimizer方法分别对应前面介绍的三步计算(归一化,损失函数,参数优化),而在train方法中就是重复调用这三个方法来不断的优化权重参数。
为了执行训练sample.softmax_train.random_data.RandomData用于随机生成样本特征样本标签数据。
下图展示了执行5000次优化过程中Loss的变化趋势:

机器学习——softmax计算

训练次数与损失函数的输出


Count表示执行训练的次数,Loss表示损失函数的输出值,可以发现几个特点:

  1. 在优化的过程中Loss是逐渐接近0的。
  2. 反复使用相同的样本(案例中随机生成了500个样本)优化器在前1000次有比较明显的效果,但是后续增长乏力。

由于使用的是随机数据,所以收敛的效果并不太理想,但是总的趋势还是收敛。后续的博文中本人会使用MNIST之类的真实数据来测试验证softmax。

Github的代码中除了softmax_train用于演示训练和收敛的效果,还有softmax_estimatorsoftmax_compute。前者提供了参数相关的磁盘操作,后者简单展示了softmax算法的编码实现,需要了解的可以到代码库中查看。