TransformerEncoder影评测试

 

import os
import keras
import tensorflow as tf
from keras import layers
import numpy as np

#加载数据
def load_data(data_dir):
    """
    data_dir:train的目录或test的目录
    输出:
        X:评论的字符串列表
        y:标签列表(0,1)
    """
    classes = ['pos', 'neg']
    X, y = [], []
    for idx, cls in enumerate(classes):
        # 拼接某个类别的目录
        cls_path = os.path.join(data_dir, cls)
        os.listdir()
        # os.listdir:函数只返回当前目录下的文件和文件夹名称,不包括子目录中的内容。
        for file in os.listdir(cls_path):
            # 拼接单个文件的目录(cls_path/file)
            file_path = os.path.join(cls_path, file)
            with open(file_path, encoding='utf-8') as f:
                X.append(f.read().strip())
                y.append(idx)
    return X, np.array(y)

# input_size:输入样本的数量(词汇表大小)
# seq_len:表示序列的长度 (列的长度)
# embed_dim:表示词向量的维度(行的长度)
#Input Embedding和Positional Encoding
class PositionalEmbedding(layers.Layer): #PositionalEmbedding继承layers.Layer
    def __init__(self, input_size, seq_len, embed_dim):
        super(PositionalEmbedding, self).__init__()
        self.seq_len = seq_len
        # 词嵌入
        self.tokens_embedding = layers.Embedding(input_size, embed_dim)
        # 位置嵌入
        self.positions_embedding = layers.Embedding(seq_len, embed_dim)

    def call(self, inputs, *args, **kwargs):
        # 生成位置id
        positions = tf.range(0, self.seq_len, dtype='int32')
        te = self.tokens_embedding(inputs)
        pe = self.positions_embedding(positions)
        return te + pe

# transformer-encoder
class TransformerEncoder(layers.Layer): #TransformerEncoder继承layers.Layer
    def __init__(self, embed_dim, hidden_dim, num_heads, **kwargs):
        super(TransformerEncoder, self).__init__(**kwargs)
        # Multi-Head Attention层; num_heads 注意头的数量;key_dim 查询和键的每个注意力头的大小
        self.attention = layers.MultiHeadAttention(
            num_heads=num_heads, key_dim=embed_dim
        )
        # Feed Forward层
        self.feed_forward = keras.Sequential([
            layers.Dense(hidden_dim, activation='relu'), #隐藏层
            layers.Dense(embed_dim)#输出层
        ])
        # layernorm层
        self.layernorm1 = layers.LayerNormalization()
        self.layernorm2 = layers.LayerNormalization()

    def call(self, inputs, *args, **kwargs):
        # 计算Self-Attention
        attention_output = self.attention(inputs, inputs)
        # 进行第一个Layer & Norm
        ff_input = self.layernorm1(inputs + attention_output)
        # Feed Forward
        ff_output = self.feed_forward(ff_input)
        # 进行第二个Layer & Norm
        outputs = self.layernorm2(ff_input + ff_output)
        return outputs


def train():
    # 超参数
    vocab_size = 20000 #词汇表
    seq_len = 180  #句子长度,超过会被截断
    batch_size = 64 #最大批次
    hidden_size = 1024 #全连接层维度
    embed_dim = 256 #词向量维度(每一个词,我们需要用多少位的向量表示)
    num_heads = 8 #多头8,也就是self-attion是8个
    # 加载数据
    X_train, y_train = load_data("C://Users//Administrator//Desktop//重要办公//gan//gan//aclImdb//train")
    X_test, y_test = load_data("C://Users//Administrator//Desktop//重要办公//gan//gan//aclImdb//test")

    #向量化 (Tokenizer分词算法是NLP大模型最基础的组件,基于Tokenizer可以将文本转换成独立的token列表,进而转换成输入的向量成为计算机可以理解的输入形式)
    vectorization = layers.TextVectorization(
        max_tokens=vocab_size,  #词表大小
        output_sequence_length=seq_len, #最大长度
        pad_to_max_tokens=True
    )
    # 构建词表
    vectorization.adapt(X_train)
    # tokenize
    X_train = vectorization(X_train)
    X_test = vectorization(X_test)
    # 构建模型
    inputs = layers.Input(shape=(seq_len,)) #输入是180个词
    # 180*20000||20000*256  == 180*256 的数据形状
    x = PositionalEmbedding(vocab_size, seq_len, embed_dim)(inputs) #输入180个词,并且限制最大输入也就是180,超过就截切成180,180不够直接padding

    x = TransformerEncoder(embed_dim, hidden_size, num_heads)(x)
    #对文本数据进行平均池化操作
    x = layers.GlobalAveragePooling1D()(x)
    x = layers.Dropout(0.5)(x)
    outputs = layers.Dense(1, activation='sigmoid')(x)
    #构建函数模型,只需要传入输入和输出
    model = keras.Model(inputs, outputs)
    model.summary()
    # 训练
    model.compile(loss='binary_crossentropy', metrics=['accuracy'])
    model.fit(
        X_train,
        y_train,
        epochs=20,
        batch_size=batch_size,
        validation_data=(X_test, y_test)
    )


if __name__ == '__main__':
    train()



'''
TextVectorization 层将分三个阶段处理文本:
首先,移除标点符号,并将输入内容转换成小写。
接下来,将文本分割成单个字符串词的列表。
最后,使用已知词汇表将字符串映射为数字输出。

我们在此处可以尝试一个简单的方法,即多热编码,只考虑评论中是否存在术语。
例如,假设层词汇表为 ['movie', 'good', 'bad'],而评论为 'This movie was bad.'。
我们会将其编码为 [1, 0, 1],其中存在 movie(第一个词汇)和 bad(最后一个词汇)。
'''

#  训练数据目录 下载地址:http://ai.stanford.edu/~amaas/data/sentiment/
# - aclImdb
#     - test
#         - neg
#         - pos
#         - labeledBow.feat
#         - urls_neg.txt
#         - urls_pos.txt
#     - train
#         - neg
#         - pos
'''
这是一个电影影评数据集,neg中包含的评论是评分较低的评论,而pos中包含的是评分较高的评论。我们需要的数据分别是test里面的neg和pos,
以及train里面的neg和pos(neg表示negative,pos表示positive)。下面我们开始处理。
'''









  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值