美文网首页
深度学习(1)

深度学习(1)

作者: 稀饭里的辣椒 | 来源:发表于2018-07-14 16:18 被阅读0次

    动机

    万事皆有因果。我之所以想要学习深度学习,是因为深度学习在学术界获得了巨大的成功。现在在数据挖掘顶会上大多数的论文都运用了深度学习。深度学习凭借其优秀的实验结果,即使解释性不强也大受欢迎,大有压过机器学习的势头。

    为了个人的发展以及发paper,我其实一直想入门深度学习。但是苦于实验室环境以及导师方向,只能自学。之前也零零散散、断断续续看过一点教程,但是都没有形成系统的知识体系。所以下定决心,利用写文档的手段督促自己保持学习的连续性,同时在这里与大家分享自己的拙见。

    说在前面

    在此之前,我对深度学习的认识仅限于听过名字而已,什么CNN,RNN根本不懂其中的原理。另外,我的数学也非常薄弱,可能一些简单的推导我都会卡半天才能理解。所以学习深度学习的过程必然是非常痛苦的,我也不知道自己能够坚持到什么时候。如果各位看官觉得我的水平不行,请出门左转。但是也欢迎留下你的高见。
    在写这篇文章之前,我已经看过一点吴恩达教授 DeepLearning的课程,所以 to be honest,这里的内容会和他的课程有一些雷同。

    交叉熵损失函数

    logistic regression: 逻辑回归是解决二分类问题的经典方法,在这里介绍它主要是想引出交叉熵损失函数 : J(W;b)= - \frac{1}{m}\sum_{i=1}^m y_i log \hat{y}_i +(1-y_i)log(1-\hat{y}_i), 其中m是样本数量, y_i是真实的样本类别, \hat{y}_i是样本属于正类的概率。

    哦?忘了介绍什么是损失函数了。 作为学习深度学习的童鞋,想必大家对损失函数肯定了解的吧,所以我还是不介绍了!!#¥%……&

    当初在学习机器学习的时候,我并没有多想为什么逻辑回归的损失函数是这样的形式,而不是(y-\hat{y})^2。直到后来发现在深度学习中交叉熵损失函数也长这样,我才发现原来事情没这么简单。

    首先吴恩达教授在他的课程里给出了一种解释:
    我们预测得到的结果\hat{y}实际上样本为正类(y=1)的概率,即P(y=1) = \hat{y}; P(y=0) = 1-\hat{y}
    这两个概率计算公式正好可以合并为:P(y=1) = {\hat{y}}^y({1-\hat{y}})^{1-y}
    这个概率计算公式就非常厉害了!!!我们可以想象一下:如果真实label = 1, 则我们希望\hat{y}越大越好;反之,如果真实label = 0,则希望\hat{y}越小越好。而上面这个公式正好可以满足。

    然后我们对这个公式求对数:
    logP(y=1) = ylog{\hat{y}} + (1-y)log({1-\hat{y}}), 然后对于多个样本进行累加,则得到 \sum_{i=1}^m y_i log \hat{y}_i +(1-y_i)log(1-\hat{y}_i), 姑且记为O好了。 那么现在我们的目标是要最大化O,换句话讲就是最小化-O,所以,就有了J(W;b)= - \sum_{i=1}^m y_i log \hat{y}_i +(1-y_i)log(1-\hat{y}_i)

    交叉熵函数的梯度下降

    现在假设神经网络结构是最简单的单层结构,也就是说所有特征输入经过一定权重累加之后,再通过sigmoid函数求出最后的输出\hat{y}
    用公式表示就是 \hat{y} = sigmoid(W^TX+b),其中W是权重向量,X是特征向量,b是偏执项,可以理解为直线方程y=ax+b中的截距。
    深度学习通过对梯度下降法不断调整参数Wb,使得最终的损失函数J(W;b)达到最小。

    sigmoid函数:S(x) = \frac{1}{1+e^{-x}},它的导数S'(x) = \frac{e^{-x}}{(1+e^{-x})^2} = S(x)(1-S(x))

    首先我们考虑简单的情形,只有一个样本。之后考虑多个样本的时候只要加上累加符号即可:
    L= y log \hat{y}+(1-y)log(1-\hat{y}) , A = W^TX+b,则\hat{y} = S(A)

    b的梯度

    我们首先看下关于偏执项b的梯度:
    \frac{\partial L}{\partial b} = \frac{\partial L}{\partial \hat{y}} \times \frac{\partial \hat{y}}{\partial A} \times \frac{\partial A}{\partial b}
    其中:
    \frac{\partial L}{\partial \hat{y}} = -\frac{y}{\hat{y}}+\frac{1-y}{1- \hat{y}}
    \frac{\partial \hat{y}}{\partial A} = S(A)(1-S(A))=\hat{y}(1- \hat{y})
    \frac{\partial A}{\partial b} = 1

    \therefore \frac{\partial L}{\partial b} = (-\frac{y}{\hat{y}}+\frac{1-y}{1- \hat{y}}) \times (\hat{y}(1- \hat{y})) \times 1 = -y(1-\hat{y}) + \hat{y}(1-y) = \hat{y}-y

    w_i的梯度

    然后我们看下关于每一个权重w_j的梯度:
    \frac{\partial L}{\partial w_j} = \frac{\partial L}{\partial \hat{y}} \times \frac{\partial \hat{y}}{\partial A} \times \frac{\partial A}{\partial w_j}

    其中:
    \frac{\partial L}{\partial \hat{y}} = \frac{y}{\hat{y}}+\frac{1-y}{1- \hat{y}}
    \frac{\partial \hat{y}}{\partial A} = S(A)(1-S(A))=\hat{y}(1- \hat{y})
    \frac{\partial A}{\partial w_j} = x_j

    \therefore \frac{\partial L}{\partial w_j} = (-\frac{y}{\hat{y}}+\frac{1-y}{1- \hat{y}}) \times (\hat{y}(1- \hat{y})) \times x_j = [-y(1-\hat{y}) + \hat{y}(1-y) ] \times x_j= (\hat{y}-y)x_j

    多个样本的梯度

    上面考虑只有一个样本的情况,现在考虑所有的样本时,只需要累加起来即可。
    \frac{\partial J}{\partial b} = \frac{1}{m}\sum_{i=1}^m\hat{y}^{(i)}-y^{(i)}
    \frac{\partial J}{\partial w_j} = \frac{1}{m}\sum_{i=1}^m(\hat{y}^{(i)}-y^{(i)})x^{(i)}_j
    这里的上标(i)表示第i个样本, 下标j表示第j维的特征。
    最后更新w_ib:
    w_j = w_j - \alpha \frac{\partial L}{\partial w_j}
    b = b - \alpha \frac{\partial L}{\partial b}

    向量化

    为了方便大家的理解,上面的内容使用累加符号对每个样本进行计算,比较直观。如果按照上面的思路,在代码实现时相信大家肯定会优先想到使用for循环。但是在所有编程语言中,for循环的效率并不高,而使用向量化的操作能够大大加快代码的运行效率。所以,在这一节,将介绍如何把上面的公式转化成向量的表达形式。

    因为电脑编辑矩阵比较麻烦,所以我手写了一份资料。


    vector.jpeg

    现在假设有样本 \bold{X},维度是 n*m,表示有m个样本,每个样本有n维特征,每一列代表一个完整的样本;
    标签数据\bold{Y},维度是1 \times m,表示每个样本的真实类别。
    另外权重矩阵Wn \times 1维的,每一行是单独的权重w_j
    然后直接利用矩阵乘法来代替原来的for循环。
    最后的\hat{y} = W^TX+b
    \frac{\partial L}{\partial b} =\frac{1}{m}sum (\hat{y}-Y)
    \frac{\partial L}{\partial w} = \frac{1}{m}X(\hat{y}-Y)^T

    从我个人学习感受来讲,这里需要注意的是原来的X矩阵中 一列代表一个样本,而不是一行代表一个样本。 然后关于权重的梯度下降向量化公式中要注意是X矩阵在前,然后要对(\hat{y}-Y)转置。

    python代码实现

    import numpy as np
    
    ##定义sigmoid函数
    def sigmoid(x):
        return 1/(1+np.exp(-x))
    
    ##初始化参数
    def initialization_parameters(dim):
        w = np.zeros((dim,1))
        b= 0.0
        return w, b
    
    ##前向传播
    def forward_propagate(w,b, X,Y):
        m = X.shape[1]
    
        A = np.dot(w.T, X) + b
        y_hat = sigmoid(A)
        cost = -1/m * np.sum(Y*np.log(y_hat) + (1-Y)*np.log(1-y_hat))
    
        ##计算梯度
        dw = np.dot(X, (y_hat-Y).T)/m
        db = np.sum(y_hat-Y)/m
    
        grad = { 'dw':dw,
                 'db':db
        }
        return grad, cost
    
    ##后向传播,调整参数
    def back_propagate(w,b,grad,alpha):
        dw = grad['dw']
        db = grad['db']
        w = w - alpha*dw
        b = b - alpha*db
    
        return w,b
    
    
    

    相关文章

      网友评论

          本文标题:深度学习(1)

          本文链接:https://www.haomeiwen.com/subject/iczspftx.html