相关知识:
- 均方损失函数:
这里 loss, x, y 的维度是一样的,可以是向量或者矩阵,i 是下标。
很多的 loss 函数都有 size_average 和 reduce 两个布尔类型的参数。因为一般损失函数都是直接计算 batch 的数据,因此返回的 loss 结果都是维度为 (batch_size, ) 的向量。
(1)如果 reduce = False,那么 size_average 参数失效,直接返回向量形式的 loss
(2)如果 reduce = True,那么 loss 返回的是标量
a)如果 size_average = True,返回 loss.mean();
b)如果 size_average = False,返回 loss.sum();
注意:默认情况下, reduce = True,size_average = True
- pytorch中model.modules()和model.children()的区别
model.modules()和model.children()均为迭代器,对于模型
model = torch.nn.Sequential( torch.nn.Linear(1, 5),
torch.nn.Tanh(),
torch.nn.Linear(5, 1),
)
输出对比如下:
print(list(model.modules()))print(list(model.children()))
modules()函数:
[Sequential(
(0): Linear(in_features=1, out_features=5, bias=True)
(1): Tanh()
(2): Linear(in_features=5, out_features=1, bias=True)
), Linear(in_features=1, out_features=5, bias=True), Tanh(), Linear(in_features=5, out_features=1, bias=True)]
children()函数:
[Linear(in_features=1, out_features=5, bias=True), Tanh(), Linear(in_features=5, out_features=1, bias=True)]
- python操作符@
python 3.5以后,@是一个操作符,表示矩阵-向量乘法
- torch.t()
torch的矩阵转置函数,例如 2*3 -> 3*2
import torch
import matplotlib.pyplot as plt
w = 2
b = 1
noise = torch.rand(100, 1)
# 因为输入层格式要为(-1, 1),所以这里将(100)的格式转成(100, 1)
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
# 拟合分布在y=2x+1上并且带有噪声的散点
y = w*x + b + noise
#自定义的网络,带有2个全连接层和一个tanh层
model = torch.nn.Sequential(
torch.nn.Linear(1, 5),
torch.nn.Tanh(),
torch.nn.Linear(5, 1),
)
# 定义损失函数为均方差
loss_fun = torch.nn.MSELoss()
# 使用adam作为优化器更新网络模型的权重,学习率为0.001
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 开启图形交互
plt.ion()
for _ in range(10000):
ax = plt.axes()
# 前向传播
output = model(x)
# 数据向后传播(经过网络层的一次计算)
loss = loss_fun(output, y)
# 计算损失值
#print("before zero_grad:{}".format(list(model.children())[0].weight.grad))
#print("-"*100)
# 优化器清空梯度
# 通过注释地方可以对比发现执行zero_grad方法以后倒数梯度将会被清0
# 如果不清空梯度的话,则会不断累加梯度,从而影响到当前梯度的计算
model.zero_grad()
#print("after zero_grad:{}".format(list(model.children())[0].weight.grad))
#print("-"*100)
# 向后传播,计算当前梯度,如果这步不执行,那么优化器更新时则会找不到梯度
loss.backward()
#通过比较会发现,经过backward得到的梯度跟执行model.zero_grad()之前的梯度是一致的
#print("after backward:{}".format(list(model.children())[0].weight.grad))
#print("-" * 100)
# 优化器更新梯度参数,如果这步不执行,那么因为梯度没有发生改变,loss会一直计算最开始的那个梯度
optimizer.step()
if _ % 100 == 0:
#清屏
plt.cla()
#画点
plt.scatter(x.data.numpy(), y.data.numpy())
#画线
plt.plot(x.data.numpy(), output.data.numpy(), 'b-', lw=2)
#写文本
plt.text(0.60, -0.5, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 10, 'color': 'red'})
plt.pause(0.1)
#t()函数是torch的矩阵转置函数,
#python 3.5以后,@是一个操作符,表示矩阵-向量乘法, 好骚的操作
print("w:", list(model.children())[0].weight.t() @ list(model.children())[-1].weight.t())
# 通过这句可以查看权值变化,可以发现最后收敛到2附近
#关闭图形交互
plt.ioff()