深度学习中的常见概念
1:批量
批量,即Batch,是深度学习中的一个重要概念。批量通常是指两个不同的概念——如果对应的是模型训练方法,那么批量指的是将所有数据处理完以后一次性更新权重或者参数的估计,简单来说就是优化器干的事。如果对应的是模型训练中的数据,那么对应的是一次输入供模型计算用的数据量,即是网络的前向传播过程。这两个概念有着紧密的关系。
2:在线学习和离线学习
在深度学习中,另外两个常见的概念是在线学习(Online Learning)和离线学习(Offline Learning)。
离线学习
近年来,我们见证了深度学习技术在很多应用中的巨大成功。学习深度神经网络面临着很多挑战,包括但不限于梯度消失、逐渐减少的特征重用、鞍点(以及局部极小值)、大量的需要调节的参数、训练过程中内部协变量的变化、选择好的正则化方法的困难、选择超参数,等等。尽管出现了一些很有希望的进展,但都是被设计用来解决优化深度神经网络时遇到的具体问题的,这些方法中绝大多数都假设深度神经网络是以批量学习的设置来训练的,这是离线学习的一种,也是最为常用的。这种设置需要所有的训练数据集在学习任务开始前准备好。这对于现实中很多数据是以流的形式先后到达的任务而言是不可能的,而且也可能没有足够的内存空间来存储。此外,数据还可能表现出概念漂移(concept drift,Gama et al. 2014)。而在线学习可以解决这样的问题。
离线学习的优点如下:
对于任何固定个数的参数,目标函数都可以直接被计算出来,因此很容易验证模型训练是否在朝着所需要的方向发展。
计算精度可以达到任意合理的程度。
可以使用各种不同的算法来尽量避免出现局部最优的情况,达到更优的局部最优或者全局最优。
可以采用训练、验证、测试三分法对模型的普适度进行验证。
可以计算预测值及其置信区间。
在线学习无法实现上述功能,因为数据并没有被存储,不能重复获取,因此对于任何固定的参数集,无法在训练集上计算损失函数,也无法在验证集上计算误差。这就造成在线算法一般来说比离线算法更加复杂和不稳定。
在线学习
在线学习(Zinkevich 2003; Cesa-Bianchi and Lugosi 2006)指的是这样一类学习算法:它们在顺序到达的数据流实例中学习优化预测模型。这种动态学习使得在线学习更具有可扩展性和更高的内存效用。数据不需要进行存储,降低了对硬件设备的要求。
3:偏移/阈值
在深度学习中,采用sigmoid激活函数的隐藏层或者输出层的神经元通常在计算网络输入时加入一个偏移值,称为Bias。对于线性输出神经元,偏移项就是回归中的截距项。
跟截距项的作用类似,偏移项可以被视为一个由特殊神经元引出的链接权重,这是因为偏移项通常链接到一个取固定单位值的偏移神经元。比如在一个多层感知器(MLP)神经网络中,某一个神经元的输入变量为N维,那么这个神经元在这个高维空间中根据参数画一个超平面,一边是正值,一边为负值。所使用的参数决定了这个超平面在输入空间中的相对位置。如果没有偏移项,这个超平面的位置就被限制住了,必须通过原点;如果多个神经元都需要其各自的超平面,那么就严重限制了模型的灵活性。这就好比一个没有截距项的回归模型,其斜率的估计值在大多数情况下会大大偏移最优估计值,因为生成的拟合曲线必须通过原点。因此,如果缺少偏移项,多层感知器的普适拟合能力就几乎不存在了。
通常来说,每个隐藏层和输出层的神经元都有自己的偏移项。但是如果输入数据已经被等比例转换到一个有限值域中,比如[0,1]区间,那么第一个隐藏层的神经元设置了偏移项以后,后面任何层跟这些具备偏移项的神经元有链接的其他神经元就不需要再额外设置偏移项了(这部分有待商榷,望看到这篇文章且知道原因的大佬们不吝赐教!!!!!!谢谢!!!!!!)。
4:标准化数据
一般来讲,如果激活函数的值域在0到1之间,那么规范化数据到[0,1]的值域区间是比较好的。另外一个考虑是规范化数据能使计算过程更加稳定,特别是在数据值域范围区别较大的时候,规范化数据总是相对稳健的一个选择。而且很多算法的初始值设定也是针对使规范化以后的数据更有效来设计的。
可以参考这篇文章:https://blog.csdn.net/qq_33590958/article/details/96346030
PyTorch中的transforms
在前面讲到过,在transforms中提供了丰富的类对载入的数据进行变换,现在让我们看看如何进行变换。我们知道,在计算机视觉中处理的数据集有很大一部分是图片类型的,而在PyTorch中实际进行计算的是Tensor数据类型的变量,所以我们首先需要解决的是数据类型转换的问题,如果获取的数据是格式或者大小不一的图片,则还需要进行归一化和大小缩放等操作,庆幸的是,这些方法在transforms中都能找到。
在transforms中有大量的数据变换类,其中有很大一部分可以用于实现数据增强(Data Argumentation)。若在我们需要解决的问题上能够参与到模型训练中的图片数据非常有限,则这时就要通过对有限的图片数据进行各种变换,来生成新的训练集了,这些变换可以是缩小或者放大图片的大小、对图片进行水平或者垂直翻转等,都是数据增强的方法。不过在手写数字识别的问题上可以不使用数据增强的方法,因为可用于模型训练的数据已经足够了。对数据进行载入及有相应变化的代码如下:
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize(mean=[0.5,0.5,0.5],
std=[0.5,0.5,0.5])])
我们可以将上面代码中的torchvision.transforms.Compose类看作是一种容器,它能够同时对多种数据变换进行组合。传入的参数是一个列表,列表中的元素就是对载入的数据进行的各种变换操作。
在以上的代码中,在torchvision.transforms.Compose类中只是用了一个类型的转换变化transfroms.ToTensor和一个数据标准化变换transforms.Normalize。这里使用的是标准化变换也叫标准差变换法,这种方法需要使用原始数据的均值(Mean)和标准差(Standard Deviation)来进行数据的标准化,在经过标准化变换之后,数据全部符合均值为0,标准差为1的标准正态分布,计算公式为:
不过这里我们偷了一个懒,均值和标准差的值并非来自原始数据的,而是自行定义了一个,不过仍然能够达到我们的目的。
下面看看在torchvision.transforms中常用的数据变换操作。
torchvision.transforms.Resize
用于对载入的图片数据按我们需求的大小进行缩放。传递给这个类的参数可以是一个整型数据,也可以是一个类似于(h ,w )的序列,其中,h 代表高度,w 代表宽度,但是如果使用的是一个整型数据,那么表示缩放的宽度和高度都是这个整型数据的值。
torchvision.transforms.Scale
用于对载入的图片数据按我们需求的大小进行缩放,用法和torchvision.transforms.Resize类似。
torchvision.transforms.CenterCrop
用于对载入的图片以图片中心为参考点,按我们需要的大小进行裁剪。传递给这个类的参数可以是一个整型数据,也可以是一个类似于(h ,w )的序列。
torchvision.transforms.RandomCrop
用于对载入的图片按我们需要的大小进行随机裁剪。传递给这个类的参数可以是一个整型数据,也可以是一个类似于(h ,w )的序列。
torchvision.transforms.RandomHorizontalFlip
用于对载入的图片按随机概率进行水平翻转。我们可以通过传递给这个类的参数自定义随机概率,如果没有定义,则使用默认的概率值0.5。
torchvision.transforms.RandomVerticalFlip
用于对载入的图片按随机概率进行垂直翻转。我们可以通过传递给这个类的参数自定义随机概率,如果没有定义,则使用默认的概率值0.5。
torchvision.transforms.ToTensor
用于对载入的图片数据进行类型转换,将之前构成PIL图片的数据转换成Tensor数据类型的变量,让PyTorch能够对其进行计算和处理。
torchvision.transforms.ToPILImage
用于将Tensor变量的数据转换成PIL图片数据,主要是为了方便图片内容的显示。
torchvision.transforms.ToTensor
对于一个图片img,调用ToTensor转化成张量的形式,发生的不是将图片的RGB三维信道矩阵变成tensor
图片在内存中以bytes的形式存储,转化过程的步骤是:
- img.tobytes() 将图片转化成内存中的存储格式
- torch.BytesStorage.frombuffer(img.tobytes() ) 将字节以流的形式输入,转化成一维的张量
- 对张量进行reshape
- 对张量进行permute(2,0,1)
- 将当前张量的每个元素除以255
- 输出张量
torchvision.transforms.ToPILImage
对于一个Tensor的转化过程是:
- 将张量的每个元素乘上255
- 将张量的数据类型有FloatTensor转化成Uint8
- 将张量转化成numpy的ndarray类型
- 对ndarray对象做permute (1, 2, 0)的操作
- 利用Image下的fromarray函数,将ndarray对象转化成PILImage形式
- 输出PILImage