Skip to content

Latest commit

 

History

History
104 lines (73 loc) · 4.11 KB

12_循环神经网络.md

File metadata and controls

104 lines (73 loc) · 4.11 KB

循环神经网络

代码示例1

代码功能:使用RNNCell和RNN学习 hello ==> ohlol

  • 使用RNNCell
    • 注意RNNCell一次只能处理一个序列中的一个字符。
    • labels 的 shape 是 (seqLen, 1)
    • 注意在一个数据集中,各个数据的输入序列长度可能是不一样的。此时需要做填充。

  • 使用RNN
    • labels 的 shape 是 (seqLen*batchSize, 1),这里最好也 view 成 (-1, 1)

image-20200821205329255

代码示例2

代码功能:实现一个增加了 embedding 层的RNN

  • 这里一定要注意 x_data 和 y_data 的维数!
import torch

####################### Part1. Prepare Dataset #######################

dictionary = ['e', 'h', 'l', 'o']
# 注意这里并没有真的用one-hot向量来表示
x_data = [[1, 0, 2, 2, 3]]  # hello
y_data = [3, 1, 2, 3, 2]  # ohlol

inputs = torch.LongTensor(x_data)
labels = torch.LongTensor(y_data)

num_class = len(dictionary)  # 字典的长度
inputs_size = num_class  # 输入的维数,不是batch_size
hidden_size = 8  # 隐藏层的维数
embedding_size = 10  # embedding向量的维数,即将one-hot压缩(扩大)至几维
num_layers = 2  # RNN的层数
batch_size = 1  # batch_size,这里只有1组数据,所以取1
seq_len = len(x_data)  # 输入序列的长度,如果各数据输入序列长度不同,则取最大值

print(inputs.size()) # torch.Size([1, 5]),即[batchSize, seqLen]
print(labels.size()) # torch.Size([5]),即[batchSize * seqLen]


####################### Part2. Design Model #######################

class MyModule(torch.nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.emb = torch.nn.Embedding(inputs_size, embedding_size)
        self.rnn = torch.nn.RNN(input_size=embedding_size,
                                hidden_size=hidden_size,
                                num_layers=num_layers,
                                batch_first=True)
        self.fc = torch.nn.Linear(hidden_size, num_class)

    def forward(self, x):
        # hidden的形状为(num_layers * num_directions, batchSize, hidden_size)
        # hidden其实就是每个元素对应的记忆细胞,所以是每组数据都要有自己的,不能共用别人的
        hidden = torch.zeros(num_layers, x.size(0), hidden_size)
        x = self.emb(x)  # 输入值形状为(batchSize, seqLen), 输出值形状为(batchSize, seqLen, embeddingSize)
        x, _ = self.rnn(x, hidden)  # 输出值形状为(batchSize, seqLen, hiddenSize)
        							# 注意这里的返回值是(output, h_n),详情参考官方文档
        x = self.fc(x)  # 输出值形状为(batchSize, seqLen, numClass)
        return x.view(-1, num_class)  # reshape是为了维度和labels匹配,然后使用CrossEntropy损失函数


model = MyModule()

####################### Part3. Construct Loss and Optimizer #######################

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

####################### Part4. Train and Test #######################

for epoch in range(15):
    y_pred = model(inputs)
    loss = criterion(y_pred, labels)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 返回输入张量给定维度上每行的最大值,并同时返回每个最大值的位置索引
    _, index = y_pred.max(dim=1)
    index = index.data.numpy()
    print("Predicted:", "".join([dictionary[x] for x in index]), end="")
    print(", Epoch [%d/15] loss = %.3f" % (epoch + 1, loss.item()))