动手学深度学习笔记

动手学深度学习公益课程笔记

batch 和 epoch的区别:
  1. batch:batch_size是一个超参数,用于定义在更新内部模型参数之前要处理的样本数
    • 批量梯度下降:batch_size = 训练集的大小
    • 随机梯度下降:batch_size = 1
    • 小批量梯度下降: 1 < batch_size < 训练集大小,常用的有32,64,128
  2. epoch是一个超参数,定义了学习算法在整个训练数据集中的工作次数。一个epoch意味着训练数据集中的每个样本都有机会更新内部模型参数。
  3. 也就是说:batch是将simples在空间上进行划分,而epoch是将训练在时间上进行划分
多层感知机
全连接层和激活函数

全连接层:只是对数据进行仿射变换,多个仿射变换的叠加任然是仿射变换

非线性变换:引入的非线性函数称为激活函数

几个常见的激活函数:
  1. ReLU函数:只保留整数元素,将负数元素清零

    定义:ReLU(x) = max(x,0)

    图像:
    在这里插入图片描述

  2. sigmoid函数:将元素变换到0和1之间
    定义:在这里插入图片描述
    图像:
    在这里插入图片描述

  3. tanh函数:将元素变换到-1和1之间,关于原点对称

    定义:在这里插入图片描述

    图像:
    在这里插入图片描述

关于激活函数的选择:
  1. ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。
  2. 用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。
  3. 在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。
  4. 在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。
关于激活函数梯度消失的问题:
  1. 因为模拟人脑的生物神经网络的方法。在2001年有研究表明生物脑的神经元工作具有稀疏性,这样可以节约尽可能多的能量,据研究,只有大约1%-4%的神经元被激活参与,绝大多数情况下,神经元是处于抑制状态的,因此ReLu函数反而是更加优秀的近似生物激活函数。抑制现象是必须发生的,这样能更好的拟合特征
  2. 关于sigmoid函数表现不好:sigmoid函数中间部分梯度值十分小(最大只有0.25),因此即使数值落在中间部分也没有办法明显激活,反而会在中间层中失活
  3. 关于ReLU函数的问题:
    • 在负向部分完全失活,如果选择的超参数不好等情况,可能会出现过多神经元失活,从而整个网络死亡
    • ReLu函数不是zero-centered,即激活函数输出的总是非负值,而gradient也是非负值,在back propagat情况下总会得到与输入x相同的结果,同正或者同负,因此收敛会显著受到影响,一些要减小的参数和要增加的参数会受到捆绑限制。
为什么添加激励函数后就能够拟合“几乎”任何一个函数?

将函数分成三类:逻辑函数,分类函数,连续函数(分类的原则是输入输出形式)

  1. 通过一个激励函数可以完成简单的或与非门逻辑,因此通过隐藏层中神经元复合就可以完成任何一个逻辑函数拟合。只需要通过神经网络的拟合将真值表完全表示

  2. 通过之前使用的线性分类器构成的线性边界进行复合便可以得到任意一个分类函数。

  3. 通过积分微元法的思想可以拟合任何一个普通的可积函数

文本预处理
预处理通常包括四个步骤:
  1. 读入文本
  2. 分词
  3. 建立字典,将每个词映射到唯一的索引
  4. 将文本从词的序列转换为索引的序列
常用于分词的几个包:
  1. spacy
  2. nltk
语言模型
时序数据的采样

在时序数据的训练的时候需要每次读取小批量的样本和标签。时序数据的一个样本通常包含连续的字符,与其他数据处理方式不同的地方在于时序数据的一个样本通常包含连续的字符。并引入了时间步这个概念,用来描述每一个样本序列含有几个字符。

时序数据采样的两种方法

注意在时序数据中是引入了时间步这一概念,

  1. 随机采样

    在随机采样中,每个样本是原始序列上任取的一段序列,相邻的两个随机小批量在原始序列上的位置不一定毗邻。重点是按照时间步进行划分,采样的过程是先把整个文本序列按照时间进行分割,每个分割好的部分可以认为是一个样本,然后从这些样本中随机抽取一个batch的数据进行训练
    在这里插入图片描述

import torch
import random
#corpus_indices是数据序列,num_steps是时间步
def data_iter_random(corpus_indices, batch_size, num_steps, device=None):
    # 减1是因为对于长度为n的序列,X最多只有包含其中的前n - 1个字符
    num_examples = (len(corpus_indices) - 1) // num_steps  # 下取整,得到不重叠情况下的样本个数
    example_indices = [i * num_steps for i in range(num_examples)]  # 每个样本的第一个字符在corpus_indices中的下标
    random.shuffle(example_indices)

    def _data(i):
        # 返回从i开始的长为num_steps的序列
        return corpus_indices[i: i + num_steps]
    if device is None:
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    
    for i in range(0, num_examples, batch_size):
        # 每次选出batch_size个随机样本
        batch_indices = example_indices[i: i + batch_size]  # 当前batch的各个样本的首字符的下标
        X = [_data(j) for j in batch_indices]
        Y = [_data(j + 1) for j in batch_indices]
        yield torch.tensor(X, device=device), torch.tensor(Y, device=device)
  1. 相邻采样

    在相邻采样中,相邻的两个随机小批量在原始序列上的位置相毗邻。特点是各个batch在训练数据上是连续的
    在这里插入图片描述

def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None):
    if device is None:
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    #以下两步是为了将剩下的字符处理成为长度为batch_size整数倍
    corpus_len = len(corpus_indices) // batch_size * batch_size  # 保留下来的序列的长度
    corpus_indices = corpus_indices[: corpus_len]  # 仅保留前corpus_len个字符
    indices = torch.tensor(corpus_indices, device=device)
    indices = indices.view(batch_size, -1)  # resize成(batch_size, )
    batch_num = (indices.shape[1] - 1) // num_steps
    for i in range(batch_num):
        i = i * num_steps
        X = indices[:, i: i + num_steps]
        Y = indices[:, i + 1: i + num_steps + 1]
        yield X, Y
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值