【DeepLearning】Basic Conceptions

Deep Learning

本文是学习深度学习入门时系统笔记。

参考资料:《deep learning》 MIT出版社和图灵参考丛书《深度学习入门(基于python的理论与实现)》。

[TOC]

Perception

多输入单输出逻辑元。两个过程:计算-->激活

典型逻辑电路AND,OR,NOT均可以表示为单层感知器,具有以下要素:

  • weight : w=[w1,w2]
  • bias : theta
  • input : x=[x1,x2]
  • output : y
  • z : activation function

并有
y=z(wx+b)=perception(x)
根据真值表设定w,b后代码如下

def AND(x):
    w=np.array([0.5,0.5])
    theta=-0.7
    y=np.sum(x*w)+theta
    if y>0:
        return 1
    elif y<0:
        return 0

A simple network

  • 初始化(设定每层个数、weight & bias)

  • 设置中间变量和激活函数

    z1=sigmoid(np.dot(x,W1)+b1)
    z2=sigmoid(np.dot(z1,W2)+b2
    
  • 设置一层softmax:取为真概率最大的预测(用于分类)

  • 预测

Softmax

用于分类的输出层,输出0-1的实数而且所有的函数值之和为1,作为输出属于某类别的概率
y_k=\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)}
注意:softmax进行了e函数计算,容易发生溢出错误

改进为
y_k=\frac{exp(a_k+logC)}{\sum_{i=1}^nexp(a_i+log C)}

Loss function

衡量预测值与真值差距的性能指标,一般用均方差(mean squared error)或者交叉熵(Cross entropy error)
MSE=\frac{1}{2}\sum_k(y_k-t_k)^2

CEE=-\sum_k{t_k}log\ {y_k}

def mean_square_error(y,t):
    return(np.sum((y-t)^2)/2)

def cross_entropy_error(y,t):
    delta=1e-10# avoid log(0)
    return(np.sum(t*np.log(y+delta)))

def cross_entropy_error_batch(y,t,):
    if y.ndim=1:
        t=t.reshape(1,t.size)
        y=y.reshape(1,y.size)
batch_num=y.shape[0]
return(np.sum(t*np.log(y+1e-10))/batch_num)

为什么设定损失函数而不是识别精度作为指标?

识别精度是离散的,而损失函数是连续的,离散函数作为优化目标导致导数大部分为0,无法使用梯度相关的算法优化。

activiation function

表示计算值使得神经元被激活(由计算值到output)的方式。

Functions:

  • step-function
  • sigmoid
  • Relu
    等激活函数

激活函数可以写成一个类,如ReLu写为

class Relu:
    def __init__(self):
        self.mask = None

    def forward(self, x):
        self.mask = (x <= 0)
        out = x.copy()
        out[self.mask] = 0

        return out

    def backward(self, dout):
        dout[self.mask] = 0
        dx = dout

        return dx
    
    
# sigmoid
class Sigmoid:
    def __init__(self):
        self.out = None

    def forward(self, x):
        out = sigmoid(x)
        self.out = out
        return out

    def backward(self, dout):
        dx = dout * (1.0 - self.out) * self.out

        return dx

Gradient

即数值微分在多元情况下。

# 求近似微分
def numerical_diff(f, x):
    h = 1e-4 # 0.0001
    return (f(x+h) - f(x-h)) / (2*h)

def numerical_grad(f,x):
    h=1e-4
    grad=np.zeros_like(x)
    
    for i in range(x.size):
        fx1=(float(x[i])+h)
        fx2=(float(x[i])-h)
        grad[i]=(fx1-fx2)/(2*h)
 
    return grad

def numerical_grad_batch(f, X):
    if x.ndim ==1:
        return numerical_grad(f,X)
    else:
        grad =np.zeros_like(X)
        for i,x in enumerate(X):
            grad[i]=numerical_grad(f,x)
        
    return grad

Gradient descent

x_0=x_0-\eta\frac{\partial{f}}{\partial{x_0}} \\ x_1=x_1-\eta\frac{\partial{f}}{\partial{x_1}}

计算步骤:

  • 选定初始点
  • 执行梯度计算
  • 梯度下降
  • 返回
def gradient_descent(f,learn_rate):
    x=np.array([np.random.rand(),np.random.rand()])
    x_history=[]
    x_new=x-learn_rate*gd.numerical_grad(f,x)
    
    while ((x_new-x).all()>1e-5):
        x=x_new
        x_new=x-learn_rate*gd.numerical_grad(f,x)
        x_history.append(x_new.copy())

    return x_new,x_history

Gradient in DL

指的是损失函数关于权重的梯度
\frac{\partial{L}}{\partial{W}}=\left( \matrix{ \frac{\partial{L}}{\partial{W_{11}}}, \frac{\partial{L}}{\partial{W_{12}}}, \frac{\partial{L}}{\partial{W_{13}}}\\ \frac{\partial{L}}{\partial{W_{21}}}, \frac{\partial{L}}{\partial{W_{22}}}, \frac{\partial{L}}{\partial{W_{23}}} }\right)

Backforward

链式法则向后传播求取导数

此处应有计算图

Simple Layer

将神经网络层实现为一个单位。

Multiplelayer:

class MulLayer:
    def __init__(self):
        self.x = None
        self.y = None

    def forward(self, x, y):
        self.x = x
        self.y = y                
        out = x * y
        return out

    def backward(self, dout):
        dx = dout * self.y
        dy = dout * self.x
        return dx, dy

Addlayer

加法层无需特别的初始化。

Affline

仿射变换:矩阵的乘积运算。

在affline层中务必注意变量的Shape。

完成的是y=wx+b操作。

class Affine:
    def __init__(self, W, b):
        self.W =W
        self.b = b
        
        self.x = None
        self.original_x_shape = None
        # 权重和偏置参数的导数
        self.dW = None
        self.db = None

    def forward(self, x):
        # 对应张量
        self.original_x_shape = x.shape
        x = x.reshape(x.shape[0], -1)
        self.x = x

        out = np.dot(self.x, self.W) + self.b

        return out

    def backward(self, dout):
        dx = np.dot(dout, self.W.T)
        self.dW = np.dot(self.x.T, dout)
        self.db = np.sum(dout, axis=0)
        
        dx = dx.reshape(*self.original_x_shape)  # 还原输入数据的形状(对应张量)
        return dx

SoftmaxwithLoss

带交叉熵损失层的softmax反向传播可以得到漂亮的结果
\frac{\partial{L}}{\partial{a_k}}=y_k-t_k
可见,反向传播中该结果直接衡量了与t标签的差距,即误差传播法。

[图片上传失败...(image-5945d8-1576044079302)]

Optimization

优化器一般定义为一个optimizer父类,在父类下定义不同的更新方法Update(grad,param),在神经网络中选取不同optimizer优化。

Stochastic gradient descent

随机梯度下降=在随机选取的mini-batch数据中实行梯队下降优化,即最简单的方法。

class SGD:
    def __init__(self, lr=0.01):
        self.lr = lr
        
    def update(self, params, grads):
        for key in params.keys():
            params[key] -= self.lr * grads[key] 

Momentum

v = \alpha v-\eta \frac{\partial{L}}{\partial{W}} \\ W=W+v

v表示速度,在梯度方向受力的动量增加

class Momentum:
    def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None
        
    def update(self, params, grads):
        if self.v is None:
            self.v = {}
            for key, val in params.items():                                
                self.v[key] = np.zeros_like(val)
                
        for key in params.keys():
            self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
            params[key] += self.v[key]

AdaGrad

自适应学习率的优化方法,更新参数时除h能减少变动较大的元素学习率。
h=h+\frac{\partial{L}}{\partial{W}}*\frac{\partial{L}}{\partial{W}} \\ W=W-\eta\frac{1}{\sqrt{h}}\frac{\partial{L}}{\partial{W}}

class AdaGrad:
    def __init__(self, lr=0.01):
        self.lr = lr
        self.h = None
        
    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros_like(val)
            
        for key in params.keys():
            self.h[key] += grads[key] * grads[key]
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

Adam

融合了momemum和adagrad(adaptive momemum),MIT DL教材189,论文来自

衰减矩估计来自适应学习。g为梯度,上面为有偏估计,下面是无偏修正。
s=\rho_1s+(1-\rho_1)g \ \ \ r=\rho_2r+(1-\rho_2)g \\ \hat{s}=\frac{s}{1-\rho_{1}^{t}} \ \ \hat{r}=\frac{r}{1-\rho_{2}^{t}}

class Adam:
    def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
        self.lr = lr
        self.beta1 = beta1
        self.beta2 = beta2
        self.iter = 0
        self.m = None
        self.v = None
        
    def update(self, params, grads):
        if self.m is None:
            self.m, self.v = {}, {}
            for key, val in params.items():
                self.m[key] = np.zeros_like(val)
                self.v[key] = np.zeros_like(val)
        
        self.iter += 1
        lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
        
        for key in params.keys():
            self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
            self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
            
            params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
            

Regularization

过拟合可能来自于过大权值、数据量过少等等。

防止过拟合的措施

Dropout

随机删除(前向传播时x删除比例,后向传播时不返回值)部分隐藏层神经元。

weight decay

对较大的权值进行惩罚(在损失函数中加上惩罚项L2范数),L2范数即所有项的平方和。
Loss'=Loss+\frac{1}{2}\lambda W^2
其中\lambda 为衰减率。

Batch-Normalization

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

推荐阅读更多精彩内容