Advertisement

pytorch nlp分类模型训练过程

阅读量:

一、数据预处理

1.首先获得需要分类的训练集
2.获取一个对训练集中的句子进行拆分的tokenizer
3.写一个方法 将句子拆分后的结果产生的单词,建立一个词汇表
4.现在已经有了词汇表,需要训练的句子,这时只需要将句子进行分词后,将分词后的结果传入到词汇表,获取句子中每个单词的token
5.需要对label也进行处理

二、 建立dataloader

主要是写一个函数,在建立dataloader时使用

复制代码
    # 对分组后的数据进行处理
    def collate_fn(batch):
    #     trian_iter中的数据都是单词
    #    比如 句子 标签
    # 这里将一个batch_size的数据参数 传入函数
    # 在将数据进行训练之前,将单词,标签等 都处理成数字对应的形式,这样模型才能对数据进行训练
    #     该函数需要返回的结果是
    #  1. batch_size * sentence_max_legth 的 tensor类型的 句子处理后的结果
    #  2. batch_size * lable长度的 tensor类型的 label处理后的结果
    text_list = []
    lable_list = []
    # 句子最大长度
    # 求出句子最大长度,在得到最终的text_list时 由于每个句子的长度都是不一样的
    # 需要将句子的长度都处理为长度相同的句子
    max_length = 0
    for (_label,_text) in batch:
        text_list.append(get_token_from_vocab(_text))
        lable_list.append(get_label(_label))
    
        if len(_text) > max_length:
            max_length = len(_text)
    
    text_list = [index + [0]*(max_length-len(index)) for index in text_list]
    return (torch.tensor(lable_list).to(torch.int64), torch.tensor(text_list).to(torch.int32))

三、建立模型

建立一个简单的模型

复制代码
    # 第三步 建立模型
    class Model(nn.Module):
    def __init__(self,vocab_size,embed_dim,num_class):
        super(Model,self).__init__()
        # 产生一个维度为 vocab_size * embed_dim大小的word_embedding 这样就通过每一行 来 唯一的确定一个单词
        self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=False)
        # 建立一个全连接层 full connection
        self.fc = nn.Linear(embed_dim, num_class)
    
    def forward(self,text_list):
        # 根据传来的batch 得到词嵌入
        embedded = self.embedding(text_list) # shape: [bs, embedding_dim]
        # 通过全连接层进行计算
        return self.fc(embedded)

四、使用模型进行训练并验证

复制代码
    # 第四部 训练
    def train(train_dataloader,eval_dataloader,model,optimizer,loss_fn,epochs,device):
    model=model.to(device)
    total_acc = 0
    start_time = time.time()
    
    for epoch in range(epochs):
        num_batches = len(train_dataloader)
        for i, (y,X) in enumerate(train_dataloader):
            X = X.to(device)
            y = y.to(device)
            pred = model(X)
            loss = loss_fn(pred, y)
            optimizer.zero_grad()
            loss.backward()
            # 梯度裁剪
            torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)
            optimizer.step()
            # 计算总的准确率
            total_acc += (pred.argmax(1) == y).sum().item()
            # 表示已经训练了多少个batch_size 一个batch_size = 64
            step = num_batches*(epoch) + i + 1
    
            if step % 300 == 0:
                elapsed = time.time() - start_time
                print(f"train_time:{elapsed} epoch_index: {epoch}, 已经训练batch_size: {step}, ema_loss: {loss.item()}")
    
        print("start to do evaluation...")
        model.eval()
        eval_acc = 0
        eval_total_account = 0
        for i, (y,X) in enumerate(eval_dataloader):
            X = X.to(device)
            y = y.to(device)
            eval_pred = model(X)
            eval_loss = loss_fn(eval_pred, y)
            eval_acc += (eval_pred.argmax(1) == y).sum().item()
            eval_total_account += y.shape[0]
        eval_acc = eval_acc / eval_total_account
        print(f"eval_loss: {eval_loss.item()}, eval_acc: {eval_acc}")
        model.train()
    print("done!")

五、调用方法

复制代码
    # 第五步 开始训练
    if __name__ == "__main__":
    vocab_size = len(vocab)
    embed_dim = 64
    BATCH_SIZE = 64
    epoches = 10
    model = Model(vocab_size,embed_dim,4)
    train_iter = AG_NEWS(root='data', split='train') # Dataset类型的对象
    eval_iter = AG_NEWS(root='data', split='test') # Dataset类型的对象
    train_dataloader = DataLoader(to_map_style_dataset(train_iter), batch_size=BATCH_SIZE, collate_fn=collate_fn, shuffle=True)
    eval_dataloader = DataLoader(to_map_style_dataset(eval_iter), batch_size=8, collate_fn=collate_fn)
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
    loss_fn = torch.nn.CrossEntropyLoss()
    train(train_dataloader,eval_dataloader,model,optimizer,loss_fn,epoches,device)

全部评论 (0)

还没有任何评论哟~