varaible
- 在module中流动的数据类型全部都是Varaible。
- Varaible的常见属性和变量有:data(包含保存的tensor)、grad(包含当前Varaible对应相应的Function的梯度)、requires_grad(bool值)、volatile(bool值,代表当前Varaible是否为推断模式)、creator(创建这个varaible的Fuction)
parameters
- Parameters是Variable的子类。
- Parameters 与 modules 一起使用时会有一些特殊的属性,其会被自动加到 Module 的parameters() 迭代器中,Variable 赋值给 modules 不会产生这样的效果。
- 用法很简单:
torch.nn.Parameter(data, requires_grad)
module
- nn.Module是nn中十分重要的类,相当于一个容器,包含网络各层的定义及forward方法。
- 定义自已的网络,需要继承nn.Module类,并实现forward方法。
- 定义自已的网络,一般把网络中具有可学习参数的层放在构造函数__init__()中,不具有可学习参数的层(如ReLU)可放在构造函数中,也可不放在构造函数中(而在forward中使用nn.functional来代替)。
- 只要在nn.Module的子类中定义了forward函数,调用backward函数时,就会自动计算forward函数里面的varaible的梯度。
- 在forward函数中可以使用任何Variable支持的函数,毕竟在整个pytorch构建的图中,是Variable在流动。
- Modules也可以包括其他Modules,运行使用树结构来嵌入,可以将子模块作为根模型的属性,这样子模型的parameters就会自动加入根模型的parameters,方便整个网络的参数的更新。从下列看出,self.conv1 , self.conv2 是模型的子模型:
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module): def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5)# submodule: Conv2d
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
关于module的其他详细信息可以参考如下网站:
https://pytorch.org/docs/stable/nn.html#module
https://zhuanlan.zhihu.com/p/34616199
https://blog.csdn.net/u012609509/article/details/81203436
forward
- 该方法是用户自定义module里面可以选择重写的方法。
- 重写的内容往往是对于输入的参数进行一些运算,然后返回运算的结果。
- 如果该运算的结果是标量,那么可以调用backward函数来计算该运算里面所有varaible的梯度,以便后续optim的参数更新。
- 常见用法如下:
class NegativeSamplingLoss(nn.Module):
def __init__(self):
super().__init__()
def forward(self, input_vectors, output_vectors, noise_vectors):
# print("----------------input_vectors.shape-------------------")
# print(input_vectors.shape)
BATCH_SIZE, embed_size = input_vectors.shape
# 将输入词向量与目标词向量作维度转化处理
input_vectors = input_vectors.view(BATCH_SIZE, embed_size, 1)
output_vectors = output_vectors.view(BATCH_SIZE, 1, embed_size)
# 目标词损失
out_loss = torch.bmm(output_vectors, input_vectors).sigmoid().log() # (B,1,1)
out_loss = out_loss.squeeze() # 降维为 B
# 负样本损失 noise_vectors.size = (BATCH_SIZE, N_SAMPLES, embed_size)
noise_loss = torch.bmm(noise_vectors.neg(), input_vectors).sigmoid().log() # (B,N_SAMPLES,1)
# print("----------------noise_loss-------------------")
# print(noise_loss)
if BATCH_SIZE != 1: # 因为当中心词到达左右两侧时,当windows_size为2时,会出现(B,N_SAMPLES,1)重的B = 1的情况,那么下面的语句会报错
noise_loss = noise_loss.squeeze().sum(1) # 多个负样本,所以要加和
# 综合计算两类损失
return -(out_loss + noise_loss).mean()
#初始化
criterion = NegativeSamplingLoss()
# 计算损失
loss = criterion(input_vectors, output_vectors, noise_vectors)
loss.backward() # 回传
optimizer.step() # 更新参数
backward
- 该函数往往对应forward函数的运算结果。
- 通过forward函数运算结果得到的标量来调用backward,可以更新该运算的相关叶子结点varaible。
关于module的其他详细信息可以参考如下网站:
https://blog.csdn.net/douhaoexia/article/details/78821428
optim
- nn内含有许多optimizer,例如SGD、Adam,每个optimizer都有自己相应的应用常见,具体可以google。
- optimizer传入的参数主要有parameters、learningRate、momentum。
- optimizer更新的原理是,根据传入parameters的grad,结合learningRate和momentum来往梯度下降的方向更新所有的parameters。
- 简单使用如下:
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()