由于我还没有学习过python,所以会很基础的理解 ,首先大概了解有关的知识
相关学习代码的链接:
https://zhuanlan.zhihu.com/p/39191116
学习笔记:
具体代码解释:
导入模块:
import torch
import torch.nn as nn
使用pytorch搭建神经网络的时候,有两个最常用的包:torch.nn和torch.optim。
torch.nn包中主要包含了用来搭建各个层的模块(Modules),比如全连接、二维卷积、池化等;torch.nn包中还包含了一系列有用的loss函数,比如CrossEntropyLoss、MSELoss等;另外,torch.nn.functional子包中包含了常用的激活函数,如relu、leaky_relu、prelu、sigmoid等。
torch.optim包则主要包含了用来更新参数的优化算法,比如SGD、AdaGrad、RMSProp、 Adam等。
python语句:import as 后续对torch.optim的引用可以直接使用optim,但是需要注意使用as语法之后,只能通过as后面的名字来访问导入的moudle
定义数据维度:
# 定义输入数据维度和超参数
input_size = 10
hidden_size = 20
num_layers = 2
output_size = 1
- input_size – 输入数据的大小,也就是前面例子中每个单词向量的长度(输入特征的维数)
- hidden_size – 隐藏层的大小(即隐藏层节点数量),输出向量的维度等于隐藏节点数(每个LSTM单元或者时间步的输出的ht的维度,单元内部有权重与偏差计算)
- num_layers – recurrent layer的数量,默认等于1(构建多层的LSTM进行堆叠)
- bias – If False, then the layer does not use bias weights b_ih and b_hh. Default: True
- batch_first – 默认为False,也就是说官方不推荐我们把batch放在第一维,这个与常见的CNN输入有点不同,此时输入输出的各个维度含义为 (seq_length,batch,feature)。当然如果你想和CNN一样把batch放在第一维,可将该参数设置为True,即 (batch,seq_length,feature),习惯上将batch_first 设置为True。
- dropout – 如果非0,就在除了最后一层的其它层都插入Dropout层,默认为0。
- bidirectional – 如果设置为 True, 则表示双向 LSTM,默认为 False
- output:output保存了最后一层,每个time step的输出h,如果是双向LSTM,每个time step的输出h = [h正向, h逆向] (同一个time step的正向和逆向的h连接起来)。
- output是一个三维的张量,第一维表示序列长度,第二维表示一批的样本数(batch),第三维是 hidden_size(隐藏层大小) * num_directions ,num_directions根据是“否为双向”取值为1或2。因此,output第三个维度的尺寸根据是否为双向而变化,如果不是双向,第三个维度等于我们定义的隐藏层大小;如果是双向的,第三个维度的大小等于2倍的隐藏层大小。为什么使用2倍的隐藏层大小?因为它把每个time step的前向和后向的输出连接起来了
- learning_rate:控制 模型的学习进度
- epoch: 所有的数据送入网络中, 完成了一次前向计算 + 反向传播的过程
创建模型:
# 创建模型实例
model = LSTMModel(input_size, hidden_size, num_layers, output_size)
定义多层LSTM:
# 定义多层LSTM模型
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# 创建LSTM层和linear层,LSTM层提取特征,linear层用作最后的预测
# LSTM算法接受三个输入:先前的隐藏状态,先前的单元状态和当前输入。
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
# forward函数的任务需要把输入层、网络层、输出层链接起来,实现信息的前向传导。
# forward该函数的参数一般为输入数据,返回值是输出数据。
def forward(self, x):
#lstm的输出是当前时间步的隐藏状态ht和单元状态ct以及输出lstm_out
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[:, -1, :])
return out
nn.Module 是 PyTorch 体系下所有神经网络模块的基类
nn.Moudle的实现:
__init__ 函数:
在 nn.Module 的 __init__
函数中,会首先被调用。super().__init__()
。只有这样才能正确地初始化自定义的神经网络模块,否则会缺少上面代码中的成员变量而导致模块被调用时出错。实际上,如果没有提前调用 super().__init__()
,在增加模块的 parameter 或者 buffer 的时候,被调用的 __setattr__
函数也会检查出父类 nn.Module 没被正确地初始化并报错。
self.training = True # 控制 training/testing 状态
self._parameters = OrderedDict() # 在训练过程中会随着 BP 而更新的参数
self._buffers = OrderedDict() # 在训练过程中不会随着 BP 而更新的参数
self._non_persistent_buffers_set = set()
self._backward_hooks = OrderedDict() # Backward 完成后会被调用的 hook
self._forward_hooks = OrderedDict() # Forward 完成后会被调用的 hook
self._forward_pre_hooks = OrderedDict() # Forward 前会被调用的 hook
self._state_dict_hooks = OrderedDict() # 得到 state_dict 以后会被调用的 hook
self._load_state_dict_pre_hooks = OrderedDict() # load state_dict 前会被调用的 hook
self._modules = OrderedDict() # 子神经网络模块
torch.zeros()函数
返回一个形状为为size,类型为torch.dtype,里面的每一个值都是0的tensor
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
参数说明
size: 定义tensor的shape ,这里可以是一个list 也可以是一个tuple
dtype:(可选)我不设置值 默认值就是torch.set_default_tensor_type制定的值,如果需要设置那就是torch.dtype的那几个。作用是指定返回tensor的数据类型
layout:(可选)值为 torch.layout。 torch.layout表示torch.Tensor内存布局的对象。有torch.strided(dense Tensors 默认)并为torch.sparse_coo(sparse COO Tensors)提供实验支持。
torch.strided代表密集张量,是最常用的内存布局。每个strided张量都会关联 一个torch.Storage,它保存着它的数据。这些张力提供了多维度, 存储的strided视图。Strides是一个整数型列表:k-th stride表示在张量的第k维从一个元素跳转到下一个元素所需的内存。关于这里的理解请看demo2
device:(可选)就是创建的tensor存放的device
requires_grad: (可选)是bool 类型的值,默认值是False
定义输入数据:
# 定义输入数据
batch_size = 16
sequence_length = 5
input_data = torch.randn(batch_size, sequence_length, input_size)
前向传播输出:
# 前向传播计算输出
output = model(input_data)
打印输出结果的形状 :
# 打印输出结果的形状
print(output.shape)
代码:
import torch
import torch.nn as nn
# 定义多层LSTM模型
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[:, -1, :])
return out
# 定义输入数据维度和超参数
input_size = 10
hidden_size = 20
num_layers = 2
output_size = 1
# 创建模型实例
model = LSTMModel(input_size, hidden_size, num_layers, output_size)
# 定义输入数据
batch_size = 16
sequence_length = 5
input_data = torch.randn(batch_size, sequence_length, input_size)
# 前向传播计算输出
output = model(input_data)
# 打印输出结果的形状
print(output.shape)