RNN BPTT(through time)
rnn网络结构
t时刻的输出受到t时刻前每一时刻w参数的影响
重要步骤 维度变化
x的维度[10,3,100] 表示一句话10个单词,一共3句话(3个batch),每个单词用100维的向量表示。
xt的维度[3,100]表示从时间维度输入x,也就是我们理解的一个单词一个单词的输入,符合我们日常的交流习惯。3表示同时输入三句话的第一个(t时刻的这一个),100表示一个单词由100维的向量表示。
nn.RNN中第一个是单词表示的维度100,第二个是memory的维度10。
时间戳
上图完美的展示了rnn输出ht与out的关系
out是所有时刻rnn最后一个状态层的输出,所以和rnn的层数没有关系。shape=[一个句子的单词个数,句子数(batch size),状态的维数 ]。理解为:方向是横向
ht是最后一个时刻的所有状态的输出,所以和rnn的层数有关,shape=[层数,句子数(batch size),状态的维数]
#不同层数对out和h维度的影响
rnn = nn.RNN(input_size=100, hidden_size=20, num_layers=1)
print(rnn)
x = torch.randn(10,3,100)
out, h = rnn(x)
print(out.shape, h.shape)
rnn = nn.RNN(input_size=100, hidden_size=20, num_layers=2)
print(rnn)
x = torch.randn(10,3,100)
out, h = rnn(x)
print(out.shape, h.shape)
x = torch.randn(10,3,100)
cell1 = nn.RNNCell(100,20)
h1 = torch.zeros(3,20)
for xt in x:
print(xt.shape)
h1 = cell1(xt,h1)
print(h1.shape)
下面是rnn预测的例子
input_size = 1
hidden_size = 10
output_size = 1
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.rnn = nn.RNN(
input_size=input_size,
hidden_size=hidden_size,
num_layers=3,
batch_first=True,
)
self.linear = nn.Linear(hidden_size, output_size)
def forward(self, x, hidden_prev):
out, hidden_prev = self.rnn(x, hidden_prev)
# out[1, seq, h]
out = out.view(-1, hidden_size)
out = self.linear(out)
out = out.unsqueeze(dim=0)
return out, hidden_prev
lr = 1e-4
model = Net()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr)
hidden_prev = torch.zeros(3, 1, hidden_size) # [b,1,10]
num_time_steps = 50
start = np.random.randint(3, size=1)[0]
time_steps = np.linspace(start, start + 10, num_time_steps)
data = np.tan(time_steps)
data = data.reshape(num_time_steps, 1)
x = torch.tensor(data[:-1]).float().view(1, num_time_steps - 1, 1)
y = torch.tensor(data[1:]).float().view(1, num_time_steps - 1, 1)
for iter in range(10000):
output, hidden_prev = model(x, hidden_prev)
hidden_prev = hidden_prev.detach()
loss = criterion(output, y)
model.zero_grad()
loss.backward()
optimizer.step()
if iter % 1000 == 0:
print('iteration{0} loss{1}'.format(iter, loss.item()))
prediction = []
input = x[:, 0, :]
for i in range(x.shape[1]):
input = input.view(1, 1, 1)
(pred, hidden_prev) = model(input, hidden_prev)
input = pred
prediction.append(pred.detach().numpy().ravel()[0])
x = x.data.numpy().ravel()
y = y.data.numpy()
plt.scatter(time_steps[:-1], x.ravel(), s=90)
plt.plot(time_steps[:-1], x.ravel())
plt.scatter(time_steps[1:], prediction)
plt.show()
这里训练的目标是:给t0到t48时刻的输入,输出t1到t49时刻的输出。
转化成代码语言就是,train的数据为f(t0),label就是f(t1),train的数据是f(t1),label就是f(t2),以此类推。‘
最后预测的流程是,给定模型一个t0时刻数据,让他自动输出t1到t48的输出。