Tensorflow 2.0 LSTM训练模型

说到lstm之前需要说一下循环神经网络(Recurrent Neural Network,RNN), RNN是一种用于处理序列数据的神经网络。相比一般的神经网络来说,他能够处理序列变化的数据,特别是时间序列数据。比如某个单词的意思会因为上文提到的内容不同而有不同的含义,RNN就能够很好地解决这类问题。

但RNN有个关键问题,在处理长序列后面时出现梯度消失和梯度爆炸的问题,lstm正好解决了这个问题。相比较RNN, lstm 在长序列数据上更容易取得更好表现。

lstm 还有一个类似的gru 模型,进一步精简了lstm的控制门数量,理论上表现应该更好。代码同lstm类似。此处不讲lstm的原理,只展示在tensorflow 2.0 中如何用lstm实现段落意义识别:

# 导入库
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
from tensorflow import keras
import numpy as np
from scipy import sparse

import os

# 只使用gpu 0
os.environ["CUDA_VISIBLE_DEVICES"] = "1" 

# 设置随机数种子
tf.random.set_seed(22)
np.random.seed(22)
assert tf.__version__.startswith('2.')

batchsz = 256 # batch size

# the most frequest words
total_words = 4096 # 要编码的字典中文字数目
max_review_len = 1995 # 序列最长包含多少词
embedding_len = 100 # 每个词编码的的长度

units = 64 # lstm layer中参数输出的维度
epochs = 100  #训练100个epches

# 读入数据,这儿是用稀疏矩阵储存的数据
matrixfile = "textword_numc_sparse.npz" # 导入自己的文字样本,文字已经转化为数字表示
targetfile = "target_5k6mer_tfidf.txt" # label,本次是二分类

allmatrix = sparse.load_npz(matrixfile).toarray() 
target = np.loadtxt(targetfile)
print("allmatrix shape: {};target shape: {}".format(allmatrix.shape, target.shape))

x = tf.convert_to_tensor(allmatrix, dtype=tf.int32)
x = keras.preprocessing.sequence.pad_sequences(x, maxlen=max_review_len)
y = tf.convert_to_tensor(target, dtype=tf.int32)

idx = tf.range(allmatrix.shape[0])
idx = tf.random.shuffle(idx)

# 划分训练集,验证集,测试集,按7:1:2比例来划分
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)):])
print(x_train.shape,x_val.shape,x_test.shape)

db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
db_train = db_train.shuffle(6000).batch(batchsz, drop_remainder=True).repeat()
db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
db_val = db_val.batch(batchsz, drop_remainder=True)
db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
db_test = db_test.batch(batchsz, drop_remainder=True)

# 搭建模型
network = Sequential([layers.Embedding(total_words, embedding_len,input_length=max_review_len),
                      layers.LSTM(units, dropout=0.5, return_sequences=True, unroll=True),
                      layers.LSTM(units, dropout=0.5, unroll=True),
					  # 如果采用gru,只需要把上面两层换成
					  # layers.GRU(units, dropout=0.5, return_sequences=True, unroll=True),
                      # layers.GRU(units, dropout=0.5, unroll=True),
                      layers.Flatten(),
                      #layers.Dense(128, activation=tf.nn.relu),
                      #layers.Dropout(0.6),
                      layers.Dense(1, activation='sigmoid')])

# 查看模型sumaary
network.build(input_shape=(None, max_review_len))
network.summary()

# 编译
network.compile(optimizer=keras.optimizers.Adam(0.001),
                  loss=tf.losses.BinaryCrossentropy(),
                  metrics=['accuracy'])

#训练,注意此处设置了setps_per_epoches, db_train中需要repeat(),不然有warning,具体见本人文章:https://blog.csdn.net/weixin_44022515/article/details/103884654

network.fit(db_train, epochs=epochs, validation_data=db_val,steps_per_epoch=x_train.shape[0]//batchsz)

network.evaluate(db_test)

注意事项:

  1. 保重gpu 足够大,不然会一直停留在如下状态:
2020-01-26 21:08:37.544395: W tensorflow/core/common_runtime/process_function_library_runtime.cc:675] Ignoring multi-device function optimization failure: Deadline exceeded: meta_optimizer exceeded deadline.
  1. 序列长度max_review_len 不能设置太长,使用imdb的数据字体长度设置为80可以取得很好效果。此例中我用max_review_len =1999或者1000效果都不是太好。使用max_review_len =4995 直接停留在1中的warning中,目前还没有好的解决办法。

如何把文字用数字唯一编码,输入tensorflow进行embeding

tensorflow要求embeding 层的输入为数字,如果‘我 爱 我 的 祖 国’ 可以用[1,2,1,3,4,5]这样每个数字代表一个字或者词组。可以用如下代码来编码

mydir=np.unique(total) # 获得字典,即文本中所有单词的唯一集合

# 为每个字命名一个数字,形成一个字典
kmerlist={
    
    } 
count=0
for kmer in mydir:
        kmerlist[kmer] = count
        count += 1
# 编码你的arrary或者文本,这儿是textword
textword_num=[[kmerlist[i] for i in text] for text in textword]

猜你喜欢

转载自blog.csdn.net/weixin_44022515/article/details/104103778