逻辑斯第回归、softmax分类与多层感知器

本专栏将推出一系列深度学习与图像处理相关的教程文章。注重原理精讲和代码实现。实现框架将重点选择Tensorflow或Pytorch。本讲从逻辑斯第回归入手,然后讲解softmax分类器,最后讲解多层感知器。文末提供注释详尽的Tensorflow代码实现。


逻辑斯第函数

逻辑斯第回归(Logistic Regression)起源于对生物学中种群数量的演变的建模。设种群数量为 P P P,环境能承载的最大人口数量为 K K K,单个生物的繁殖率为常数 r r r,则种群的增长率

\begin{equation}
\frac{\partial P}{\partial t} = r P (1 - \frac{P}{K})
\tag{1}
\end{equation}

这个微分方程的解为

\begin{equation}
P(t) = \frac{P(0) \exp{( rt)}}{1 + P(0) (\exp( rt) - 1) / K}
\tag{2}
\end{equation}

上式也就是逻辑斯第函数的来源,它对生物种群数量变化拟合效果较好。这个公式可以形式化为

\begin{equation}
F(t) = \frac{1}{1 + \exp( -(t - \mu) / s )}
\tag{3}
\end{equation}
其中 μ , s \mu, s μ,s为常数参数。下图展示了逻辑斯第函数的形态:

逻辑斯第函数的形态
逻辑斯第函数的形态 (图片来自维基百科)

二分类——逻辑斯第回归

逻辑斯第回归本是用于解决二分类问题,之所以称之为回归,是因为它解决问题的方法是对样本对应的概率值直接建模,而这又是一个回归问题。

如果向量样本 x ∈ R m x \in R^m xRm只可能属于两个类别 y ∈ { 0 , 1 } y \in \{0, 1\} y{0,1}。逻辑斯第回归假设样本 ( x , y ) (x, y) (x,y)满足这样的概率分布:
\begin{equation}
P(y=1 | x) = \frac{\exp(w^T x + b)}{1 + \exp(w^T x + b)}
\tag{4}
\end{equation}
从而

\begin{equation}
P(y=0 | x) = \frac{1}{1 + \exp(w^T x + b)}
\tag{5}
\end{equation}

其中 w ∈ R m w \in R^m wRm为待定参数向量。不难发现,式(5)与式(3)具有一致的形式。从某种程度上说,逻辑斯第回归是把样本向量 x x x通过与向量参数 w w w的内积服从的概率分布,映射到自然界中生物种群数量增长的分布上。

建好了概率模型之后,我们还需要建立目标函数求解模型参数 w , b w, b w,b。记 h w ( x ) = P ( Y = 1 ∣ x ) h_w(x)=P(Y=1|x) hw(x)=P(Y=1x),训练样本数据为 ( x i , y i ) (x_i, y_i) (xi,yi),根据极大似然思想,似然函数为
\begin{equation}
\max_{w,b} \prod_i h_w(x_i)^{y_i} (1-h_w(x_i))^{1- y_i}
\tag{6}
\end{equation}
从而对数似然函数为
\begin{equation}
\max_{w, b} \sum_i y_i \ln(h_w(x_i)) + (1 - y_i) \ln(1 - h_w(x_i))
\tag{7}
\end{equation}
而对对数似然函数的相反数求最小,就是交叉熵损失函数(Cross Entropy Loss)

关于逻辑斯第回归的更多细节,请参考博文:浅析Logistic Regression

多分类——Softmax分类

逻辑斯第回归用于解决二分类问题,一个自然的问题是多分类问题怎么解决?

Softmax分类就是逻辑斯蒂回归到多分类问题的推广,其概率预测模型定义为
\begin{equation}
\hat{y}=\textbf{softmax}(W x + b)
\tag{8}
\end{equation}
其中 y ^ \hat{y} y^的第 c c c个元素 [ y ^ ] c [\hat{y}]_c [y^]c表示数据 x x x属于第 c c c个类别的概率。而 softmax ( z ) \textbf{softmax}(z) softmax(z)的第 c c c个元素定义为
(9) [ softmax ( z ) ] c = exp ⁡ ( [ z ] c ) ∑ k = 1 p exp ⁡ ( [ z ] k ) [\textbf{softmax}(z)]_c = \frac{\exp({[z]_c})}{\sum_{k=1}^p \exp({[z]_k})} \tag{9} [softmax(z)]c=k=1pexp([z]k)exp([z]c)(9)

设样本数据为 ( x i , y i ) (x_i, y_i) (xi,yi),其中 x i ∈ R p x_i \in R^p xiRp为特征向量, y i ∈ R C y_i \in R^C yiRC的第c个维度为1,其他维度为0,则表示样本类别为第c类。为了求解模型参数 W , b W,b Wb,记 h W ( x ) = softmax ( W x + b ) h_W(x) = \textbf{softmax}(Wx+b) hW(x)=softmax(Wx+b)同样利用极大似然的思路,建立似然函数为
(10) max ⁡ W , b ∏ i ∏ c [ h W ( x i ) ] c [ y i ] c \max_{W,b} \prod_i \prod_c {[h_W(x_i)]}_c^{[y_i]_c} \tag{10} W,bmaxic[hW(xi)]c[yi]c(10)
其中 [ h W ( x i ) ] c [h_W(x_i)]_c [hW(xi)]c表示向量 h W ( x i ) h_W(x_i) hW(xi)的第c个元素, [ y i ] c [y_i]_c [yi]c表示向量 y i y_i yi的第c个元素。从而对数似然函数为
(11) max ⁡ W , b ∑ i ∑ c [ y i ] c ln ⁡ ( [ h W ( x i ) ] c ) \max_{W,b} \sum_i \sum_c [y_i]_c \ln( [h_W(x_i)]_c ) \tag{11} W,bmaxic[yi]cln([hW(xi)]c)(11)

与逻辑斯第回归一样,对对数似然函数的相反数求最小,就是多分类问题的交叉熵损失函数(Cross Entropy Loss)

在实现过程中,目标函数的求解由Tensorflow、Pytorch等计算框架完成,故这里不再分析。

多层感知器

多层感知器(Multi-layer Perceptron, MLP)的第一个隐层的神经元 k k k(节点)是线性变换复合一个非线性变换:
\begin{equation}
y_k = a_k(x) = \textbf{hardlim}(w_k^T x + b)
\tag{12}
\end{equation}
其中 hardlim \textbf{hardlim} hardlim是硬极限函数
(13) hardlim ( x ) = { 1 , x > 0 0 , x ≤ 0 \textbf{hardlim}(x) = \left\{ \begin{aligned} 1, \quad & x > 0 \\ 0, \quad & x \le 0 \end{aligned} \right. \tag{13} hardlim(x)={1,0,x>0x0(13)
它是一种非线性激活函数。它的输入输出都是标量。硬极限函数导数为0(原点处无导数),无法反向传播。因此改进形式有simgoid,tanh或者ReLU:
Sigomid函数
\begin{equation}
\sigma(t) = \frac{1}{1 + e^{-t}}
\tag{14}
\end{equation}
tanh函数
\begin{equation}
tanh(t) = 2\sigma(2t) - 1 = \frac{1 - e^{-2t}}{1 + e^{-2t}}
\tag{15}
\end{equation}
ReLU函数
(16) r e l u ( t ) = max ⁡ ( t , 0 ) = { t , t > 0 0 , t ≤ 0 relu(t) = \max(t, 0) = \left\{ \begin{aligned} t, \quad & t > 0 \\ 0, \quad & t \le 0 \end{aligned} \right. \tag{16} relu(t)=max(t,0)={t,0,t>0t0(16)
不同激活函数的优劣请参考知乎专栏:https://zhuanlan.zhihu.com/p/21462488?refer=intelligentunit。

如果我们定义向量输入的硬极限函数输出是对元素逐个进行相应的标量操作,多层感知器的第一个隐层可以写为
\begin{equation}
y = a(x) = \textbf{hardlim}(W x + b)
\tag{17}
\end{equation}
这一层的输入是向量 x x x,而输出是向量 y y y

多层感知器的隐层的向量输出作为softmax回归的输入,形成一个完整的多层感知器:
\begin{equation}
y = \textbf{softmax}(a(x) )
\tag{18}
\end{equation}

一般多层感知器的最后一个隐层输出是多个隐层的复合函数。一个 k k k层感知器(包含 k − 1 k-1 k1个隐层和一个输出层)的函数表达如下:
\begin{equation}
y = mlp(x) = \textbf{softmax}( a_{k - 1} ( \cdots a_1(x) \cdots ) )
\tag{19}
\end{equation}

多层感知器的训练目标函数与softmax分类器完全相同,仅仅是对分类概率建模不同。

Tensorflow实现

程序的目标是分别训练一个softmax和mlp模型,对MNIST手写数字数据集进行分类。输入为 28 × 28 = 784 28\times28=784 28×28=784维向量,输出为10维向量,标记输入灰度图像属于 0 − 9 0-9 09哪个类别。

# coding=utf8
from __future__ import print_function
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
# 指定运算设备
device = "/gpu:0"
# 设置训练轮次
train_epoch_num = 100
# 设置随机梯度下降的批大小
batch_size= 50
# 设置训练总迭代数
train_iter_num = 55000 / batch_size * train_epoch_num
# 加载训练数据
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
trX, trY = mnist.train.images, mnist.train.labels
print('len trX : ', len(trX))
# 开启Tensorflow的会话
sess = tf.InteractiveSession()
# 定义模型输入
x = tf.placeholder(tf.float32, shape=[None, 784], name="x")
# 定义模型输出
y_ = tf.placeholder(tf.float32, shape=[None, 10], name="y")
# 训练
def train(train_model, y):
    # 标记模型在测试样本上正确的样本
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
    # 计算模型在测试样本上的正确率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 初始化tf的计算图中所有变量
    sess.run(tf.global_variables_initializer())
    # 指定运算设备
    with tf.device(device):
        # 随机梯度下降法:迭代优化
        for i in range(train_iter_num):
            # 从训练样本中随机抽取一个批
            batch = mnist.train.next_batch(batch_size)
            # 用批数据优化模型参数
            train_model.run(feed_dict={x:batch[0], y_: batch[1]})
            # 打印第i次迭代的正确率
            if i % 1000 == 0:
                print(i, accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
def train2(train_model, y):
    # 标记模型在测试样本上正确的样本
    predict_y = tf.argmax(y, 1)
    # 初始化tf的计算图中所有变量
    sess.run(tf.global_variables_initializer())
    # 开始训练轮次
    for i in range(train_epoch_num):
        # 将所有训练样本依次分割成批
        for start, end in zip(range(0, len(trX), batch_size), range(batch_size, len(trX) + 1, batch_size)):
            # 用批数据优化模型参数
            sess.run(train_model, feed_dict={x: trX[start:end], y_: trY[start:end]})
        # 计算模型在测试样本上的正确率
        acc = np.mean(np.argmax(mnist.test.labels, axis=1) == sess.run(predict_y, feed_dict={x: mnist.test.images}))
        # 打印第i个轮次的正确率
        print(i, acc)
# 用正态分布随机数初始化权重
def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))
# 建立softmax分类器
def softmax_model():
    # 定义权重变量
    W = tf.Variable(tf.zeros([784, 10]))
    b = tf.Variable(tf.zeros([10]))
    # 初始化权重变量
    W = init_weights(W.get_shape())
    b = init_weights(b.get_shape())
    # softmax模型的线性部分
    y = tf.matmul(x, W) + b
    # 定义softmax和交叉熵目标函数
    cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y, labels=y_))
    # 定义优化算子为梯度下降算子,步长0.1
    train_model = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy)
    return train_model, y
# 建立多层感知器
def mlp_model():
    # 定义第一层权重变量
    W = tf.Variable(tf.zeros([784, 625]))
    # 定义第二次权重变量
    W2 = tf.Variable(tf.zeros([625, 10]))
    # 初始化权重非常重要,否则GradientDescent收敛非常慢
    W = init_weights(W.get_shape())
    W2 = init_weights(W2.get_shape())
    # 定义第一层
    h = tf.sigmoid( tf.matmul(x,W))
    # 定义第二层
    y = tf.matmul(h, W2)
    # 定义最后一层softmax和交叉熵目标函数
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y, labels=y_))
    # 定义优化算子为梯度下降算子,步长0.1
    train_model = tf.train.GradientDescentOptimizer(0.1).minimize(cost)
    return train_model, y
###############################
# 建模和训练
def softmax():
    train_model, y = softmax_model()
    #train(train_model, y)
    train2(train_model, y)
def mlp():
    train_model, y = mlp_model()
    #train(train_model, y)
    train2(train_model, y)
# 开始执行
print('softmax regression')
softmax()
print('mlp')
mlp()

代码中提供了两种训练方法。函数train从训练样本中随机抽取批(batch),优化模型参数。函数train2则是将全部训练数据分成批遍历一遍,进行多个轮次(Epoch)。当随机函数设计得当,两种训练方法在相同训练次数下的得到的模型性能相近。

运行结果:

softmax regression
0 0.9069
1 0.9125
2 0.9146
...
98 0.9223
99 0.9223
mlp
0 0.8743
1 0.8991
2 0.9079
...
98 0.9787
99 0.9786

可以看出多层感知器的学习能力显著强于softmax分类器。

微信公众号同步更新

![微信公众号](https://img-blog.csdn.net/20180226131119877?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG9taGVhdmVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) TomHeaven的博客,欢迎关注 :)
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TomHeaven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值