08 Rnn Basics
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')one-hot向量
用到了scatter_函数
def one_hot(x, n_class, dtype=torch.float32):
result = torch.zeros(x.shape[0], n_class, dtype=dtype, device=x.device) # shape: (n, n_class)
result.scatter_(1, x.long().view(-1, 1), 1) # result[i, x[i, 0]] = 1
return result
x = torch.tensor([0, 2])
x_one_hot = one_hot(x, vocab_size)
print(x_one_hot)
print(x_one_hot.shape)
print(x_one_hot.sum(axis=1))
tensor([[1., 0., 0., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.]])
torch.Size([2, 1027])
tensor([1., 1.])scatter_(input, dim, index, src)将src中数据根据index中的索引按照dim的方向填进input中。
参考:https://blog.csdn.net/qq_16234613/article/details/79827006
初始化模型参数
裁剪梯度
预测函数
给定输入prefix,预测接下来的num_chars个字符。
首先初始化隐藏状态state为一个(1, num_hiddens)的零向量,假设输入的prefix是“分开”两个字符,num_chars是10,即预测接下来的10个字符。首先output列表的初始值设为“分开”的第一个字符“分”对应的index,将这个index转化为one_hot向量,作为输入X,通过rnn,得到Y和隐藏状态。这里的X是前一个字符,Y是预测X的后一个字符。所以当t小于输入字符的长度时,Y就是X的真实下一个字符。即“分”的下一个字符是“开”,但是“开”的下一个字符呢?不知道,需要通过rnn预测得到。
这个过程无法并行。因为只有通过X得到预测的Y,才能有下一步的输入X。
最后将所有的Y转化为字符输出即可。
当我们再训练网络的时候可能希望保持一部分的网络参数不变,只对其中一部分的参数进行调整;或者值训练部分分支网络,并不让其梯度对主网络的梯度造成影响,这时候我们就需要使用detach()函数来切断一些分支的反向传播
detach():
返回一个新的Variable,从当前计算图中分离下来的,但是仍指向原变量的存放位置,不同之处只是requires_grad为false,得到的这个Variable永远不需要计算其梯度,不具有grad。 即使之后重新将它的requires_grad置为true,它也不会具有梯度grad .这样我们就会继续使用这个新的Variable进行计算,后面当我们进行反向传播时,到该调用detach()的Variable就会停止,不能再继续向前进行传播
detach_()
将一个Variable从创建它的图中分离,并把它设置成叶子variable .其实就相当于变量之间的关系本来是x -> m -> y,这里的叶子variable是x,但是这个时候对m进行了.detach_()操作,其实就是进行了两个操作:
1.将m的grad_fn的值设置为None,这样m就不会再与前一个节点x关联,这里的关系就会变成x, m -> y,此时的m就变成了叶子结点。
2.然后会将m的requires_grad设置为False,这样对y进行backward()时就不会求m的梯度。
其实detach()和detach_()很像,两个的区别就是detach_()是对本身的更改,detach()则是生成了一个新的variable 。比如x -> m -> y中如果对m进行detach(),后面如果反悔想还是对原来的计算图进行操作还是可以的 。但是如果是进行了detach_(),那么原来的计算图也发生了变化,就不能反悔了。
参考https://www.cnblogs.com/wanghui-garcia/p/10677071.html;参考:https://pytorch-cn.readthedocs.io/zh/latest/package_references/torch-autograd/#detachsource。
困惑度
我们通常使用困惑度(perplexity)来评价语言模型的好坏。回忆一下“softmax回归”一节中交叉熵损失函数的定义。困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,
最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。
显然,任何一个有效模型的困惑度必须小于类别个数。在本例中,困惑度必须小于词典大小vocab_size。
Last updated
Was this helpful?