美文网首页
【DeepLearning】Basic Conceptions

【DeepLearning】Basic Conceptions

作者: 乞力马扎罗的雪人 | 来源:发表于2019-12-11 14:01 被阅读0次

    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

    相关文章

      网友评论

          本文标题:【DeepLearning】Basic Conceptions

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