基于Python的宋词生成器

资源下载地址:https://download.csdn.net/download/sheziqiong/85631523

1. 背景

我有两个爱好,一个是传统文化,另一个是高新技术。

传统文化,我喜欢唐诗宋词、笔墨丹青,高新技术我则从事前沿的IT编程,喜欢研究人工智能。

我很想让这两者联系起来,这一老一新,不知道会碰撞出什么火花。

2. 成果

通过试验,利用循环神经网络结合文本生成,我最终练成神功:提供一个开头,他就会自动生成一篇宋词。而且,这篇新词绝对是原创。

开头生成细雨细雨仙桂春。明月此,梦断在愁何。等闲帘寒,归。正在栖鸦啼来。清风清风到破向,貌成眠无风。人在梦断杜鹃风韵。门外插人莫造。怯霜晨。高楼高楼灯火,九街风月。今夜楼外步辇,行时笺散学空。但洗。俯为人间五色。海风海风落今夜,何处凤楼偏好。奇妙。残月破。将心青山上,落分离。今夜今夜谁和泪倚阑干。薰风却足轻。似泠愁绪。似清波似玉人。羞见。

对于诗词稍有研究的我,对于上面”高楼”一词生成的文本,比较满意。

高楼灯火,九街风月。今夜楼外步辇,行时笺散学空。但洗。俯为人间五色。

高楼处在高处,后面的文本也体现了”高”的特色,”高楼望街”是一番意境,”高楼望夜”又是另一番意境,最后出了一个”俯看五色”,一个”俯”字,也是体现了居高临下,整篇文本无不围绕”高”的主题。实乃绝妙!

下面就来剖析下,宋词生成是如何实现的。

3. 实现方式

3.1 数据的准备

我找到了一个宋词数据集,是一个csv格式的文件,里面有2万首宋词。

文档的第一列是词牌名,第二列是作者,第三列是正文。其中正文,已经做好了分词处理。

想要了解分词,可以查看NLP知识点:中文分词

基于Python的宋词生成器

; 3.2 数据的读入

首先导入整个项目涉及到的包。

import csv
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
from tensorflow.python.keras.engine.sequential import Sequential
from tensorflow.keras import layers
from tensorflow.keras.optimizers import Adam

下面是加载数据集文件中数据的方法。

def load_data(num = 1000):

    csv_reader = csv.reader(open("./ci.csv",encoding="gbk"))

    ci_list = []
    for row in csv_reader:

        ci_list.append(row[2])

        if len(ci_list) > num:break
    return ci_list

然后进行数据序列化。

这里要重点说明一下,因为要做文本预测的训练,需要从上面的词语推断出下面的词语,所以这里做了一些加工。

比如”看山 不是 山 , 看山 又是 山”这一句,它给转化成了多句:

看山 不是
看山 不是 山
看山 不是 山 ,
看山 不是 山 , 看山
看山 不是 山 , 看山 又是
看山 不是 山 , 看山 又是 山

这么做的目的就是告诉神经网络,如果前面是”看山”,后面跟一个词语是”不是”。当前面变成”看山 不是 山 , 看山”时,这时”看山”后面就变成”又是”了。

“看山”后面并不是固定的,而是根据它前面一串词语综合判断而决定的。

将一句话,切成多句话,这是一个特殊处理的地方,就是下面代码做的事情:

for i in range(1, len(token_list)):
    n_gram_sequence = token_list[:i+1]
    input_sequences.append(n_gram_sequence)

3.3 构建模型

要训练数据,我们首先得有一个神经网络模型,下面是构建了一个网络模型序列。

def create_model(vocab_size, embedding_dim, max_length):

    model = Sequential()

    model.add(layers.Embedding(vocab_size, embedding_dim, input_length = max_length))

    model.add(layers.Bidirectional(layers.LSTM(512)))

    model.add(layers.Dense(vocab_size, activation='softmax'))

    adam = Adam(lr=0.01)

    model.compile(loss='categorical_crossentropy',optimizer=adam, metrics=['accuracy'])

    return model

关于模型、层、激活函数的知识点,有专门解释:神经网络模型的序列和层激活函数


假设我们得到了训练序列input_sequences是:

[0, 0, 1, 2]
[0, 0, 3, 4]
[0, 3, 4, 5]
[3, 4, 5, 6]


对应文字就是:

[0, 0, 春花, 秋月]
[0, 0, 一江, 春水]
[0, 一江, 春水, 向东]
[一江, 春水, 向东, 流]


对于训练,一般都是成对的。一个输入,一个输出。机器将学习从输入推断出输出的诀窍。

在这个例子中,因为是从上一个词推断出下一个词,所以输入和输出都要从上面的语料库中来取。

下面这段代码就是从input_sequences取出了输入和输出:
`python
xs = input_sequences[:,:-1]
labels = input_sequences[:,-1]

输入 xs输出 labels[0, 0, 春花][秋月][0, 0, 一江][春水][0, 一江, 春水][向东][一江, 春水, 向东][流 ]

因为模型里面激活函数使用了 activation='softmax',所以这个输出要通过 tf.keras.utils.to_categorical转化成了独热编码。

此时,需要强调几个概念:

  • 文本序列的最大长度 max_sequence_len就是 [一江, 春水, 向东, 流]的长度,此处值为4。主要作用是定义一个固定的训练长度,长度不足时补0,超出时裁剪。

为什么要这么做,可以点击此处了解

  • 输入序列的长度 input_length就是 [0, 一江, 春水]的长度,固定为3,是从 max_sequence_len截取出来的,最后一个词不要。主要作用是作为输入。

3.5 进行预测

训练完成之后,我们就可以享受胜利果实,开始进行预测了。

预测需要给一个开头的词语,并且指定后面需要预测多少个词语。

预测B

预测C

预测D

预测后面N个词

开头词语 A

AB

ABC

ABCD

首先,根据开始的词语,通过 model.predict_classes(token_list)预测出下一个词语,接着开头词语连同预测词语两方再作为输入,继续预测下一个词语。如此类推,像贪吃蛇一样,从一个开头词语慢慢地引出一个长句子。句子中每个词语是有语义上的前后关系的。

这就是宋词生成器的实现逻辑,希望对你有所帮助。

资源下载地址:https://download.csdn.net/download/sheziqiong/85631523

Original: https://blog.csdn.net/newlw/article/details/122546983
Author: biyezuopinvip
Title: 基于Python的宋词生成器

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/531961/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球