机器学习——神经网络,反向传播注解

机器学习——神经网络,反向传播注解


我们是要用数据网络实现一个多分类问题

多变量相对于单变量我们至少还要考虑两个问题:

  • 编码问题

    对于这些类别无序关系的离散变量可以用one-hot编码。

    采用sklearn.preprocessing进行

    from sklearn.preprocessing import OneHotEncoder
    
    encoder = OneHotEncoder(sparse=False)
    y_onehot = encoder.fit_transform(y)
    y_onehot.shape
    
  • 向量化

  • 给出代价函数

J ( θ ) = 1 m ∑ i = 1 m ∑ k = 1 K [ − y k ( i ) log ⁡ ( ( h θ ( x ( i ) ) ) k ) − ( 1 − y k ( i ) ) log ⁡ ( 1 − ( h θ ( x ( i ) ) ) k ) ] + λ 2 m [ ∑ j = 1 25 ∑ k = 1 400 ( Θ j , k ( 1 ) ) 2 + ∑ j = 1 10 ∑ k = 1 25 ( Θ j , k ( 2 ) ) 2 ] \begin{aligned}J(\theta)=& \frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{K}\left[-y_{k}^{(i)} \log \left(\left(h_{\theta}\left(x^{(i)}\right)\right)_{k}\right)-\left(1-y_{k}^{(i)}\right) \log \left(1-\left(h_{\theta}\left(x^{(i)}\right)\right)_{k}\right)\right]+\\& \frac{\lambda}{2 m}\left[\sum_{j=1}^{25} \sum_{k=1}^{400}\left(\Theta_{j, k}^{(1)}\right)^{2}+\sum_{j=1}^{10} \sum_{k=1}^{25}\left(\Theta_{j, k}^{(2)}\right)^{2}\right]\end{aligned} J(θ)=m1i=1mk=1K[yk(i)log((hθ(x(i)))k)(1yk(i))log(1(hθ(x(i)))k)]+2mλ[j=125k=1400(Θj,k(1))2+j=110k=125(Θj,k(2))2]

相对于二分类,输出只有一个,在这里,我们发现,这里是对K个输出都要求代价然后求和。正则化项是根据神经元个数及参数进行设定。400个输入,中间层是25个神经单元,输出层是10个单元,对应最终的0—9这10个数字的分类。参数矩阵400*25,25*10.

那么参数是如何设定和更新的呢?

设定不同层之间连接的参数,我们一般是随机置数,一般是一些比较小的数。在输入数据之后,通过前向传播和反向传播算法对参数进行更新

每个神经元中的激活函数我们选择 s i g m o d sigmod sigmod函数。

代价函数选择交叉熵函数:

def cost(params,input_size,hidden_size,num_label,X,y,learning_rate):
    #m是样本数
    m = X.shape[0]
    X = np.matrix(X)
    y = np.matrix(y)
    
    #只是截取参数而已,而且只是针对这样一个只有一层隐藏层的神经网络
    theta1 = np.matrix(np.reshape(params[:hidden_size(input_size+1)],(hidden_size,(input_size+1))))
    theta2 = np.matrix(np.reshape(params[hidden_size*(input_size+1):],(num_label,(hidden_size+1))))

   
    a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
    #
    J = 0
    for i in range (m):
        #采用交叉熵代价函数
        first_term = np.multiply(-y[i,:],np.log(h[i,:]))
        second_term = np.multiply(1-y[i,:],np.log(1-h[i,:]))
        J += np.sum(first_term-second_term)
        
    J = J / m

    return J

梯度检验

首先梯度检验是对于任意函数都是可行的。

Gradient checking works for any function where you are computing the cost and the gradient.

因为神经网络中的参数比较多,然后步骤又比较多,所以梯度检验只是类似于一个检查的过程,是针对我们的参数更新是否合理,看反向传播中梯度值是否有较大差别。size函数的一个作用就可以让我了解之间的数据,防止我们的维数不匹配。

用数值梯度(numerical gradient对梯度的估计)检验解析梯度(analytic gradient,可谓函数的实际梯度值)。

反向传播

关键在于求偏导的链式法则:

​ 链式法则。为了更加具体,避免太抽象,我直接适用 s i g m o d sigmod sigmod函数

​ 代价函数对 J ( s i g m o d ( θ . T ∗ a i ) ) J(sigmod(\theta.T*a_{i})) J(sigmod(θ.Tai)) s i g m o d ( θ . T ∗ a i ) sigmod(\theta.T*a_{i}) sigmod(θ.Tai)求偏导, s i g m o d ( θ . T ∗ a i ) sigmod(\theta.T*a_{i}) sigmod(θ.Tai再对 θ . T ∗ a i \theta.T*a_{i} θ.Tai求偏导, θ . T ∗ a i \theta.T*a_{i} θ.Tai在对 θ \theta θ求偏。

结果显而易见,最终结果是 a i ∗ s i g m o d ′ ∗ J ′ a_{i}*{sigmod'}*J' aisigmodJ

J ′ J' J不论是交叉熵函数,还是平方误差最后的结果其实会发现惊人的想似,就是 1 m ∑ i = 1 m ( h x − y ) x i \frac{1}{m}\sum_{i=1}^{m}(h_{x}-y)x_{i} m1i=1m(hxy)xi

那么我们这里将之后的一系列求导代替 x i x_{i} xi,那么我们就可以得到 J J J θ \theta θ求导结果为 1 m ∑ i = 1 m ( h x − y ) ∗ a i ∗ s i g m o d ′ \frac{1}{m}\sum_{i=1}^{m}(h_{x}-y)*a_{i}*{sigmod'} m1i=1m(hxy)aisigmod求和用 θ . T \theta.T θ.T替代 ( h x − y ) ∗ θ T ∗ a i ∗ s i g m o d ′ (h_{x}-y)*{\theta^T}*a_{i}*{sigmod'} (hxy)θTaisigmod

在吴恩达的课程中为了避免引入求偏导,链式法则这些微积分的内容,而进行了略过,并代之以一些隐藏细节的概念,直接给出的第几层的误差等等。因而给大家带来来一些困扰。

而这些完全可以直接从损失函数直接推导得出。只是吴恩达课程中隐藏,代之以一些概念。

猜你喜欢

转载自blog.csdn.net/qq_45175218/article/details/105234854