关于MNIST Handwritten Digit Recognition in PyTorch的一些问题
MNIST Handwritten Digit Recognition in PyTorch传送门
torch.backends.cudnn.enabled = False
cuDNN非确定性算法
torch.backends.cudnn.enabled = False #禁用
torch.backends.cudnn.enabled = True #打开
若将其打开,那么cuDNN使用的非确定性算法就会自动寻找最适合当前配置的高效算法,来达到优化运行效率的问题
一般来讲,应该遵循以下准则:
- 如果网络的输入数据维度或类型上变化不大,设置 torch.backends.cudnn.benchmark = true 可以增加运行效率;
- 如果网络的输入数据在每次 iteration 都变化的话,会导致 cnDNN 每次都会去寻找一遍最优配置,这样反而会降低运行效率。
所以我们经常看见在代码开始出两者同时设置:
torch.backends.cudnn.enabled = True
torch.backends.cudnn.benchmark = True
torch.manual_seed(int seed)
torch.manual_seed(1)
torch.rand(1,2)
无论执行多少次,(注意是一起执行这两行代码),输出的结果都是一样的
若去掉 torch.manual_seed(1) 直接torch.rand(1,2) 则生成的结果是不一样的
参数 seed 的理解
可以理解为一个rand 的index,index相同,则rand的结果是相同的
torch.manual_seed(2)
print(torch.rand(2))
torch.manual_seed(1)
print(torch.rand(2))
torch.manual_seed(2)
print(torch.rand(2))
torch.manual_seed(1)
print(torch.rand(2))
输出结果:
tensor([0.6147, 0.3810])
tensor([0.7576, 0.2793])
tensor([0.6147, 0.3810])
tensor([0.7576, 0.2793])
理解: seed=1,rand产生的是 tensor([0.7576, 0.2793]); seed=2,rand产生的是 tensor([0.6147, 0.3810]);
GPU
torch.cuda.manual_seed(int.seed):为当前GPU设置随机种子
torch.cuda.manual_seed_all(int.seed):为所有的GPU设置种子
torchvision.datasets.MNIST
class
torchvision.datasets.MNIST(root, train=True, transform=None, target_transform=None, download=False)
- root(string)– 数据集的根目录,其中存放processed/training.pt和processed/test.pt文件。(数据下在存放的完整地址)
- train(bool, 可选)– 如果设置为True,从training.pt创建数据集,否则从test.pt创建。
- download(bool, 可选)– 如果设置为True, 从互联网下载数据并放到root文件夹下。如果root目录下已经存在数据,不会再次下载。
- transform(可被调用 , 可选)– 一种函数或变换,输入PIL图片,返回变换之后的数据。如:transforms.RandomCrop。
- target_transform (可被调用 , 可选)– 一种函数或变换,输入目标,进行变换。
torchvision.transforms.Compose()
torchvision.transforms 参数解读/中文使用手册
其作用是将多个变换方式结合在一起:
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])
class
torchvision.transforms.Normalize(mean,std)
用均值和标准差对张量图像进行标准化处理。给定n通道的均值(M1, … , Mn) 和标准差(S1, … ,Sn), 这个变化将会归一化根据均值和标准差归一化每个通道值。例如,input[channel] = (input[channel]-mean[channel])/std(channel)
参数:
- mean (squence) ——每个通道的均值
- std (sequence) —— 每个通道的标准差
class
torchvision.transforms.ToTensor()
将PIL图片或者numpy.ndarray转成Tensor类型的
将PIL图片或者numpy.ndarray(HxWxC) (范围在0-255) 转成torch.FloatTensor (CxHxW) (范围为0.0-1.0)
torch.utils.data.DataLoader()
train_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('/files/', train=True, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size_train, shuffle=True)
class
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None, *, prefetch_factor=2, persistent_workers=False)
因为本项目字涉及到其中的三个参数所以只介绍dataset
、batch_size
、shuffle
若想了解更多请参考官网链接
- dataset (Dataset) – 要从中加载数据的数据集
- batch_size (int, 可选)– 每批装载多少样本(默认: 1).
- shuffle (bool, 可选) – 设置
True
在每次迭代中打乱顺序 (默认:False
).
enumerate()
enumerate(sequence, [start=0])
函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
- sequence – 一个序列、迭代器或其他支持迭代对象。
- start – 下标起始位置。
举例
>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1)) # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
next()
next(iterable, [default])
- iterable – 可迭代对象。
- default – 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。
可迭代的对象(可以用for循环的对象)Iterable:
一类:list,tuple,dict,set,str
二类:generator,包含生成器和带yield的generatoe function
而生成器不但可以作用于for,还可以被next()函数不断调用并返回下一个值,可以被next()函数不断返回下一个值的对象称为迭代器:Iterator
生成器都是Iterator对象,但list,dict,str是Iterable,但不是Iterator,要把list,dict,str等Iterable转换为Iterator可以使用iter()函数
figure()
figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
- num:图像编号或名称,数字为编号 ,字符串为名称
- figsize:指定figure的宽和高,单位为英寸;
- dpi:参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 1英寸等于2.5cm,A4纸是 21*30cm的纸张
- facecolor:背景颜色
- edgecolor:边框颜色
- frameon:是否显示边框
matplotlib.pyplot.imshow()
matplotlib.pyplot.imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, *, filternorm=True, filterrad=4.0, resample=None, url=None, data=None, **kwargs)
-
X:array_like对象/数列类对象,shape(n,m) 或者(n,m,3)或者(n,m,4)
把X代表的图片显示在当前坐标轴中。X可以是数列类格式、或者PIL图片。如果X是数列类对象,它可以有如下3种情况&类型:
MN - 用来作图的数列值:float类型 / INT类型
MN3 - RGB数列:float类型 / unit8类型
MN4 - RGBA数列:float类型 / unit8类型
MN3和MN4的float数列,取值范围限定为[0.0, 1.0]。MN类数列是基于norm(采用标量对映射到标量方法作图)和cmap(将标准化标量映射为颜色)。 -
interplotation:默认"None",可用字符串类型命令设定
可设定的字符串命令为:‘none’,‘nearest’,‘bilinear’,‘bicubic’,‘spline16’, ‘spline36’, ‘hanning’, ‘hamming’, ‘hermite’, ‘kaiser’,‘quadric’,‘catrom’,‘gaussian’,‘bessel’,‘mitchell’, ‘sinc’,'lanczos
如果"None",默认rc image.interpolation。
如果是"none",则在Agg,ps和pdf后端不进行插值。其他后端将会落到“最近”。 -
cmap:默认"None",可设为 “colormap"
如果是“None”,默认rc值符合 image.cmap 。如果X是3-D,则cmap会被忽略,而采用 具体的RGB(A)值。
nn.Conv2d()
nn.Conv2d(in_channels, out_channels, kernel_size)
- in_channels—这个很好理解,就是输入的四维张量[N, C, H, W]中的C了,即输入张量的channels数。这个形参是确定权重等可学习参数的shape所必需的。
- out_channels—也很好理解,即期望的四维输出张量的channels数
- kernel_size—卷积核的大小,一般我们会使用5x5、3x3这种左右两个数相同的卷积核,因此这种情况只需要写kernel_size = 5这样的就行了。如果左右两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个tuple,而不能写一个列表(list)。
Dropout2d()
防止过拟合
Dropout的过程
- 按照概率p,对每个输入channel进行伯努利采样,随机采样到的channel置为0,输出
- 将1.的输出结果乘以1/(1-p)就是做了dropout的结果
nn.Linear()
PyTorch的nn.Linear()是用于设置网络中的全连接层的,需要注意的是全连接层的输入与输出都是二维张量,一般形状为[batch_size, size]
,不同于卷积层要求输入输出是四维张量。
class
torch.nn.Linear(in_features, out_features, bias=True)
- in_features—指的是输入的二维张量的大小,即输入的
[batch_size, size]
中的size - out_features—指的是输出的二维张量的大小,即输出的二维张量的形状为
[batch_size,output_size]
,当然,它也代表了该全连接层的神经元个数。从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]
的输出张量。 - bias=True—如果设置为False,层将不会学习附加偏差。默认值为True