pytorch+huggingface+bert实现一个文本分类

pytorch+huggingface+bert实现一个文本分类

1,下载模型

bert模型的目前方便的有两种:一种是huggingface_hub以及/AutoModel.load, 一种torch.hub。

(1) 使用huggingface_hub或者下载模型。

# repo_id:模型名称or用户名/模型名称

from huggingface_hub import hf_hub_download
from transformers import AutoModel, AutoTokenizer
hf_hub_download(repo_id='bert-base-chinese', filename="pytorch_model.bin", local_dir='./bert-base-chinese') # 共下载五个:pytorch_model.bin, config.json,vocab.txt, tokenizer_config.json, tokenizer.json


# 直接下载/从~/.cache/huggingface/hub或者从指定文件夹
model = AutoModel.from_pretrain('bert-base-chinese')
tokenizer = AutoTokenizer.from_pretrain('bert-base-chinese')

(2) 使用torch.hub下载模型

# repo_or_dir:例如hugggingface/pytorch-transformers或者pytorch/vision, 或者本地目录
# source:github/local,默认是="github"
model = torch.hub.load('huggignface/pytorch-transformers', 'model', 'bert-base-chinese',source='github')
tokenizer = torch.hub.load('huggingface/pytorch-transformers', 'tokenizer', 'bert-base-chinese', source='github')

2, 使用模型

tokenizer(text):返回字典,包含:input_ids, token_type_ids,attention_mask。

tokenizer.encode(text):只返回input_dis。

两种方式都限定了text的方式,要么是单句,要么是列表。返回的结果也只有两种:[seq_length], [batch_size, seq_length]。

注意一,如果设定return_tensors=‘pt’,那么只会返回一种[batch_size, seq-length]。预训练模型只接受[batch_size, seq_length]形式输入。

注意二,bert模型返回两个结果,第一个是所有的最后一层hidden, 第二个是pooler_output,也就是所有最后一层hidden的加和平均值。models默认返回dict结果,使用mdoel().keys()返回变量值。使用values()返回结果。

from transformers import AutoModel, AutoTokenizer
import torch

model = AutoModel.from_pretrained('./bert-base-chinese')
tokenizer = AutoTokenizer.from_pretrained('./bert-base-chinese')

def bert_encode(line):
    tokens = tokenizer(line, add_special_tokens=False, return_tensors='pt', padding=True, truncation=True, max_length=20)
    with torch.no_grad():
        last_hiddens, pooler_hidden = model(**tokens).values()
    return last_hiddens, pooler_hidden

3,利用last_hidden通过rnn+dense进行文本分类。

rnn模型的本质只需要注意输入的形状:input:[seq_length, batch_size, feature_size] ,hidden_size:[num_layers, batch_size, hidden_size]。batch_size,都是放在中间,符合rnn处理的特点。

其次注意一点,rnn返回两个个向量:

一个是所有token的最后一层hidden, [seq_length, batch_size, hidden_size]

一个是最后一个token的[num_layers, batch_size, hidden_size]

# 定义一个rnn模型
import torch
import torch.nn as nn
import torch.nn.functional as f

class myRNN(nn.Module):
    def __init__(self, input_size, output_size, hidden_size, num_layers):
        super().__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.rnn = nn.RNN(input_size, hidden_size, num_layers=num_layers)
        self.dense = nn.Linear(hidden_size * num_layers, output_size)

    def forward(self, input_tokens):
        """
        :param input_tokens: size()=[batch_size, seq_legnth, input_size]
        :return: [batch_size, output_size]
        """
        batch_size = input_tokens.size()[0]
        hidden0 = self.init_hidden(batch_size)
        input_tokens = input_tokens.transpose(0, 1)
        all_hiddens, last_hiddens = self.rnn(input_tokens, hidden0) # last_hiddensize.size() = [num_layers, batch_szie, hidden_size]
        last_hiddens = last_hiddens.transpose(0,1).reshape((batch_size, -1))
        last_hiddens = f.relu(last_hiddens)
        return self.dense(last_hiddens)


    def init_hidden(self, batch_size):
        return torch.zeros(size=(self.num_layers, batch_size, self.hidden_size))

4, 组装模型。

import torch.nn as nn
import torch

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.bert = bert_encode
        self.rnn = myRNN(768,2, 768, 2)

    def forward(self, lines):
        tokens = self.bert(lines)[0]
        return self.rnn(tokens)

5, 编写训练脚本。

训练脚本具有通用性,参见训练脚本介绍。

from tqdm import tqdm
import torch
import time
import pickle

def train(epoches, model, dataloader, optim, criterion, model_save_path):
    loss_mark = float('inf')
    loss_store = [] # 收集每一轮的loss
    acc_store = [] # 收集每一轮的acc率
    model_num = 0
    for epoch in tqdm(range(epoches)):
        loss_sum = 0
        acc_sum = 0
        start = time.time()
        for batch_num , (batch_line, batch_category) in tqdm(enumerate(dataloader)):
            batch_pred = model(batch_line)
            acc = (batch_pred.argmax(-1) == batch_category).sum().item()
            acc_sum += acc
            loss = criterion(batch_pred, batch_category)
            loss_sum += loss.item()
            optim.zero_grad()
            loss.backward()
            optim.step()
            if batch_num % 100 == 0:
                print(f"batch_num: {batch_num} | timesince: {time.time() - start}")
                start = time.time()
                print(f"loss: {loss} | acc: {acc/len(batch_category)}")
        print(f"epoch {epoch} | loss: {loss_sum / len(dataloader)} | acc: {acc_sum}")
        loss_store.append(loss_sum/len(dataloader))
        acc_store.append(acc_sum)
        if loss_sum  < loss_mark:
            loss_store = loss_sum
            torch.save(f'{model_save_path}/{model_num}.pth', pickle_module=pickle, pickle_protocol=2)
            model_num += 1
        return loss_store, acc_store

6, 编写测试脚本

def valid(model, dataloader, criterion):
    loss_sum = 0
    with torch.no_grad():
        for batch_line, batch_category in dataloader:
            batch_pred = model(batch_line)
            loss = criterion(batch_pred, batch_category)
            loss_sum += loss.item()
    return loss_sum / len(dataloader)

7, 读取数据,进行训练。

主要是dataset的构建。

import pandas as pd
from torch.utils.data import Dataset, DataLoader

class MyDataset(Dataset):
    def __init__(self, lines, category):
        super().__init__()
        self.lines = lines
        self.category = category

    def __getitem__(self, item):
        return self.lines[item], self.category[item]

    def __len__(self):
        return len(self.lines)

train_data = pd.read_csv('./train_data.csv', header=None, sep='\t')
category, lines = train_data[0].tolist(), train_data[1].tolist()
datasets = MyDataset(lines, category)
dataloader = DataLoader(datasets, batch_size=10, shuffle=True)

model = Model()
optim = Adam(model.parameters(), lr=1e-3)
criterion = CrossEntropyLoss()

train(epoches=1, model=model, dataloader=dataloader, optim=optim, criterion=criterion, model_save_path='./models')
	

8,读取模型进行预测。

读取模型时注意,如果保存的是模型全模型,那么在当前文件内需要有模型的定义。如果是参数,那么需要实体化一类模型类,使用load_state_dict()方法。

import torch
import pickle
from bert_encode import bert_encode
from MyRnn import myRNN
import torch.nn as nn

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.bert = bert_encode
        self.rnn = myRNN(768, 2, 768, 2)

    def forward(self, lines):
        tokens = self.bert(lines)[0]
        return self.rnn(tokens)

model = torch.load('./models/1.pth', pickle_module=pickle)

def predict(batch_lines, model):
    batch_output = model(batch_lines)
    return batch_output.argmax(-1)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要用PyTorch实现BERT的中文多分类任务,可以按照以下步骤进行: 1. 准备数据:首先需要将中文多分类数据集准备好,并对其进行处理,使其适合输入BERT模型。可以使用PyTorch提供的Dataset和DataLoader类来加载数据集,并将文本数据转化为BERT模型需要的张量形式。 2. 加载预训练模型PyTorch提供了许多已经在海量文本数据上预训练好的BERT模型。可以使用HuggingFace提供的transformers库中的预训练模型进行加载。 3. 修改网络结构:加载预训练模型后,需要对其进行微调,以适应中文多分类任务。可以添加一个全连接层,将预训练模型的输出连接到全连接层,从而得到最终的分类结果。 4. 训练模型:将准备好的数据集输入到BERT模型中,使用反向传播算法更新模型参数,直到训练损失收敛。 5. 模型评估:使用测试集对模型进行评估,可以计算准确率、精度、召回率等指标,以评估模型的性能。 以上是使用PyTorch实现BERT中文多分类的大致步骤。具体实现需要参考相关文档和代码。 ### 回答2: PyTorch一个非常流行的深度学习库,可以用于实现BERT中文多分类任务。下面我将简要介绍如何使用PyTorch实现这个任务。 首先,我们需要安装PyTorch和transformers(一个用于自然语言处理的库,其中包括了预训练的BERT模型)。 接下来,我们需要加载预训练的BERT模型和tokenizer。你可以通过以下代码加载中文的BERT模型: ```python from transformers import BertForSequenceClassification, BertTokenizer model_name = 'bert-base-chinese' num_labels = 10 # 根据你的分类任务设定类别数量 tokenizer = BertTokenizer.from_pretrained(model_name) model = BertForSequenceClassification.from_pretrained(model_name, num_labels=num_labels) ``` 然后,我们需要加载和预处理我们的数据。你可以使用PyTorch的Dataset和DataLoader来完成这个任务。你需要将你的文本数据转换为BERT可以理解的格式: ```python # 假设你的数据是一个包含文本和标签的列表 data = [ {'text': '这是文本1', 'label': 0}, {'text': '这是文本2', 'label': 1}, # 更多样本... ] # 将文本转换为BERT可以理解的格式 inputs = tokenizer.batch_encode_plus( [item['text'] for item in data], pad_to_max_length=True, max_length=512, # 根据你的文本长度设定 truncation=True, return_tensors='pt' ) # 创建PyTorch的Dataset dataset = torch.utils.data.TensorDataset( inputs['input_ids'], inputs['attention_mask'], torch.tensor([item['label'] for item in data]) ) # 创建PyTorch的DataLoader dataloader = torch.utils.data.DataLoader( dataset, batch_size=16, # 根据你的显存大小设定 shuffle=True ) ``` 最后,我们可以开始训练模型。下面是一个非常简单的训练循环: ```python device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model.to(device) optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5) for epoch in range(10): # 根据你的训练需求设定迭代次数 model.train() for input_ids, attention_mask, labels in dataloader: input_ids = input_ids.to(device) attention_mask = attention_mask.to(device) labels = labels.to(device) optimizer.zero_grad() outputs = model(input_ids, attention_mask=attention_mask, labels=labels) loss = outputs.loss loss.backward() optimizer.step() ``` 这是一个简单的PyTorch实现BERT中文多分类的示例。你可以根据你的具体任务需求进行适当的修改和调整。同时,你可能还需要评估模型和保存/加载模型等操作。 ### 回答3: PyTorch一个开源深度学习框架,可以方便地实现BERT中文多分类任务。下面是一个使用PyTorch实现BERT中文多分类的简单示例: 1. 数据准备:首先,需要准备用于训练和测试的中文文本数据集。数据集应包含已经标注好类别的样本。 2. 数据预处理:使用中文分词工具对文本数据进行分词处理,并根据需要进行数据清洗和处理。可以使用NLTK或jieba等开源中文分词工具。 3. BERT模型加载:从Hugging Face的Transformers库中导入预训练的BERT模型和tokenizer。可以选择不同的中文BERT模型,如BERT-Base、BERT-Large等。 4. 构建模型:使用PyTorch构建BERT分类模型。根据需要,可以添加dropout层、全连接层等。 5. 设置优化器和损失函数:选择一个合适的优化器和损失函数,如Adam优化器和交叉熵损失函数。 6. 训练模型:使用训练数据来训练BERT模型。可以选择合适的epochs、batch size等参数。 7. 模型评估:使用测试数据对训练好的模型进行评估。计算模型在测试集上的准确率、精确率、召回率等指标。 8. 模型应用:使用已经训练好的模型对新的中文文本进行分类预测。 需要注意的是,以上是一个简要的流程,实际应用中还需要对数据进行进一步处理和优化,例如处理不平衡的类别分布、调整模型参数等。此外,还可以使用交叉验证等技术来进一步提高模型的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值