循环神经网络(RNN)
循环神经网络RNN能处理时间序列,过去几年中,应用 RNN 在语音识别,语言建模,翻译,图片描述等问题上已经取得一定成功,并且这个列表还在增长。RNN模型的一个代表是LSTM ,这是一种特别的 RNN,比标准的 RNN 在很多的任务上都表现得更好,因此获得了非常多的应用。值得一提的是,lstm的作者也Jürgen Schmidhuber 也是机器学习领域的大牛,名气比三巨头稍微低一些。该大牛和GAN的发明者Ian Goodfellow 之间有些互怼冲突,感兴趣的朋友可以查看这个文章从PM到GAN——LSTM之父Schmidhuber横跨22年的怨念(文字版) 。
双向循环神经网络(BRNN)
RNN和LSTM都只能依据之前时刻的时序信息来预测下一时刻的输出,但在有些问题中,当前时刻的输出不仅和之前的状态有关,还可能和未来的状态有关系。比如预测一句话中缺失的单词不仅需要根据前文来判断,还需要考虑它后面的内容,真正做到基于上下文判断。BRNN有两个RNN上下叠加在一起组成的,输出由这两个RNN的状态共同决定。因此BRNN是综合前后的信息来训练模型,在DNA结构预测等应用很多。关于BRNN可以参考这篇文章通俗易懂理解——双向LSTM.
使用双向LSTM预测DNA序列
将DNA序列用one_hot编码后,使用lstm和卷积神经网络连用可以用来预测DNA的功能,本代码试图复制论文“DanQ: a hybrid convolutional and recurrent deep neural network for quantifying the function of DNA sequences (Nucleic Acids Research, 2016, Vol. 44, No. 11 e107)“的网络结构,供感兴趣大家参考。one-hot编码请看本人文章字符串(如DNA序列,蛋白质序列)的编码和用于机器学习和神经网络
网络结构:
代码:
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
import numpy as np
from scipy import sparse
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
#导入要训练的数据
allmatrix = sparse.load_npz('allmatrix_sparse.npz').toarray().astype('float32') # 稀疏矩阵存储的数据
allmatrix = allmatrix.reshape(21030, 2000, 4) # one-hot编码
target = np.load('target.txt.npy')
x = tf.convert_to_tensor(allmatrix)
y = tf.convert_to_tensor(target, dtype=tf.int32)
# 分训练集,验证集,测试集(70:10:20)
idx = tf.range(allmatrix.shape[0])
idx = tf.random.shuffle(idx)
x_train, y_train = tf.gather(x, idx[:int(0.7 * len(idx))]), tf.gather(y, idx[:int(0.7 * len(idx))])
x_val, y_val = tf.gather(x, idx[int(0.7 * len(idx)):int(0.8 * len(idx))]), tf.gather(y, idx[int(0.7 * len(idx)):int(
0.8 * len(idx))])
x_test, y_test = tf.gather(x, idx[int(0.8 * len(idx)):]), tf.gather(y, idx[int(0.8 * len(idx)):])
batchsz = 256
db = tf.data.Dataset.from_tensor_slices((x_train, y_train))
db = db.shuffle(6000).batch(batchsz).repeat()
db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
db_val = db_val.batch(batchsz)
db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
db_test = db_test.batch(batchsz)
#构建双向LSTM
forward_lstm = layers.LSTM(320, return_sequences=True, unroll=True) # go_backwards 默认为false
backward_lstm = layers.LSTM(320,go_backwards=True,return_sequences=True, unroll=True)
# 注意前后lstm的 go_backwards 必须设置不同,一个为false一个为true
brnn = layers.Bidirectional(forward_lstm,merge_mode='concat',backward_layer=backward_lstm)
# 构建全局网络,包含卷积层,池化层,双向LSTM层
network = Sequential([layers.Conv1D(320, kernel_size=26, padding='valid', activation=tf.nn.relu), #1D卷积
layers.MaxPooling1D(13, 13), # 1D 池化层
layers.Dropout(0.2),
brnn, # 双向lstm
layers.Flatten(),
layers.Dense(64, activation=tf.nn.relu),
layers.Dropout(0.4),
layers.Dense(1, activation='sigmoid')])
# 查看网络结构
network.build(input_shape=(None, 2000, 4))
network.summary()
# 编译网络
network.compile(optimizer=optimizers.Adam(lr=0.5),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy']
)
# 训练网络
network.fit(db, epochs=200, validation_data=db_val,
validation_steps=2, steps_per_epoch=x_train.shape[0]//batchsz)
# 测试网络
network.evaluate(db_test)