13 dropout
正则化:在数据加入噪音
dropout(丢弃法):在层与层之间加入噪音。对每个元素进行扰动。
概念问答:
什么是dropout?
Dropout是一种用于防止过拟合的正则化技术。它是通过在训练过程中随机地将一部分神经元的输出设置为零来实现的。
具体而言,Dropout会在每次训练迭代时,以一定的概率(通常为0.5)随机地将某些神经元的输出值设为零。这样做的效果相当于在每个训练样本上使用不同的网络结构,因为每个神经元都有可能被临时“删除”。在前向传播过程中,被删除的神经元不参与计算;在反向传播时,也不会更新它们的权重。
通过引入Dropout,可以减少神经元之间的共适应性,从而使得模型更加鲁棒、泛化能力更强。它可以降低过拟合的风险,使模型更好地适应新的未见过的数据。
测试阶段,Dropout不起作用,所有的神经元都参与计算,但最后的输出值会按照训练时的比例进行缩放,以保持期望输出的一致性。
Dropout已经成为深度学习中常用的正则化方法之一,广泛应用于各种类型的神经网络模型。它可以提高模型的泛化能力,减少过拟合,并促进深度学习模型的稳定训练。
什么是正则化?和dropout法有什么区别?
正则化是一种常用的技术,用于减少模型在训练数据上的过拟合现象。它通过对模型的损失函数引入额外的惩罚项,限制模型参数的取值范围或复杂度,以提高模型的泛化能力。
正则化方法的目标是防止模型过度依赖于训练数据中的噪声和细节,从而帮助模型更好地适应未见过的测试数据。常见的正则化方法包括L1正则化、L2正则化和弹性网络(Elastic Net)等。
与正则化不同,Dropout是一种特定的正则化技术,主要用于深度神经网络中。它通过在训练过程中随机地将一部分神经元的输出设置为零来减少过拟合。
Dropout的工作原理是在每个训练迭代时随机地“丢弃”(即将输出设为零)一些神经元。这样做可以减少神经元之间的共适应性,使得模型更加鲁棒和泛化能力更强。
与传统的正则化方法相比,Dropout具有以下特点:
- Dropout是在训练过程中随机地丢弃神经元,但在推理阶段(测试阶段)所有神经元都参与计算,只是最后的输出值按照训练时的比例进行缩放。
- Dropout相当于在每个训练样本上使用了不同的网络结构,从而增加了模型的鲁棒性和泛化能力。
- Dropout可以更好地处理深度神经网络中的过拟合问题。
总之,正则化是一种常用的技术,用于减少过拟合现象。而Dropout则是一种特定的正则化方法,在深度学习中被广泛应用于减少过拟合,并提高模型的性能和泛化能力。
14 数值稳定性
向量关于向量的导数是一个矩阵
神经网络的梯度:
梯度消失:
和很小的数连乘,数值越来越小。还没有收敛,就停止更新参数了。底部的层,即靠近输入数据的那些层,梯度是0的话,不管学习率多少,都跑不动,那么和很浅的神经网络没有区别。
15 房价预测
kaggle竞赛要去官网下数据集到本地
数据:
数据预处理:用pandas中的concat拼接
数据标准化:令每一列是数值的特征:均值变为0,方差变为1。
fillna(0):没有采样的数据全设为0.
处理完后,特征会变大,有331个特征。
One-hot编码是一种用于将分类变量转换为数值变量的技术。
在进行分类任务时,某些算法要求输入是数值型数据,而无法直接处理分类变量。这时,我们可以使用one-hot编码来表示分类变量。
具体地,one-hot编码将每个分类变量拆分成多个二进制特征。对于一个有n个不同取值的分类变量,one-hot编码将会生成n个二进制特征,其中只有一个特征为1,其余特征都为0。这样,每个不同的取值就被表示为一个独立的特征。
举个例子,假设有一个分类变量"颜色",可能的取值为{"红", "绿", "蓝"}。使用one-hot编码后,"红"将会被编码为[1, 0, 0],"绿"编码为[0, 1, 0],"蓝"编码为[0, 0, 1]。这样,原本的单一特征被转换为了三个独立的二进制特征。
通过one-hot编码,我们可以将分类变量用于各种机器学习算法,例如逻辑回归、决策树等。同时,由于使用了二进制编码,还可以保持原始特征之间的互斥性,避免引入不必要的数值关系。需要注意的是,如果分类变量的取值较多,使用one-hot编码可能会导致特征维度过高,从而增加计算和存储成本。在这种情况下,可以考虑使用其他编码方式或者进行特征选择来降低维度。
在某些情况下,数据预处理后可能会导致数据量增加的原因有以下几点:
One-Hot编码:当对分类变量进行One-Hot编码时,每个不同的分类值将会被转换成一个独立的二进制特征。这会导致特征的维度增加,从而使数据量增多。
特征生成:在数据预处理过程中,可以通过组合、转换或提取原始特征来生成新的特征。例如,可以通过将两个数值特征相乘生成一个新的特征。这样做可以提供更多的信息,但也会增加数据量。
数据复制:在一些数据处理操作中,为了平衡类别分布或者扩充数据集大小,可能会使用数据复制的方法。这意味着将现有的数据复制多次,以增加数据量。
数据填充:在处理缺失值时,常常采用填充的方式来替代缺失值。填充通常是通过使用统计指标(如均值、中位数)或者插值方法(如线性插值、多项式插值)来填补缺失值。填充过程会增加数据集中的样本数量。
数据增强:在某些机器学习任务中,为了增加模型的泛化能力和鲁棒性,可以采用数据增强技术。数据增强通过对原始数据进行旋转、翻转、裁剪等操作来生成新的样本。这种方式也会导致数据量的增加。
损失函数:MSE。训练用单层的线性回归。但是在房价预测中,用rmse,先取对数
通常,在机器学习中,使用二维数组来表示数据集,其中每一行代表一个样本,每一列代表一个特征。因此,
train_feature.shape[0]
给出了训练数据集中样本的数量。这个值在模型训练和评估中经常被用作循环迭代、计算指标或分割数据集等操作的依据。
train_feature.shape[0]
表示训练数据集(或特征)的行数。在Python中,NumPy和Pandas等库提供了多维数组对象,其中包含了用于描述数组形状的属性。.shape
是一个返回数组形状的属性,它是一个元组,包含了数组的维度信息。对于二维数组(例如DataFrame),
.shape
返回一个包含两个元素的元组(行数, 列数)
,因此train_feature.shape[0]
就是训练数据集的行数。
验证:
调参数:epoch、lr、Weight_decay、batch_size,以及网络模型,不断调整,令平均验证log rmse最少。
Weight decay(权重衰减)是一种用于正则化模型的技术,通过在损失函数中添加一个正则项,来惩罚模型的参数值过大,以防止过拟合。
在训练神经网络时,通常使用优化算法(如梯度下降)来最小化损失函数,从而调整模型的参数使其适应训练数据。然而,当模型的参数值过大时,容易导致过拟合问题。
为了避免模型参数过大,可以在损失函数中添加一个权重衰减项。该项是由模型的参数值的平方和与一个称为衰减系数(weight decay coefficient)的超参数相乘得到。衰减系数控制着权重衰减的强度,较大的衰减系数会更强烈地抑制参数的大小。
通过引入权重衰减项,优化算法在调整模型参数时会同时考虑减小损失函数和减小参数的大小。这样可以使得模型在平衡拟合训练数据和保持参数较小之间找到一个合适的折中点,从而提高模型的泛化能力。
需要注意的是,权重衰减不会将参数直接设置为零,而是通过在损失函数中添加一个正则项来调整参数的更新。这样,在训练过程中,模型的参数可以同时学习适应数据和保持较小的权重值,以获得更好的性能。
最后提交结果
16 PyTorch 神经网络基础
1.模型构造
2.参数管理
3.自定义层
4.读写文件
块的组成
块(block)可以描述单个层、由多个层组成的组件或整个模型本身。 使用块进行抽象的一个好处是可以将一些块组合成更大的组件, 这一过程通常是递归的。
从编程的角度来看,块由类(class)表示。 它的任何子类都必须定义一个将其输入转换为输出的前向传播函数, 并且必须存储任何必需的参数。 注意,有些块不需要任何参数。 最后,为了计算梯度,块必须具有反向传播函数。 在定义我们自己的块时,由于自动微分提供了一些后端实现,我们只需要考虑前向传播函数和必需的参数。
块需要提供的基本功能
①将输入数据作为其前向传播函数的参数。
②通过前向传播函数来生成输出。注:输出的形状可能与输入的形状不同。
③计算其输出关于输入的梯度,可通过其反向传播函数进行访问。通常这是自动发生的。
④存储和访问前向传播计算所需的参数。
⑤根据需要初始化模型参数。
自定义块
这段代码里包含一个多层感知机,其具有256个隐藏单元的隐藏层和一个10维输出层。 注意,下面的MLP类继承了表示块的类。我们的实现只需要提供我们自己的构造函数(Python中的__init__函数)和前向传播函数。
class MLP(nn.Module):
# 用模型参数声明层。这里,我们声明两个全连接的层
def __init__(self):
# 调用MLP的父类Module的构造函数来执行必要的初始化。
# 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
super().__init__()
self.hidden = nn.Linear(20, 256) # 隐藏层
self.out = nn.Linear(256, 10) # 输出层
# 定义模型的前向传播,即如何根据输入X返回所需的模型输出
def forward(self, X):
# 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。
return self.out(F.relu(self.hidden(X)))
顺序块
Sequential的设计是为了把其他模块串起来。 为了构建我们自己的简化的MySequential, 我们只需要定义两个关键函数:
①一种将块逐个追加到列表中的函数。
②一种前向传播函数,用于将输入按追加块的顺序传递给块组成的“链条”。
下面的MySequential类提供了与默认Sequential类相同的功能:
class MySequential(nn.Module):
def __init__(self, *args):
super().__init__()
for idx, module in enumerate(args):
# 这里,module是Module子类的一个实例。我们把它保存在'Module'类的成员
# 变量_modules中。_module的类型是OrderedDict
self._modules[str(idx)] = module
def forward(self, X):
# OrderedDict保证了按照成员添加的顺序遍历它们
for block in self._modules.values():
X = block(X)
return X
2.参数访问
先定义如下神经网络:
import torch
from torch import nn
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
net(X)
从已有模型中访问参数。 当通过Sequential类定义模型时, 我们可以通过索引来访问模型的任意层。 这就像模型是一个列表一样,每层的参数都在其属性中。 如下所示,我们可以检查第二个全连接层的参数。