构建一个神经网络:逻辑分类函数


实现神经网络:逻辑分类函数

如果想用神经网络来完成分类的工作,我们需要对输出 t 输出一个概率分布。

如果只分两类:t=1t=0,我们用逻辑回归中的逻辑函数。

如果要分多类,上述函数有扩展版本称为 softmax function

下面我们主要讲一下逻辑函数。

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline

逻辑函数

目标是通过输入z预测目标类t。输入z被归为 t=1 时的概率 P(t=1 \mid z) 用逻辑函数 y = \sigma(z) 的输出y来表示。\sigma即是逻辑函数,其定义为:

\sigma(z) = \frac{1}{1+e^{-z}}

对于给定的输入z,分类的两种结果的概率分别写为:

P(t=1\mid z) = \sigma(z) = \frac{1}{1+e^{-z}}
P(t=0\mid z) = 1 - \sigma(z) = \frac{e^{-z}}{1+e^{-z}}

注意这里的输入 z 其实就是概率比的对数:

log \frac{P(t=1\mid z)}{P(t=0\mid z)} = log \frac{\frac{1}{1+e^{-z}}}{\frac{e^{-z}}{1+e^{-z}}} = log \frac{1}{e^{-z}} = log(1) - log(e^{-z}) = z

这意味着 对数概率比(log odds ratio): log(P(t=1\mid z)/P(t=0\mid z)) 随着z是线性变化的。那么如果说神经网络中 z = x * w,那么对数概率比随着参数 w 和输入样本 x 线性变化。

def logistic(z):
    return 1/(1+np.exp(-z))
z = np.linspace(-6,6,100)
plt.plot(z, logistic(z), 'b-')
plt.xlabel('$z$', fontsize=15)
plt.ylabel('$\sigma(z)$', fontsize=15)
plt.title('logistic function')
plt.grid()
plt.show()

png

逻辑函数的导数

神经网络中经常使用基于梯度的优化技术,所以有必要计算一下输出 y 关于输入 x 的导数。

\frac{\partial y}{\partial z} = \frac{\partial \sigma(z)}{\partial z} = \frac{\partial \frac{1}{1+e^{-z}}}{\partial z} = \frac{-1}{(1+e^{-z})^2} *e^{-z}*-1 = \frac{1}{1+e^{-z}} \frac{e^{-z}}{1+e^{-z}} = y(1-y)
def logistic_derivative(z):
    return logistic(z)*(1-logistic(z))
z = np.linspace(-6,6,100)
plt.plot(z, logistic_derivative(z), 'r-')
plt.xlabel('$z$', fontsize=15)
plt.ylabel('$\\frac{\\partial \\sigma(z)}{\\partial z}$', fontsize=15)
plt.title('derivative of the logistic function')
plt.grid()
plt.show()

png

逻辑函数的 交叉熵成本函数

回顾一下逻辑函数 y = \sigma (z),输入z属于一类(t=1)的概率为y,属于另一类(t=0)的概率为 1-y。我们记为:P(t=1\mid z) = \sigma(z) = y

在这个情况下如何优化神经网络模型呢?

在线性回归问题中,我们用的 J(\theta) 在这里并不适用,因为它不再是一个凸函数,所以我们得重新去想一个误差函数来评价并优化我们的神经网络。

理想状态下,当y=h_\theta时,误差为零;y+h_\theta = 1时,误差为正无穷。Andrew Ng 讲到直接采用-log(h_\theta)(0,1]上的性质来达到这一目的,但是正面推导采用了极大似然估计(MLE)他跳过没讲。这里我们讲一下具体的推导。

对于每一个输入的样本,给定的一系列参数\theta可以准确预测出正确的类,这样的事件是有一定的似然(likelihood),我们要做的就是对这个似然求极大。对于每个样本i,参数\theta可以被转换成逻辑函数的输入 z_i。极大似然可以写成:

\arg\max_\theta \mathcal{L}(\theta \mid t,z) = \arg\max_\theta \prod_{i=1}^{n} \mathcal{L}(\theta \mid t_i,z_i)

似然 \mathcal{L}(\theta \mid t,z) 可以被重新写成联合概率的形式 P(t,z \mid \theta)。由条件概率的定义 P(A,B) = P(A \mid B) * P(B),有:

P(t,z \mid \theta) = P(t \mid z,\theta)P(z \mid \theta)

我们对z的概率不感兴趣,所以我们可以写成:

\mathcal{L}(\theta\mid t,z) = P(t \mid z,\theta) = \prod_{i=1}^{n} P(t_i \mid z_i,\theta)

由于 t_i 是伯努利变量【伯努利分布 = 0-1分布 = 两点分布】,且对于给定的\thetaP(t \mid z) = y, 所以我们可以重写:

P(t\mid z) = \prod_{i=1}^{n} P(t_i=1 \mid z_i)^{t_i} * (1 - P(t_i=1 \mid z_i))^{1-t_i} = \prod_{i=1}^{n} y_i^{t_i} * (1 - y_i)^{1-t_i}

因为逻辑函数是一个单调递增函数,所以我们可以优化 对数-似然函数 \arg\max_\theta \log \mathcal{L}(\theta \mid t,z)。这个最大值和正常的似然函数最大值相同。

log \mathcal{L}(\theta\mid t,z) = log \prod_{i=1}^{n} y_i^{t_i} * (1 - y_i)^{1-t_i} = \sum_{i=1}^{n} t_i log(y_i) + (1-t_i) log(1 - y_i)

显然这个函数是负值。要想求最大似然,就得求函数的负值的最小值。

误差函数 \xi(t,y)被称为 交叉熵误差函数(对数损失):

\xi(t,y) = - log \mathcal{L}(\theta\mid t,z) = - \sum_{i=1}^{n} \left[ t_i log(y_i) + (1-t_i)log(1-y_i) \right] = - \sum_{i=1}^{n} \left[ t_i log(\sigma(z) + (1-t_i)log(1-\sigma(z)) \right]

重写:

\xi(t_i,y_i) = \begin{cases} -log(y_i) & \text{if } t_i = 1 \\ -log(1-y_i) & \text{if } t_i = 0 \end{cases}

这样,当 t=1 而 y=0 时,误差趋近于正无穷;y=1 时误差趋近于0。

鉴于t取值非0即1,我们可以重写函数:

\xi(t,y) = -t * log(y) - (1-t) * log(1-y)

n个样本的和加起来,则有:

\xi(t,y) = - \sum_{i=1}^{n} \left[ t_i log(y_i) + (1-t_i)log(1-y_i) \right]

逻辑函数的交叉熵成本函数的导数

\frac{\partial \xi}{\partial y} = \frac{\partial (-t * log(y) - (1-t)* log(1-y))}{\partial y} = \frac{\partial (-t * log(y))}{\partial y} + \frac{\partial (- (1-t)*log(1-y))}{\partial y} = -\frac{t}{y} + \frac{1-t}{1-y} = \frac{y-t}{y(1-y)}
\frac{\partial \xi}{\partial z} = \frac{\partial y}{\partial z} \frac{\partial \xi}{\partial y} = y (1-y) \frac{y-t}{y(1-y)} = y-t