赞
踩
GRU(Gated Recurrent Unit)是一种循环神经网络,它包含了一些特殊的门控机制,用于控制信息的流动和更新。比起RNN(Recurrent Neural Network),GRU支持隐状态的门控,这意味着模型有专门的机制来确定应该何时更新隐状态,以及应该何时重置隐状态。
GRU中的更新门(Update Gate)是其中一种门控机制,它可以控制新状态中有多少个是旧状态的副本。在GRU中,每个时刻都会有一个新的输入向量和一个旧的状态向量。更新门是一个sigmoid函数,它的输出控制了新状态中有多少是由旧状态的副本组成的。如果更新门的输出接近1,那么新状态就会完全由旧状态的副本组成,新的输入信息就会被完全忽略掉。如果更新门的输出接近0,那么旧状态就会被完全忽略掉,新的输入信息就会完全覆盖旧状态。此门控机制的好处是:它可以让模型根据需要选择性地保留旧状态中有用的信息,并忽略不必要的信息,从而更好地适应不同的输入序列。这对于处理长序列的任务特别有用,因为长序列中可能包含很多无关信息,而GRU的更新门可以帮助模型过滤掉这些无关信息,只保留有用的信息。
重置门(Reset Gate)也是GRU中的一种门控机制,它的作用是控制模型在当前时间步是否需要“遗忘”过去的状态信息。更具体地说,重置门允许我们控制“可能还想记住”的过去状态的数量。在GRU中,每个时间步都有一个当前的输入向量和一个旧的状态向量。重置门是一个sigmoid函数,它的输出表示在当前时间步,模型是否需要丢弃之前的状态信息。如果重置门的输出接近0,那么模型会忽略之前的状态信息,只根据当前输入来更新状态,从而更好地适应短序列数据。如果重置门的输出接近1,那么模型会保留之前的状态信息,并结合当前输入来更新状态,从而更好地适应长序列数据。此门控机制的好处是:它允许我们控制模型在当前时间步是否需要“遗忘”过去的状态信息,并且可以自适应地调整遗忘的数量。这种门控机制的设计可以让模型更好地适应不同的序列数据,从而提高模型的泛化能力和性能。
候选隐状态是更新门(Update Gate)和重置门(Reset Gate)所计算出的隐状态。具体来说,GRU的候选隐状态由以下公式计算:
其中,是当前时间步的输入,是上一个时间步的隐状态,是重置门,表示按元素相乘,、、和是可学习的参数。
在计算候选隐状态时,重置门和上一个时间步的隐状态相乘,得到的结果表示应该保留多少上一个时间步的信息。然后将当前时间步的输入和上一步的隐状态分别与对应的参数进行线性变换,再加上偏置项,得到两个向量。这两个向量分别与重置门相乘,得到的结果表示应该保留多少当前时间步的信息。将这两个向量相加,再通过tanh函数进行激活,得到候选隐状态。
接下来我来展示以下如何利用Keras来实现GRU的方法:(讲个题外话,之前我的前一篇文章LSTM我是用Pytorch实现的,但我发现相比于Keras的API更面向人类编程,更适合初学者,所以本篇教程我将用Keras来实现)
- from keras.models import Sequential
- from keras.layers import GRU, Dense
-
- model = Sequential()
- model.add(GRU(units=64, activation='tanh', input_shape=(10, 1)))
- model.add(Dense(units=1, activation='sigmoid'))
-
- model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
-
- # X_train shape: (batch_size, timesteps, input_dim)
- # y_train shape: (batch_size, output_dim)
- model.fit(X_train, y_train, batch_size=32, epochs=10)
首先导入了需要的库和模块,然后使用Sequential()
构建了一个序列模型。
在序列模型中,我添加了一个GRU层,该层具有64个神经元和tanh激活函数,并且输入形状为(10, 1)
。在此基础上我添加了一个全连接层,具有一个输出单元和sigmoid激活函数。
我使用compile()
方法来编译模型,指定优化器、损失函数和评估指标,并使用fit()
方法来训练模型。
GRU层的input_shape
应该是一个三元组(timesteps, input_dim)
,其中timesteps
表示输入序列的时间步数,input_dim
表示每个时间步的输入特征维度。在上面的代码中,我将timesteps
设置为10,input_dim
设置为1。
fit()
方法的输入数据X_train
和y_train
应该是Numpy数组,其中X_train
的形状应该是(batch_size, timesteps, input_dim)
,y_train
的形状应该是(batch_size, output_dim)
。
以下是使用Keras实现GRU模型来对MNIST手写数字数据集进行分类的代码示范,希望能对你对于如何代码实现GRU模型有更深的印象:
- import tensorflow as tf
- from keras.layers import GRU, Dense
- from keras.models import Sequential
- from keras.datasets import mnist
- from keras.utils import to_categorical
-
- # 加载数据集
- (x_train, y_train), (x_test, y_test) = mnist.load_data()
-
- # 数据预处理
- x_train = x_train.astype('float32') / 255.
- x_test = x_test.astype('float32') / 255.
- y_train = to_categorical(y_train, num_classes=10)
- y_test = to_categorical(y_test, num_classes=10)
-
- # 构建模型
- model = Sequential()
- model.add(GRU(units=128, activation='tanh', input_shape=(28, 28)))
- model.add(Dense(units=10, activation='softmax'))
-
- # 编译模型
- model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
-
- # 训练模型
- model.fit(x_train, y_train, batch_size=128, epochs=10, validation_data=(x_test, y_test))
-
- # 在测试集上评估模型
- test_loss, test_acc = model.evaluate(x_test, y_test)
- print('Test accuracy:', test_acc)
参考文献:
文章图片来自A. Zhang, Z. C. Lipton, M. Li and A. J. Smola, "Dive into Deep Learning," arXiv preprint arXiv:2106.11342, 2021.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。