p2p网站制作流程,flash美食网站论文,安徽网站推广系统,婚庆门户源码v2.0 婚庆公司网站源码 婚庆网源码 婚庆门户网源码注#xff1a;本文为《动手学深度学习》开源内容#xff0c;部分标注了个人理解#xff0c;仅为个人学习记录#xff0c;无抄袭搬运意图 6.3 语言模型数据集#xff08;周杰伦专辑歌词#xff09;
本节将介绍如何预处理一个语言模型数据集#xff0c;并将其转换成字符级… 注本文为《动手学深度学习》开源内容部分标注了个人理解仅为个人学习记录无抄袭搬运意图 6.3 语言模型数据集周杰伦专辑歌词
本节将介绍如何预处理一个语言模型数据集并将其转换成字符级循环神经网络所需要的输入格式。为此我们收集了周杰伦从第一张专辑《Jay》到第十张专辑《跨时代》中的歌词并在后面几节里应用循环神经网络来训练一个语言模型。当模型训练好后我们就可以用这个模型来创作歌词。
6.3.1 读取数据集
首先读取这个数据集看看前40个字符是什么样的。
import torch
import random
import zipfilewith zipfile.ZipFile(../../data/jaychou_lyrics.txt.zip) as zin:with zin.open(jaychou_lyrics.txt) as f:corpus_chars f.read().decode(utf-8)
corpus_chars[:40]输出
想要有直升机\n想要和你飞到宇宙去\n想要和你融化在一起\n融化在宇宙里\n我每天每天每这个数据集有6万多个字符。为了打印方便我们把换行符替换成空格然后仅使用前1万个字符来训练模型。
corpus_chars corpus_chars.replace(\n, ).replace(\r, )
corpus_chars corpus_chars[0:10000]6.3.2 建立字符索引
我们将每个字符映射成一个从0开始的连续整数又称索引来方便之后的数据处理。为了得到索引我们将数据集里所有不同字符取出来然后将其逐一映射到索引来构造词典。接着打印vocab_size即词典中不同字符的个数又称词典大小。
idx_to_char list(set(corpus_chars))
char_to_idx dict([(char, i) for i, char in enumerate(idx_to_char)])
vocab_size len(char_to_idx)
vocab_size # 1027之后将训练数据集中每个字符转化为索引并打印前20个字符及其对应的索引。
corpus_indices [char_to_idx[char] for char in corpus_chars]
sample corpus_indices[:20]
print(chars:, .join([idx_to_char[idx] for idx in sample]))
print(indices:, sample)输出
chars: 想要有直升机 想要和你飞到宇宙去 想要和
indices: [250, 164, 576, 421, 674, 653, 357, 250, 164, 850, 217, 910, 1012, 261, 275, 366, 357, 250, 164, 850]我们将以上代码封装在d2lzh_pytorch包里的load_data_jay_lyrics函数中以方便后面章节调用。调用该函数后会依次得到corpus_indices、char_to_idx、idx_to_char和vocab_size这4个变量。
6.3.3 时序数据的采样
在训练中我们需要每次随机读取小批量样本和标签。与之前章节的实验数据不同的是时序数据的一个样本通常包含连续的字符。假设时间步数为5样本序列为5个字符即“想”“要”“有”“直”“升”。该样本的标签序列为这些字符分别在训练集中的下一个字符即“要”“有”“直”“升”“机”。我们有两种方式对时序数据进行采样分别是随机采样和相邻采样。
6.3.3.1 随机采样
下面的代码每次从数据里随机采样一个小批量。其中批量大小batch_size指每个小批量的样本数num_steps为每个样本所包含的时间步数。 在随机采样中每个样本是原始序列上任意截取的一段序列。相邻的两个随机小批量在原始序列上的位置不一定相毗邻。因此我们无法用一个小批量最终时间步的隐藏状态来初始化下一个小批量的隐藏状态。在训练模型时每次随机采样前都需要重新初始化隐藏状态。
# 本函数已保存在d2lzh_pytorch包中方便以后使用
def data_iter_random(corpus_indices, batch_size, num_steps, deviceNone):# 减1是因为输出的索引x是相应输入的索引y加1num_examples (len(corpus_indices) - 1) // num_stepsepoch_size num_examples // batch_sizeexample_indices list(range(num_examples))random.shuffle(example_indices)# 返回从pos开始的长为num_steps的序列def _data(pos):return corpus_indices[pos: pos num_steps]if device is None:device torch.device(cuda if torch.cuda.is_available() else cpu)for i in range(epoch_size):# 每次读取batch_size个随机样本i i * batch_sizebatch_indices example_indices[i: i batch_size]X [_data(j * num_steps) for j in batch_indices]Y [_data(j * num_steps 1) for j in batch_indices]yield torch.tensor(X, dtypetorch.float32, devicedevice), torch.tensor(Y, dtypetorch.float32, devicedevice)让我们输入一个从0到29的连续整数的人工序列。设批量大小和时间步数分别为2和6。打印随机采样每次读取的小批量样本的输入X和标签Y。可见相邻的两个随机小批量在原始序列上的位置不一定相毗邻。
my_seq list(range(30))
for X, Y in data_iter_random(my_seq, batch_size2, num_steps6):print(X: , X, \nY:, Y, \n)输出
X: tensor([[18., 19., 20., 21., 22., 23.],[12., 13., 14., 15., 16., 17.]])
Y: tensor([[19., 20., 21., 22., 23., 24.],[13., 14., 15., 16., 17., 18.]]) X: tensor([[ 0., 1., 2., 3., 4., 5.],[ 6., 7., 8., 9., 10., 11.]])
Y: tensor([[ 1., 2., 3., 4., 5., 6.],[ 7., 8., 9., 10., 11., 12.]]) 6.3.3.2 相邻采样
除对原始序列做随机采样之外我们还可以令相邻的两个随机小批量在原始序列上的位置相毗邻。这时候我们就可以用一个小批量最终时间步的隐藏状态来初始化下一个小批量的隐藏状态从而使下一个小批量的输出也取决于当前小批量的输入并如此循环下去。这对实现循环神经网络造成了两方面影响一方面 在训练模型时我们只需在每一个迭代周期开始时初始化隐藏状态另一方面当多个相邻小批量通过传递隐藏状态串联起来时模型参数的梯度计算将依赖所有串联起来的小批量序列。同一迭代周期中随着迭代次数的增加梯度的计算开销会越来越大。 为了使模型参数的梯度计算只依赖一次迭代读取的小批量序列我们可以在每次读取小批量前将隐藏状态从计算图中分离出来。我们将在下一节循环神经网络的从零开始实现的实现中了解这种处理方式。
# 本函数已保存在d2lzh_pytorch包中方便以后使用
def data_iter_consecutive(corpus_indices, batch_size, num_steps, deviceNone):if device is None:device torch.device(cuda if torch.cuda.is_available() else cpu)corpus_indices torch.tensor(corpus_indices, dtypetorch.float32, devicedevice)data_len len(corpus_indices)batch_len data_len // batch_sizeindices corpus_indices[0: batch_size*batch_len].view(batch_size, batch_len)epoch_size (batch_len - 1) // num_stepsfor i in range(epoch_size):i i * num_stepsX indices[:, i: i num_steps]Y indices[:, i 1: i num_steps 1]yield X, Y同样的设置下打印相邻采样每次读取的小批量样本的输入X和标签Y。相邻的两个随机小批量在原始序列上的位置相毗邻。
for X, Y in data_iter_consecutive(my_seq, batch_size2, num_steps6):print(X: , X, \nY:, Y, \n)输出
X: tensor([[ 0., 1., 2., 3., 4., 5.],[15., 16., 17., 18., 19., 20.]])
Y: tensor([[ 1., 2., 3., 4., 5., 6.],[16., 17., 18., 19., 20., 21.]]) X: tensor([[ 6., 7., 8., 9., 10., 11.],[21., 22., 23., 24., 25., 26.]])
Y: tensor([[ 7., 8., 9., 10., 11., 12.],[22., 23., 24., 25., 26., 27.]]) 小结
时序数据采样方式包括随机采样和相邻采样。使用这两种方式的循环神经网络训练在实现上略有不同。 注除代码外本节与原书此节基本相同原书传送门