文章目录

  • 1、导入需要的库
  • 2、加载数据集
  • 3、相邻采样
  • 4、定义模型
    • 4.1 定义循环神经网络层
    • 4.2 定义循环神经网络
  • 5、定义预测函数
  • 6、裁剪梯度
  • 7、定义模型训练函数
    • 7.1 困惑度
    • 7.2 初始化优化器
    • 7.3 定义梯度下降函数
    • 7.4 定义训练函数
    • 7.5 训练

在 Tensorflow2.0之从零开始实现循环神经网络中,我们介绍了循环神经网络的原理以及如何使用低级API来实现循环神经网络,在这篇文章中,我们将使用 tensorflow2.0 来更简洁地实现循环神经网络。
在这里,我们将实现一个循环神经网络来自动生成周杰伦歌词。代码中的数据集加载以及采样函数在 Tensorflow2.0之语言模型数据集(周杰伦专辑歌词)预处理中已经介绍过了,在这里不再赘述。

1、导入需要的库

import tensorflow as tf
from tensorflow import keras
import numpy as np
import zipfile
import math

2、加载数据集

def load_data_jay_lyrics():"""加载周杰伦歌词数据集"""with zipfile.ZipFile('./jaychou_lyrics.txt.zip') as zin:with zin.open('jaychou_lyrics.txt') as f:corpus_chars = f.read().decode('utf-8')corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')corpus_chars = corpus_chars[0:10000]idx_to_char = list(set(corpus_chars))char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])vocab_size = len(char_to_idx)corpus_indices = [char_to_idx[char] for char in corpus_chars]return corpus_indices, char_to_idx, idx_to_char, vocab_size(corpus_indices, char_to_idx, idx_to_char, vocab_size) = load_data_jay_lyrics()

3、相邻采样

def data_iter_consecutive(corpus_indices, batch_size, num_steps, ctx=None):corpus_indices = np.array(corpus_indices)data_len = len(corpus_indices)batch_len = data_len // batch_sizeindices = corpus_indices[0: batch_size*batch_len].reshape((batch_size, batch_len))epoch_size = (batch_len - 1) // num_stepsfor i in range(epoch_size):i = i * num_stepsX = indices[:, i: i + num_steps]Y = indices[:, i + 1: i + num_steps + 1]yield X, Y

4、定义模型

4.1 定义循环神经网络层

Keras 的 Rnn 模块提供了循环神经网络的实现。下面构造一个含单隐藏层、隐藏单元个数为256的循环神经网络层 rnn_layer,并对权重做初始化。

num_hiddens = 256
cell = keras.layers.SimpleRNNCell(num_hiddens, kernel_initializer='glorot_uniform')
rnn_layer = keras.layers.RNN(cell,time_major=True,return_sequences=True,return_state=True)

其中,rnn_layer 的输入形状为 (时间步数, 批量大小, 词典大小),在前向计算后会分别返回输出和隐藏状态。

其中输出指的是隐藏层在各个时间步上计算并输出的隐藏状态,它们通常作为后续输出层的输入。需要强调的是,该“输出”本身并不涉及输出层计算,形状为 (时间步数, 批量大小, 隐藏单元个数)

返回的隐藏状态指的是隐藏层在最后时间步的隐藏状态:当隐藏层有多层时,每一层的隐藏状态都会记录在该变量中。

举例来说:
我们要先初始化隐藏状态

batch_size = 2
state = rnn_layer.cell.get_initial_state(batch_size=batch_size,dtype=tf.float32)
state.shape
TensorShape([2, 256])

可见隐藏状态的形状为 (批量大小, 隐藏单元个数)

num_steps = 35
X = tf.random.uniform(shape=(num_steps, batch_size, vocab_size))
print(X.shape)
Y, state_new = rnn_layer(X, state)
print(Y.shape)
print(len(state_new))
print(state_new[0].shape)
(35, 2, 1027)
(35, 2, 256)
2
(256,)

4.2 定义循环神经网络

class RNNModel(tf.keras.Model):def __init__(self, rnn_layer, vocab_size):super().__init__()self.rnn = rnn_layerself.vocab_size = vocab_sizeself.dense = keras.layers.Dense(vocab_size)def call(self, inputs, state):# 将输入转置成(num_steps, batch_size)后获取one-hot向量表示X = tf.one_hot(tf.transpose(inputs), self.vocab_size)Y, state = self.rnn(X, state)# 全连接层会首先将Y的形状变成(num_steps * batch_size, num_hiddens),# 它的输出形状为(num_steps * batch_size, vocab_size)output = self.dense(tf.reshape(Y, (-1, Y.shape[-1])))return output, statedef get_initial_state(self, *args, **kwargs):return self.rnn.cell.get_initial_state(*args, **kwargs)model = RNNModel(rnn_layer, vocab_size)

将经过采样后的样本直接输入此网络中时,它经过的处理操作依次为:

  • 输入形状为 (批量大小, 时间步数)
  • 将输入转置成 (时间步数, 批量大小)
  • 利用独热编码得到 (时间步数, 批量大小, 词典大小)
  • 输入到 rnn 层,得到 (时间步数, 批量大小, 隐藏单元个数)
  • reshape(时间步数x批量大小, 隐藏单元个数)
  • 经过 Dense 层,得到 (时间步数x批量大小, 词典大小)

5、定义预测函数

def predict_rnn_keras(prefix, num_chars):# 使用model的成员函数来初始化隐藏状态state = model.get_initial_state(batch_size=1,dtype=tf.float32)output = [char_to_idx[prefix[0]]]for t in range(num_chars + len(prefix) - 1):X = np.array([output[-1]]).reshape((1, 1))Y, state = model(X, state)  # 前向计算不需要传入模型参数if t < len(prefix) - 1:output.append(char_to_idx[prefix[t + 1]])else:output.append(int(np.array(tf.argmax(Y,axis=-1))))return ''.join([idx_to_char[i] for i in output])

其中,num_chars 表示要预测多少个字符。
我们可以先试验一下:

predict_rnn_keras('分开', 10)

得到:

'分开缸池升脑霜陪身纳梦旋'

因为模型参数为随机值,所以预测结果也是随机的。

6、裁剪梯度

循环神经网络中较容易出现梯度衰减或梯度爆炸。为了应对梯度爆炸,我们可以裁剪梯度(clip gradient)。假设我们把所有模型参数梯度的元素拼接成一个向量 g\boldsymbol{g}g,并设裁剪的阈值是 θ\thetaθ。裁剪后的梯度

min⁡(θ∣g∣,1)g\min\left(\frac{\theta}{|\boldsymbol{g}|}, 1\right)\boldsymbol{g}min(∣g∣θ​,1)g

的L2L_2L2​范数不超过θ\thetaθ。

# 计算裁剪后的梯度
def grad_clipping(grads,theta):norm = np.array([0])for i in range(len(grads)):norm+=tf.math.reduce_sum(grads[i] ** 2)norm = np.sqrt(norm).item()new_gradient=[]if norm > theta:for grad in grads:new_gradient.append(grad * theta / norm)else:for grad in grads:new_gradient.append(grad)  return new_gradient

7、定义模型训练函数

7.1 困惑度

我们通常使用困惑度(perplexity)来评价语言模型的好坏。困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,

  • 最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
  • 最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
  • 基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。

显然,任何一个有效模型的困惑度必须小于类别个数。在本例中,困惑度必须小于词典大小vocab_size。

7.2 初始化优化器

lr = 1e2
optimizer=tf.keras.optimizers.SGD(learning_rate=lr)

7.3 定义梯度下降函数

loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
def train_step(X, state, Y, clipping_theta=1e-2):with tf.GradientTape(persistent=True) as tape:(outputs, state) = model(X, state)y = Y.T.reshape((-1,))l = loss_object(y,outputs)grads = tape.gradient(l, model.variables)# 梯度裁剪grads=grad_clipping(grads, clipping_theta)optimizer.apply_gradients(zip(grads, model.variables))  # 因为已经误差取过均值,梯度不用再做平均return l, y

7.4 定义训练函数

  • num_epochs:训练次数;
  • batch_size:批次大小;
  • pred_period:间隔多少次展示一次结果;
  • pred_len:要求预测的字符长度。
def train_and_predict_rnn_keras(num_epochs, batch_size, pred_period, pred_len, prefixes):for epoch in range(num_epochs):l_sum, n = 0.0, 0data_iter = data_iter_consecutive(corpus_indices, batch_size, num_steps)state = model.get_initial_state(batch_size=batch_size,dtype=tf.float32)for X, Y in data_iter:l, y = train_step(X, state, Y)l_sum += np.array(l).item() * len(y)n += len(y)if (epoch + 1) % pred_period == 0:print('epoch %d, perplexity %f' % (epoch + 1, math.exp(l_sum / n)))for prefix in prefixes:print(' -', predict_rnn_keras(prefix, pred_len))

7.5 训练

num_epochs, batch_size = 250, 32
pred_period, pred_len, prefixes = 50, 50, ['分开', '不分开']
train_and_predict_rnn_keras(num_epochs, batch_size, pred_period,pred_len, prefixes)

Tensorflow2.0之用循环神经网络生成周杰伦歌词相关推荐

  1. Nat. Mach. Intell. | 利用条件循环神经网络生成特定性质分子

    作者 | 陆丰庆 今天给大家介绍瑞士知名药企阿斯利康和伯尔尼大学的 Esben Jannik Bjerrum团队在Nature Machine Intelligence上的一篇论文.该研究提出基于分子 ...

  2. 利用循环神经网络生成唐诗_PyTorch实现用于文本生成的循环神经网络

    自然语言处理(NLP)有很多有趣的应用,文本生成就是其中一个有趣的应用. 当一个机器学习模型工作在诸如循环神经网络.LSTM-RNN.GRU等序列模型上时,它们可以生成输入文本的下一个序列. PyTo ...

  3. Paper:RNN之《Generating Sequences With Recurrent Neural Networks用循环神经网络生成序列》的翻译和解读

    Paper:<Generating Sequences With Recurrent Neural Networks>的翻译和解读 目录 Generating Sequences With ...

  4. 利用循环神经网络生成唐诗_【机器学习】【期末复习】闲聊神经网络 分类

    类似于人脑的一种神经递质,有一个信号经过一系列传到有一个输出(单线).既然是网络,应该就是一堆上述带有输入输出的线构成的网络吧. reference: 一文看懂四种基本的神经网络架构​www.jian ...

  5. 利用循环神经网络生成唐诗_11种主要神经网络结构图解

    图文解读主要的神经网络结构. 作者:Andre Ye 编译:McGL 公众号:PyVision(欢迎关注,专注CV,偶尔CS) 11 Essential Neural Network Architec ...

  6. 利用循环神经网络生成唐诗_可视化解释11种基本神经网络架构

    > Source: Pixabay 标准,循环,卷积和自动编码器网络 随着深度学习的飞速发展,已经创建了完整的神经网络体系结构主机,以解决各种各样的任务和问题. 尽管有无数的神经网络架构,但对于 ...

  7. 利用循环神经网络生成唐诗_进化神经网络基本概念入门

    深入介绍了神经进化,其理论基础和该领域的标志性研究. 这篇博客文章是我关于该主题的系列文章中的第一篇文章. 神经进化是一种机器学习技术,可通过进化算法生成越来越好的拓扑,权重和超参数,从而改善作为人工 ...

  8. TensorFlow2.0(三)--Keras构建神经网络回归模型

    Keras构建神经网络回归模型 1. 前言 1. 导入相应的库 2. 数据导入与处理 2.1 加载数据集 2.2 划分数据集 2.3 数据归一化 3. 模型构建与训练 3.1 神经网络回归模型的构建 ...

  9. TensorFlow2.0(二)--Keras构建神经网络分类模型

    Keras构建分类模型 1. tf.keras简介 2. 利用tf.keras构建神经网络分类模型 2.1 导入相应的库 2.2 数据读取与展示 2.3 数据归一化 2.4 构建模型 2.5 模型的编 ...

最新文章

  1. 使用注解开发SpringMVC详细配置教程
  2. mysql当前时间减1小时_最佳睡眠时间:晚上睡眠不超8小时,午睡不超1小时
  3. Hyperlink的target属性的用法
  4. Android(五)——控制UI界面的方法
  5. C语言学习之有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中
  6. 一刀传世网页破天服务器同步,一刀传世破天1844服开服时间表_一刀传世新区开服预告_第一手游网手游开服表...
  7. 连续一个月,每天只吃一个苹果,身体会怎么样?
  8. python3 range函数_为什么python3中的xrange函数不能用
  9. 撩课-Java面试宝典-第十六篇
  10. 仿支付宝手势密码解锁
  11. oracle建表类型,oracle 建表类型以及约束
  12. 1.金融点滴 - 什么是做多、做空?国内股市为什么不能做空?
  13. 物联网-移远m26使用MQTT协议,AT指令对接阿里云
  14. 1233850-99-1|2-(4-丙氧基苯基)咪唑[4,5f][1,10]邻菲啰啉|分子式:C22H18N4O-齐岳配体
  15. 为什么onenote一直在加载_2.为什么人人都需要OneNote?
  16. Win10任务栏图标一直刷新的解决方法
  17. 《自然语言处理学习之路》 13 RNN简述,LSTM情感分析
  18. 【黑金ZYNQ7000系列原创视频教程】07.自定义IP——定制RTC IP实验
  19. Nextjs从入坑到发疯,开发起来太抓狂
  20. ZJYYC 黄月英奇门遁甲 ZJYYC1301

热门文章

  1. 豆瓣评分9.6,推荐一本人工智能入门书籍《21天学通Python》
  2. python自动产品分类_商品分类(一堆多)
  3. 粒子滤波 PF(Particle filter)算法
  4. uc打开html文件是空的,UC浏览器中打开不出现主页的解决方法
  5. 微型计算机结构框图,微型计算机系统结构图.doc
  6. Win11如何自动清理垃圾?Win11自动删除文件设置方法
  7. Matlab中的数值精度问题
  8. img的title和alt区别
  9. 你是哪类人?愚蠢的五大基本定律
  10. UE4材质UV纹理扭曲效果