第一次作业:深度学习基础

第一次作业:深度学习基础

目录

  1. 视频学习心得及问题总结
    • 1.1 心得
    • 1.2 问题
  2. 代码练习
    • 2.1 代码1
    • 2.2 代码2
    • 2.3 代码3
    • 2.4 代码4

1. 视频学习心得及问题总结

1.1 心得
第一部分
  • 机器学习:模型,策略与算法,模型是对问题进行建模,策略是确定目标函数,算法求解模型参数

  • 监督/无监督学习模型根据是否具有确定的标记来区分,半监督学习则是部分具有标记,一般是由于数据难以获得造成的,强化学习则是知道标记的反馈。

  • 生成模型:对输入X和输出Y的联合分布P(X,Y)建模

    判别模型:对已知输入X条件下输出Y的条件分布P(Y|X)建模

  • 深度学习模型是深层次的神经网络模型,最简单的神经网络模型是感知机。对深度学习模型进行训练使用BP算法

第二部分
  • 深度学习的几点限制
    • 算法输出不稳定
    • 模型复杂度高,难以纠错调试
    • 模型层级复合程度高,参数不透明
    • 对数据依赖性强
    • 推理能力有待加强
    • 存在机器偏见
  • 常用激活函数:sigmoid函数,ReLU函数,tanh函数,Leaky ReLU函数
  • \(\color{red}{sigmoid函数一般用于二分类问题}\)
  • 万有逼近定理
    • 如果\(\color{#FF0000}{一个}\)隐层包含\(\color{red}{足够多}\)的神经元,\(\color{#FF0000}{三层}\)前馈神经网络(输入-隐层-输出)能以任意精度逼近任意预定的\(\color{#FF0000}{连续}\)函数
    • 当隐层足够\(\color{#FF0000}{宽}\)时,\(\color{#FF0000}{双隐层}\)感知器(输入-隐层1-隐层2-输出)可以逼近任意\(\color{#FF0000}{非连续函数}\),可以解决任何复杂的分类问题
  • 神经网络各层的作用
    • 线性变换(Wx)
      • 升/降维度
      • 放大/缩小
      • 旋转
    • 偏置(+b)
      • 平移
    • 激活函数a(·)
      • 弯曲
  • 神经网络深度对逼近函数的贡献是指数上升的,而增加宽度则是线性上升的。
  • 深度过深会引起梯度消失问题。对sigmoid函数更为明显
  • 梯度下降法
    • 对凸函数(局部极值点则为全局最优点),可以使用梯度下降法找到函数的最值
    • 对非凸函数,使用梯度下降法有可能会陷入到局部极值点,导致学习效果不理想
  • BP(反向传播)算法是首先前馈神经网络,计算出当前预测值和实际值的差值,计算出loss(损失),而后将该loss反向传播,更新每一个结点的权重。在反向传播时使用梯度下降法逐步逼近loss函数的极值(凸函数则是最值),直至训练过程收敛。可以参阅代码3部分。
  • 可以采用逐层预训练与微调的方式改善陷入局部极小值的窘境,逐层预训练的效果较好。逐层预训练的方法主要有自编码器和受限玻尔兹曼机。
  • \(\color{red}{自编码器可以用于图像去噪}\)
第三部分
  • pytorch, tensorflow为深度学习框架,pytorch流行于学术界,而tensorflow则流行于工业界

    pytorch为动态图,而tensorflow为静态图。pytorch较容易上手。

  • pytorch等一系列科学计算库具有两个核心问题:

    • 如何表示数据?
    • 如何对数据进行运算?

    pytorch使用张量(torch.Tensor)表示数据,使用定义在Tensor类上的torch.autograd.Function函数类对Tensor进行运算。

  • 各种运算的使用参见教程。

  • 有关函数backward()

    >>>import torch
    >>>x = torch.rand(2,2,requires_grad=True)
    >>>y = x + 2
    >>>z = 3 * y**2
    >>>out = z.mean()
    >>>out.backward()
    >>>x.grad
    

    tensor([[3.6051, 4.1434], [3.4039, 3.5650]])

    >>>x

    tensor([[0.4034, 0.7622], [0.2692, 0.3767]], requires_grad=True)

    >>>c = (3/2)*(x+2) #这部分计算的是∂out/∂x,省略了步骤

    >>>c

    tensor([[3.6051, 4.1434], [3.4039, 3.5650]], grad_fn=)

    我们可以得到backword()的功能是计算

\[\frac{\partial{out}}{\partial{x}}\bigg|_{x=x_{i,j,···}} \]

​ 其中 i,j,··· 为张量x的维度指标。

1.2 问题
  • 如何根据问题的类型和规模确定神经网络的基本模型(即深度和每一层次的神经元个数)
  • backward()的功能比较容易理解,结合运算的动态图表示也比较易于理解其求解的大体步骤。但其具体是如何实现的?
  • 逐层预处理部分两个模型(自编码器、受限玻尔兹曼机)的实现机理。

2. 代码练习

2.1 代码1
  • 黑白图像处理

    camera[30:100, 10:100] = 0 #camera为某黑白图像,30-99行,10-99列亮度置为0
    camera[:10] = 0            #起始行-第9行,所有列亮度置为0
    mask = camera < 80         #将亮度值低于80的改为255,即高亮显示
    camera[mask] = 255   
    
  • 彩色图像处理

    reddish = cat[:, :, 0] > 160   #所有行所有列,选中第一通道(即RGB中的R)值大于160的点
                                   #其中cat为一张猫的图像
    red_cat[reddish] = [255, 0, 0] #将这些点的RGB值设为255,0,0,即为大红色
    BGR_cat = cat[:, :, ::-1]      #将RGB转换为BGR,即翻转,-1表示从最后一个元素到第一个元素
                                   #反向
    
  • 显示图像直方图

    plt.hist(img.ravel(), bins=256, histtype='step', color='black')
                                   #分为256个单位
    
  • 填补空洞

    ndi.binary_fill_holes(img_edges)
    
  • 改变对比度

    p2, p98 = np.percentile(img, (2, 98))   #寻找分位点
    exposure.rescale_intensity(img, in_range=(p2, p98)) #in_range表示可以输入的亮度范围
    
  • 直方图均衡化

    img_eq = exposure.equalize_hist(img)
    
  • 自适应直方图均衡

    img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
    
2.2 代码2
  • 创建Tensor

    torch.tensor(666)
    torch.tensor([1,2,3,4,5,6])
    torch.ones(2,3)
    torch.ones(2,3,4)
    torch.empty(5,3)
    torch.rand(5,3)
    torch.zeros(5,3)
    torch.arange(1, 5)       #[1,2,3,4],没有5
    x.new_ones(5,3)          #x为已存在的张量,该函数饭会一个dtype,device相同的张量
    torch.randn_like(x, dtype=torch.float)  #返回与x同样维度但重定义了dtype的张量
    torch.linspace(3, 8, 20)  #从3.0~8.0等距分割20个点(含有3.0和8.0)
    
  • 张量操作

    m = torch.Tensor([[2, 5, 3, 7],
                      [4, 2, 1, 9]])
    #元素个数
    m.numel()        
    m[0][2]
    m[:, 1]
    m[0, :]
    #标量积
    m @ v
    #转置
    m.t()
    # matlabplotlib 只能显示numpy类型的数据,下面展示了转换数据类型,然后显示
    # 注意 randn 是生成均值为 0, 方差为 1 的随机数
    # 下面是生成 1000 个随机数,并按照 100 个 bin 统计直方图
    plt.hist(torch.randn(1000).numpy(), 100);  
    
    
    
    # 创建两个 1x4 的tensor
    a = torch.Tensor([[1, 2, 3, 4]])
    b = torch.Tensor([[5, 6, 7, 8]])
    
    # 在 0 方向拼接 (即在 Y 方各上拼接), 会得到 2x4 的矩阵
    torch.cat((a,b), 0)
    tensor([[1., 2., 3., 4.],
            [5., 6., 7., 8.]])
    
    # 在 1 方向拼接 (即在 X 方各上拼接), 会得到 1x8 的矩阵
    torch.cat((a,b), 1)
    tensor([[1., 2., 3., 4., 5., 6., 7., 8.]])
    
  • 对张量内部的数据进行数据转换可以使用type_as()函数

    tensor1=torch.FloatTensor(4)
    tensor2=torch.IntTensor(3)
    tensor1=tensor1.type_as(tensor2)
    

    该方法用于解决以下错误

    RuntimeError: Expected object of scalar type Float but got scalar type Long for argument #3 'vec' in call to _th_addmv_out
    
2.3 代码3
  • 对模型进行训练的一种样例

    for t in range(迭代次数):
        # 把数据输入模型,得到预测结果
        y_pred = model(数据集)             #model为定义好的模型
        # 计算损失
        loss = criterion(y_pred, Y)
        # 反向传播前把梯度置 0 
        optimizer.zero_grad()
        # 反向传播优化 
        loss.backward()
        # 更新全部参数
        optimizer.step()
    
  • 损失函数和优化器

    损失函数的选取根据数据的分布情况决定,一般有交叉熵和均方方差等

    \(\color{red}{优化器主要有SGD和Adam两种,一般而言,使用Adam就可以,效果比较好。}\)

  • 两种模型的对比

    第一种模型为:

    \[h_\theta(x)=f(\boldsymbol{w^Tx}+b) \]

    其中激活函数为:

    \[a(x)=x \]

    第二种激活函数则为:

    \[a(x)=ReLU(x)=max(0,x) \]

    选择非线性的激活函数可以拟合非线性的模型,而选择线性激活函数仅能升降维度、放大缩小、旋转或平移,难以拟合非线性的模型。

  • 存在的问题

    • 如何进行损失函数和优化器的选取?
2.4 代码4
  • 绘制散点图

    import numpy as np
    import matplotlib.pyplot as plt
    plt.scatter(x,y)       #x,y为数组,张量和numpy矩阵都可以
    tensor1.numpy()        
    
  • 绘制折线图,如果参照点比较多,则会看起来像光滑的

    x = torch.linspace(0,10,12)  #看起来会有点不光滑,可以将12调到100,则会变光滑
    y = x*x
    plt.plot(x,y)
    plt.plot(x,y,'r-')           #红色折线
    plt.plot(x,y,'y-')           #黄色折线
    
  • 还有的问题

    • ReLU拟合出来为什么是类似折线的函数?
    • tanh激活函数为什么没有ReLU收敛速度快?
    • 绘制散点图时的一些参数的含义不明确。
    • 权重衰减(weight_decay)的含义以及如何设置其值。

你可能感兴趣的:(第一次作业:深度学习基础)