视频链接
- [从零开始实现]www.bilibili.com/video/BV1kq…
- [简洁实现]www.bilibili.com/video/BV1kq…
- [QA]www.bilibili.com/video/BV1kq…
注解
一、 为什么要做X.T?
05:10
原本数据的形状是(batch_size, num_step),其中的batch_size是指一个批量的大小、num_step是指一个样本的序列长度,即一个样本中取多少个tokens;
做了X.T转置后,数据的形状变成了(num_step, batch_size),进行独热编码后,形状变成了(num_step, batch_size, 特征长度),将num_step所在轴定为时间轴,如上图例子,即:,则后两维即可代表在该时刻下的,便于后续for loop的迭代(for loop默认迭代第一维的数据)
二、为什么要初始化隐藏状态?
10:41 在初始时刻我们的隐藏状态是不存在的
即初始化第一个隐变量,这里将隐藏状态放在一个元组里,便于后续的LSTM加入新的状态
三、outputs的形状是什么?
16:46
outputs列表里的每一个元素的形状为(batch_size, 特征长度),这里按照第0维进行拼接,最后返回值的形状就是(batch_size * num_step, 特征长度)
四、为什么这里不care输出?
27:44
因为prefix中的tokens是已知的,做这个循环的目的只是通过prefix中的数据计算出相应的隐藏状态state
五、为什么要用argmax()方法?
29:14
因为这里的y是一个(1, 特征长度)的向量,因此我们将其为1的那个维度的下标取出来,放进词表中转换成对应的token
六、为什么use_random_iter时,每次迭代都要初始化状态
35:47
因为当使用use_random_iter时,我们每次选取的序列之间没有时序关系,因此每次都要初始化隐藏状态;反过来讲,但不使用use_random_iter时(同时当前不是第一次迭代时),我们不需要初始化隐藏状态,这时我们只需要取上次迭代中最后一个隐藏状态来作为这次迭代的初始隐藏状态