深度学习(1)

动机

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

为了个人的发展以及发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


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容