过拟合欠拟合及其解决方案
概念:
- 欠拟合(underfitting):模型无法得到较低的训练误差。
- 过拟合(overfitting):训练误差远小于它在测试数据集上的误差。
主要的影响因素是模型的复杂度和训练数据集的大小,通常模型复杂度低容易欠拟合,复杂度高容易过拟合;数据集小容易过拟合。
常用的解决方案:
- 从数据集角度:K折交叉验证,提高数据的利用率。
- 从模型复杂度角度:可以才用权重衰减正则和dropout。权重衰减即为增加一个模型参数的范数作为惩罚项来表征模型的复杂度,L1,L2皆可,其中L2正则较为常用。dropout策略是即为使网络中的节点随机失活,为了保证训练集和验证集的结果期望一致,对输出进行拉伸。
编码中的笔记:
def dropout(X, drop_prob):
X = X.float()
assert 0 <= drop_prob <= 1
keep_prob = 1 - drop_prob
# 这种情况下把全部元素都丢弃
if keep_prob == 0:
return torch.zeros_like(X)
mask = (torch.rand(X.shape) < keep_prob).float()
return mask * X / keep_prob
从return语句中可以看出,dropout是对所有的输出都进行拉伸而不是概率拉伸。
梯度消失、梯度爆炸
- 当神经网络的层数较多时,模型的数值稳定性容易变差。在优化的过程中,梯度反向传播,传播得越深,就会出现消失或者爆炸。
- 参数随机初始化,是为了提高模型的复杂度。常用的有正态分布初始化和均匀分布初始化。
- 三个偏移:协变量偏移,标签偏移,概念偏移。
- Kaggle实战一般流程:数据获取——数据预处理——模型训练——参数选择——模型选择
循环神经网络进阶
- GRU
重置⻔有助于捕捉时间序列⾥短期的依赖关系;
更新⻔有助于捕捉时间序列⾥⻓期的依赖关系。
2.LSTM
遗忘门:控制上一时间步的记忆细胞
输出门:控制从记忆细胞到隐藏状态
输入门:控制当前时间步的输入
记忆细胞:⼀种特殊的隐藏状态的信息的流动
GRU和LSTM是带有遗忘功能的RNN,这种遗忘功能可以缓解梯度衰减或者梯度爆炸,也更能模拟人类的记忆行为。
深度循环神经网络即增加RNN的层数,层数多可以学习到更加抽象的特征,但是并不是越深越好。
双向循环神经网络相当于将训练数据正序和逆序输入两个网络,将网络的结果concat拼接起来,这样的结构可以同时记录前向和后向的联系。
机器翻译及其相关技术
本章主要介绍了MT的数据处理方法,基本模型框架,损失函数以及其他解决方法。
- 数据处理。这一部分主要是讲述如何建立从文本到数据的映射:用正则表达式对文本进行规整,然后建立从idex到vocabulary的list和map。
- 为了解决翻译时文字不等长的问题,提出了encoder-decoder的框架,先对编码器输出训练数据,训练出一个RNN,然后对解码器输入label对RNN结构进行调整。
- MT中用到的损失函数是softmax,因为文字是离散的数据,用softmax效果更好,其中在code的过程中,因为要保证每个batch的大小一致,所以针对不同长度的语句会进行padding,整理成一样大小后再输入网络。这里就涉及到了有效长度的概念和解除padding的操作。
def SequenceMask(X, X_len,value=0):
maxlen = X.size(1)
mask = torch.arange(maxlen)[None, :].to(X_len.device) < X_len[:, None]
X[~mask]=value
return X
- Beam Search。这是一种为了提高模型精度的策略。采用了贪心的思想,因为词与词之间有联系,所以每次输出的结果可能是局部最优而非全局最优,所以这里每次保留最优和次优的结果,增大了解空间,提高了模型的精度。
注意力机制与Seq2Seq模型
Attention 是一种通用的带权池化方法,输入由两部分构成:询问(query)和键值对(key-value pairs)。 ki∈Rdk,vi∈Rdv . Query q∈Rdq , attention layer得到输出与value的维度一致 o∈Rdv . 对于一个query来说,attention layer 会与每一个key计算注意力分数并进行权重的归一化,输出的向量 o 则是value的加权求和,而每个key计算的权重与value一一对应。
在MT的encoder-decoder框架中,引入Attention机制可以将目标单词的翻译选择过程显式地建模。
query 和 keys 的计算可以采用点积也可以采用多层感知机,多层感知机用得相对广泛
卷积神经网络
CNN和普通的神经网络的不同在于卷积操作。但卷积层中用到的并非卷积运算而是互相关运算。我们将核数组上下翻转、左右翻转,再与输入数组做互相关运算,这一过程就是卷积运算。由于卷积层的核数组是可学习的,所以使用互相关运算与使用卷积运算并无本质区别。
- 通道
CNN在输出上有一个新的概念——通道。因为图片的颜色是有通道的,所以很自然地引入了这个概念,在我看来,这个概念是和图片的形状正交的,所以这个概念可以扩展,扩展到除了颜色的其他特征维度,故而有了出入通道和输出通道的引入。 - 卷积
在单个通道上的卷积操作实际上是前面提到的互相关运算,在计算时可以通过调节kernel的size,padding和stride的大小而控制卷积层的输出size,所以在卷积操作中,整个kernel核组成的二维数组等同于全连接层中的一个w,所以有了下面的代码中bias的size
class Conv2D(nn.Module):
def __init__(self, kernel_size):
super(Conv2D, self).__init__()
self.weight = nn.Parameter(torch.randn(kernel_size))
self.bias = nn.Parameter(torch.randn(1))
def forward(self, x):
return corr2d(x, self.weight) + self.bias
- 池化
池化层主要用于缓解卷积层对位置的过度敏感性。同卷积层一样,池化层每次对输入数据的一个固定形状窗口(又称池化窗口)中的元素计算输出,池化层直接计算池化窗口内元素的最大值或者平均值,该运算也分别叫做最大池化或平均池化。
池化层也可以在输入的高和宽两侧填充并调整窗口的移动步幅来改变输出形状。池化层填充和步幅与卷积层填充和步幅的工作机制一样。
在处理多通道输入数据时,池化层对每个输入通道分别池化,但不会像卷积层那样将各通道的结果按通道相加。这意味着池化层的输出通道数与输入通道数相等。