RNN 情感分类问题实战

#RNN 情感分类问题实战
#import  os
import  tensorflow as tf
import  numpy as np
from tensorflow import keras
from tensorflow.keras import layers, losses, optimizers, Sequential
tf.random.set_seed(22)
np.random.seed(22)

batchsz = 512 # 批量大小
total_words = 10000 # 词汇表大小N_vocab
max_review_len = 80 # 句子最大长度s,大于的句子部分将截断,小于的将填充
embedding_len = 100 # 词向量特征长度f

# 加载IMDB数据集,此处的数据采用数字编码,一个数字代表一个单词
#(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=total_words)
# 将数据保存到本地文件
#np.savez_compressed('data/ch12DL/imdb_data.npz', x_train=x_train, y_train=y_train, x_test=x_test, y_test=y_test)
#上面的代码将 IMDb 数据集下载并保存为一个名为 imdb_data.npz 的压缩文件。在这个文件中,你将包含训练集和测试集的输入数据 (x_train, x_test) 以及相应的标签数据 (y_train, y_test)。
#当你需要加载这些本地数据时,可以使用以下代码:
data = np.load('imdb_data.npz',allow_pickle=True)
x_train, y_train, x_test, y_test = data['x_train'], data['y_train'], data['x_test'], data['y_test']

print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
#查看样本数据
id=20
#此处的数据采用数字编码,一个数字代表一个单词
####参考教材内容,补全关键代码,重新运行#####
print(x_train(id))

#word_index = keras.datasets.imdb.get_word_index()
# 保存 word_index 字典到本地文件
#np.save("data/ch12DL/imdb_word_index.npy", word_index)

# 从本地文件重新加载 word_index 字典
word_index = np.load("imdb_word_index.npy", allow_pickle=True).item()
####参考教材内容,补全关键代码,重新运行##### 
word_index=keras.datasets.imdb.get_word_index()
print(word_index)

word_index = {k:(v+3) for k,v in word_index.items()}
word_index["<PAD>"] = 0
word_index["<START>"] = 1
word_index["<UNK>"] = 2  # unknown
word_index["<UNUSED>"] = 3
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
#print(reverse_word_index)
def decode_data(text):
    return ' '.join([reverse_word_index.get(i, '?') for i in text])
#查看样本数据
id=20
#此处的数据采用数字编码,一个数字代表一个单词
print(x_train[id])
# #查看样本数据:变换后
####参考教材内容,补全关键代码,重新运行##### 
print(decode_data(x_train[id]))

# 截断和填充句子,使得等长,此处长句子保留句子后面的部分,短句子在前面填充
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=max_review_len)
####参考教材内容,补全关键代码,重新运行#####  
x_test= keras.preprocessing.sequence.pad_sequences(x_test, maxlen=max_review_len)
# 构建数据集,打散,批量,并丢掉最后一个不够batchsz的batch
db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
db_train = db_train.shuffle(1000).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)
print('x_train shape:', x_train.shape, tf.reduce_max(y_train), tf.reduce_min(y_train))
print('x_test shape:', x_test.shape)
#查看样本数据
####参考教材内容,补全关键代码,重新运行#####   
decode_data(x_train[id])
class RNN_Model(keras.Model):
    # Cell方式构建多层网络
    def __init__(self, units):
        super(RNN_Model, self).__init__() 
        # 词向量编码 [b, 80] => [b, 80, 100]
####参考教材内容,补全关键代码,重新运行#####  
        self.embedding=layers.Embedding(total_words,embedding_len,input_length=max_review_len)
        # 构建RNN ,SimpleRNN方式
####参考教材内容,补全关键代码,重新运行#####  
        self.rnn=keras.Sequential([
            layers.SimpleRNN(units,dropout=0.5,return_sequences=True),
            layers.SimpleRNN(units,dropout=0.5)
        ])
        
        # 构建分类网络,用于将CELL的输出特征进行分类,2分类
        # [b, 80, 100] => [b, 64] => [b, 1]
####参考教材内容,补全关键代码,重新运行##### 
        self.outlayer=sequential([
            layers.Dense(32),
            layers.Dropout(rate=0.5),
            layers.ReLU(),
            layers.Dense(1)])

    def call(self, inputs, training=None):
        x = inputs # [b, 80]
        # embedding: [b, 80] => [b, 80, 100]
        x = self.embedding(x)
        # rnn cell compute,[b, 80, 100] => [b, 64]
        x = self.rnn(x)
        # 末层最后一个输出作为分类网络的输入: [b, 64] => [b, 1]
        x = self.outlayer(x,training)
        # p(y is pos|x)
        prob = tf.sigmoid(x)

        return prob

if __name__ == '__main__':
    units = 64 # RNN状态向量长度f
    epochs = 6   #50 # 训练epochs

    model = RNN_Model(units)
    # 装配
####参考教材内容,补全关键代码,重新运行#####
    model.compile(optimizer=optimizers.Adam(0.0001),loss=losses.BinaryCrossentropy(),metrics=['accuracy'])
    # 训练和验证
####参考教材内容,补全关键代码,重新运行##### 
    model.fit(db_train,epochs=epochs,validation_data=db_test)
    # 测试
    model.evaluate(db_test)