• 【Coggle 30 Days of ML】汽车领域多语种迁移学习挑战赛(4)


    目录

    任务

    Just Do It!  

     1.Bert模型入门

    1.1前置知识

    1.2导入预训练模型

    1.3训练数据处理

     1.4数据及读取及模型定义

    2.Bert文本分类

    2.1开始读取数据集

    2.2加载模型

    2.3开始训练

     2.4预测


    任务

    Just Do It!  

     1.Bert模型入门

    1.1前置知识

    bert模型用的库主要是huggingface的transformers库

    目前Transformers 库支持三个最流行的深度学习库(PyTorch、TensorFlow 和 JAX)。

    Transformers 库比较重要的有:pipeline、AutoTokenizer、AutoModelForSequenceClassification等等的使用。

    Pipeline

    pipeline() 的作用是使用预训练模型进行推断,它支持从 这里 下载的所有模型。它将模型的预处理, 后处理等步骤包装起来,使得我们可以直接定义好任务名称后,输出文本,直接得到我们需要的结果。这是一个高级的API,可以让我们领略到transformers 这个库的强大且友好。

    使用pipeline的api,可以使用transformers快速完成各种任务.

    主要有以下三个步骤被包装起来了:

    1. 输入文本被预处理成机器可以理解的格式
    2. 被处理后的输入被传入模型中
    3. 模型的预测结果经过后处理,得到人类可以理解的结果

    eg:

    上述是调用pipeline快速使用transformer,上述选择模型部分除了指定model外,还可以使用本地加载。

    1. from transformers import AutoModelForSequenceClassification
    2. from transformers import AutoTokenizer
    3. from transformers import pipeline
    4. model_path = r"ckiplab/bert-base-chinese-ner"
    5. model = AutoModelForSequenceClassification.from_pretrained(model_path)
    6. tokenizer = AutoTokenizer.from_pretrained(model_path)
    7. classifier = pipeline(task='ner',model=model,tokenizer=tokenizer)
    8. text = '我爱自然语言处理技术.我爱北京天安门!'
    9. for entity in generator(text):
    10. print(entity)

    AutoTokenizer

    这个类是用来自动下载与模型相关联的标记器,并且可以进行实例化。主要是在将数据喂给模型之前,将数据进行预处理(Tokenize、填充、截断等)。

    AutoModelForSequenceClassification

    主要是用来加载模型的。这个类是用来去下载模型本身。(注意:⚠️如果我们在别的任务上使用这个库,模型的类会发生改变)

    我们已经得到了预训练模型,那么下面就要将输入转化为模型能够接受的形式。怎么转化呢?就是把输入的字符串通过刚刚导入的分词器tokenizer进行转化。

    1. inputs = tokenizer(["阿水很帅,我也这样觉得。", "不对啊,你在欺骗我"], truncation=True, max_length=20, padding=True)
    2. inputs
    3. # input_ids:这个字在vocab次序
    4. # token_type_ids:字符是第一个句子的,还是第二个句子的
    5. # attention_mask:字符是不是padding的?

    tokenizer后的inputs为字典,包含三个键input_ids、token_type_ids、attention_mask。

    inputs_ids:为输入字符串中的每个字对应到词典vocab中的序号。其中每句话的开头结尾都添加了特殊标记,开头的特殊标记经过tokenizer变成了101,结尾的编程102。

    token_type_ids:字符是第一个句子的,还是第二个句子的。不同的句子对应的标记值也不一样。

    attention_mask:主要输入的几个句子当中最长的一句,如果打开了padding,那他就会把其他比最长的一句用0给填补上。观察上图attention_mask的后面3个0就意味着填补。


    前置知识了解的差不多了,下面对应到比赛中,步骤如下:

    1.2导入预训练模型

    我们要做的第一件事就是导入预训练模型

    1. from transformers import AutoTokenizer, AutoModelForMaskedLM, AutoConfig, BertModel, AutoModel
    2. model = AutoModel.from_pretrained("hfl/chinese-roberta-wwm-ext")
    3. tokenizer = AutoTokenizer.from_pretrained("bert-base-multilingual-cased")
    4. config = AutoConfig.from_pretrained("bert-base-multilingual-cased")

    1.3训练数据处理

    我们需要先对训练集做一些处理,把训练集中的标签种类去掉。

    1. for tag in ['intent', 'device', 'mode', 'offset', 'endloc', 'landmark', 'singer', 'song']:
    2. train_ja['槽值1'] = train_ja['槽值1'].str.replace(f'{tag}:', '')
    3. train_ja['槽值2'] = train_ja['槽值2'].str.replace(f'{tag}:', '')
    4. train_cn['槽值1'] = train_cn['槽值1'].str.replace(f'{tag}:', '')
    5. train_cn['槽值2'] = train_cn['槽值2'].str.replace(f'{tag}:', '')
    6. train_en['槽值1'] = train_en['槽值1'].str.replace(f'{tag}:', '')
    7. train_en['槽值2'] = train_en['槽值2'].str.replace(f'{tag}:', '')

    然后再将训练集中的中英日文拼接在一起,再使用pd.factorize对训练集进行编码。

    pd.factorize简单来说就是将所有输入的字符做一个unique,去掉相同的字,只剩下两两互斥的列表,假设叫list_unique。然后遍历一遍输入的每个字,根据这个字在list_unique中的位置做一个编码。

    1. train_df = pd.concat([
    2. train_ja[['原始文本', '意图', '槽值1', '槽值2']],
    3. train_cn[['原始文本', '意图', '槽值1', '槽值2']].sample(10000),
    4. train_en[['原始文本', '意图', '槽值1', '槽值2']],
    5. ],axis = 0)
    6. train_df = train_df.sample(frac=1.0)
    7. train_df['意图_encode'], lbl_ecode = pd.factorize(train_df['意图'])

     1.4数据及读取及模型定义

    定义数据集读取类和模型类

    1. from torch.utils.data import Dataset, DataLoader, TensorDataset
    2. import torch
    3. from torch import nn
    4. # 数据集读取
    5. class XunFeiDataset(Dataset):
    6. def __init__(self, encodings, intent):
    7. self.encodings = encodings
    8. self.intent = intent
    9. # 读取单个样本
    10. def __getitem__(self, idx):
    11. item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
    12. item['label'] = torch.tensor(int(self.intent[idx]))
    13. return item
    14. def __len__(self):
    15. return len(self.intent)
    16. class XunFeiModel(nn.Module):
    17. def __init__(self, num_labels):
    18. super(XunFeiModel,self).__init__()
    19. self.model = model = AutoModel.from_pretrained("bert-base-multilingual-cased")
    20. self.dropout = nn.Dropout(0.1)
    21. self.classifier = nn.Linear(768, num_labels)
    22. def forward(self, input_ids=None, attention_mask=None,labels=None):
    23. outputs = self.model(input_ids=input_ids, attention_mask=attention_mask)
    24. sequence_output = self.dropout(outputs[0]) #outputs[0]=last hidden state
    25. logits = self.classifier(sequence_output[:,0,:].view(-1,768))
    26. return logits

    2.Bert文本分类

    2.1开始读取数据集

    1. train_encoding = tokenizer(train_df['原始文本'].tolist()[:-500], truncation=True, padding=True, max_length=40)
    2. val_encoding = tokenizer(train_df['原始文本'].tolist()[-500:], truncation=True, padding=True, max_length=40)
    3. train_dataset = XunFeiDataset(train_encoding, train_df['意图_encode'].tolist()[:-500])
    4. val_dataset = XunFeiDataset(val_encoding, train_df['意图_encode'].tolist()[-500:])
    5. # 单个读取到批量读取
    6. train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
    7. val_dataloader = DataLoader(val_dataset, batch_size=16, shuffle=False)

    2.2加载模型

    将模型加载到gpu上(如果有的话),没有gpu就用cpu加载。

    1. model = XunFeiModel(18)
    2. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    3. # device = 'cpu'
    4. model = model.to(device)

    2.3开始训练

    1. from torch.nn import CrossEntropyLoss
    2. from torch.optim import AdamW
    3. loss_fn = CrossEntropyLoss() # ingore index = -1
    4. optim = AdamW(model.parameters(), lr=5e-5)
    5. def train():
    6. model.train()
    7. total_train_loss = 0
    8. iter_num = 0
    9. total_iter = len(train_loader)
    10. for batch in train_loader:
    11. # 正向传播
    12. optim.zero_grad()
    13. input_ids = batch['input_ids'].to(device)
    14. attention_mask = batch['attention_mask'].to(device)
    15. label = batch['label'].to(device)
    16. pred = model(
    17. input_ids,
    18. attention_mask
    19. )
    20. loss = loss_fn(pred, label)
    21. # 反向梯度信息
    22. loss.backward()
    23. torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    24. # 参数更新
    25. optim.step()
    26. iter_num += 1
    27. if(iter_num % 100 == 0):
    28. print("iter_num: %d, loss: %.4f, %.2f%% %.4f" % (
    29. iter_num, loss.item(), iter_num/total_iter*100,
    30. (pred.argmax(1) == label).float().data.cpu().numpy().mean(),
    31. ))
    32. def validation():
    33. model.eval()
    34. label_acc = 0
    35. for batch in val_dataloader:
    36. with torch.no_grad():
    37. input_ids = batch['input_ids'].to(device)
    38. attention_mask = batch['attention_mask'].to(device)
    39. label = batch['label'].to(device)
    40. pred = model(
    41. input_ids,
    42. attention_mask
    43. )
    44. label_acc += (pred.argmax(1) == label).float().sum().item()
    45. label_acc = label_acc / len(val_dataloader.dataset)
    46. print("-------------------------------")
    47. print("Accuracy: %.4f" % (label_acc))
    48. print("-------------------------------")
    49. for epoch in range(2):
    50. train()
    51. validation()

     2.4预测

    1. def prediction():
    2. model.eval()
    3. test_label = []
    4. for batch in test_dataloader:
    5. with torch.no_grad():
    6. input_ids = batch['input_ids'].to(device)
    7. attention_mask = batch['attention_mask'].to(device)
    8. pred = model(input_ids, attention_mask)
    9. test_label += list(pred.argmax(1).data.cpu().numpy())
    10. return test_label
    11. test_encoding = tokenizer(test_en['原始文本'].tolist(), truncation=True, padding=True, max_length=40)
    12. test_dataset = XunFeiDataset(test_encoding, [0] * len(test_en))
    13. test_dataloader = DataLoader(test_dataset, batch_size=16, shuffle=False)
    14. test_en_intent = prediction()
    15. test_encoding = tokenizer(test_ja['原始文本'].tolist(), truncation=True, padding=True, max_length=40)
    16. test_dataset = XunFeiDataset(test_encoding, [0] * len(test_ja))
    17. test_dataloader = DataLoader(test_dataset, batch_size=16, shuffle=False)
    18. test_ja_intent = prediction()
    19. test_ja['意图'] = [lbl_ecode[x] for x in test_ja_intent]
    20. test_en['意图'] = [lbl_ecode[x] for x in test_en_intent]
    21. test_en['槽值1'] = np.nan
    22. test_en['槽值2'] = np.nan
    23. test_ja['槽值1'] = np.nan
    24. test_ja['槽值2'] = np.nan
    25. writer = pd.ExcelWriter('submit.xlsx')
    26. test_en[['意图', '槽值1', '槽值2']].to_excel(writer, sheet_name='英文_testA', index=None)
    27. test_ja[['意图', '槽值1', '槽值2']].to_excel(writer, sheet_name='日语_testA', index=None)
    28. writer.save()
    29. writer.close()


    参考内容:

    transformers库的使用【一】——pipeline的简单使用_桉夏与猫的博客-CSDN博客_transformers库使用

    Transformers 库的基本使用_空杯的境界的博客-CSDN博客_transformers库

    🤗 Transformers

    GitHub - huggingface/transformers: 🤗 Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX.

    2 🤗 Transformers pipeline 使用 - 知乎

    pd.factorize ( ) 解析_code_new_life的博客-CSDN博客_pd.factorize

  • 相关阅读:
    OneFlow源码解析:算子指令在虚拟机中的执行
    用 Python 算法识别股价支撑位和阻力位
    自己动手实现一个深度学习算法——三、神经网络的学习
    Chainlit快速实现AI对话应用并将聊天数据的AWS S3 和 Azure Blob云服务中
    java计算机毕业设计二手车交易平台源码+mysql数据库+系统+lw文档+部署
    正厚技术 | Jmeter分布式设置操作说明
    21.Redis系列之缓存穿透、击穿、雪崩
    RabbitMQ-简述
    Mistral 7B 比Llama 2更好的开源大模型 (四)
    VUE 学习
  • 原文地址:https://blog.csdn.net/doubleguy/article/details/125874100