hongtao avatar

Tensorflow 2.0 —— RNN实战路透社新闻分类

hongtao

Published: 20 Jan 2020 › Updated: 20 Jan 2020Tensorflow 2.0 —— RNN实战路透社新闻分类

Tensorflow 2.0 —— RNN实战路透社新闻分类

img

Image from unsplash.com by @Jason_xj

之前的文章我们介绍了 RNN 循环网络并用循环网络成功地预测了牛奶产量。这篇文章我们继续使用 RNN 以及 LSTM 和 GRU 处理分类问题。我们使用的是 Keras 自带的数据集——路透社新闻分类问题。

关注微信公众号获取源代码(二维码见文末)

1. RNN 回顾

与卷积神经网络处理空间局部相关性数据不同,循环网络主要用于处理时间序列 (Sequence)相关的问题,既数据具有时间前后相关性,比如股市行情,语音文本等。

我们当然可以使用全连接的神经网络处时间理序列问题,但是对于该类问题循环网络相对于全连接网络的优势有两个:

1.RNN 可以通过共享权值,大大减少了参数数量。

举一个语句情感分类的例子:一段影评到底是正面还是负面。如果使用全连接的神经网络,那么我们可能会将一个评论里面的每一个单词都建一个神经网络,每个神经网络虽然可以结构相同但是参数是不同的。

循环神经网络可以共享一套权值,单词通过这一个神经网络按时间顺序输入即可。

2.全连接神经网络无法像 RNN 这样感知前文 (甚至后文) 的语义信息,导致整个句子语义丢失。

2. 数据集简介及导入

该数据集包含 11,228 条新闻,被标记成了 46 个类别,应该就是时政,娱乐什么之类的。模型的训练目标既为读新闻内容识别新闻类别。

数据导入跟之前没有太大差别,但是需要注意的是我们拿到的训练集 x_trian 是一个单词已经被数字编码了。

(x_train, y_train),(x_test, y_test) = keras.datasets.reuters.load_data(num_words = total_words)

这里需要注意的是原始数据每篇新闻的长度不同,新闻是以 list 的形式存在一维 numpy array 中的。这我们需要统一新闻长度,将不足长度的地方 pad 为0。

## pad sequence to the same length
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen = max_news_words)
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen = max_news_words)

数据预处理部分并没有 reshape 输入,仅仅是将标签 y 进行了 one hot 编码。

同时需要注意在 batch 处理数据的时候让 drop_remainder = True,这样可以丢弃掉最后一个数量不足 batch size 的 batch.

def preprocess(x,y):
  y = tf.one_hot(y, depth=num_classes)
  return x, y

# shuffle and batch dataset and drop the last batch shorter than batch_size
ds_train = ds_train.shuffle(1000).map(preprocess).batch(batch_size, drop_remainder = True)
ds_test = ds_test.shuffle(1000).map(preprocess).batch(batch_size, drop_remainder = True)

3. RNN模型建立

在 keras 当中我们有两种方式建立 RNN 模型,比较推荐的方式是调用 layers.SimpleRNN 类。该类之前文章介绍的方式一致,比较简单,不需要手动处理层与层之间的状态信息。

另一种方式是调用 layers.SimpleRNNCell,这种方式比较底层,需要手动处理层与层之间的状态信息。这种方式虽然麻烦,但是有利于加深我们对 RNN 的理解,所以本文以这种方式为主介绍 RNN 模型的建立。

首先,定义状态参数,没层RNN 只有一个状态参数,初始化为0,注意其 shape

class RNN(keras.Model):
  def __init__(self, num_units, num_classes):
    super().__init__()
  
    #state = [[h]] -> [[b, unites]]
    self.state0 = [tf.zeros([batch_size, num_units])]
    self.state1 = [tf.zeros([batch_size, num_units])]

其次,这里需要添加一个 embbeding 层,需要强调的是对于文本处理 embbeding 是必要的。其作用是将输入的单词进行编码。这里我们直接使用 Keras 的 layers.Embedding层进行编码。

embbeding 转化后的 shape 是这样的 [batch_size, seq_len, feature_len],其中 seq_len 表示一个句子中有多少个单词,这里我们定义为 max_new_words。feature_len 表示编码后,一个单词的特征纬度,这里我们设置为 embedding_len。

注意这一层也是参与训练的。

    # embedding [b, 200] -> [b, 200, 100]
    self.embedding = layers.Embedding(total_words, embedding_len, input_length=max_news_words)

然后,定义两层带 dropout 的 RNN 层,和最后一个全连接的输出层

    self.RNNcell0 = layers.SimpleRNNCell(num_units, dropout=0.5)
    self.RNNcell1 = layers.SimpleRNNCell(num_units, dropout=0.5)
    self.fc = layers.Dense(num_classes)

最后,当然是定义 call 函数。这里注意两点

  1. 由于带有 dropout 所以需要传入 training 参数,以便区分训练和验证两种状态。
  2. State 参数需要手动更新。
def call(self, inputs, training = None):


    #[b, max_news_words] -> [b, max_news_words, embedding_len]
    words = self.embedding(inputs)

    # for every words in sequence
    # [b, max_news_words, embedding_len] -> unstack [b, embedding_len]

    state0 = self.state0
    state1 = self.state1

    for word in tf.unstack(words, axis = 1):
      # state1 = out1 = x*w_x + state0*w_state + b
      # state out [b, num_units]
      out0, state0 = self.RNNcell0(word, state0, training)
      out1, state1 = self.RNNcell1(out0, state1, training)

    outputs = self.fc(out1)

    return outputs

4. 模型的训练可视化

模型的训练与之前相同既可以使用 Keras 封装好的,compile 和 fit 方法,也可以使用更加灵活的 Tensorflow 2.0 就不在这里赘述了,tf.GradientTape() 方式。不过注意的是在使用 model.fit 方式的时候需要设置一个参数 experimental_run_tf_function=False, 否则会报错。我也不知道什么原因,官方目前也没解释。

可视化的化,当然推荐使用 Tensorboard,祥见前文

5. 使用 LSTM 和 GRU

将 Simple RNN 替换成 LSTM 和 GRU 的方法非常简单,基本上就是将 layers.SimpleRNNCell 替换成 layers.LSTMCelllayers.GRUCell即可。但是需要注意的是 LSTM 状态信息参数是两个 h 和 c。 所以初始化 state 参数的时候两个参数都需要初始化。

# state=[h,c] =[[b, units],[b,units]]
    self.state0 = [tf.zeros([batch_size, num_units]), tf.zeros([batch_size, num_units])]
    self.state1 = [tf.zeros([batch_size, num_units]), tf.zeros([batch_size, num_units])]

相关文章

Tensorflow 2.0 --- ResNet 实战 CIFAR100 数据集

Tensorflow2.0——可视化工具tensorboard

Tensorflow2.0-数据加载和预处理

Tensorflow 2.0 快速入门 —— 引入Keras 自定义模型

Tensorflow 2.0 快速入门 —— 自动求导与线性回归

Tensorflow 2.0 轻松实现迁移学习

Tensorflow入门——Eager模式像原生Python一样简洁优雅

Tensorflow 2.0 —— 与 Keras 的深度融合

同步到我的简书

欢迎扫描二维码关注我的微信公众号“tensorflow机器学习”,一起学习,共同进步

image-20200120124818801

Leave Tensorflow 2.0 —— RNN实战路透社新闻分类 to:

Written by

Read more #cn-stem posts


Best Posts From hongtao

We have not curated any of hongtao's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From hongtao