2 pytorch基础【代码例子】

线性模型 # -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltx_data = https://tazarkount.com/read/[1.0, 2.0, 3.0]y_data = [2.0, 4.0, 6.0]def forward(x):return x * wdef loss(x, y):y_pred = forward(x)return (y_pred - y) * (y_pred - y)# 保存权重w_list = []# 保存权重的损失函数值mse_list = []# 穷举w值对应的损失函数MSEfor w in np.arange(0.0, 4.1, 0.1):print('w = ', w)loss_sum = 0for x_val, y_val in zip(x_data, y_data):# 为了打印y预测值,其实loss里也计算了y_pred_val = forward(x_val)loss_val = loss(x_val, y_val)loss_sum += loss_valprint('\t', x_val, y_val,y_pred_val, loss_val)print('MSE = ', loss_sum / 3)print('='*60)w_list.append(w)mse_list.append(loss_sum / 3)# 绘loss变化图,横坐标是w,纵坐标是lossplt.plot(w_list, mse_list)plt.ylabel('Loss')plt.xlabel('w')plt.show()=========================================w =0.01.0 2.0 0.0 4.02.0 4.0 0.0 16.03.0 6.0 0.0 36.0MSE =18.666666666666668============================================================w =0.11.0 2.0 0.1 3.612.0 4.0 0.2 14.443.0 6.0 0.30000000000000004 32.49MSE =16.846666666666668============================================================w =0.21.0 2.0 0.2 3.242.0 4.0 0.4 12.963.0 6.0 0.6000000000000001 29.160000000000004MSE =15.120000000000003============================================================w =0.300000000000000041.0 2.0 0.30000000000000004 2.88999999999999972.0 4.0 0.6000000000000001 11.5599999999999993.0 6.0 0.9000000000000001 26.009999999999998MSE =13.486666666666665============================================================w =0.41.0 2.0 0.4 2.56000000000000052.0 4.0 0.8 10.2400000000000023.0 6.0 1.2000000000000002 23.04MSE =11.946666666666667============================================================w =0.51.0 2.0 0.5 2.252.0 4.0 1.0 9.03.0 6.0 1.5 20.25MSE =10.5============================================================w =0.60000000000000011.0 2.0 0.6000000000000001 1.95999999999999972.0 4.0 1.2000000000000002 7.8399999999999993.0 6.0 1.8000000000000003 17.639999999999993MSE =9.146666666666663============================================================w =0.70000000000000011.0 2.0 0.7000000000000001 1.68999999999999952.0 4.0 1.4000000000000001 6.7599999999999983.0 6.0 2.1 15.209999999999999MSE =7.886666666666666============================================================w =0.81.0 2.0 0.8 1.442.0 4.0 1.6 5.763.0 6.0 2.4000000000000004 12.959999999999997MSE =6.719999999999999============================================================w =0.91.0 2.0 0.9 1.21000000000000022.0 4.0 1.8 4.8400000000000013.0 6.0 2.7 10.889999999999999MSE =5.646666666666666============================================================w =1.01.0 2.0 1.0 1.02.0 4.0 2.0 4.03.0 6.0 3.0 9.0MSE =4.666666666666667============================================================w =1.11.0 2.0 1.1 0.80999999999999982.0 4.0 2.2 3.23999999999999933.0 6.0 3.3000000000000003 7.289999999999998MSE =3.779999999999999============================================================w =1.20000000000000021.0 2.0 1.2000000000000002 0.63999999999999972.0 4.0 2.4000000000000004 2.55999999999999873.0 6.0 3.6000000000000005 5.759999999999997MSE =2.986666666666665============================================================w =1.31.0 2.0 1.3 0.489999999999999942.0 4.0 2.6 1.95999999999999973.0 6.0 3.9000000000000004 4.409999999999998MSE =2.2866666666666657============================================================w =1.40000000000000011.0 2.0 1.4000000000000001 0.35999999999999982.0 4.0 2.8000000000000003 1.43999999999999933.0 6.0 4.2 3.2399999999999993MSE =1.6799999999999995============================================================w =1.51.0 2.0 1.5 0.252.0 4.0 3.0 1.03.0 6.0 4.5 2.25MSE =1.1666666666666667============================================================w =1.61.0 2.0 1.6 0.159999999999999922.0 4.0 3.2 0.63999999999999973.0 6.0 4.800000000000001 1.4399999999999984MSE =0.746666666666666============================================================w =1.70000000000000021.0 2.0 1.7000000000000002 0.08999999999999992.0 4.0 3.4000000000000004 0.35999999999999963.0 6.0 5.1000000000000005 0.809999999999999MSE =0.4199999999999995============================================================w =1.81.0 2.0 1.8 0.039999999999999982.0 4.0 3.6 0.159999999999999923.0 6.0 5.4 0.3599999999999996MSE =0.1866666666666665============================================================w =1.90000000000000011.0 2.0 1.9000000000000001 0.0099999999999999742.0 4.0 3.8000000000000003 0.03999999999999993.0 6.0 5.7 0.0899999999999999MSE =0.046666666666666586============================================================w =2.01.0 2.0 2.0 0.02.0 4.0 4.0 0.03.0 6.0 6.0 0.0MSE =0.0============================================================w =2.11.0 2.0 2.1 0.0100000000000000182.0 4.0 4.2 0.040000000000000073.0 6.0 6.300000000000001 0.09000000000000043MSE =0.046666666666666835============================================================w =2.21.0 2.0 2.2 0.040000000000000072.0 4.0 4.4 0.160000000000000283.0 6.0 6.6000000000000005 0.36000000000000065MSE =0.18666666666666698============================================================w =2.30000000000000031.0 2.0 2.3000000000000003 0.090000000000000162.0 4.0 4.6000000000000005 0.360000000000000653.0 6.0 6.9 0.8100000000000006MSE =0.42000000000000054============================================================w =2.40000000000000041.0 2.0 2.4000000000000004 0.160000000000000282.0 4.0 4.800000000000001 0.64000000000000113.0 6.0 7.200000000000001 1.4400000000000026MSE =0.7466666666666679============================================================w =2.51.0 2.0 2.5 0.252.0 4.0 5.0 1.03.0 6.0 7.5 2.25MSE =1.1666666666666667============================================================w =2.61.0 2.0 2.6 0.36000000000000012.0 4.0 5.2 1.44000000000000043.0 6.0 7.800000000000001 3.2400000000000024MSE =1.6800000000000008============================================================w =2.71.0 2.0 2.7 0.490000000000000272.0 4.0 5.4 1.9600000000000013.0 6.0 8.100000000000001 4.410000000000006MSE =2.2866666666666693============================================================w =2.80000000000000031.0 2.0 2.8000000000000003 0.64000000000000052.0 4.0 5.6000000000000005 2.5600000000000023.0 6.0 8.4 5.760000000000002MSE =2.986666666666668============================================================w =2.90000000000000041.0 2.0 2.9000000000000004 0.81000000000000062.0 4.0 5.800000000000001 3.24000000000000243.0 6.0 8.700000000000001 7.290000000000005MSE =3.780000000000003============================================================w =3.01.0 2.0 3.0 1.02.0 4.0 6.0 4.03.0 6.0 9.0 9.0MSE =4.666666666666667============================================================w =3.11.0 2.0 3.1 1.21000000000000022.0 4.0 6.2 4.8400000000000013.0 6.0 9.3 10.890000000000004MSE =5.646666666666668============================================================w =3.21.0 2.0 3.2 1.44000000000000042.0 4.0 6.4 5.7600000000000023.0 6.0 9.600000000000001 12.96000000000001MSE =6.720000000000003============================================================w =3.30000000000000031.0 2.0 3.3000000000000003 1.69000000000000062.0 4.0 6.6000000000000005 6.76000000000000253.0 6.0 9.9 15.210000000000003MSE =7.886666666666668============================================================w =3.40000000000000041.0 2.0 3.4000000000000004 1.9600000000000012.0 4.0 6.800000000000001 7.8400000000000043.0 6.0 10.200000000000001 17.640000000000008MSE =9.14666666666667============================================================w =3.51.0 2.0 3.5 2.252.0 4.0 7.0 9.03.0 6.0 10.5 20.25MSE =10.5============================================================w =3.61.0 2.0 3.6 2.56000000000000052.0 4.0 7.2 10.2400000000000023.0 6.0 10.8 23.040000000000006MSE =11.94666666666667============================================================w =3.71.0 2.0 3.7 2.89000000000000062.0 4.0 7.4 11.5600000000000023.0 6.0 11.100000000000001 26.010000000000016MSE =13.486666666666673============================================================w =3.80000000000000031.0 2.0 3.8000000000000003 3.2400000000000012.0 4.0 7.6000000000000005 12.9600000000000043.0 6.0 11.4 29.160000000000004MSE =15.120000000000005============================================================w =3.90000000000000041.0 2.0 3.9000000000000004 3.6100000000000012.0 4.0 7.800000000000001 14.4400000000000053.0 6.0 11.700000000000001 32.49000000000001MSE =16.84666666666667============================================================w =4.01.0 2.0 4.0 4.02.0 4.0 8.0 16.03.0 6.0 12.0 36.0MSE =18.666666666666668============================================================
自动求导机制 # -*- coding: utf-8 -*-"""Created on Fri Oct 15 21:07:32 2021@author: 86493=0"""import torch# require_grad=True用来追踪计算历史x = torch.ones(2, 2, requires_grad = True)print(x)print('-' * 50)# 对张量作指数运算y = x ** 2print(y) # y是计算的结果,所以又grad_fn属性print(y.grad_fn)print('-' * 50)z = y * y * 3out = z.mean() # 计算所有元素的平均值print("z:", z)print("out:", out)print('-' * 50)# requires_grad默认为Falsea = torch.randn(2, 2)print("初始的a值为:\n", a)a = ((a * 3) / (a - 1))print("运算后的a值为:\n", a)print(a.requires_grad) # 默认为Falsea.requires_grad_(True)print(a.requires_grad)b = (a * a).sum()print(b.grad_fn) # b是计算的结果,所有它有grad_fn属性print('-' * 50)# ==================================# 求梯度out.backward() # out是一个标量print(x.grad) # 输入导数d(out)/dxprint('-' *50)# 再来反向传播,注意grad是累加的(加多一次梯度)# out2.backward()# print(x.grad)out3 = x.sum()# 一般在反向传播前把梯度清零(以防累加)x.grad.data.zero_() out3.backward()print(x.grad)print('-' *50)# 雅克比向量积x = torch.randn(3, requires_grad = True)print(x)y = x * 2i = 0 # norm是求该tensor的L2范数while y.data.norm() < 1000:y = y * 2i = i + 1print("y:\n", y, '\n')print("i:", i)v = torch.tensor([0.1, 1.0, 0.0001],dtype = torch.float)y.backward(v)print("x.grad:\n", x.grad)# 可以通过将代码块包装在with torch.no_grad()中# 来阻止autograd跟踪设置了requires_grad=Trueprint(x.requires_grad)print((x ** 2).requires_grad)with torch.no_grad():print((x ** 2).requires_grad)print('-' *50)# 想修改tensor的数值,又不希望被autograd记录# 即不会影响反向传播,可以对tensor.data操作x = torch.ones(1, requires_grad = True)print("x: ", x)print(x.data) # 还是一个tensor# 但是已经独立于计算图之外print(x.data.requires_grad)y = 2 * x# 只改变了值,不会记录在计算图,所以不会影响梯度传播x.data *= 100y.backward()# 更改data值也会影响tensor的值print(x)print(x.grad) 【2 pytorch基础【代码例子】】tensor([[1., 1.],[1., 1.]], requires_grad=True)--------------------------------------------------tensor([[1., 1.],[1., 1.]], grad_fn=)--------------------------------------------------z: tensor([[3., 3.],[3., 3.]], grad_fn=)out: tensor(3., grad_fn=)--------------------------------------------------初始的a值为: tensor([[-0.5364, -0.5926],[-0.5702, -0.7497]])运算后的a值为: tensor([[1.0474, 1.1163],[1.0894, 1.2855]])FalseTrueobject at 0x000001D745FEDF70>--------------------------------------------------tensor([[3., 3.],[3., 3.]])--------------------------------------------------tensor([[1., 1.],[1., 1.]])--------------------------------------------------tensor([ 0.4216,0.1233, -0.3729], requires_grad=True)y: tensor([ 863.4903,252.5478, -763.7181], grad_fn=) i: 10x.grad: tensor([2.0480e+02, 2.0480e+03, 2.0480e-01])TrueTrueFalse--------------------------------------------------x:tensor([1.], requires_grad=True)tensor([1.])Falserunfile('D:/桌面文件/matrix/code/Torch/grad.py', wdir='D:/桌面文件/matrix/code/Torch')tensor([[1., 1.],[1., 1.]], requires_grad=True)--------------------------------------------------tensor([[1., 1.],[1., 1.]], grad_fn=)--------------------------------------------------z: tensor([[3., 3.],[3., 3.]], grad_fn=)out: tensor(3., grad_fn=)--------------------------------------------------初始的a值为: tensor([[ 0.1064, -1.0084],[-0.2516, -0.4749]])运算后的a值为: tensor([[-0.3570,1.5063],[ 0.6030,0.9660]])FalseTrueobject at 0x000001D745593FD0>--------------------------------------------------tensor([[3., 3.],[3., 3.]])--------------------------------------------------tensor([[1., 1.],[1., 1.]])--------------------------------------------------tensor([-0.8706, -1.1828, -0.8192], requires_grad=True)y: tensor([ -891.5447, -1211.1826,-838.8481], grad_fn=) i: 9x.grad: tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])TrueTrueFalse--------------------------------------------------x:tensor([1.], requires_grad=True)tensor([1.])Falsetensor([100.], requires_grad=True)tensor([2.]) 梯度下降 损失函数:
cost=1N∑n=1N(yn^?yn)2cost=\frac{1}{N}\sum_{n=1}^{N}(\hat{y_n}-y_n)^2cost=N1?∑n=1N?(yn?^??yn?)2
w=w?α1N∑n=1n2Xn(xnw?yn)w=w-α\frac{1}{N}\sum_{n=1}^{n}2X_n(x_nw-y_n)w=w?αN1?∑n=1n?2Xn?(xn?w?yn?)
绘制loss图43 # -*- coding: utf-8 -*-"""Created on Sun Oct 17 14:42:34 2021@author: 86493"""import numpy as npimport matplotlib.pyplot as pltx_data = https://tazarkount.com/read/[1.0, 2.0, 3.0]y_data = [2.0, 4.0, 6.0]costlst = []w = 1.0# 向前传播def forward(x):return x * w# 损失函数def cost(allx, ally):cost = 0for x, y in zip(allx, ally):y_predict = forward(x)cost += (y_predict - y) ** 2return cost / len(allx)# 求梯度def gradient(allx, ally):grad = 0for x, y in zip(allx, ally):# 向前传播temp = forward(x)# 求梯度grad += 2 * x *(temp - y)return grad / len(allx)# trainfor epoch in range(100):# 求损失值cost_val = cost(x_data, y_data)costlst.append(cost_val)# 求梯度值grad_val = gradient(x_data, y_data)# 更新参数ww -= 0.01 *grad_valprint("Epoch: ", epoch, "w = ", w, "loss = ", cost_val)print("Predict(after training)", 4, forward(4))# 绘图plt.plot(range(100), costlst)plt.ylabel("Cost")plt.xlabel("Epoch")plt.show()
随机梯度下降SGD
SGD的优点:可能跨越鞍点 。
SGD:根据每一个样本的梯度来进行更新 。而以前是根据全部样本的梯度均值进行更新权重 。
# -*- coding: utf-8 -*-"""Created on Sun Oct 17 15:24:05 2021@author: 86493"""import numpy as npimport matplotlib.pyplot as pltx_data = https://tazarkount.com/read/[1.0, 2.0, 3.0]y_data = [2.0, 4.0, 6.0]lostlst = []w = 1.0# 向前传播def forward(x):return x * w# 损失函数def cost(allx, ally):cost = 0for x, y in zip(allx, ally):y_predict = forward(x)cost += (y_predict - y) ** 2return cost / len(allx)# 求单个lossdef loss(x, y):y_predict = forward(x)return (y_predict - y) ** 2"""# 求梯度def gradient(allx, ally):grad = 0for x, y in zip(allx, ally):# 向前传播temp = forward(x)# 求梯度grad += 2 * x *(temp - y)return grad / len(allx)"""# 求梯度def gradient(x, y):return 2 * x * (x * w - y)"""# trainfor epoch in range(100):# 求损失值cost_val = cost(x_data, y_data)costlst.append(cost_val)# 求梯度值grad_val = gradient(x_data, y_data)# 更新参数ww -= 0.01 *grad_valprint("Epoch: ", epoch, "w = ", w, "loss = ", cost_val)print("Predict(after training)", 4, forward(4))"""# SGD随机梯度下降for epoch in range(100):for x, y in zip(x_data, y_data):# 对每一个样本来求梯度,然后就进行更新grad = gradient(x, y)w -= 0.01 * gradprint("\tgrad: ", x, y, grad)l = loss(x, y)# print("l = ", l)print("progress: ", epoch, "w = ", w, "loss = ", l)print("Predict(after training)", 4, forward(4)) Epoch:0 w =1.0933333333333333 loss =4.666666666666667Epoch:1 w =1.1779555555555554 loss =3.8362074074074086Epoch:2 w =1.2546797037037036 loss =3.1535329869958857Epoch:3 w =1.3242429313580246 loss =2.592344272332262Epoch:4 w =1.3873135910979424 loss =2.1310222071581117Epoch:5 w =1.4444976559288012 loss =1.7517949663820642Epoch:6 w =1.4963445413754464 loss =1.440053319920117........................Epoch:93 w =1.9998999817997325 loss =5.678969725349543e-08Epoch:94 w =1.9999093168317574 loss =4.66836551287917e-08Epoch:95 w =1.9999177805941268 loss =3.8376039345125727e-08Epoch:96 w =1.9999254544053418 loss =3.154680994333735e-08Epoch:97 w =1.9999324119941766 loss =2.593287985380858e-08Epoch:98 w =1.9999387202080534 loss =2.131797981222471e-08Epoch:99 w =1.9999444396553017 loss =1.752432687141379e-08Predict(after training) 4 7.999777758621207 正向传递
反向传播
线性模型的计算图
# -*- coding: utf-8 -*-"""Created on Sun Oct 17 19:39:32 2021@author: 86493"""import torchx_data = https://tazarkount.com/read/[1.0, 2.0, 3.0]y_data = [2.0, 4.0, 6.0]w = torch.Tensor([1.0])w.requires_grad = True# 向前传递def forward(x):return x * w# 这里使用SGDdef loss(x, y):y_pred = forward(x)return (y_pred - y) ** 2print("predict (before training)", 4,forward(4).item())# 训练过程,SGDfor epoch in range(100):for x, y in zip(x_data, y_data):# 向前传播,计算lossl = loss(x, y)# 计算requires_grad为true的tensor的梯度l.backward()print('\tgrad:', x, y, w.grad.item())w.data = https://tazarkount.com/read/w.data - 0.01 * w.grad.data# 反向传播后grad会被重复计算,所以记得清零梯度w.grad.data.zero_()print("progress:", epoch, l.item())print("predict (after training)", 4,forward(4).item()) 注意:
(1)loss实际在构建计算图,每次运行完后计算图就释放了 。
(2)Tensor的Grad也是一个Tensor 。更新权重
w.data = https://tazarkount.com/read/w.data - 0.01 * w.grad.data的0.01乘那坨其实是在建立计算图,而我们这里要乘0.01 * grad.data,这样是不会建立计算图的(并不希望修改权重w,后面还有求梯度) 。
(3)w.grad.item()是直接把w.grad的数值取出,变成一个标量(也是为了防止产生计算图) 。总之,牢记权重更新过程中要使用data 。

(4)如果不像上面计算一个样本的loss,想算所有样本的loss(cost),
然后就加上sum += l,注意此时sum是关于张量lll 的一个计算图,又未对sum做backward操作,随着$l$越加越多会导致内存爆炸 。
正确做法:sum += l.item(),别把损失直接加到sum里面 。
Tensor在做加法运算时会构建计算图
5)backward后的梯度一定要记得清零w.grad.data.zero()

(6)训练过程:先计算loss损失值,然后backward反向传播,现在就有了梯度了 。通过梯度下降更新参数:

1.self.linear()是一个可调用对象(callable),类似下图有__call__成员函数 。

2.只要是要调用计算图,都需要继承module类 。
3.过程:求y;求loss;求backward;更新 。
import torchimport torch.nn as nn import matplotlib.pyplot as plt# x和y数据必须是矩阵,所以如[1.0]x_data = https://tazarkount.com/read/torch.Tensor([[1.0], [2.0], [3.0]])y_data = torch.Tensor([[2.0], [4.0], [6.0]])losslst = []class LinearModel(nn.Module):def __init__(self):super(LinearModel, self).__init__()# 实例化一个linear对象self.linear = nn.Linear(1, 1)def forward(self, x):# 可调用的对象,pythonicy_pred = self.linear(x)return y_predmodel = LinearModel()# 这里的MSE不除以N# criterion = torch.nn.MSELoss(size_average=False)criterion = torch.nn.MSELoss(reduction ='sum')optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)#model.parameters()为该实例中可优化的参数,lr为参数优化的选项(学习率等)# 训练for epoch in range(100):y_pred = model(x_data)loss = criterion(y_pred, y_data)# 打印loss对象会自动调用__str__(),不会产生计算图print(epoch, loss.item())losslst.append(loss.item())optimizer.zero_grad()# 梯度归零后反向传播loss.backward()optimizer.step()# 画图plt.plot(range(100), losslst)plt.ylabel('Loss')plt.xlabel('epoch')plt.show()# 输出weight和bias# 不用item也行,但就是矩阵[[]] print('w = ', model.linear.weight.item())print('b = ', model.linear.bias.item())print('-' *60)# Test model# 输入是1×1矩阵,输出也是1×1矩阵x_test = torch.Tensor([[4.0]]) y_test = model(x_test)print('y_pred = ', y_test.data) >>> m = nn.Linear(20, 30)>>> input = torch.randn(128, 20)>>> output = m(input)>>> print(output.size())torch.Size([128, 30])