【PyTorch深度学习项目实战100例】—— 使用pytorch实现LSTM自动AI作诗(藏头诗和首句续写)| 第6例

前言

大家好,我是阿光。

本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

正在更新中~ ✨

🚨 我的项目环境:

  • 平台:Windows10
  • 语言环境:python3.7
  • 编译器:PyCharm
  • PyTorch版本:1.8.1

💥 项目专栏:【PyTorch深度学习项目实战100例】


一、LSTM自动AI作诗

本项目使用了LSTM作为模型实现AI作诗,作诗模式分为两种,一是根据给定诗句继续生成完整诗句,二是给定诗头生成藏头诗。

在这里插入图片描述

二、数据集介绍

数据来源于chinese-poetry,最全中文诗歌古典文集数据库

最全的中华古典文集数据库,包含 5.5 万首唐诗、26 万首宋诗、2.1 万首宋词和其他古典文集。诗 人包括唐宋两朝近 1.4 万古诗人,和两宋时期 1.5 千古词人。

实验使用预处理过的二进制文件 tang.npz 作为数据集,含有 57580 首唐诗,每首诗限定在 125 词, 不足 125 词的以空格填充。数据集以 npz 文件形式保存,包含三个部分:

data: (57580,125) 的 numpy 数组,总共有 57580 首诗歌,每首诗歌长度为 125 字符 (不足 125 补空格,超过 125 的丢弃),将诗词中的字转化为其在字典中的序号表示

  • ix2word: 序号到字的映射
  • word2ix: 字到序号的映射

三、算法流程介绍

1.输入数据为input,形状为 124 * 16
2.输入数据的label为 124 * 16

  1. 之后需要对输入数据进行嵌入,如果不嵌入那么每个古诗的字应为对应的索引,为了能够进行训练所以需要将其进行嵌入,然后形成连续性变量。
  2. 之后我们的数据就变成了 124 * 16 * embedding_dim
  3. 然后将其导入到LSTM模块中,则形成的形状为 124 * 16 * hidden_dim
  4. 之后将其导入到全连接层,形成分类,变为的形状为 124 * 16 ,vocab_size

注意
一定要清楚各个位置不同变量的形状,这些在代码中已经注明,一定要弄明白batch_sizetime_stepembedding_dimvocal_sizenum_layershidden_dim以及input_size在代码中的意义。

四、定义网络模型

项目中使用的模型是LSTM,在模型中我们定义了三个组件,分别是embedding层lstm层全连接层

  • Embedding层:将每个词生成对应的嵌入向量,就是利用一个连续型向量来表示每个词
  • Lstm层:提取诗句中的语义信息
  • Linear层:将结果映射成vocab_size大小用于分类,即每个字的概率
class LSTM(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim):
        super(LSTM, self).__init__()
        self.hidden_dim = hidden_dim
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers)
        self.linear = nn.Linear(hidden_dim, vocab_size)

    def forward(self, x, hidden=None):
        time_step, batch_size = x.size()  # 124, 16
        if hidden is None:
            h_0 = x.data.new(num_layers, batch_size, self.hidden_dim).fill_(0).float()
            c_0 = x.data.new(num_layers, batch_size, self.hidden_dim).fill_(0).float()
        else:
            h_0, c_0 = hidden
        embeds = self.embeddings(x)
        output, (h_n, c_n) = self.lstm(embeds, (h_0, c_0))
        output = self.linear(output.reshape(time_step * batch_size, -1))
        return output, (h_n, c_n)

五、给定首句生成古诗

该函数会根据给定的语句生成一段古诗,会根据start_words继续生成下一个字,对于给定的语句生成相应的hidden,然后将最后一个字和对应的hidden将其输入到模型中,生成新的下一个字,然后将新生成的字作为新的输入。

此外还可以加入诗句前缀,加入的目的是会影响生成诗句的风格,首先利用prefix_words生成对应的hidden,然后将hidden送入模型生成诗句,此hidden中包含了前缀中的语义信息。

  • start_words:给定的初始语句,基于它生成之后的诗句
  • prefix_words:前缀诗句,该句会影响诗句的风格,因为首先会学习对应的hidden然后将其和开始词送入模型生成对应的诗句

六、生成藏头诗

生成藏头诗的原理与上述函数同理,只不过是利用给定的藏头字分别作为输入,一旦遇到特殊符号就说明该句生成结束,继续生成下一句藏头诗

同理这个函数也会包含诗句前缀,影响诗句的风格

七、模型训练

对于模型训练最重要的就是模型的输入和输出,针对于写诗这个任务,我们的输入应该是给定一句诗,然后错位1位作为它的标签用于监督,例如:

床前明月光疑是地上霜
那么我们的输入、输出就应该为:
输入数据:床前明月光疑是地上
输出数据:前明月光疑是地上霜

每个时间步对应的输出应该是他下个时间步对应的字
每个时间步的输出应该是vocab_size维度,就是词大小,用于全分类,这样就会根据概率获得该时间步对应的字。

由于本项目中采用的是唐诗数据集,数据为data: (57580,125) 的 numpy 数组,也就是每个样本为一句诗,每首诗中含有125个字,相当于不同的时间步,然后将每个字进行embedding进行编码,这里我们将输入作为124,也就是像上面所说,利用前124个字和他对应之后的124个字进行监督。

def train():
    if use_gpu:
        device = torch.device("cuda")
    else:
        device = torch.device("cpu")
    # 获取数据
    datas = np.load("tang.npz", allow_pickle=True)
    data = datas['data']
    ix2word = datas['ix2word'].item()
    word2ix = datas['word2ix'].item()
    data = torch.from_numpy(data)
    dataloader = DataLoader(data,
                            batch_size=batch_size,
                            shuffle=True)

    # 定义模型
    model = LSTM(len(word2ix),
                 embedding_dim=embedding_dim,
                 hidden_dim=hidden_dim)
    Configimizer = optim.Adam(model.parameters(), lr=lr)
    criterion = nn.CrossEntropyLoss()
    #     if model_path:
    #         model.load_state_dict(torch.load(model_path,map_location='cpu'))
    # 转移到相应计算设备上
    model.to(device)
    loss_meter = meter.AverageValueMeter()
    # 进行训练
    f = open('result.txt', 'w')
    hidden = None
    for epoch in range(epochs):
        loss_meter.reset()
        for li, data_ in tqdm.tqdm(enumerate(dataloader)):
            #             print(data_.shape) # 16 * 125  batch_size * time_step
            data_ = data_.long().transpose(1, 0).contiguous()  # 125 * 16  time_step * batch_size
            # 注意这里,也转移到了计算设备上
            data_ = data_.to(device)
            Configimizer.zero_grad()
            # n个句子,前n-1句作为输入,后n-1句作为输出,二者一一对应
            input_, target = data_[:-1, :], data_[1:, :]  # 都是124 * 16
            output, hidden = model(input_, hidden)  # 1984 * 8293   [batch_size * time_step, vocab_size] 124为时间步大小
            #             print("Here",output.shape)
            #             # 这里为什么view(-1)
            # output:1984 * 8293
            # target.view(-1):1984
            # 可以直接放入,因为是交叉熵损失函数,target为标签,而output每个样本的输出为所有样本的类别概率
            loss = criterion(output, target.view(-1))
            loss.backward()
            Configimizer.step()
            loss_meter.add(loss.item())

            # 进行可视化
            if (1 + li) % plot_every == 0:
                print("训练损失为%s" % (str(loss_meter.mean)))
                f.write("训练损失为%s" % (str(loss_meter.mean)))
                for word in list(u"春江花朝秋月夜"):
                    gen_poetry = ''.join(generate(model, word, ix2word, word2ix))
                    print(gen_poetry)
                    f.write(gen_poetry)
                    f.write("\n\n\n")
                    f.flush()
        torch.save(model.state_dict(), '%s_%s.pth' % (model_prefix, epoch))

八、生成诗句

该函数用于进行测试生成语句,我们会首先加载我们训练好的模型,然后传入续写的诗句或者需要加入的前缀信息,形成诗句。

完整源码

【PyTorch深度学习项目实战100例】—— 使用pytorch实现LSTM自动AI作诗(藏头诗和首句续写)| 第6例_咕 嘟的博客-CSDN博客_pytorch基于 lstm 的自动写诗

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容