热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自然语言处理模仿莎士比亚风格自动生成诗歌

导入需要的工具包诗词句子很短,每个of等词都有意义,不需要过滤词汇,所以预处理过程比较简短。importtensorflowastf

导入需要的工具包

诗词句子很短,每个of等词都有意义,不需要过滤词汇,所以预处理过程比较简短。

import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional, Dropout
from tensorflow.keras.models import Sequential
from tensorflow.keras import regularizers
from tensorflow.keras.optimizers import Adam
import numpy as np

定义tokenizer对象,并准备训练数据

tokenizer = Tokenizer()data= open('sonnets.txt').read()corpus = data.lower().split('\n')tokenizer.fit_on_texts(corpus)
total_words = len(tokenizer.word_index) + 1#print(tokenizer.word_index)
print(len(corpus))
print(total_words)

所以一共由2159句诗词,总共有3211个单词
21593211
‘from fairest creatures we desire increase,’, “that thereby beauty’s rose might never die,”

在这里插入图片描述前两行是’from fairest creatures we desire increase,’, “that thereby beauty’s rose might never die,”在这里插入图片描述

input_sequences = []for line in corpus:token_list = tokenizer.texts_to_sequences([line])[0]for i in range(1, len(token_list)):n_gram_sequence = token_list[:i+1]input_sequences.append(n_gram_sequence)print(len(input_sequences))#pad sequences
max_sequence_len = max([len(seq) for seq in input_sequences])print(max_sequence_len, total_words)input_sequences = np.array(pad_sequences(input_sequences, padding='pre', maxlen=max_sequence_len))
print(input_sequences[:,-1].shape)#构建训练数据对
xs, labels = input_sequences[:,:-1], input_sequences[:,-1]ys = tf.keras.utils.to_categorical(labels, num_classes=total_words)
print(ys.shape)

在这里插入图片描述
input_suquences中34 417分别代表着from 、fairest
在这里插入图片描述
input_sequences中,第一行代表from 、fairest
第五行代表from fairest creatures we desire increase
第10行代表that thereby beauty’s rose might never die
在这里插入图片描述
由xs表示seed 来推测下一个单词labels。
比如input_sequences第一行就是用from推出下一个单词fairest
然后在用from fairest推出下一个单词creatures

由以上分析知道:input_sequeces 有15462行,每行的 前:-1的单词作为x,而最后一个单词作为y。
一共有15462对(x,y)
给每个单词一个做一个onehot编码。然后每个y对应编码形式、
ys就是表示了将15462个y,每个都用单词的编号进行表示。
在这里插入图片描述

构建深度模型并训练

双边:从开头到结尾,从结尾到开头,能够有更好的记忆
embed_dim数据重复了100多次

embed_dim = 100model = Sequential()
model.add(Embedding(total_words, embed_dim, input_length=max_sequence_len-1))
model.add(Bidirectional(LSTM(128)))
#model.add(Bidirectional(LSTM(96)))
#model.add(Dropout(0.3))
#model.add(Dense(total_words/2, activation='relu', kernel_regularizer=regularizers.l2(0.01)))
model.add(Dense(total_words, activation='softmax'))model.summary()

在这里插入图片描述

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
history = model.fit(xs, ys, batch_size=64, epochs=100, verbose=1)

在这里插入图片描述

画出精度随epoch变化曲线

注意观察模型在什么时候开始收敛

import matplotlib.pyplot as pltdef plot_graphs(history, string):plt.plot(history.history[string])plt.xlabel("Epochs")plt.ylabel(string)plt.show()plot_graphs(history, 'acc')
plot_graphs(history, 'loss')

在这里插入图片描述
Epochs不是越多越好,选择50 就可以了。

保存训练好的模型

model.save('shakespeare_model.h5')

输入种子文本,并产生接下来的50个单词


def predict_next_words(seed_text, next_words):for _ in range(next_words):token_list = tokenizer.texts_to_sequences([seed_text])[0]token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')#predicted = model.predict_classes(token_list, verbose=0)predicted = np.argmax(model.predict(token_list), axis=-1)output_word = ""for word, index in tokenizer.word_index.items():#print(word,type(index))if index == predicted:output_word = wordbreakseed_text += " " + output_wordprint(seed_text)return seed_textseed_text = "from fairest creatures we desire increase"
next_words = 50generated_text = predict_next_words(seed_text, next_words)

在这里插入图片描述

seed_text = "making a famine where"
generated_text = predict_next_words(seed_text, next_words)

在这里插入图片描述
每一行不多于11词,每次需要加入换行,
给定了种子,每次结果是一样的,生成的文本确定性问题,但是不需要文本一样,所以需要一定的随机性,但也不能完全随机,如果随机从文本中输出单词就没有意义了。max对应概率最大的进行输出。

解释numpy.random.multinomial()函数:

从多项式分布中提取样本。

多项式分布是二项式分布的多元推广。做一个有P个可能结果的实验。这种实验的一个例子是掷骰子,结果可以是1到6。从分布图中提取的每个样本代表n个这样的实验。其值x_i = [x_0,x_1,…,x_p] 表示结果为i的次数。

函数语法

numpy.random.multinomial(n, pvals, size=None)

参数
n : int:实验次数
pvals&#xff1a;浮点数序列&#xff0c;长度p。P个不同结果的概率。这些值应该和为1&#xff08;但是&#xff0c;只要求和&#xff08;pvals[&#xff1a;-1]&#xff09;<&#61;1&#xff0c;最后一个元素总是被假定为考虑剩余的概率&#xff09;。
size : int 或 int的元组&#xff0c;可选。 输出形状。如果给定形状为&#xff08;m&#xff0c;n&#xff0c;k&#xff09;&#xff0c;则绘制 mnk 样本。默认值为无&#xff0c;在这种情况下返回单个值。
返回值
ndarray&#xff0c;每个条目 [i&#xff0c;j&#xff0c;…&#xff0c;&#xff1a;] 都是从分布中提取的一个n维值。

实例

  1. 掷骰子20次&#xff1a;

np.random.multinomial(20, [1/6.]*6, size&#61;1)
array([[4, 1, 7, 5, 2, 1]])
表示它落在14次&#xff0c;落在21次&#xff0c;等等

修改代码&#xff1a;

def predict_next_words(seed_text, next_words):for _ in range(next_words):token_list &#61; tokenizer.texts_to_sequences([seed_text])[0]token_list &#61; pad_sequences([token_list], maxlen&#61;max_sequence_len-1, padding&#61;&#39;pre&#39;)#predicted &#61; model.predict_classes(token_list, verbose&#61;0)#predicted &#61; np.argmax(model.predict(token_list), axis&#61;-1)predicted&#61;model.predict(token_list,verbose&#61;0)[0]len_p&#61;len(predicted)#print(predicted)temperature&#61;0.5predicted&#61;predicted**(1/temperature)p&#61;predicted/np.sum(predicted)top_n&#61;5vocab_size&#61;1p[np.argsort(p)[:-top_n]] &#61; 0#选取了概率较大的前k个p &#61; p / np.sum(p) # 归一化概率 predicted &#61; np.random.choice(list(range(0,len_p)), 1, p&#61;p)[0]# 随机选取一个字符output_word &#61; ""for word, index in tokenizer.word_index.items():#print(word,type(index))if index &#61;&#61; predicted:output_word &#61; wordbreakseed_text &#43;&#61; " " &#43; output_wordprint(seed_text)
return seed_text

修改后可以看见&#xff0c;输出不同的内容。
因为每一行不超过11个词&#xff0c;所以如果长度大于11了&#xff0c;就自动换行。

def predict_next_words(seed_text, next_words):count&#61;0for _ in range(next_words):token_list &#61; tokenizer.texts_to_sequences([seed_text])[0]token_list &#61; pad_sequences([token_list], maxlen&#61;max_sequence_len-1, padding&#61;&#39;pre&#39;)#predicted &#61; model.predict_classes(token_list, verbose&#61;0)#predicted &#61; np.argmax(model.predict(token_list), axis&#61;-1)predicted&#61;model.predict(token_list,verbose&#61;0)[0]len_p&#61;len(predicted)#print(predicted)temperature&#61;0.5predicted&#61;predicted**(1/temperature)p&#61;predicted/np.sum(predicted)top_n&#61;5vocab_size&#61;1p[np.argsort(p)[:-top_n]] &#61; 0p &#61; p / np.sum(p) # 归一化概率 predicted &#61; np.random.choice(list(range(0,len_p)), 1, p&#61;p)[0]# 随机选取一个字符output_word &#61; ""for word, index in tokenizer.word_index.items():#print(word,type(index))if index &#61;&#61; predicted:output_word &#61; wordbreakcount&#61;count&#43;1if count&#61;&#61;10:output_word&#61;output_word&#43;"\n"count&#61;0seed_text &#43;&#61; " " &#43; output_wordprint(seed_text)
return seed_text

于是生成了有不同结果&#xff0c;且可以换行的诗句。

总结

1.在生成文本时&#xff0c;需要给一个种子片段作为输入&#xff0c;然后就可以进行生成&#xff0c;重复进行以下几步&#xff1a;
把segment输入神经网络
神经网络输出各个字符的概率
从概率值中进行Sample得到next_char
把新生成的字符接到片段的后面

2.可以通过画图的方式 画出精度随epoch变化曲线&#xff0c;观察模型在什么时候开始收敛&#xff0c;选择epoch参数。

3.通过多项式抽样&#xff0c;可以使得生成文本有一定程度的随机性。
预测下一个字符时
在模型搭建好后&#xff0c;我们有以下三种策略来选择下一个字符。
Option 1&#xff1a;Greedy selection
第一种方法是进行贪婪选择&#xff0c;直接选最大概率的那个。但这种方法生成的文本是确定的&#xff0c;文章都是固定的&#xff0c;可读性极差

predicted&#61;model.predict(token_list,verbose&#61;0)[0]
predicted &#61; np.argmax(model.predict(token_list), axis&#61;-1)

Option 2&#xff1a;Sampling from the multinomial distribution
第二种方法是根据输出的各个字符概率值进行多项式分别抽样&#xff0c;这种情况下具有随机性&#xff0c;生成效果较好。但是可能过于随机。

predicted&#61;model.predict(token_list,verbose&#61;0)[0]
Next_onehot&#61;np.random.multinomial(1,predicted,1)
Next_index&#61;np.argmax(next_onehot)

Option 3&#xff1a;adjust the multinomial distribution
第三种方式则是在原始概率分布上加幂次再重新计算概率分别&#xff0c;这种情况下&#xff0c;会使得在方法二中概率大的更大一些。效果也更好一些。这种方法使综合了方法1和2的优点&#xff0c;具有随机性&#xff0c;也能控制随机性

predicted&#61;model.predict(token_list,verbose&#61;0)[0]
temperature&#61;0.5
predicted&#61;predicted**(1/temperature)
Predicted&#61;predicted/np.sum(predicted)

4.换行&#xff0c;诗词的每一行不会超过11个&#xff0c;所以对输出文本进行技术&#xff0c;如果超过了11就输出\n


推荐阅读
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
author-avatar
shmily志伟
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有