softmax与交叉墒层的实现原理以及梯度计算

softmax,看名字就知道,就是如果判断输入属于某个类的概率大于属于其它类的概率,那么这个类对应的值就逼近于1,其它类的值就逼近于0,该算法的主要应用就是多分类,而且是互斥的,即只能属于其中一个类,和sigmoid类的激活函数不同的是,一般的激活函数只能分两类,所以可以理解成softmax是sigmoid类的激活函数的扩展。它的算法如下:

\mathbf{softmax(z_i)=\frac{e^{z_i}}{\sum_{n=0}^{N}e^{z_n}}}

它的图形化原理如下:

也就是把所有的值用e的指数函数表示出来,求和后算每个值占的比率,保证总和为1,一般就可以认为softmax得出的就是概率.

抽象层面的原理如下所示:

在网络层面,它可以表示为:

c语言实现: 

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>

void softmax(const float *input, const uint32_t dim_vec, float *output)
{
    float sum = 0.0f;         

    for(int i = 0; i < dim_vec; i++)
    {                         
        output[i] = expf(input[i]);
        sum = sum + output[i];
    }                         

    for(int i = 0; i < dim_vec; i++)
    {                         
        output[i] = output[i] / sum;
    }                         
}

int main(void)
{
	float input[10] = {1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1};
    float output[10]={0};

	softmax(input, 10, output);

	int i;
	for(i = 0; i < 10; i ++)
	{
		printf("%f ", output[i]);
	}

	printf("\n");

	return 0;
}

编译:

gcc softmax.c -lm -o softmax

测试:

可以看到,最后输出的概率和值是成正相关的。

expf是libm.a中提供的库函数,实现的是指数函数,在musl libc中的实现如下:

图形化表示:

在实际的网络中,softmax通常和交叉熵误差(cross entropy error)联合在一起用,作为网络的最后一层,这一层没有训练参数,如下图所示.

变量之间的关系如下:

y_i=\frac{e^{x_i}}{\sum_{k=1}^{n} e^{x_k}}

Loss=-\sum_{i=1}^{n}t_ilog (y_i)

以上图为例,展开后:

Loss=-\sum_{i=1}^{n}t_ilog (y_i)=-\big[t_1log(y_1)+t_2log(y_2)+t_3log(y_3)\big]

进一步化简得:

Loss=-\big[t_1log(\frac{e^{x_1}}{e^{x_1}+e^{x_2}+e^{x_3}})+t_2log(\frac{e^{x_2}}{e^{x_1}+e^{x_2}+e^{x_3}})+t_3log(\frac{e^{x_3}}{e^{x_1}+e^{x_2}+e^{x_3}})\big]

\\\boldsymbol{Loss=-\bigg[t_1\big[x_1-log(e^{x_1}+e^{x_2}+e^{x_3})\big]+t_2\big[x_2-log(e^{x_1}+e^{x_2}+e^{x_3})\big]+t_3\big[x_3-log(e^{x_1}+e^{x_2}+e^{x_3})\big]\bigg]}

\\Loss=(t_1+t_2+t_3)log(e^{x_1}+e^{x_2}+e^{x_3})-t_1x_1-t_2x_2-t_3x_3

由于是onehot标签,每组只有一个1,所以

t_1+t_2+t_3=1

所以:

\\Loss=log(e^{x_1}+e^{x_2}+e^{x_3})-t_1x_1-t_2x_2-t_3x_3

所以:

\\ \frac{\partial Loss}{\partial x_1}=\frac{e^{x_1}}{e^{x_1}+e^{x_2}+e^{x_3}}-t_1=y_1-t_1

\\ \frac{\partial Loss}{\partial x_2}=\frac{e^{x_2}}{e^{x_1}+e^{x_2}+e^{x_3}}-t_2=y_2-t_2

\\ \frac{\partial Loss}{\partial x_3}=\frac{e^{x_3}}{e^{x_1}+e^{x_2}+e^{x_3}}-t_3=y_3-t_3

过程虽然复杂,但是根据求导的链式法则,经过层层计算后,得到了非常具有美感的结果,实际上,这样漂亮的结果并非偶然,而是为了得到这样的结果,故意实际了交叉墒误差函数,神经网络中的误差函数很多都是人为设计的。


结束!

おすすめ

転載: blog.csdn.net/tugouxp/article/details/120400444
おすすめ