机器学习——softmax计算

作者: 随风溜达的向日葵 | 来源:发表于2019-01-03 18:08 被阅读4次

    概念与应用

    Softmax是机器学习中一个非常重要的工具,他可以兼容 logistics 算法、可以独立作为机器学习的模型进行建模训练、还可以作为深度学习的激励函数。
    softmax的作用简单的说就计算一组数值中每个值的占比,公式一般性描述为:
    设一共有n个用数值表示的分类S_k,k\in(0,n],其中n表示分类的个数。那么softmax计算公式为:
    P(S_i)=\frac{e^{g_i}}{\sum_k^ne^{g_k}},i表示k中的某个分类,g_i表示该分类的值

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

    softmax的例子

    看一个例子能更好的理解softmax
    设有三个数值A=5,B=1,C=-1,那么他们的softmax占比为:
    P(A)=\frac{e^5}{e^5+e+e^{-1}}
    P(B)=\frac{e}{e^5+e+e^{-1}}
    P(C)=\frac{e^{-1}}{e^5+e+e^{-1}}
    计算结果为:
    P(A)=0.9817,P(B)=0.0180,P(C)=0.0003
    P(A)+P(B)+P(C)=1

    基本特性

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

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

    softmax的损失函数

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

    熵与交叉熵

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

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

    交叉熵

    在实际使用中大部分事物都不是均匀分布的,比如一篇英文文章中'e'出现出现的频率明显多于其他字符,而且有时也无法知道真实分布的情况。这时计算信息量就可以使用交叉熵,它是在非均匀分布下信息量的一种表述表示:
    H(p,g)=\sum_i^Np_i\log_x\frac{1}{q_i}。这里p_j表示每一个事物的真实概率,q_j表示对应的预估概率。
    关于交叉熵的详细说明可以看本人这篇MNIST介绍的文章关于熵与交叉熵的解释说明

    极大似然评估

    softmax算法可以看做是一个概率问题,设A_i表示不同的分类,每个分类的概率表示为P(A_i|w_{ij}x_j),其中i \in (0,N]表示分类的个数。j\in(0.M] x_j表示特征数。设q_i=P(A_i|w_{ij}x_j)),那么在softmax中\sum_i^N q_i = 1。用p_i表示分类的真实分布,由于事物分类遵守MECE原则,所以所有的p_i组合在一起实际上是个由1和0组成的数组,只有一个元素为1值。可以参照logistics回归算法:P=q^p(1-q)^{(1-p)},softmax也可以使用类似的结构:P=\prod_i^N q_i^{p_i} 。用对数最大似然评估作为损失函数:
    L=\log\prod_i^Nq_i^{p_i}=\sum_i^Np_i\log{q_i}
    可以看出极大似然评估和交叉熵最后得到的是一模一样的表达式。
    将公式扩展为M个样本的情况:
    L=\frac{1}{M}\log\prod_k^M\prod_i^Nq_{ij}^{p_{ij}}=\frac{1}{M}\sum_k^M\sum_i^N p_{kj}\log q_{kj}, k\in(0,M]

    损失函数的含义

    前面已经提到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],这个时候对于损失函数的计算结果是:0×\ln 0.2+1×\ln 0.6 + 0 × \ln 0.2 = \ln 0.6 \approx -0.51
    我们放大真实分布的比重为[0.1,0.8,0.1]后,计算结果:\ln 0.8 \approx -0.22,放大到[0.05,0.9,0.05]得:\approx -0.10。所以一个很直观的感受是:损失函数是从负数无限接近0。

    下面通过大量的数据来模拟这个过程。假设所有的样本属于2个分类,样本分类的标注固定为[1,0],随机生成100个样本模拟分类的概率为:
    \begin{matrix} p_1&p_2\\ 0.2&0.8 \\ 0.7&0.3 \\ 0.9&0.1 \\ …&… \end{matrix}
    那么这100组数据和损失函数计算结果构成的关系如下图:

    交叉熵与分类的概率的关系
    由于所有样本的标注都是[1,0],所以 标注项占比与交叉熵关系趋势
    图中softmax highest表示标注项的概率(占比),corss entropy就是损失函数的计算结果。可以看到当标记项概率越接近1,损失的计算结果越接近0。如果有兴趣可以使用生成图像的代码了解分析过程。

    建模

    softmax计算

    上面的内容介绍了softmax的公式以及损失函数。下面说明其如何运算。
    在实际应用中一个样本的特征是一个的向量:X={x_1,x_2,x_3,....x_n},每一个特征在计算过程中都有一个权重,所以引入权重参数建立权重结构(直线结构):
    g(x)=w_0+w_1x_1+w_2x_2+...+w_nx_n=w_jx_jj\in[0,n],x_0=1
    所以softmax更加完整的代数表达式是:
    softmax(x)=\frac{e^{w_{ij}x_j}}{\sum_j^ne^{w_ijx_j}}
    其中i表示计算结果有多少个分类i\in(0,m),j表示特征的个数j\in[0.n]
    o个样本时就扩展为一个2阶张量,那么用矩阵形式表述更加简洁:
    softmax(X)=\frac{e^{XW^T}}{e^{XW^T}E}
    用下标_{(o)}表示当前的特征属于第几个样本,例如x_{(1)3}表示第1个样本的第3个特征。矩阵的计算过程如下:

    1.计算权重指数

    G=exp\left( \begin{bmatrix} x_{(1)0}&x_{(1)1}&x_{(1)2}&\cdots&x_{(1)n}\\ x_{(2)0}&x_{(2)1}&x_{(2)2}&\cdots&x_{(2)n}\\ x_{(3)0}&x_{(3)1}&x_{(3)2}&\cdots&x_{(3)n}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ x_{(o)0}&x_{(o)1}&x_{(o)2}&\cdots&x_{(o)n} \end{bmatrix} × \begin{bmatrix} w_{10}&w_{20}&w_{30}&\cdots&w_{m0}\\ w_{11}&w_{21}&w_{31}&\cdots&w_{m1}\\ w_{12}&w_{22}&w_{32}&\cdots&w_{m2}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ w_{1n}&w_{2n}&w_{3n}&\cdots&w_{mn}\\ \end{bmatrix}\right)
    矩阵中x_{(o)0} = 1
    exp()表示矩阵每一个元素求e指数。所以得到:

    G= \begin{bmatrix} e^{\sum_j^nw_{1j}x_{(1)j}}&e^{\sum_j^nw_{2j}x_{(1)j}}&e^{\sum_j^nw_{3j}x_{(1)j}}&\cdots&e^{\sum_j^nw_{mj}x_{(1)j}}\\ e^{\sum_j^nw_{1j}x_{(2)j}}&e^{\sum_j^nw_{2j}x_{(2)j}}&e^{\sum_j^nw_{3j}x_{(2)j}}&\cdots&e^{\sum_j^nw_{mj}x_{(2)j}}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ e^{\sum_j^nw_{1j}x_{(o)j}}&e^{\sum_j^nw_{2j}x_{(o)j}}&e^{\sum_j^nw_{3j}x_{(o)j}}&\cdots&e^{\sum_j^nw_{mj}x_{(o)j}} \end{bmatrix}

    c_{ki}=c(w_{ij},x_{(k)j})=e^{\sum_j^nw_{ij}x_{(k)j}},k\in(0,o],有:

    G=G(x)= \begin{bmatrix} c_{11}&c_{12}&c_{13}&\cdots&c_{1m}\\ c_{21}&c_{22}&c_{23}&\cdots&c_{2m}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ c_{o1}&c_{o2}&c_{o3}&\cdots&c_{om}\\ \end{bmatrix}

    2.计算分母

    现在Softmax=S(x)=\frac{G}{G×E}
    E是一个形状为m×1元素全为1的矩阵:
    E=\begin{bmatrix} 1\\ 1\\ \cdots\\ 1 \end{bmatrix}

    分母:S=G×E=\begin{bmatrix} c_{11}&c_{12}&c_{13}&\cdots&c_{1m}\\ c_{21}&c_{22}&c_{23}&\cdots&c_{2m}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ c_{o1}&c_{o2}&c_{o3}&\cdots&c_{om}\\ \end{bmatrix}×\begin{bmatrix} 1\\ 1\\ \cdots\\ 1 \end{bmatrix}
    所以:S=\begin{bmatrix} \sum_i^mc_{1i}\\ \sum_i^mc_{2i}\\ \sum_i^mc_{3i}\\ \cdots\\ \sum_i^mc_{oi} \end{bmatrix}=\begin{bmatrix}s_1\\s_2\\s_3\\\cdots\\s_o\end{bmatrix}

    3.归一化

    现在Q=softmax=\frac{G}{S}=\begin{bmatrix} c_{11}&c_{12}&c_{13}&\cdots&c_{1m}\\ c_{21}&c_{22}&c_{23}&\cdots&c_{2m}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ c_{o1}&c_{o2}&c_{o3}&\cdots&c_{om}\\ \end{bmatrix}\div\begin{bmatrix}s_1\\s_2\\s_3\\\cdots\\s_o\end{bmatrix}
    所以最终Q=\begin{bmatrix} \frac{c_{11}}{d_1}&\frac{c_{12}}{d_1}&\frac{c_{13}}{d_1}&\cdots&\frac{c_{1m}}{d_1}\\ \frac{c_{21}}{d_2}&\frac{c_{22}}{d_2}&\frac{c_{23}}{d_2}&\cdots&\frac{c_{2m}}{d_2}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ \frac{c_{o1}}{d_o}&\frac{c_{12}}{d_o}&\frac{c_{12}}{d_o}&\cdots&\frac{c_{1m}}{d_o}\\ \end{bmatrix}=\begin{bmatrix} q_{11}&q_{12}&q_{13}&\cdots&q_{1m}\\ q_{21}&q_{22}&q_{23}&\cdots&q_{2m}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ q_{o1}&s_{o2}&q_{o3}&\cdots&q_{om}\\ \end{bmatrix}

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

    根据交叉熵的公式L=\sum_i^mp_i\log q_i,这里p_i是样本的真实分类(标签label),q_i是softmax计算的结果。用矩阵结构表示:
    L=\frac{1}{o}\left[P\log\left(Q^T\right)\right]^D×E,矩阵A_{m×n}^D表示取对角线元素形成一个1×n的矩阵。

    1.对数及矩阵乘积

    \left[P\log\left(S^T\right)\right]^D= \left[\begin{bmatrix} p_{(1)1}&p_{(1)2}&p_{(1)3}&\cdots&p_{(1)m}\\ p_{(2)1}&p_{(2)2}&p_{(2)3}&\cdots&p_{(2)m}\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ p_{(o)1}&p_{(o)2}&p_{(o)3}&\cdots&p_{(o)m}\\ \end{bmatrix}×\log\left(\begin{bmatrix} s_{11}&s_{21}&\cdots&s_{o1}\\ s_{12}&s_{22}&\cdots&s_{o2}\\ \vdots&\vdots&\ddots&\vdots\\ s_{1m}&s_{2m}&\cdots&s_{om}\\ \end{bmatrix}\right)\right]^D
    对数\log()表示对每个元素进行对数运算,他仅改变每个元素的值,对矩阵结构没任何影响,所以下面用s_{om}表示\log(s_{om})继续表示:
    \left[P\log\left(S^T\right)\right]^D= \begin{bmatrix} \sum_i^m(p_{(1)i}s_{(1)i})& \sum_i^m(p_{(2)i}s_{(2)i})& \cdots& \sum_i^m(p_{(o)i}s_{(o)i}) \end{bmatrix}

    2.交叉熵计算

    L=\frac{1}{o}×\begin{bmatrix} \sum_i^m(p_{(1)i}s_{(1)i})& \sum_i^m(p_{(2)i}s_{(2)i})& \cdots& \sum_i^m(p_{(o)i}s_{(o)i}) \end{bmatrix}×\begin{bmatrix} 1\\ 1\\ \cdots\\ 1 \end{bmatrix}
    \log符号带入公式得到最终的损失函数矩阵计算结果:
    L=\frac{1}{o}\begin{bmatrix}\sum_k^o\sum_i^m\left[p_{(o)i}\log(s_{(o)i}) \right]\end{bmatrix}
    把矩阵符号去掉,这里的结果和前面最大似然评估推导的结果一致。

    参数优化

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

    既然这是一个极限过程,自然就可以用积分原理逐渐计算合理的参数。现在的目标是通过导数和找到递增量可以逐步求解w_{ij}值:
    \nabla_{ij}表示w_{ij}的偏导函数:\nabla_{ij}=\frac{\partial L(w_{ij})}{\partial w_{ij}}w_{ij}的更新公式为:w_{ij}=w_{ij}+\eta\nabla_{ij}\eta表示每一步更新的步长。
    如果损失函数前携带了负号,那么更新公式应该修改为w_{ij}=w_{ij}-\eta\nabla_{ij},即越来越小。

    1.求偏导函数

    目的已经明确,那么接下来就是数学运算了:
    设softmax计算结果一共有M个分类,输入模型的一个样本一共有N个特征。
    g_i表示权重计算的结果,下标i表示所属的分类,用数组可以表示为:
    \begin{bmatrix} g_1=\sum_j^Nw_{1j}x_j\\ g_2=\sum_j^Nw_{2j}x_j\\ \vdots\\ g_i=\sum_j^Nw_{ij}x_j\\ \vdots\\ g_M=\sum_j^Nw_{Mj}x_j\\ \end{bmatrix}
    q_i表示每一个分类softmax计算的结果:q_i=\frac{g_i}{\sum_k^Mg_k},k表示分类迭代求和的下标:用数组表示为:
    \begin{bmatrix} q_1=\frac{e^{g_1}}{\sum_k^Me^{g_k}}\\ q_2=\frac{e^{g_2}}{\sum_k^Me^{g_k}}\\ \vdots\\ q_i=\frac{e^{g_i}}{\sum_k^Me^{g_k}}\\ \vdots\\ q_M=\frac{e^{g_M}}{\sum_k^Me^{g_k}}\\ \end{bmatrix}
    Loss是最终的损失函数:Loss=\sum_k^M L_k = \sum_k^M p_k\ln q_kp_k表示每一个softmax分类对应的真实概率,取值0或1。
    优化参数是不断的调优权重参数,所以把w_{ij}看做自变量求导:
    \nabla_{ij}=\frac{\partial Loss}{\partial w_{ij}}
    按照前面给出的公式将损失函数的计算分为3步:1)计算权重模型,2)计算softmax,3)计算交叉熵。现在把求导过程分为这3步对q_ig_i以及w_{ij}复合求导:
    \begin{split} \nabla_{ij}&=\left(\sum_k^M p_k\ln q_k\right)'\\ &=\sum_k^M\frac{p_k}{q_k}\left(\sum_k^M\frac{e^{g_k}}{\sum_l^Me^{g_l}} \right)'\\ &=\sum_k^M\frac{p_k}{q_k}\frac{\left(e^{g_k}\right)'\sum_l^Me^{g_l} - e^{g_k}\left(\sum_l^Me^{g_l}\right)'}{\left(\sum_l^Me^{g_l}\right)^2}\\ &=\sum_k^M\frac{p_k}{q_k}\left[\frac{\left(e^{g_k}\right)'}{\sum_l^Me^{g_l}} - \frac{e^{g_k}}{\sum_l^Me^{g_l}}\frac{e^{g_i}}{\sum_l^Me^{g_l}}\left(g_k\right)'\right] \end{split}

    计算到这里需要注意一个问题。因为目标是对w_{ij}求导,所以在求和公式中包含w_{ij}的项(即包含g_i的项)和不包含的项求导的结果是不一样的,所以需要将g_i项单独拿出来求导。所以有:
    \begin{split} \nabla_{ij}&=\frac{p_i}{q_i}\left[\frac{\left(e^{g_i}\right)'}{\sum_l^Me^{g_l}} - \frac{e^{g_i}}{\sum_l^Me^{g_l}}\frac{e^{g_i}}{\sum_l^Me^{g_l}}\left(g_k\right)'\right] + \sum_{k \neq i}^M\frac{p_k}{q_k}\left[\frac{\left(e^{g_k}\right)'}{\sum_l^Me^{g_l}} - \frac{e^{g_k}}{\sum_l^Me^{g_l}}\frac{e^{g_i}}{\sum_l^Me^{g_l}}\left(g_k\right)'\right]\\ &=\frac{p_i}{q_i}\left(q_i-q_i^2\right)\left(g_k\right)'-\sum_{k \neq i}^M\frac{p_k}{q_k}q_kq_i\left(g_k\right)'\\ &=\left[p_i-\left(p_iq_i+\sum_{k\neq i}^Mp_kq_i\right)\right]\left(g_k\right)'\\ &=\left(p_i-q_i\sum_{k}^Mp_k\right)\frac{\partial\sum_j^N w_{ij}x_j}{\partial w_{ij}}\\ &=\left(p_i-q_i\sum_{k}^Mp_k\right)x_j \end{split}
    p_k是一个结构为[0,0,0,1,0,0......]的只有一个元素是1其余元素为0的数组,所以它的合计为1,因此得:

    \nabla_{ij} = \left(p_i-q_i\right)x_j

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

    2.多个样本与矩阵运算

    上面求导的过程并没有考虑多个样本的情况,设现在有O个样本。那么求导公式变成:
    \nabla_{ij}=\frac{1}{O}\sum_k^O(p_{(k)i}-q_i)x_{(k)j}
    因为每一个子项的求导结果都是向0接近,所以求和再平分之后也是靠近0的。
    现在模型参数的更新公式用矩阵表示为:
    W=W+\eta D。其中D\nabla_{ij}的矩阵形,\eta是一个常量,Ww_{ij}的矩阵形。
    设P表示样本真实分布的矩阵(即标记矩阵),Q是文章前面介绍的softmax矩阵计算的结果,X表示样本矩阵。那么D的矩阵表示为:D=(P-Q)^TX

    计算法则总结与编码实现

    算法总结

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

    1.定义

    O个样本、N个特征、M个分类,。
    X是样本(feature)矩阵,形状为(O,N)
    W是权重矩阵,形状为(M,N)
    P是标签(label)矩阵,形状为(O,M)
    Q是softmax计算后得到的矩阵,形状为(O,M)
    E_1,E_2是两个用于合并计算的单位矩阵,形状为(M,1)和(O,1),E=\begin{bmatrix} 1\\1\\ \cdots \\1 \end{bmatrix}
    矩阵A^T表示转置矩阵,A^D表示取矩阵的对角线元素(类似于特征)。

    2.softmax计算

    权重指数:G=e^{XW^T}
    归一化:Q=Softmax=\frac{G}{G*E_1}

    3.损失函数

    Loss=\frac{1}{o}\left[Plog(Q^T)\right]^D×E

    4.参数训练

    W=W+\eta\frac{\left(P-Q\right)^T×X}{O},训练会重复这个计算,直到变化率“接近”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的变化趋势:

    训练次数与损失函数的输出
    Count表示执行训练的次数,Loss表示损失函数的输出值,可以发现几个特点:
    1. 在优化的过程中Loss是逐渐接近0的。
    2. 反复使用相同的样本(案例中随机生成了500个样本)优化器在前1000次有比较明显的效果,但是后续增长乏力。

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

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

    相关文章

      网友评论

        本文标题:机器学习——softmax计算

        本文链接:https://www.haomeiwen.com/subject/nyfafqtx.html