5.1 机器学习的基本任务
5.2 机器学习一般流程
定义问题,收集数据,探索数据,预处理数据,训练模型,评估模型,优化模型
在选择合适的模型后,需要考虑:
5.2.5 评估与优化模型
1)留出法:分为训练集,验证集,测试集。训练集用来训练模型,验证集用来调优超参数,测试集用来测试模型的泛化能力
2)K折交叉验证:不重复地随机将训练数据集划分为k个,其中k-1个用于模型训练,剩余的一个用于测试
3)重复的K折交叉验证:当数据量比较小,数据分布不很均匀时可以采用这种方法
5.3 过拟合与欠拟合
欠拟合:高偏差
过拟合:情况如下:初期测试误差减小,后期测试误差变大
5.3.1 权重正则化
正则化不仅可以有效地降低高方差,还有利于降低偏差。在机器学习中,很多被显式地用来减少测试误差的策略,统称为正则化,正则化旨在减少泛化误差而不是训练误差
5.3.2 Dropout正则化
即在训练过程中按一定比例(比例参数可设置)随机忽略或屏蔽一些神经元,这些神经元会被随机抛弃,即它们在正向传播过程中对于下游神经元的贡献效果暂时消失了,反向传播时该神经元也不会有任何权重的更新。
好处:提升泛化能力,不容易过拟合
5.3.3 批量正则化 Batch Normalization
解决梯度消失的问题
在实际训练过程中 ,经常会出现隐含层因为数据分布不均,导致梯度消失或者不起作用的情况。如采用sigmoid函数或tanh函数为激活函数时,如果数据分布在两侧,这些激活函数的导数就接近于0.这样BP算法得到的梯度也就消失了
BN不仅可以有效解决梯度消失问题,还可以让调试超参数更加简单,在提高训练模型效率的同时,也可以让神经网络模型更加健壮。
5.4选择合适的激活函数
如果搭建的神经网络层数不多,选择sigmoid,tanh, relu, softmax都可以;如果搭建的网络层次较多,选择不当就会导致梯度消失问题。此时一般不宜选择sigmoid, tanh激活函数,因为它们的导师都<1, 尤其是sigmoid的导数在[0, 1/4]之间,多层叠加后,根据微积分链式法则,随着层数增多,导数或偏导数指数级变小。所以层数较多的激活函数需要考虑其导数不宜小于1,也不能大于1(会导致梯度爆炸),导数为1最好,而激活函数relu正好可以满足这个条件,所以搭建比较深的神经网络时一般使用relu激活函数。
激活函数softmax常用于多分类神经网络输出层
5.5 选择合适的损失函数
机器学习中的常用损失函数有两种:
- 交叉熵(Cross Entropy) 分类问题
- 均方误差(Mean squared error, MSE) 回归问题
交叉熵反映的是两个概率分布的距离(不是欧式距离)
回归问题预测的是一个任意实数,反映的预测值和实际值之间的距离可以用欧氏距离来表示
1) torch.nn.MSELoss
2)torch.nn.CrossEntropyLoss
在pytorch中,它不是严格意义上的交叉熵损失函数,而是先将Input经过softmax激活函数,将向量归一化成概率形式,再与target计算严格意义上的交叉熵损失。
在多分类任务中,经常采用softmax激活函数+交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布形式,所以需要softmax激活函数将一个向量进行归一化成概率分布形式,再采用交叉熵损失函数计算loss
5.6 选择合适优化器
5.6.1 传统梯度优化的不足
假设需更新的参数为
θ
\theta
θ, 梯度为g,则其更新策略可表示为:
θ
=
θ
−
λ
g
\theta=\theta-\lambda g
θ=θ−λg
这种方法,当学习率取值恰当时,可以收敛到全面最优点或局部最优点
缺点:对超参数学习率比较敏感(过小导致收敛速度过慢,过大又越过极值点)在比较平坦的区域,因梯度接近于0,易导致提前终止训练。
**影响优化的两个因素:**梯度方向, 学习率
5.6.2 动量算法
梯度下降法在遇到平坦或高曲率区域时,学习过程有时会很慢。
不使用动量算法的SGD学习速度较慢,振幅较大;使用动量算法的SGD,振幅较小,而且会较快到达极值点。动量算法可以增加收敛速度和稳定性
RMSprop, Adam, Adadelta被认为是自适应优化算法,因为它们会自动更新学习率
而使用SGD时,必须手动选择学习率和动量参数,通常会随着时间的推移而降低学习率
5.7 GPU加速
图形处理器(Graphic Process Units, GPU),PyTorch一般把GPU作用于张量(Tensor)或模型(包括torch.nn下面的一些网络模型以及自己创建的模型)等数据结构上
通过torch.cuda.is_available()
来判断是否可以使用GPU, 返回True则具有能够使用的GPU
通过torch.cuda.device_count()
方法可以获得能够使用的GPU数量
查看平台GPU的配置信息,在命令行输入命令“nvidia-smi”即可,适用于Linux或windows环境,下图为GPU配置信息样例,从中可以看出共有2个GPU
把数据从内存转移到GPU, 一般针对张量(我们需要的数据)和模型。对张量(类型为FloatTensor或者是LongTensor等),一律直接使用方法.to(device)或.cuda()
5.7.2 多GPU加速
单机多GPU主要采用了DataParallel函数
# 对模型
net = torch.nn.DataParallel(model)
# 这时,默认所有存在的显卡都会被使用
如果电脑中有很多显卡,但只想使用其中的一部分,如只使用编号为0, 1, 3, 4的4个GPU
则可以采用以下方式:
# 假设有4个GPU,其id设置如下
device_ids = [0,1,2,3]
# 对数据
input_data = input_data.to(device = device_ids[0])
# 对模型
net = torch.nn.DataParallel(model)
net.to(device)
或者
os.environ["CUDA_VISIBLE_DEVICES"] = ',',join(map(str,[0,1,2,3]))
net = torch.nn.DataParallel(model)
其中CUDA_VISIBLE_DEVICES表示当前可以被Pytorch程序检测到的GPU
5.7.3 使用GPU注意事项
可以提升训练速度,但如果使用不当,可能影响使用效率
1)GPU的数量尽量为偶数,奇数的GPU有可能会出现异常中断的情况
2)GPU很快,但数据量较小时,效果可能没有单GPU好
3)如果内存不够大,使用多GPU训练的时候可设置pin_memory为False,