【NLP】医疗诊疗对话意图识别挑战赛【阿里云:天池比赛】
·
比赛地址:医疗诊疗对话意图识别
V1:
方案:BERT
预训练模型:bert-base-chinese
分数:0.8043
Val P: 0.7621, Val R: 76.7676%, Val F1: 0.7619, Val Acc: 81.5204%
V2:
分数:0.8158
排名:长期赛:193(本次)/1561
方案:BERT+CNN
预训练模型:bert-base-chinese
训练结果:
Val P: 0.758, Val R: 76.6730%, Val F1: 0.7595, Val Acc: 81.7135%
后期优化思路:
1、使用行业模型微调
2、尝试bert+bilstm+crf
3、词嵌入时单独增加角色信息编码
4、多模型融合
运行脚本:
python run_bert.py
源码下载:
比赛地址:医疗诊疗对话意图识别挑战赛BERT/BERT+CNN资源-CSDN文库
模型:配置bert
import torch
import torch.nn as nn
# from pytorch_pretrained_bert import BertModel, BertTokenizer
from transformers import BertModel, BertTokenizer, BertConfig
from transformers import AutoModel, AutoTokenizer, AutoConfig
import os
class Config(object):
"""配置参数"""
def __init__(self, dataset, local=False):
self.local = local
self.date='20241106'
self.model_name = 'bert_'+self.date
self.train_path = dataset + '/data/train.txt' # 训练集
self.dev_path = dataset + '/data/dev.txt' # 验证集
self.test_path = dataset + '/data/test.txt' # 测试集
self.class_list = [x.strip() for x in open(
dataset + '/data/class.txt').readlines()] # 类别名单
self.save_path = dataset + '/saved_dict/'+self.model_name+'.ckpt' # 模型训练结果
self.save_path_best = dataset + '/saved_dict/'+self.model_name+'.ckpt' # 模型训练结果
self.save_path_test_org = dataset + '/data_old/test.json' # 测试源文件
self.save_path_test = dataset + '/saved_dict/test'+self.date+'.json' # 测试结果
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设备
self.require_improvement = 1000 # 若超过1000batch效果还没提升,则提前结束训练
self.num_classes = len(self.class_list) # 类别数
self.batch_size = 128 # mini-batch大小
self.pad_size = 256 # 每句话处理成的长度(短填长切)
self.learning_rate = 5e-5 # 学习率
self.dropout = 0.3
if local and local == True:
self.bert_path = 'E:/models/bert-base-chinese'
self.num_epochs = 1 # epoch数
else:
self.bert_path = '/data/nfs/baozhi/models/google-bert_bert-base-chinese'
self.num_epochs = 10 # epoch数
self.tokenizer = BertTokenizer.from_pretrained(self.bert_path)
self.transformer_config = BertConfig.from_pretrained(self.bert_path)
# self.tokenizer = AutoTokenizer.from_pretrained(self.bert_path)
# self.transformer_config = AutoConfig.from_pretrained(self.bert_path)
self.hidden_size = 768
class Model(nn.Module):
def __init__(self, config: Config):
super(Model, self).__init__()
self.bert = BertModel.from_pretrained(config.bert_path)
for param in self.bert.parameters():
param.requires_grad = True
self.dropout = nn.Dropout(config.dropout)
# self.fc = nn.Linear(config.hidden_size, config.num_classes)
self.linear = nn.Linear(config.hidden_size, config.num_classes)
# def forward(self, token_ids, attention_masks, token_type_ids):
# bert_outputs = self.bert(
# input_ids=token_ids,
# attention_mask=attention_masks,
# token_type_ids=token_type_ids,
# )
# seq_out = bert_outputs[1]
# seq_out = self.dropout(seq_out)
# seq_out = self.linear(seq_out)
# return seq_out
def forward(self, x):
context = x[0] # 输入的句子
mask = x[2] # 对padding部分进行mask,和句子一个size,padding部分用0表示,如:[1, 1, 1, 1, 0, 0]
bert_outputs = self.bert(context, attention_mask=mask)
seq_out = bert_outputs[1]
seq_out = self.dropout(seq_out)
seq_out = self.linear(seq_out)
return seq_out
模型+配置:bert+cnn
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import BertModel, BertTokenizer, BertConfig
class Config(object):
"""配置参数"""
def __init__(self, dataset, local=False):
self.local = local
self.date = '20241106'
self.model_name = 'bert_' + self.date
self.train_path = dataset + '/data/train.txt' # 训练集
self.dev_path = dataset + '/data/dev.txt' # 验证集
self.test_path = dataset + '/data/test.txt' # 测试集
self.class_list = [x.strip() for x in open(
dataset + '/data/class.txt').readlines()] # 类别名单
self.save_path = dataset + '/saved_dict/' + self.model_name + '.ckpt' # 模型训练结果
self.save_path_best = dataset + '/saved_dict/' + self.model_name + '.ckpt' # 模型训练结果
self.save_path_test_org = dataset + '/data_old/test.json' # 测试源文件
self.save_path_test = dataset + '/saved_dict/test' + self.date + '.json' # 测试结果
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设备
self.require_improvement = 1000 # 若超过1000batch效果还没提升,则提前结束训练
self.num_classes = len(self.class_list) # 类别数
self.learning_rate = 5e-5 # 学习率
self.dropout = 0.1
if local and local == True:
self.bert_path = 'E:/models/bert-base-chinese'
self.num_epochs = 1 # epoch数
self.pad_size = 32 # 每句话处理成的长度(短填长切)
self.batch_size = 16 # mini-batch大小
else:
self.bert_path = '/data/nfs/baozhi/models/google-bert_bert-base-chinese'
self.num_epochs = 10 # epoch数
self.pad_size = 256 # 每句话处理成的长度(短填长切)
self.batch_size = 128 # mini-batch大小
self.tokenizer = BertTokenizer.from_pretrained(self.bert_path)
self.transformer_config = BertConfig.from_pretrained(self.bert_path)
# self.tokenizer = AutoTokenizer.from_pretrained(self.bert_path)
# self.transformer_config = AutoConfig.from_pretrained(self.bert_path)
self.hidden_size = 768
self.filter_sizes = [2, 3, 4] # 卷积核尺寸
self.num_filters = 256 # 卷积核数量(channels数)
class Model(nn.Module):
def __init__(self, config):
super(Model, self).__init__()
self.bert = BertModel.from_pretrained(config.bert_path)
for param in self.bert.parameters():
param.requires_grad = True
self.convs = nn.ModuleList(
[nn.Conv2d(1, config.num_filters, (k, config.hidden_size)) for k in config.filter_sizes])
self.dropout = nn.Dropout(config.dropout)
self.fc_cnn = nn.Linear(config.num_filters * len(config.filter_sizes), config.num_classes)
def conv_and_pool(self, x, conv):
x = F.relu(conv(x)).squeeze(3)
x = F.max_pool1d(x, x.size(2)).squeeze(2)
return x
def forward(self, x):
context = x[0] # 输入的句子
mask = x[2] # 对padding部分进行mask,和句子一个size,padding部分用0表示,如:[1, 1, 1, 1, 0, 0]
outputs = self.bert(context, attention_mask=mask)
bert_output = outputs.last_hidden_state # (batch_size, seq_len, 768)
bert_output = bert_output.unsqueeze(1) # (batch_size, 1, seq_len, 768)
conv_outputs = [conv(bert_output).squeeze(3) for conv in self.convs] # [(batch_size, num_filters, seq_len - fs + 1)]
pooled_outputs = [nn.functional.max_pool1d(co, co.size(2)).squeeze(2) for co in conv_outputs] # [(batch_size, num_filters)]
concatenated = torch.cat(pooled_outputs, 1) # (batch_size, num_filters * len(filter_sizes))
concatenated = self.dropout(concatenated)
logits = self.fc_cnn(concatenated)
return logits
更多推荐


所有评论(0)