一、GRU简介
循环神经网络(Recurrent Neural Network, RNN)一般用于处理序列数据。长短期记忆(Long Short-Term Memory, LSTM)是用于解决传统RNN无法处理长序列数据的问题。然而,LSTM参数过多,训练起来非常耗时。出于对参数数量和训练时间的考虑,Gated Recurrent Unit(GRU)诞生了。相对于LSTM,GRU拥有更少的参数以及更快的训练速度,而且在许多任务上的表现也相当不错。
GRU通过引入重置门(reset gate)和更新门(update gate)来控制序列和隐藏状态的信息流,以实现记忆单元和长短期记忆单元的功能。如果前一个时间步的输出不重要,则更新门将其设置为值为零。重置门有利于减少图像化贡献和自我注重性,以增强RNN对局部特征的表达能力。
二、KerasGRU模型结构
Keras是一种高级神经网络API,支持几乎所有类型的神经网络模型。在Keras中,使用GRU是非常简单的,理解模型的结构将使您更容易使用GRU及其他类型的神经网络。
GRU层可以通过keras.layers.GRU类来创建。以下是一个具有一个GRU层的简单Keras模型:
from keras.models import Sequential
from keras.layers import GRU, Dense
model = Sequential()
model.add(GRU(64, input_shape=(10, 32)))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
上面的代码片段是一个简单的Keras分类模型,其中包含一个具有64个节点的GRU层和一个sigmoid激活函数的密集层。维度(10,32)指的是输入序列的长度为10,每个时间步的维数为32。优化器使用Adam,损失函数为二元交叉熵。
三、KerasGRU参数详解
1. activation
GRU输出和隐藏状态的激活函数。默认为超bolic正切(tanh),但是也可以使用其他激活函数,例如ReLU或Sigmoid。
2. recurrent_activation
GRU重置门和更新门的激活函数。默认为超bolic正切(tanh),但是也可以使用其他激活函数,例如ReLU或Sigmoid。
3. use_bias
表示GRU是否使用偏置。默认为True。当设置为False时,初始状态必须提供。
4. kernel_initializer、recurrent_initializer、bias_initializer
初始化GRU层内权重和偏置的方法。默认为'glorot_uniform',即Xavier(高斯)初始化用于权重和偏置,但其他初始化方法也可以使用,例如'zeros'或'ones'等。
5. kernel_regularizer、recurrent_regularizer、bias_regularizer
正则化GRU权重和偏差的方法。例如,可以使用L1或L2正则化(通过设置'keras.regularizers.l1'或'keras.regularizers.l2')。使用正则化可以减少过拟合。
6. dropout、recurrent_dropout
Dropout是一种广泛用于神经网络的正则化方法,用于减少过拟合。dropout是一个小小的概率,在每个时间步应用于GRU输出,以丢弃一些节点,以提高网络的泛化能力和鲁棒性。recurrent_dropout是类似的机制,但是在重置门和更新门上应用。
7. implementation
GRU的内部计算可以使用高效的基于GPU的方法或者更慢但更精确的基于CPU的方法。默认情况下,'CuDNN'高效GPU实现被选择,但在某些情况下(例如,使用GPU下降器)它可能无法使用。因此,'cpu'可能更好。
四、KerasGRU应用
1.文本分类
GRU常用于处理文本数据的序列生成和分类问题。可以使用预训练的词嵌入器初始化GRU层,并使用softmax激活函数对输出进行分类。以下是一个示例,使用IMDB数据集对情感分析进行文本分类。
from keras.datasets import imdb
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Embedding, GRU, Dense
max_features = 10000
max_len = 500
batch_size = 32
print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')
print('Pad sequences (samples x time)...')
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)
model = Sequential()
model.add(Embedding(max_features, 32))
model.add(GRU(64, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(x_train, y_train, batch_size=batch_size, epochs=5, validation_data=(x_test, y_test))
score, acc = model.evaluate(x_test, y_test, batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
2.序列生成
通过预训练的GRU层,您可以将序列生成的问题看作是序列到序列(sequence-to-sequence)的问题。这里是一个实现元音字母的语音序列生成的示例。注意,这是一个基于字符的序列生成,GRU的输出维度为5(元音字母a,e,i,o,u)。
import numpy as np
from keras.models import Sequential
from keras.layers import GRU, Dense
from keras.optimizers import RMSprop
# Vocabulary
vowels = ['a', 'e', 'i', 'o', 'u']
vowels_idx = dict((c, i) for i, c in enumerate(vowels))
n_vowels = len(vowels)
# Dataset: Generate n dataset samples of length m
n, m = 32000, 10
x = np.random.choice(vowels, (n, m))
y = (x == 'a') | (x == 'e') | (x == 'i') | (x == 'o') | (x == 'u')
# One-hot encoding
x_ohe = np.zeros((n, m, n_vowels), dtype=np.bool)
for i in range(n):
for j in range(m):
x_ohe[i, j, vowels_idx[x[i, j]]] = 1
y_ohe = y.astype(np.float32)
# Split into train and test
split = int(0.8 * len(x))
x_train, y_train = x_ohe[:split], y_ohe[:split]
x_test, y_test = x_ohe[split:], y_ohe[split:]
# Build model
model = Sequential()
model.add(GRU(32, input_shape=(None, n_vowels)))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer=RMSprop(lr=0.01))
# Train the model
model.fit(x_train, y_train, batch_size=32, epochs=10, validation_data=(x_test, y_test))
# Predict vowel based on previous 3 characters
x_test = np.array([['u', 'o', 'u'], ['i', 'o', 'i']]) # 'ouu' and 'ioi'
x_test_ohe = np.zeros((2, 3, n_vowels), dtype=np.bool)
for i in range(2):
for j in range(3):
x_test_ohe[i, j, vowels_idx[x_test[i, j]]] = 1
y_test_pred = model.predict(x_test_ohe, verbose=0)
print(y_test_pred)
3.时间序列
GRU可用于时间序列问题,例如用于预测未来的股票价格。这里是一个小样本模拟,它说明如何使用KerasGRU建立和训练模型,以预测时间序列中的下一个步骤。
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import GRU, Dense
from keras.optimizers import RMSprop
# Generate noisy time series data
t = np.arange(0, 30, 0.1)
noise = np.random.randn(len(t))
x = np.sin(0.3 * t) + 0.1 * noise
plt.plot(t, x)
# Dataset
lookback = 10
delay = 3
n_train = 1500
n_test = 1000
def create_dataset(data, lookback, delay, min_index, max_index):
data = data.astype(np.float32)
samples = []
targets = []
for start in range(min_index, max_index - lookback - delay):
samples.append(data[start:start+lookback])
targets.append(data[start+lookback+delay])
return np.array(samples), np.array(targets)
x_train, y_train = create_dataset(x, lookback, delay, 0, n_train)
x_test, y_test = create_dataset(x, lookback, delay, n_train, n_train + n_test)
print(x_train.shape, y_train.shape)
# Build model
model = Sequential()
model.add(GRU(32, input_shape=(None, 1)))
model.add(Dense(1))
model.compile(loss='mse', optimizer=RMSprop(lr=0.01))
# Train the model
model.fit(np.expand_dims(x_train, axis=-1), y_train, batch_size=128, epochs=10, validation_data=(np.expand_dims(x_test, axis=-1), y_test))
# Predict future values
predictions = model.predict(np.expand_dims(x_test, axis=-1))
plt.plot(t[:len(x_test)], predictions)
plt.show()