使用RNN生成莎士比亚文本(三)生成假莎士比亚文本


该系列的Jupyter源码以及Char-RNN的模型权重&训练历史已放到附件以供下载:

源码和模型数据点击下载

使用RNN生成莎士比亚文本(二)训练Char-RNN模型

Char-RNN能够根据字符串生成下一个概率最大的字母,所以只要以此类推,模型就能生成文本。但是这样有一个问题,就是会导致相同的单词一遍又一遍的重复。为了解决这个问题,我们可以使用Tensorflow的tf.random.categorical()函数估计出来的概率随机选择下一个字符,以产生更多变的文本。
给定对数概率logitscategorical()函数会对随机索引进行采样。为了增强文本的多样性, 我们对于logits除以一个“温度”(temperature)变量,这样可以根据自己的需要进行调整。

  • temperature接近0,函数趋向于选择高概率的字符。temperature越高,各个字符概率越接近。

我们编写一个函数next_char来选择字符,以添加到输入文本的后面:

tf.random.set_seed(42)
tf.random.categorical([[np.log(0.5), np.log(0.4), np.log(0.1)]], num_samples=40).numpy()

def next_char(text, temperature=1):
    X_new = preprocess([text])
    y_proba = model(X_new)[0, -1:, :]
    rescaled_logits = tf.math.log(y_proba) / temperature
    char_id = tf.random.categorical(rescaled_logits, num_samples=1) + 1
    return tokenizer.sequences_to_texts(char_id.numpy())[0]

再用How are yo来测试一下这个函数

tf.random.set_seed(42)

next_char("How are yo", temperature=1)
输出:u

预测成功!


next_char函数的基础上,编写生成整篇文本的函数(指定长度为50个字符)

def complete_text(text, n_chars=50, temperature=1):
    for _ in range(n_chars):
        text += next_char(text, temperature)
    return text

测试生成文本

我们制定不同的温度,测试模型在不同温度的表现:
以t开头,温度0.2

print(complete_text("t", temperature=0.2))

输出:

t the matter for a schoolmaster will have a schoolm

以t开头,温度1

print(complete_text("t", temperature=1))

输出:

tonour,'tyough in you beholding tanning friends,
sa

(家人们,他甚至学到了分行)

以t开头,温度2

print(complete_text("t", temperature=2))

输出:

truss: takes suitousie, for it in sw
in swept; and

温度到2就开始胡言乱语了

模型再接近1的温度下,效果最佳。

至此,生成莎士比亚文本的模型大功告成!

模型的缺点

由于我们是按照长度n_steps=100+1进行分窗的,所以模型无法学习比n_steps更长的模式。而如果把n_steps设置的更长的话,训练难度会变得更大。LSTM和GRU都无法处理很长的序列。想要处理更长的序列,可以使用有状态RNN

关于模型的提高

如果要生成更像人话的莎士比亚文本,可以尝试用更多的GRU层,每层加上更多的GRU神经元,只不过训练的时间会变得更长。

声明:奋斗小刘|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 使用RNN生成莎士比亚文本(三)生成假莎士比亚文本


Make Everyday Count