该系列的Jupyter源码以及Char-RNN的模型权重&训练历史已放到附件以供下载:
使用RNN生成莎士比亚文本(二)训练Char-RNN模型
Char-RNN能够根据字符串生成下一个概率最大的字母,所以只要以此类推,模型就能生成文本。但是这样有一个问题,就是会导致相同的单词一遍又一遍的重复。为了解决这个问题,我们可以使用Tensorflow的tf.random.categorical()
函数估计出来的概率随机选择下一个字符,以产生更多变的文本。
给定对数概率logits
,categorical()
函数会对随机索引进行采样。为了增强文本的多样性, 我们对于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神经元,只不过训练的时间会变得更长。
Comments | NOTHING