千言万语带你用PyTorch搞深度学习
作者:互联网
千言万语带你用PyTorch搞深度学习
大纲:
*深度学习
*前言
1.基础数据:Tensor
1.1 张量的创建
1.2 火炬。浮点张量
1.3 火炬。整数张量
1.4 火炬.randn
1.5 火炬范围
1.6 torch.zeros/ones/empty
2.二、Tensor的操作
2.1 火炬.abs
2.2 火炬.add
2.3 手电筒.clamp
2.4 火炬.div
2.5 火炬.pow
2.6 火炬.mm
2.7 火炬.mv
3.三、神经网络工具箱torch.nn
3.1 毫米。模块类
3.2 构建一个简单的神经网络
4.Torch实现完整的神经网络
4.1 torch.autograd 和变量
4.2 自定义传播函数
4.3 PyTorch 的 torch.nn
4.3.1 torch.nn.Sequential
4.3.2 torch.nn.Linear
4.3.3 火炬.nn.ReLU
4.3.4 火炬.nn.MSELoss
4.3.4 火炬.nn.L1损失
4.3.5 torch.nn.CrossEntropyLoss
4.3.5 使用损失函数的神经网络
4.4 PyTorch 的 Torch.optim
5.五、构建神经网络实现手写数据集
5.1 火炬视觉
5.1.1 火炬视觉.数据集
5.1.2 火炬视觉.models
5.1.3 火炬转换
5.1.3.1 torchvision.transforms.Resize
5.1.3.2 torchvision.transforms.Scale
5.1.3.3 火炬视觉.transforms.CenterCrop
5.1.3.4 火炬视觉.transforms.RandomCrop
5.1.3.5 torchvision.transforms.RandomHorizontalFlip
5.1.3.6 torchvision.transforms.RandomVerticalFlip
5.1.3.7 火炬视觉.transforms.ToTensor
5.1.3.8 torchvision.transforms.ToPILImage:
5.1.4 火炬工具
5.2 模型构建和参数优化
5.2.1 火炬.nn.Conv2d
5.2.2 火炬.nn.MaxPool2d
5.2.3 火炬.nn.Dropout
5.3 参数优化
5.3.1 模型训练
5.4 模型验证
5.5 完整代码
六、结论
前言
学习一个伟大的深度学习框架很重要,现在主流框架是Pytorch和Tesnsorflow,今天我们一起来学习一下pytorch吧!
基本数据:张量:
张量或张量是 PyTorch 中的基本操作数,可以被认为是包含单一数据类型元素的多维矩阵。从使用上来看,Tensor 和 NumPy 的 ndarray 很像,可以自由转换,只是 Tensor 还支持 GPU 加速。
在开始之前,提醒...:在我的文章中, 斜线是代码 .
1.1 张量的创建
1.2 火炬。浮点张量
火炬。 FloatTensor 用于生成浮点数据类型的张量并传递给torch。 floatTensor 参数可以是列表或维度值。
进口火炬
a = 火炬.FloatTensor(2,3)
b = torch.FloatTensor([2,3,4,5])
一,乙
输出是:
(张量([[1.0561e-38, 1.0102e-38, 9.6429e-39],
[8.4490e-39, 9.6429e-39, 9.1837e-39]]),
张量([2., 3., 4., 5.]))
1.3 火炬。整数张量
火炬。 IntTensor 用于生成整数类型的张量,传递给 Torch。 AntTensor 的参数可以是列表,也可以是维度值。
进口火炬
a = 火炬.FloatTensor(2,3)
b = torch.FloatTensor([2,3,4,5])
一,乙
进口火炬
a = 火炬.rand(2,3)
一个
得到:
张量([[0.5625, 0.5815, 0.8221],
[0.3589, 0.4180, 0.2158]])
1.4 火炬.randn
用于生成具有浮点数据类型和指定维度的随机 Tensor 的方法类似于 numpy.randn 中用于生成随机数的方法,其中随机生成的浮点数的值满足正态分布均值为 0,方差为 1。
进口火炬
a = 火炬.randn(2,3)
一个
得到:
张量([[-0.0067,-0.0707,-0.6682],
[ 0.8141, 1.1436, 0.5963]])
1.5 火炬范围
torch.range 用于生成具有浮点数据类型和开始和结束范围的 Tensor,因此向 torch.range 传递了三个参数,分别是开始值、结束值和步长,其中步长size 用于指定每一步从开始值到结束值的数据间隔。
进口火炬
a = 火炬范围(1,20,2)
一个
得到:
张量([1., 3., 5., 7., 9., 11., 13., 15., 17., 19.])
1.6 torch.zeros/ones/empty
torch.zeros 用于生成具有浮点类型和指定维度的数据类型的张量,但是这个浮点张量中的元素值都是 0。
torch.ones 生成一个全为 1 的数组。
torch.empty 创建一个未初始化的值张量,张量的大小由大小决定,size:定义张量的形状,可以是列表也可以是元组。
进口火炬
a = 火炬.zeros(2,3)
一个
得到:
张量([[0., 0., 0.],
[0., 0., 0.]])
二、Tensor的操作
2.1 火炬.abs
将参数传给torch.abs后返回输入参数的绝对值作为输出,输入参数必须是张量数据类型的变量,如:
进口火炬
a = 火炬.randn(2,3)
一个
结果 a 是:
张量([[ 0.0948, 0.0530, -0.0986],
[1.8926,-2.0569,1.6617]])
A 用 abs 处理:
b = 火炬.abs(a)
b
得到:
张量([[0.0948, 0.0530, 0.0986],
[1.8926, 2.0569, 1.6617]])
2.2 火炬.add
将参数传递给torch.add将输入参数的求和结果作为输出返回,可以是Tensor数据类型的所有变量,也可以是Tensor数据类型的一个变量,也可以是一个标量。
_进口火炬
a = 火炬.randn(2,3)
一个
tensor([[-0.1146, -0.3282, -0.2517],
[-0.2474, 0.8323, -0.9292]])_
_b = 火炬.randn(2,3)
b
tensor([[ 0.9526, 1.5841, -3.2665],
[-0.4831, 0.9259, -0.5054]])_
c = 火炬.add(a,b)
C
c的输出:
张量([[ 0.8379, 1.2559, -3.5182],
[-0.7305, 1.7582, -1.4346]])
另一个:
d = 火炬.randn(2,3)
d
_#我们得到d是...
tensor([[ 0.1473, 0.7631, -0.1953],
[-0.2796, -0.7265, 0.7142]])_
我们将 d 添加到标量 10:
e = 火炬.add(d,10)
e
得到:
张量([[10.1473, 10.7631, 9.8047],
[9.7204、9.2735、10.7142]])
2.3 手电筒.clamp
torch.clamp 是根据自定义范围对输入参数进行裁剪,最后将参数裁剪的结果作为输出,所以输入参数一共有三个,即需要裁剪的Tensor数据类型的变量,裁剪的上边界和裁剪的下边界,具体裁剪过程是:使用变量中的每个元素比较裁剪的上边界和裁剪的下边界的值,如果元素小于裁剪下边界的值,该元素被重写为裁剪下边界的值;类似地,如果一个元素的值大于裁剪上界的值,则该元素被重写为裁剪上界的值。我们直接看例子:
_a = 火炬.randn(2,3)
一个
我们得到一个是:
tensor([[-1.4049, 1.0336, 1.2820],
[ 0.7610, -1.7475, 0.2414]])_
我们对 b 进行钳位操作:
_b = 火炬.clamp(a,-0.1,0.1)
b
我们得到b是:
tensor([[-0.1000, 0.1000, 0.1000],
[ 0.1000, -0.1000, 0.1000]])_
2.4 火炬.div
Torch.div 是将参数传给torch.div 并返回输入参数的商结果作为输出的结果,同样,参与运算的参数都可以是Tensor 数据类型的变量,也可以是组合张量数据
_a = 火炬.randn(2,3)
一个
我们得到一个……:
tensor([[ 0.6276, 0.6397, -0.0762],
[-0.4193, -0.5528, 1.5192]])_
_b = 火炬.randn(2,3)
b
我们得到b…:
tensor([[ 0.9219, 0.2120, 0.1155],
[ 1.1086, -1.1442, 0.2999]])_
对a、b进行div操作
_c = 火炬.div(a,b)
C
get c…:
tensor([[ 0.6808, 3.0173, -0.6602],
[-0.3782, 0.4831, 5.0657]])_
2.5 火炬.pow
torch.pow:将参数传递给torch.pow后,将输入参数的幂的结果作为输出返回,参与运算的参数都可以是Tensor数据类型的变量,也可以是组合张量数据类型和标量的变量。
_a = 火炬.randn(2,3)
一个
得到一个是……:
tensor([[ 0.3896, -0.1475, 0.1104],
[-0.6908, -0.0472, -1.5310]])_
正方形
_b = 火炬.pow(a,2)
b
我们得到b是a的平方:
tensor([[1.5181e-01, 2.1767e-02, 1.2196e-02],
[4.7722e-01, 2.2276e-03, 2.3441e+00]])_
2.6 火炬.mm
orch.mm:将参数传递给torch.mm,并将输入参数的乘积结果作为输出返回,但是这个乘积和之前的torch.mul操作方法不一样,torch.mm使用的是两者之间的乘法规则矩阵进行计算,所以传入的参数会被当作一个矩阵,参数的维数自然也满足矩阵乘法的前提条件,即前一个矩阵的行数必须等于前一个矩阵的列数后一个矩阵
让我们看一个例子:
_a = 火炬.randn(2,3)
一个
我们得到一个……:
tensor([[ 0.1057, 0.0104, -0.1547],
[ 0.5010, -0.0735, 0.4067]])_
和…
_b = 火炬.randn(2,3)
b
我们得到b:
tensor([[ 1.1971, -1.4010, 1.1277],
[-0.3076, 0.9171, 1.9135]])_
然后我们对结果 a,b 执行矩阵乘法运算:
_c = 火炬.mm(a,bT)
C
tensor([[-0.0625, -0.3190],
[ 1.1613, 0.5567]])_
2.7 火炬.mv
将参数传给torch.mv后返回输入参数的乘积结果作为输出,torch.mv使用矩阵与向量的乘法规则计算,传入的第一个参数代表矩阵,第二个参数代表向量,并且顺序不能颠倒。
让我们看一个例子:
_a = 火炬.randn(2,3)
一个
我们得到一个……:
tensor([[ 1.0909, -1.1679, 0.3161],
[-0.8952, -2.1351, -0.9667]])_
_b = 火炬.randn(3)
b
我们得到b…:
tensor([-1.4689, 1.6197, 0.7209])_
然后我们对结果 a,b 执行矩阵乘法运算:
_c = 火炬.mv(a,b)
C
张量([-3.2663,-2.8402])_
三、神经网络工具箱“torch.nn”
虽然torch.autograd库实现了autodevation和梯度反向传播,但是如果我们要完成一个模型的训练,还是需要手写参数的自动更新和训练过程的控制,还是不够方便。为此,PyTorch进一步提供了集成度更高的模块化接口torch.nn,它建立在Autograd之上,提供了网络模块、优化器、初始化策略等一系列功能。
3.1 毫米。模块类
nn。 Module是PyTorch提供的一个神经网络类,实现了网络各层的定义以及类中的前向计算和反向传播机制。在实际使用中,如果要实现神经网络,只需要继承nn即可。模块,在初始化时定义模型结构和参数,并在函数forward()中编写网络转发过程。
1.参数功能
2.带有反向传播的forward()函数
3. 多个模块的嵌套
4.模块和 nn.functional 库
5.顺序()模块
我们使用“torch.nn”来实现一个MLP
从火炬进口nn
MLP 类(nn.Module):
# 类 MLP 我 继承自 nn.Module _
def init(self, in_dim, hid_dim1, hid_dim2, out_dim):
超级(MLP,自我).init()
self.layer = nn.Sequential(
nn.Linear(in_dim, hid_dim1),
nn.ReLU(),
nn.Linear(hid_dim1, hid_dim2),
nn.ReLU(),
nn.Linear(hid_dim2, out_dim),
nn.ReLU()
)
def 前向(自我,x):
x = self.layer(x)
返回 x_
3.2 构建一个简单的神经网络
下面我们使用torch构建一个简单的神经网络:
1、我们设置输入节点为1000,隐藏层节点为100,输出层节点为10
2、输入100个数据有1000个特征,经过隐藏层变成100个特征有10个分类结果,然后将结果反向传播
进口火炬
batch_n = 100 #每批输入数据的数量
隐藏层 = 100
input_data = 1000 #每个数据的特征是1000
输出数据 = 10
x = torch.randn(batch_n,input_data)
y = torch.randn(batch_n,output_data)
w1 = torch.randn(input_data,hidden_layer)
w2 = torch.randn(hidden_layer,output_data)
epoch_n = 20
lr = 1e-6
对于范围内的纪元(epoch_n):
h1=x.mm(w1)#(100,1000)(1000,100) →100100
打印(h1.shape)
h1=h1.clamp(min=0)
y_pred = h1.mm(w2)
损失 = (y_pred-y).pow(2).sum()
print(“epoch:{},loss:{:.4f}”.format(epoch,loss))
grad_y_pred = 2*(y_pred-y)
grad_w2 = h1.t().mm(grad_y_pred)
grad_h = grad_y_pred.clone()
grad_h = grad_h.mm(w2.t())
grad_h.clamp_(min=0)#将所有小于0的值赋值为0,等效sigmoid
grad_w1 = xt().mm(grad_h)
w1 = w1 -lrgrad_w1
w2 = w2 -lrgrad_w2
然后……我们得到
火炬大小([100, 100])
纪元:0,损失:112145.7578
火炬大小([100, 100])
纪元:1,损失:110014.8203
火炬大小([100, 100])
纪元:2,损失:107948.0156
火炬大小([100, 100])
纪元:3,损失:105938.6719
火炬大小([100, 100])
纪元:4,损失:103985.1406
火炬大小([100, 100])
纪元:5,损失:102084.9609
火炬大小([100, 100])
纪元:6,损失:100236.9844
火炬大小([100, 100])
纪元:7,损失:98443.3359
火炬大小([100, 100])
纪元:8,损失:96699.5938
火炬大小([100, 100])
纪元:9,损失:95002.5234
火炬大小([100, 100])
纪元:10,损失:93349.7969
火炬大小([100, 100])
纪元:11,损失:91739.8438
火炬大小([100, 100])
纪元:12,损失:90171.6875
火炬大小([100, 100])
纪元:13,损失:88643.1094
火炬大小([100, 100])
纪元:14,损失:87152.6406
火炬大小([100, 100])
纪元:15,损失:85699.4297
火炬大小([100, 100])
纪元:16,损失:84282.2500
火炬大小([100, 100])
纪元:17,损失:82899.9062
火炬大小([100, 100])
纪元:18,损失:81550.3984
火炬大小([100, 100])
纪元:19,损失:80231.1484
越来越低的损失。
Torch 实现了一个完整的神经网络
4.1 torch.autograd 和变量
torch.autograd包的主要作用是完成神经网络反向传播中的链式微分,手动编写这些衍生程序会导致重复造轮子的现象。
自动梯度的功能过程大致如下:首先在神经网络的前向传播过程中通过输入Tensor数据类型的变量生成计算图,然后根据下式精确计算出每个参数需要更新的梯度这个计算图和输出结果,并通过完成传播来完成参数的梯度更新。
完成自动梯度所需的torch.autograd包中的Variable类封装了我们定义的张量数据类型变量,封装后计算图中的每个节点都是一个Variable对象,从而实现了自动梯度的功能可以应用。
下面我们使用autograd来实现一个两层结构的神经网络模型。
进口火炬
从 torch.autograd 导入变量
批次_n = 100
隐藏层 = 100
输入数据 = 1000
输出数据 = 10
_x = 变量(torch.randn(batch_n,input_data),requires_grad=False)
y = 变量(torch.randn(batch_n,output_data),requires_grad=False)
用Variable对张量数据类型变量进行封装操作。 requires_grad 如果为False,则表示该变量在自动梯度计算过程中不保留梯度值。
w1 = 变量(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = 变量(torch.randn(hidden_layer,output_data),requires_grad=True)_
#学习率和迭代次数分配
epoch_n=50
lr=1e-6
_对于范围内的纪元(epoch_n):
h1=x.mm(w1)#(100,1000)(1000,100) →100100
打印(h1.shape)
h1=h1.clamp(min=0)
y_pred = h1.mm(w2)
y_pred = x.mm(w1).clamp(min=0).mm(w2)
损失 = (y_pred-y).pow(2).sum()
print(“epoch:{},loss:{:.4f}”.format(epoch,loss.data))_
grad_y_pred = 2*(y_pred-y)
grad_w2 = h1.t().mm(grad_y_pred)
loss.backward()#backprobagation
grad_h = grad_y_pred.clone()
grad_h = grad_h.mm(w2.t())
grad_h.clamp_(min=0)#将所有小于0的值赋值为0,相当于一个sigmoid
grad_w1 = xt().mm(grad_h)
w1.data -= lrw1.grad.data
w2.data -= lrw2.grad.data
w1.grad.data.zero()
w2.grad.data.zero_()_
w1 = w1 -lr*grad_w1
w2 = w2 -lr*grad_w2
我们得到……
得到结果:
火炬大小([100, 100])
纪元:0,损失:54572212.0000
火炬大小([100, 100])
纪元:1,损失:133787328.0000
火炬大小([100, 100])
纪元:2,损失:491439904.0000
火炬大小([100, 100])
纪元:3,损失:683004416.0000
火炬大小([100, 100])
纪元:4,损失:13681055.0000
火炬大小([100, 100])
纪元:5,损失:8058388.0000
火炬大小([100, 100])
纪元:6,损失:5327059.5000
火炬大小([100, 100])
纪元:7,损失:3777382.5000
火炬大小([100, 100])
纪元:8,损失:2818449.5000
火炬大小([100, 100])
纪元:9,损失:2190285.0000
火炬大小([100, 100])
纪元:10,损失:1760991.0000
火炬大小([100, 100])
纪元:11,损失:1457116.3750
火炬大小([100, 100])
纪元:12,损失:1235850.6250
火炬大小([100, 100])
纪元:13,损失:1069994.0000
火炬大小([100, 100])
纪元:14,损失:942082.4375
火炬大小([100, 100])
纪元:15,损失:841170.6250
火炬大小([100, 100])
纪元:16,损失:759670.1875
火炬大小([100, 100])
纪元:17,损失:692380.5625
火炬大小([100, 100])
纪元:18,损失:635755.0625
火炬大小([100, 100])
纪元:19,损失:587267.1250
火炬大小([100, 100])
纪元:20,损失:545102.0000
火炬大小([100, 100])
纪元:21,损失:508050.6250
火炬大小([100, 100])
纪元:22,损失:475169.9375
火炬大小([100, 100])
纪元:23,损失:445762.8750
火炬大小([100, 100])
纪元:24,损失:419216.2812
火炬大小([100, 100])
纪元:25,损失:395124.9375
火炬大小([100, 100])
纪元:26,损失:373154.8438
火炬大小([100, 100])
纪元:27,损失:352987.6875
火炬大小([100, 100])
纪元:28,损失:334429.0000
火炬大小([100, 100])
纪元:29,损失:317317.7500
火炬大小([100, 100])
纪元:30,损失:301475.8125
火炬大小([100, 100])
纪元:31,损失:286776.8750
火炬大小([100, 100])
纪元:32,损失:273114.4062
火炬大小([100, 100])
纪元:33,损失:260383.6406
火炬大小([100, 100])
纪元:34,损失:248532.8125
火炬大小([100, 100])
纪元:35,损失:237452.3750
火炬大小([100, 100])
纪元:36,损失:227080.5156
火炬大小([100, 100])
纪元:37,损失:217362.9375
火炬大小([100, 100])
纪元:38,损失:208250.5312
火炬大小([100, 100])
纪元:39,损失:199686.1094
火炬大小([100, 100])
纪元:40,损失:191620.0312
火炬大小([100, 100])
纪元:41,损失:184017.4375
火炬大小([100, 100])
纪元:42,损失:176841.0156
火炬大小([100, 100])
纪元:43,损失:170073.1719
火炬大小([100, 100])
纪元:44,损失:163686.5000
火炬大小([100, 100])
纪元:45,损失:157641.5000
火炬大小([100, 100])
纪元:46,损失:151907.0000
火炬大小([100, 100])
纪元:47,损失:146470.1250
火炬大小([100, 100])
纪元:48,损失:141305.3594
火炬大小([100, 100])
纪元:49,损失:136396.7031
同样,越来越低的损失……
4.2 自定义传播函数
其实除了自动梯度法,我们还可以通过新建一个继承torch.nn.Module的类来完成前向传播函数和后向传播函数的重写。在这个新类中,我们使用 forward 作为前向传播函数的关键字,backward 作为后向传播函数的关键字。让我们做一个自定义传播函数:
进口火炬
从 torch.autograd 导入变量
批处理_n = 64
隐藏层 = 100
输入数据 = 1000
输出数据 = 10
class Model(torch.nn.Module): #完成类继承的操作
def init(self):
super(Model,self).init()#初始化类
def forward(自我,输入,w1,w2):
x = 火炬.mm(输入,w1)
x = torch.clamp(x,min = 0)
x = 火炬.mm(x,w2)
返回 x
向后定义(自我):
经过
模型 = 模型()
x = 变量(torch.randn(batch_n,input_data),requires_grad=False)
y = 变量(torch.randn(batch_n,output_data),requires_grad=False)
用Variable对张量数据类型变量进行封装操作。 requires_grad 如果为F,则表示该变量在自动梯度计算过程中不保留梯度值。
w1 = 变量(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = 变量(torch.randn(hidden_layer,output_data),requires_grad=True)
epoch_n=30
对于范围内的纪元(epoch_n):
y_pred = 模型(x,w1,w2)
损失 = (y_pred-y).pow(2).sum()
print(“epoch:{},loss:{:.4f}”.format(epoch,loss.data))
loss.backward()
w1.data -= lrw1.grad.data
w2.data -= lrw2.grad.data
w1.grad.data.zero()
w2.grad.data.zero_()_
我们得到结果:
lower & lower loss…
4.3 PyTorch 的 torch.nn
4.3.1 torch.nn.Sequential
torch.nn.Sequential 类是torch.nn中的一个序列容器,它通过在容器中嵌套各种实现来实现神经网络模型,最重要的是参数是按照我们定义的序列自动传递的。
进口火炬
从 torch.autograd 导入变量
批次_n = 100
隐藏层 = 100
输入数据 = 1000
输出数据 = 10
_x = 变量(torch.randn(batch_n,input_data),requires_grad=False)
y = 变量(torch.randn(batch_n,output_data),requires_grad=False)
模型 = torch.nn.Sequential(
torch.nn.Linear(input_data,hidden_layer),
火炬.nn.ReLU(),
torch.nn.Linear(hidden_layer,output_data)
)
torch.nn.Sequential是我们搭建的神经网络模型的具体结构,Linear完成了从隐藏层到输出层的线性变换,然后用ReLU激活函数激活
torch.nn.Sequential类是torch.nn中的一个序列容器,通过在容器中嵌套各类神经网络模型来实现神经网络模型的构建。
最重要的是,参数按照我们定义的顺序自动传递。_
4.3.2 torch.nn.Linear
torch.nn.Linear 类用于定义模型的线性层,即完成前面提到的不同层之间的线性变换。线性层接受的参数有3个:输入特征个数,输出特征个数,是否使用bias,默认为True,使用torch.nn.Linear类,对应维度的权重参数和bias将自动生成,对于生成的权重参数和偏差,我们的模型默认使用比之前简单随机方法更好的参数初始化方法。
4.3.3 火炬.nn.ReLU
torch.nn.ReLU 属于非线性激活分类,定义时默认不需要输入参数。当然,torch.nn 包中有很多类别的非线性激活函数可供选择,例如 PReLU、LeaKyReLU、Tanh、Sigmoid、Softmax 等。
4.3.4 火炬.nn.MSELoss
torch.nn.MSELoss 类使用均方误差函数计算损失值,定义类的对象时不传入任何参数,但在使用实例时需要输入两个相同维度的参数。
_进口火炬
从 torch.autograd 导入变量
loss_f = torch.nn.MSELoss()
x = 变量(torch.randn(100,100))
y = 变量(torch.randn(100,100))
损失 = loss_f(x,y)
损失数据
张量(1.9529)_
4.3.4 火炬.nn.L1损失
torch.nn.L1Loss 类使用平均绝对误差函数计算损失值,定义类的对象时不传入任何参数,但使用实例时需要输入两个相同维度的参数计算。
_进口火炬
从 torch.autograd 导入变量
loss_f = torch.nn.L1Loss()
x = 变量(torch.randn(100,100))
y = 变量(torch.randn(100,100))
损失 = loss_f(x,y)
损失数据
张量(1.1356)_
4.3.5 torch.nn.CrossEntropyLoss
torch.nn.CrossEntropyLoss 类用于计算交叉熵,定义该类的对象时不传入任何参数,但在使用实例时,需要输入两个满足交叉熵计算条件的参数。
进口火炬
从 torch.autograd 导入变量
loss_f = torch.nn.CrossEntropyLoss()
x = 变量(torch.randn(3,5))
y = Variable(torch.LongTensor(3).random(5))#3 个随机数,其中 0 4
损失 = loss_f(x,y)
损失数据
张量(2.3413)_
4.3.5 使用损失函数的神经网络
进口火炬
从 torch.autograd 导入变量
进口火炬
从 torch.autograd 导入变量
loss_fn = torch.nn.MSELoss()
x = 变量(torch.randn(100,100))
y = 变量(torch.randn(100,100))
损失 = loss_fn(x,y)
批次_n = 100
隐藏层 = 100
输入数据 = 1000
输出数据 = 10
x = 变量(torch.randn(batch_n,input_data),requires_grad=False)
y = 变量(torch.randn(batch_n,output_data),requires_grad=False)
_模型 = torch.nn.Sequential(
torch.nn.Linear(input_data,hidden_layer),
火炬.nn.ReLU(),
torch.nn.Linear(hidden_layer,output_data)
)
torch.nn.Sequential_
_括号里面是我们搭建的神经网络模型的具体结构,Linear完成了从隐藏层到输出层的线性变换,然后用ReLU激活函数激活
torch.nn.Sequential类是torch.nn中的一个序列容器,通过在容器中嵌套各类神经网络模型来实现神经网络模型的构建。
最重要的是,参数按照我们定义的顺序自动传递。_
对于范围内的纪元(epoch_n):
y_pred = 模型(x)
损失 = loss_fn(y_pred,y)
如果 epoch%1000 == 0:
print(“epoch:{},loss:{:.4f}”.format(epoch,loss.data))
模型.zero_grad()
loss.backward()
对于models.parameters()中的参数:
param.data -= param.grad.data*lr
4.4 PyTorch 的 Torch.optim
torch.optim 包提供了非常多的能够自动优化参数的类,例如 SGD、AdaGrad、RMSProp、Adam 等。
使用自动优化的类实现神经网络:
进口火炬
从 torch.autograd 导入变量
批次_n = 100
隐藏层 = 100
输入数据 = 1000
输出数据 = 10
x = 变量(torch.randn(batch_n,input_data),requires_grad=False)
y = 变量(torch.randn(batch_n,output_data),requires_grad=False)
模型 = torch.nn.Sequential(
torch.nn.Linear(input_data,hidden_layer),
火炬.nn.ReLU(),
torch.nn.Linear(hidden_layer,output_data)
)
_# loss_fn = torch.nn.MSELoss()
x = 变量(torch.randn(100,100))
y = 变量(torch.randn(100,100))
损失 = loss_fn(x,y)_
epoch_n=10000
lr=1e-4
loss_fn = torch.nn.MSELoss()
_优化器 = torch.optim.Adam(models.parameters(),lr=lr)
use torch.optim.Adam 类作为我们模型参数的优化函数,其中输入是:优化参数和学习率的初始值。
因为我们需要优化的是模型中的所有参数,所以传递的参数是models.parameters()_
#为此,模型训练的代码如下:
对于范围内的纪元(epoch_n):
y_pred = 模型(x)
损失 = loss_fn(y_pred,y)
print(“Epoch:{},Loss:{:.4f}”.format(epoch,loss.data))
optimzer.zero_grad()#将模型参数的梯度归一化为0
loss.backward()
optimzer.step()#每个节点的参数都用计算出的梯度值进行更新。
五、构建神经网络实现手写数据集
5.1 火炬视觉
Torchvision 是 PyTorch 中专门用于处理图像的库。这个包中有四大类。
torchvision.datasets
torchvision.models
torchvision.transforms
torchvision.utils
5.1.1 火炬视觉.数据集
torchvision.datasets 可以在某些数据集上下载和加载,例如 MNIST 可以使用 torchvision.datasets.MNIST COCO、ImageNet、CIFCAR 等进行下载和加载。
这是加载了 torchvision.datasets 的 MNIST 数据集:
data_train = datasets.MNIST(root=”./data/”,
变换=变换,
火车=真,
下载=真)
data_test = datasets.MNIST(root=”./data/”,
变换=变换,
火车=假)
5.1.2 火炬视觉.models
Torchvision.models 为我们提供了一个经过训练的模型,我们可以在加载后直接使用它。
torchvision.models 模块的子模块包含以下模型结构。作为:
亚历克斯网
VGG
资源网
挤压网
密集网等
我们可以直接使用下面的代码快速创建一个随机初始化权重的模型:
导入 torchvision.models 作为模型
resnet18 = models.resnet18()
alexnet = models.alexnet()
挤压网=models.squeezenet1_0()
密集网络 = 模型.密集网络_161()
也可以使用 pretrained=True 加载预训练模型:
导入 torchvision.models 作为模型
resnet18 = models.resnet18(预训练=真)
alexnet = models.alexnet(pretrained=True)
5.1.3 火炬转换
torch.transforms 中有许多数据转换类,例如:
5.1.3.1 torchvision.transforms.Resize
用于将加载的图像数据缩放到我们需要的大小。传递的参数可以是整型数据,也可以是类似于 (h,w) 的序列。 h 代表高度,w 代表宽度,如果输入整数数据,则 h 和 w 等于该数字。
5.1.3.2 torchvision.transforms.Scale
用于将加载的图像数据缩放到我们需要的大小。类似于调整大小。
5.1.3.3 火炬视觉.transforms.CenterCrop
用于以图像中心为参考点,将加载的图片裁剪成我们需要的大小。传递给此类的参数可以是整数数据或类似于 (h,w) 的序列。
5.1.3.4 火炬视觉.transforms.RandomCrop
用于将加载的图像随机裁剪为我们需要的大小。传递给此类的参数可以是整数数据或类似于 (h,w) 的序列。
5.1.3.5 torchvision.transforms.RandomHorizontalFlip
用于以随机概率水平翻转加载的图片。我们将自定义随机概率传递给此类,如果未定义,则使用默认概率 0.5
5.1.3.6 torchvision.transforms.RandomVerticalFlip
用于以随机概率垂直翻转加载的图片。我们将自定义随机概率传递给此类,如果未定义,则使用默认概率 0.5
5.1.3.7 火炬视觉.transforms.ToTensor
它用于对加载的图像数据进行类型化,将先前形成 PIL 图像数据的变量转换为张量数据类型,从而允许 PyTorch 计算和处理它们。
5.1.3.8 torchvision.transforms.ToPILImage:
用于将张量变量的数据转换成PIL图像数据,主要是为了方便图像显示。
以下是使用转换器操作 MNIST 数据集的方式:
_#torchvision.transforms:常见的图像变换,如裁剪、旋转等;
变换=变换。撰写(
[transforms.ToTensor(),#将PILImage类型转换为张量类型!
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
Anterior(0.5,0.5,0.5)是RGB的三个通道上的均值,后面的(0.5,0.5,0.5)是三个通道的标准差
])
上面的代码我们可以放置变换。 Compose() 被视为同时组合多个数据转换的容器。
传入的参数是一个列表,列表中的元素是对加载数据的变换。_
5.1.4 火炬工具
关于 torchvision.utils 我们引入了一个加载数据的类:torch.utils.data.DataLoader 和
在torch.utils.data.DataLoader类中,dataset参数指定我们加载的数据集的名称,batch_size参数设置每个包的图片数量,shuffle设置为True表示加载过程会随机打乱数据并将其打包。
_data_loader_train=torch.utils.data.DataLoader(dataset=data_train,
批量大小=64,
洗牌=真,
num_workers=2
)
data_loader_test=torch.utils.data.DataLoader(dataset=data_test,
批量大小=64,
洗牌=真)
num_workers=2)_
还有torchvision.utils.make_grid 将一批图片构造成一个网格状的图片。
_图像,标签 = 下一个(iter(data_loader_train))
dataiter = iter(data_loader_train)
图像,标签 = dataiter.next()_
img = torchvision.utils.make_grid(图像)
img = img.numpy().transpose(1,2,0)
标准 = [0.5,0.5,0.5]
平均值 = [0.5,0.5,0.5]
img = img*std+mean
print([labels[i] for i in range(64)])
plt.imshow(img)
在这里,iter和next得到一批图片数据及其对应的图片标签,然后使用torchvision.utils.make_grid将一批图片构造成网格图案torchvision.utils.make_grid后,图片维度变为channel,h, w 三维的,因为图片是用matplotlib显示的。我们要使用的数据是一个数组,维度是(height, weight, channel)即最后的颜色通道,所以我们需要使用numpy和transpose来完成原始数据类型的转换和数据的交换方面。
5.2 模型构建和参数优化
实现卷积神经网络模型构建:
导入数学
进口火炬
将 torch.nn 导入为 nn
类模型(nn.Module):
def init(self):
超级(模型,自我).init()
构建卷积层后的全连接层,以及分类器 _
self.conv1 = nn.Sequential(
nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),
nn.ReLU(),
nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2d(stride=2,kernel_size=2)
)_
self.dense = torch.nn.Sequential(
nn.Linear(1414128,1024),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(1024,10)
)
def 前进(自我,x):
x=self.conv1(x)
x=x.view(-1,1414128)
x=self.dense(x)
返回 x
5.2.1 火炬.nn.Conv2d
用于构建卷积神经网络的卷积层的主要参数有:
输入通道数、输出通道数、卷积核大小、卷积核移动步长和paddingde值(用于填充边界像素)
5.2.2 火炬.nn.MaxPool2d
实现卷积姐妹神经网络最大池化层,主要参数有:
池化窗口大小、池化窗口移动步长和paddingde值
5.2.3 火炬.nn.Dropout
用于防止卷积神经网络在训练时过拟合,其原理是将卷积神经网络模型的一些参数以一定的随机概率归零,以达到减少相邻两层之间神经连接的目的
5.3 参数优化
建立模型后,我们可以训练和优化模型的参数:
模型 = 模型()
成本 = nn.CrossEntropyLoss()
优化器 = torch.optim.Adam(model.parameters())
打印(模型)
5.3.1 模型训练
n_epochs = 5
_对于范围内的纪元(n_epochs):
running_loss = 0.0
运行正确 = 0
print(“Epoch {}/{}”.format(epoch,n_epochs))
打印(“-”*10)
对于 data_loader_train 中的数据:
X_train,y_train = 数据
X_train,y_train = 变量(X_train),变量(y_train)
输出 = 模型(X_train)
,pred=torch.max(outputs.data,1)
优化器.zero_grad()
损失=成本(输出,y_train)
loss.backward()
优化器.step()
running_loss += loss.data
running_correct += torch.sum(pred == y_train.data)
测试正确 = 0
对于 data_loader_test 中的数据:
X_test,y_test = 数据
X_test,y_test = 变量(X_test),变量(y_test)
输出 = 模型(X_test)
_,pred=torch.max(outputs.data,1)
testing_correct += torch.sum(pred == y_test.data)
print("Loss is:{:4f},Train Accuracy is:{:.4f}%,Test Accuracy is:{:.4f}".format(running_loss/len(data_train),100running_correct/len(data_train)
,100testing_correct/len(data_test)))
5.4 模型验证
为了验证我们训练的模型真的和显示的已知结果一样准确,最好的方法是随机选择测试集中的一部分图片,使用训练好的模型进行预测,看看距离真正的价值,并可视化结果。测试代码如下:
_data_loader_test = torch.utils.data.DataLoader(dataset=data_test,
批量大小 = 4,
洗牌=真)
X_test,y_test = next(iter(data_loader_test))
输入 = 变量(X_test)
pred = 模型(输入)
,pred = torch.max(pred,1)
print("预测标签是:",[i for i in pred.data])
print(“真实标签是:”,[i for i in y_test])
img = torchvision.utils.make_grid(X_test)
img = img.numpy().transpose(1,2,0)
标准 = [0.5,0.5,0.5]
平均值 = [0.5,0.5,0.5]
img = img*std+mean
plt.imshow(img)
得到:
5.5 完整代码
进口火炬
导入torchvision
从 torchvision 导入数据集,转换
从 torch.autograd 导入变量
将 numpy 导入为 np
将 matplotlib.pyplot 导入为 plt
变换 = 变换.Compose([
transforms.ToTensor(),
transforms.Lambda(lambda x: x.repeat(3,1,1)),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])
data_train = datasets.MNIST(root=”./data/”,
变换=变换,
火车=真,
下载=真)
data_test = datasets.MNIST(root=”./data/”,
变换=变换,
火车=假)
_data_loader_train=torch.utils.data.DataLoader(dataset=data_train,
批量大小=64,
洗牌=真,
num_workers=2
)
data_loader_test=torch.utils.data.DataLoader(dataset=data_test,
批量大小=64,
洗牌=真)
num_workers=2)
图像,标签 = 下一个(iter(data_loader_train))
dataiter = iter(data_loader_train)
图像,标签 = dataiter.next()_
img = torchvision.utils.make_grid(图像)
img = img.numpy().transpose(1,2,0)
标准 = [0.5,0.5,0.5]
平均值 = [0.5,0.5,0.5]
img = img*std+mean
print([labels[i] for i in range(64)])
plt.imshow(img)
导入数学
进口火炬
将 torch.nn 导入为 nn
类模型(nn.Module):
def init(self):
超级(模型,自我).init()
self.conv1 = nn.Sequential(
nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),
nn.ReLU(),
nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2d(stride=2,kernel_size=2)
)
self.dense = torch.nn.Sequential(
nn.Linear(1414128,1024),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(1024,10)
)
def 前进(自我,x):
x=self.conv1(x)
x=x.view(-1,1414128)
x=self.dense(x)
返回 x
模型 = 模型()
成本 = nn.CrossEntropyLoss()
优化器 = torch.optim.Adam(model.parameters())
打印(模型)
n_epochs = 5
_对于范围内的纪元(n_epochs):
running_loss = 0.0
运行正确 = 0
print(“Epoch {}/{}”.format(epoch,n_epochs))
打印(“-”*10)
对于 data_loader_train 中的数据:
X_train,y_train = 数据
X_train,y_train = 变量(X_train),变量(y_train)
输出 = 模型(X_train)
,pred=torch.max(outputs.data,1)
优化器.zero_grad()
损失=成本(输出,y_train)
loss.backward()
优化器.step()
running_loss += loss.data
running_correct += torch.sum(pred == y_train.data)
测试正确 = 0
对于 data_loader_test 中的数据:
X_test,y_test = 数据
X_test,y_test = 变量(X_test),变量(y_test)
输出 = 模型(X_test)
_,pred=torch.max(outputs.data,1)
testing_correct += torch.sum(pred == y_test.data)
print("Loss is:{:4f},Train Accuracy is:{:.4f}%,Test Accuracy is:{:.4f}".format(running_loss/len(data_train),100running_correct/len(data_train)
,100testing_correct/len(data_test)))
_data_loader_test = torch.utils.data.DataLoader(dataset=data_test,
批量大小 = 4,
洗牌=真)
X_test,y_test = next(iter(data_loader_test))
输入 = 变量(X_test)
pred = 模型(输入)
,pred = torch.max(pred,1)
print("预测标签是:",[i for i in pred.data])
print(“真实标签是:”,[i for i in y_test])
img = torchvision.utils.make_grid(X_test)
img = img.numpy().transpose(1,2,0)
标准 = [0.5,0.5,0.5]
平均值 = [0.5,0.5,0.5]
img = img*std+mean
plt.imshow(img)
六、结论
关于pytorch的一个学习总结,期待大家和我交流,留言或者私信我的instagram或者邮箱,一起学习,一起进步!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
本文链接:https://www.qanswer.top/29406/15291201
标签:nn,torch,火炬,PyTorch,深度,100,data,千言万语,纪元 来源: https://www.cnblogs.com/amboke/p/16685283.html