【参考资料】
【1】http://deeplearning.stanford.edu/wiki/index.php/Softmax回归
【2】《统计学习方法》
【3】《深度学习》花书 3.13
【4】http://deeplearning.stanford.edu/wiki/index.php/Softmax回归
基本定义
首先给出softmax的数学定义,如下:
softmax是用于进行多目标分类的,也就是当我们得到一堆输入样本x(x是一个包含多个特征的向量)时,它可能属于类型A、也可能属于类型B。就想多层神经网络最后添加的softmax层一样,输出的是一个概率。比如输入的人脸,在输出时可以是张三的概率0.4,李四的概率0.6。
回到上面数学公式,模型是这样一批条件概率的组合,即参数为 (注意这里的不是随机变量)下,输出关于为某一个分类的条件概率。后面增加是为了做归一化,也就是所有概率加起来是1。
代价函数
这里要单独把代价函数拿出来,其实logistic回归的问题也一样,即要回答在概率情况下我们用什么样的方式来表示代价?好比在一个距离空间里我们用什么来定义距离。
1. 自信息
在信息论基础下,认为信息中包含一个事件,其发生概率越小越有用。例如“今天天晴”和“今天台风”相比,后者发生概率更小,信息量更大。用白话说就是大家都知道的就是废话。 自信息用数学公式表示如下: ,单位是奈特(nats),即用概率1/e发生的事件。
2. 香农熵
自信息只是一个信息单个的,而我们定义整个分布的信息为香农熵(在连续时也称为微分熵):也就是
举例:对于二项分布其香农熵相对于概率p为:
3. KL散度
如果同一个随机变量有两种独立的概率分布P(X)和Q(X),则两种分布的差异定义为:
当KL散度为0时,则认为两者具有相同的分布形式。也可以写为
举例:
采用均匀分布来近似观察分布的KL散度为a
采用二项分布来近似观察分布的KL散度为b
若a > b,则认为二项分布与观测分布更加接近,因为KL散度更小。
对于softmax的代价损失函数及梯度
对于训练集,其中
我们定义参数下,将x分类到的概率为:
通过上一部分香农熵的概念,我们定义softmax的损失函数如下:
,对此公式求偏导
备注:上面那个推导实在没经历写latex公式,也比较简单,就是复合函数求导,希望以后还能看明白
softmax例子(基于sklearn)
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
def _test_softmax():
"""
虚拟构造数据,我们假设构造一个x1, x2的二维特征平面,其范围都是10
假定x1为水平方向、x2为垂直方向
存在两个分割线
1)2*x1 + 5 = x2
2)2*x1 - 5 = x2
当特征点在直线1上方时,为分类1,在直线1和2之间时为分类2,在直线2下方时为分类3
"""
x1 = np.linspace(0, 10, 500)
x2 = np.random.random_sample(500)*25
y = np.zeros(500)
for i in range(0, 500) :
if x2[i] >= (2 * x1[i] + 5):
y[i] = 1
elif x2[i] >= (2 * x1[i] - 5):
y[i] = 2
else :
y[i] = 3
#构造二维特征的输入矩阵
h = np.transpose(np.vstack((x1, x2)))
"""
构筑softmax回归模型
"""
clf = linear_model.LogisticRegression(multi_class="multinomial", solver="lbfgs", C=10.0)
clf.fit(h, y)
"""
测试结果如下
预测为: [1.] 各类概率为 [[1.00000000e+00 1.98641177e-24 5.38851421e-61]]
预测为: [2.] 各类概率为 [[6.66670055e-10 9.99999985e-01 1.43504834e-08]]
预测为: [3.] 各类概率为 [[1.52911535e-63 1.58007802e-21 1.00000000e+00]]
"""
predict = clf.predict([[1, 20]])
predict_pro = clf.predict_proba([[1, 20]])
print('预测为:', predict, '各类概率为', predict_pro)
predict = clf.predict([[10, 20]])
predict_pro = clf.predict_proba([[10, 20]])
print('预测为:', predict, '各类概率为', predict_pro)
predict = clf.predict([[10, 2]])
predict_pro = clf.predict_proba([[10, 2]])
print('预测为:', predict, '各类概率为', predict_pro)
pass
"""
说明:
softmax分类代码实现,对应的笔记《分类器(softmax回归)》
作者:fredric
日期:2018-9-4
"""
if __name__ == "__main__":
_test_softmax()