比賽:https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517
Intel? DevCloud for oneAPI:https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToolkitSamples/
Intel? DevCloud for oneAPI 和 Intel? Optimization for PyTorch
在本次實(shí)驗(yàn)中,我們在Intel? DevCloud for oneAPI上搭建實(shí)驗(yàn),借助完全虛擬化的環(huán)境,專注于模型開發(fā)與優(yōu)化,無需關(guān)心底層配置。使用Intel? Optimization for PyTorch,對PyTorch模型進(jìn)行高效優(yōu)化。
我們充分發(fā)揮了PyTorch和Intel? Optimization for PyTorch的強(qiáng)大功能,經(jīng)過仔細(xì)的優(yōu)化和拓展。這些優(yōu)化措施極大地提升了PyTorch在各種任務(wù)中的性能,尤其是在英特爾硬件上的表現(xiàn)更為卓越。通過這些優(yōu)化方法,我們的模型在訓(xùn)練和推斷過程中變得更加敏捷高效,大幅縮短了計算時間,從而提升了整體效率。借助深度融合硬件與軟件的巧妙設(shè)計,我們成功地釋放了硬件潛力,使模型的訓(xùn)練和應(yīng)用變得更加迅速高效。這些優(yōu)化舉措為人工智能應(yīng)用開辟了嶄新的前景,帶來了全新的可能性。
基于BERT預(yù)訓(xùn)練模型的命名體識別任務(wù)
基于BERT預(yù)訓(xùn)練模型的第五個下游任務(wù)場景,即如何完成命名體識別(Named Entity Recognition, NER)任務(wù)。所謂命名體指的是給模型輸入一句文本,最后需要模型將其中的實(shí)體(例如人名、地名、組織等等)標(biāo)記出來。
1 句子:涂伊說,如果有機(jī)會他想去黃州赤壁看一看!
2 標(biāo)簽:['B-PER', 'I-PER', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-LOC', 'I-LOC', 'B-LOC', 'I-LOC', 'O', 'O', 'O', 'O']
3 實(shí)體:涂伊(人名)、黃州(地名)、赤壁(地名)
通常來講,對于任意一個NLP任務(wù)來說模型最后所要完成的基本上都是一個分類任務(wù),盡管表面上看起來可能不太像。根據(jù)給出的標(biāo)簽來看,對于原始句子中的每個字符來說其都有一個對應(yīng)的類別標(biāo)簽,因此對于NER任務(wù)來說只需要對原始句子里的每個字符進(jìn)行分類即可,然后再將預(yù)測后的結(jié)果進(jìn)行后處理便能夠得到句子從存在的相應(yīng)實(shí)體。
原始數(shù)據(jù)輸入為一個句子,我們只需要在句子的首尾分別加上[CLS]和[SEP],然后輸入到模型當(dāng)中進(jìn)行特征提取并最終通過一個分類層對輸出的每個Token進(jìn)行分類即可,最后只需要對各個Token的預(yù)測結(jié)果進(jìn)行后處理便能夠?qū)崿F(xiàn)整個NER任務(wù)。
語料介紹
一個中文命名體識別數(shù)據(jù)集https://github.com/zjy-ucas/ChineseNER,如下所示便是原始數(shù)據(jù)的存儲形式:
1 涂 B-PER
2 伊 I-PER
3 說 O
4 , O
5 如 O
6 果 O
7 有 O
8 機(jī) O
9 會 O
10 他 O
11 想 O
12 去 O
13 黃 B-LOC
14 州 I-LOC
15 赤 B-LOC
16 壁 I-LOC
17 看 O
18 一 O
19 看 O
20 !O
其中每一行包含一個字符和其對應(yīng)的所屬類別,B-表示該類實(shí)體的開始標(biāo)志,I-表示該類實(shí)體的延續(xù)標(biāo)志。例如對于13-16行來說其對應(yīng)了“黃州”和“赤壁”這兩個實(shí)體。同時,對于這個數(shù)據(jù)集來說,其一共包含有3類實(shí)體(人名、地名和組織),因此其對應(yīng)的分類總數(shù)便為7,如下所示:
1 {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}
對于數(shù)據(jù)預(yù)處理部分我們可以繼續(xù)繼承之前文本分類處理中的LoadSingleSentenceClassificationDataset類,然后再稍微修改其中的部分方法即可。
數(shù)據(jù)集構(gòu)建
在說完數(shù)據(jù)集構(gòu)造的整理思路后,下面我們就來正式編碼實(shí)現(xiàn)整個數(shù)據(jù)集的構(gòu)造過程。同樣,對于數(shù)據(jù)預(yù)處理部分我們可以繼續(xù)繼承之前文本分類處理中的LoadSingleSentenceClassificationDataset類,然后再稍微修改其中的部分方法即可。
class LoadChineseNERDataset(LoadSingleSentenceClassificationDataset):
def __init__(self, entities=None, num_labels=None, ignore_idx=-100, **kwargs):
super(LoadChineseNERDataset, self).__init__(**kwargs)
self.entities = entities
self.num_labels = num_labels
self.IGNORE_IDX = ignore_idx
if self.entities is None or self.num_labels is None:
raise ValueError(f"類 {self.__class__.__name__} 中參數(shù) entities 或 num_labels 不能為空!")
@cache
def data_process(self, filepath, postfix='cache'):
raw_iter = open(filepath, encoding="utf8").readlines()
data = []
max_len = 0
tmp_token_ids = []
tmp_sentence = ""
tmp_label = []
tmp_entity = []
for raw in tqdm(raw_iter, ncols=80):
line = raw.rstrip("\n").split(self.split_sep)
if len(line) != 1 and len(line) != 2:
raise ValueError(f"數(shù)據(jù)標(biāo)注有誤{line}")
if len(line) == 1: # 表示得到一個完整的token id樣本
if len(tmp_token_ids) > self.max_position_embeddings - 2:
tmp_token_ids = tmp_token_ids[:self.max_position_embeddings - 2]
tmp_label = tmp_label[:self.max_position_embeddings - 2]
max_len = max(max_len, len(tmp_label) + 2)
token_ids = torch.tensor([self.CLS_IDX] + tmp_token_ids +
[self.SEP_IDX], dtype=torch.long)
labels = torch.tensor([self.IGNORE_IDX] + tmp_label +
[self.IGNORE_IDX], dtype=torch.long)
data.append([tmp_sentence, token_ids, labels])
logging.debug(" ### 樣本構(gòu)造結(jié)果為:")
logging.debug(f" ## 句子: {tmp_sentence}")
logging.debug(f" ## 實(shí)體: {tmp_entity}")
logging.debug(f" ## input_ids: {token_ids.tolist()}")
logging.debug(f" ## label: {labels.tolist()}")
logging.debug(f" ================================\n")
assert len(tmp_token_ids) == len(tmp_label)
tmp_token_ids = []
tmp_sentence = ""
tmp_label = []
tmp_entity = []
continue
tmp_sentence += line[0]
tmp_token_ids.append(self.vocab[line[0]])
tmp_label.append(self.entities[line[-1]])
tmp_entity.append(line[-1])
return data, max_len
def generate_batch(self, data_batch):
batch_sentence, batch_token_ids, batch_label = [], [], []
for (sen, token_ids, label) in data_batch: # 開始對一個batch中的每一個樣本進(jìn)行處理。
batch_sentence.append(sen)
batch_token_ids.append(token_ids)
batch_label.append(label)
batch_token_ids = pad_sequence(batch_token_ids, # [batch_size,max_len]
padding_value=self.PAD_IDX,
batch_first=False,
max_len=self.max_sen_len)
batch_label = pad_sequence(batch_label, # [batch_size,max_len]
padding_value=self.IGNORE_IDX,
batch_first=False,
max_len=self.max_sen_len)
# ① 因?yàn)閘abel的長度各不相同,所以同一個batch中的label需要padding到相同的長度;
# ② 因?yàn)檫M(jìn)行了padding操作,所以在計算損失的時候需要把padding部分的損失忽略掉;
# ③ 又因?yàn)閘abel中有0這個類別的存在,所以不能用詞表中的PAD_IDX進(jìn)行padding(PAD_IDX為0),所以要另外取一個IGNORE_IDX
return batch_sentence, batch_token_ids, batch_label
def make_inference_samples(self, sentences):
if not isinstance(sentences, list):
sentences = [sentences]
data = []
for sen in sentences:
tokens = [self.vocab[word] for word in sen]
label = [-1] * len(tokens)
token_ids = torch.tensor([self.CLS_IDX] + tokens + [self.SEP_IDX], dtype=torch.long)
labels = torch.tensor([self.IGNORE_IDX] + label + [self.IGNORE_IDX], dtype=torch.long)
data.append([sen, token_ids, labels])
return self.generate_batch(data)
使用示例
在完成數(shù)據(jù)集構(gòu)造部分的相關(guān)代碼實(shí)現(xiàn)之后,便可以通過如下所示的方式進(jìn)行使用,代碼如下:
class ModelConfig:
def __init__(self):
self.project_dir = os.path.dirname(os.path.abspath(__file__))
self.dataset_dir = os.path.join(self.project_dir, 'ChineseNERdata')
self.pretrained_model_dir = os.path.join(self.project_dir, "pretraining")
self.vocab_path = os.path.join(self.pretrained_model_dir, 'vocab.txt')
self.device = torch.device('xpu' if torch.cuda.is_available() else 'cpu')
self.train_file_path = os.path.join(self.dataset_dir, 'example_train.txt')
self.val_file_path = os.path.join(self.dataset_dir, 'example_dev.txt')
self.test_file_path = os.path.join(self.dataset_dir, 'example_test.txt')
self.model_save_dir = os.path.join(self.project_dir, 'cache')
self.model_save_name = "ner_model.pt"
self.logs_save_dir = os.path.join(self.project_dir, 'logs')
self.split_sep = ' '
self.is_sample_shuffle = True
self.batch_size = 6
self.max_sen_len = None
self.epochs = 10
self.learning_rate = 1e-5
self.model_val_per_epoch = 2
self.entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}
self.num_labels = len(self.entities)
self.ignore_idx = -100
logger_init(log_file_name='ner', log_level=logging.DEBUG,
log_dir=self.logs_save_dir)
if not os.path.exists(self.model_save_dir):
os.makedirs(self.model_save_dir)
# 把原始bert中的配置參數(shù)也導(dǎo)入進(jìn)來
bert_config_path = os.path.join(self.pretrained_model_dir, "config.json")
bert_config = BertConfig.from_json_file(bert_config_path)
for key, value in bert_config.__dict__.items():
self.__dict__[key] = value
# 將當(dāng)前配置打印到日志文件中
logging.info(" ### 將當(dāng)前配置打印到日志文件中 ")
for key, value in self.__dict__.items():
logging.info(f"### {key} = {value}")
命名體識別模型
前向傳播
我們只需要在原始BERT模型的基礎(chǔ)上再加一個對所有Token進(jìn)行分類的分類層即可,因此這部分代碼相對來說也比較容易理解。首先需要在DownstreamTasks目錄下新建一個BertForTokenClassification模塊,并完成整個模型的初始化和前向傳播過程,代碼如下:
from ..BasicBert.Bert import BertModel
import torch.nn as nn
class BertForTokenClassification(nn.Module):
def __init__(self, config, bert_pretrained_model_dir=None):
super(BertForTokenClassification, self).__init__()
self.num_labels = config.num_labels
if bert_pretrained_model_dir is not None:
self.bert = BertModel.from_pretrained(config, bert_pretrained_model_dir)
else:
self.bert = BertModel(config)
self.dropout = nn.Dropout(config.hidden_dropout_prob)
self.classifier = nn.Linear(config.hidden_size, self.num_labels)
self.config = config
def forward(self,
input_ids=None,
attention_mask=None,
token_type_ids=None,
position_ids=None,
labels=None):
"""
:param input_ids: [src_len,batch_size]
:param attention_mask: [batch_size, src_len]
:param token_type_ids:
:param position_ids:
:param labels: [src_len,batch_size]
:return:
"""
_, all_encoder_outputs = self.bert(input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids) # [batch_size,hidden_size]
sequence_output = all_encoder_outputs[-1] # 取最后一層
# sequence_output: [src_len, batch_size, hidden_size]
sequence_output = self.dropout(sequence_output)
logits = self.classifier(sequence_output)
# logit: [src_len, batch_size, num_labels]
if labels is not None: # [src_len,batch_size]
loss_fct = nn.CrossEntropyLoss(ignore_index=self.config.ignore_idx)
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
return loss, logits
else:
return logits
模型訓(xùn)練
對于模型訓(xùn)練這部分內(nèi)容來說,首先我們需要在Tasks目錄下新建一個TaskForChineseNER.py模塊,并新建一個配置類ModelConfig來管理整個模型需要用到的參數(shù),代碼實(shí)現(xiàn)如下:
class ModelConfig:
def __init__(self):
self.project_dir = os.path.dirname(os.path.abspath(__file__))
self.dataset_dir = os.path.join(self.project_dir, 'ChineseNERdata')
self.pretrained_model_dir = os.path.join(self.project_dir, "pretraining")
self.vocab_path = os.path.join(self.pretrained_model_dir, 'vocab.txt')
self.device = torch.device('xpu' if torch.cuda.is_available() else 'cpu')
self.train_file_path = os.path.join(self.dataset_dir, 'example_train.txt')
self.val_file_path = os.path.join(self.dataset_dir, 'example_dev.txt')
self.test_file_path = os.path.join(self.dataset_dir, 'example_test.txt')
self.model_save_dir = os.path.join(self.project_dir, 'cache')
self.model_save_name = "ner_model.pt"
self.logs_save_dir = os.path.join(self.project_dir, 'logs')
self.split_sep = ' '
self.is_sample_shuffle = True
self.batch_size = 6
self.max_sen_len = None
self.epochs = 10
self.learning_rate = 1e-5
self.model_val_per_epoch = 2
self.entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}
self.num_labels = len(self.entities)
self.ignore_idx = -100
logger_init(log_file_name='ner', log_level=logging.DEBUG,
log_dir=self.logs_save_dir)
if not os.path.exists(self.model_save_dir):
os.makedirs(self.model_save_dir)
# 把原始bert中的配置參數(shù)也導(dǎo)入進(jìn)來
bert_config_path = os.path.join(self.pretrained_model_dir, "config.json")
bert_config = BertConfig.from_json_file(bert_config_path)
for key, value in bert_config.__dict__.items():
self.__dict__[key] = value
# 將當(dāng)前配置打印到日志文件中
logging.info(" ### 將當(dāng)前配置打印到日志文件中 ")
for key, value in self.__dict__.items():
logging.info(f"### {key} = {value}")
因?yàn)樵谀P陀?xùn)練過程中需要計算相關(guān)的評價指標(biāo),如準(zhǔn)確率、精確率和召回率等,因此需要對這部分進(jìn)行實(shí)現(xiàn),代碼如下
def accuracy(logits, y_true, ignore_idx=-100):
"""
:param logits: [src_len,batch_size,num_labels]
:param y_true: [src_len,batch_size]
:param ignore_idx: 默認(rèn)情況為-100
:return:
e.g.
y_true = torch.tensor([[-100, 0, 0, 1, -100],
[-100, 2, 0, -100, -100]]).transpose(0, 1)
logits = torch.tensor([[[0.5, 0.1, 0.2], [0.5, 0.4, 0.1], [0.7, 0.2, 0.3], [0.5, 0.7, 0.2], [0.1, 0.2, 0.5]],
[[0.3, 0.2, 0.5], [0.7, 0.2, 0.4], [0.8, 0.1, 0.3], [0.9, 0.2, 0.1], [0.1, 0.5, 0.2]]])
logits = logits.transpose(0, 1)
print(accuracy(logits, y_true, -100)) # (0.8, 4, 5)
"""
y_pred = logits.transpose(0, 1).argmax(axis=2).reshape(-1).tolist()
# 將 [src_len,batch_size,num_labels] 轉(zhuǎn)成 [batch_size, src_len,num_labels]
y_true = y_true.transpose(0, 1).reshape(-1).tolist()
real_pred, real_true = [], []
for item in zip(y_pred, y_true):
if item[1] != ignore_idx:
real_pred.append(item[0])
real_true.append(item[1])
return accuracy_score(real_true, real_pred), real_true, real_pred
為了能夠在模型訓(xùn)練或推理過程中輸入模型的預(yù)測結(jié)果,因此我們需要實(shí)現(xiàn)3個輔助函數(shù)來完成。首先需要實(shí)現(xiàn)根據(jù)logits和input_token_ids來得到每個預(yù)測值對應(yīng)的實(shí)體標(biāo)簽,代碼如下:
def get_ner_tags(logits, token_ids, entities, SEP_IDX=102):
"""
:param logits: [src_len,batch_size,num_samples]
:param token_ids: # [src_len,batch_size]
:return:
e.g.
logits = torch.tensor([[[0.4, 0.7, 0.2],[0.5, 0.4, 0.1],[0.1, 0.2, 0.3],[0.5, 0.7, 0.2],[0.1, 0.2, 0.5]],
[[0.3, 0.2, 0.5],[0.7, 0.8, 0.4],[0.1, 0.1, 0.3],[0.9, 0.2, 0.1],[0.1, 0.5,0.2]]])
logits = logits.transpose(0, 1) # [src_len,batch_size,num_samples]
token_ids = torch.tensor([[101, 2769, 511, 102, 0],
[101, 56, 33, 22, 102]]).transpose(0, 1) # [src_len,batch_size]
labels, probs = get_ner_tags(logits, token_ids, entities)
[['O', 'B-LOC'], ['B-ORG', 'B-LOC', 'O']]
[[0.5, 0.30000001192092896], [0.800000011920929, 0.30000001192092896, 0.8999999761581421]]
"""
# entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}
label_list = list(entities.keys())
logits = logits[1:].transpose(0, 1) # [batch_size,src_len-1,num_samples]
prob, y_pred = torch.max(logits, dim=-1) # prob, y_pred: [batch_size,src_len-1]
token_ids = token_ids[1:].transpose(0, 1) # [ batch_size,src_len-1], 去掉[cls]
assert y_pred.shape == token_ids.shape
labels = []
probs = []
for sample in zip(y_pred, token_ids, prob):
tmp_label, tmp_prob = [], []
for item in zip(*sample):
if item[1] == SEP_IDX: # 忽略最后一個[SEP]字符
break
tmp_label.append(label_list[item[0]])
tmp_prob.append(item[2].item())
labels.append(tmp_label)
probs.append(tmp_prob)
return labels, probs
進(jìn)一步,在得到每個輸入句子的預(yù)測結(jié)果后,還需要將其進(jìn)行格式化處理得到最終的預(yù)測結(jié)果,實(shí)現(xiàn)代碼如下:
def pretty_print(sentences, labels, entities):
"""
:param sentences:
:param labels:
:param entities:
:return:
e.g.
labels = [['B-PER','I-PER', 'O','O','O','O','O','O','O','O','O','O','B-LOC','I-LOC','B-LOC','I-LOC','O','O','O','O'],
['B-LOC','I-LOC','O','B-LOC','I-LOC','O','B-LOC','I-LOC','I-LOC','O','B-LOC','I-LOC','O','O','O','B-PER','I-PER','O','O','O','O','O','O']]
sentences=["涂伊說,如果有機(jī)會他想去赤壁看一看!",
"麗江、大理、九寨溝、黃龍等都是涂伊想去的地方!"]
entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}
句子:涂伊說,如果有機(jī)會他想去黃州赤壁看一看!
涂伊: PER
黃州: LOC
赤壁: LOC
句子:麗江、大理、九寨溝、黃龍等都是涂伊想去的地方!
麗江: LOC
大理: LOC
九寨溝: LOC
黃龍: LOC
涂伊: PER
"""
sep_tag = [tag for tag in list(entities.keys()) if 'I' not in tag]
result = []
for sen, label in zip(sentences, labels):
logging.info(f"句子:{sen}")
last_tag = None
for item in zip(sen + "O", label + ['O']):
if item[1] in sep_tag: #
if len(result) > 0:
entity = "".join(result)
logging.info(f"\t{entity}: {last_tag.split('-')[-1]}")
result = []
if item[1] != 'O':
result.append(item[0])
last_tag = item[1]
else:
result.append(item[0])
last_tag = item[1]
輸出結(jié)果如下:
1 句子:涂伊說,如果有機(jī)會他想去黃州赤壁看一看!
2 涂伊: PER
3 黃州: LOC
4 赤壁: LOC
5 句子:麗江、大理、九寨溝、黃龍等都是涂伊想去的地方!
6 麗江: LOC
7 大理: LOC
8 九寨溝: LOC
9 黃龍: LOC
10 涂伊: PER
在完成上述所有鋪墊之后,便可以來實(shí)現(xiàn)模型的訓(xùn)練部分,代碼如下(下面只摘錄核心部分進(jìn)行介紹):
def train(config):
model = BertForTokenClassification(config,
config.pretrained_model_dir)
model_save_path = os.path.join(config.model_save_dir,
config.model_save_name)
global_steps = 0
if os.path.exists(model_save_path):
checkpoint = torch.load(model_save_path)
global_steps = checkpoint['last_epoch']
loaded_paras = checkpoint['model_state_dict']
model.load_state_dict(loaded_paras)
logging.info("## 成功載入已有模型,進(jìn)行追加訓(xùn)練......")
model = model.to(config.device)
optimizer = torch.optim.Adam(model.parameters(), lr=config.learning_rate)
'''
Apply Intel Extension for PyTorch optimization against the model object and optimizer object.
'''
model, optimizer = ipex.optimize(model, optimizer=optimizer)
model.train()
data_loader = LoadChineseNERDataset(
entities=config.entities,
num_labels=config.num_labels,
ignore_idx=config.ignore_idx,
vocab_path=config.vocab_path,
tokenizer=BertTokenizer.from_pretrained(
config.pretrained_model_dir).tokenize,
batch_size=config.batch_size,
max_sen_len=config.max_sen_len,
split_sep=config.split_sep,
max_position_embeddings=config.max_position_embeddings,
pad_index=config.pad_token_id,
is_sample_shuffle=config.is_sample_shuffle)
train_iter, test_iter, val_iter = \
data_loader.load_train_val_test_data(train_file_path=config.train_file_path,
val_file_path=config.val_file_path,
test_file_path=config.test_file_path,
only_test=False)
max_acc = 0
for epoch in range(config.epochs):
losses = 0
start_time = time.time()
for idx, (sen, token_ids, labels) in enumerate(train_iter):
token_ids = token_ids.to(config.device)
labels = labels.to(config.device)
padding_mask = (token_ids == data_loader.PAD_IDX).transpose(0, 1)
loss, logits = model(input_ids=token_ids, # [src_len, batch_size]
attention_mask=padding_mask, # [batch_size,src_len]
token_type_ids=None,
position_ids=None,
labels=labels) # [src_len, batch_size]
# logit: [src_len, batch_size, num_labels]
optimizer.zero_grad()
loss.backward()
optimizer.step()
losses += loss.item()
global_steps += 1
acc, _, _ = accuracy(logits, labels, config.ignore_idx)
if idx % 20 == 0:
logging.info(f"Epoch: {epoch}, Batch[{idx}/{len(train_iter)}], "
f"Train loss :{loss.item():.3f}, Train acc: {round(acc, 5)}")
if idx % 100 == 0:
show_result(sen[:10], logits[:, :10], token_ids[:, :10], config.entities)
end_time = time.time()
train_loss = losses / len(train_iter)
logging.info(f"Epoch: [{epoch + 1}/{config.epochs}],"
f" Train loss: {train_loss:.3f}, Epoch time = {(end_time - start_time):.3f}s")
if (epoch + 1) % config.model_val_per_epoch == 0:
acc = evaluate(config, val_iter, model, data_loader)
logging.info(f"Accuracy on val {acc:.3f}")
if acc > max_acc:
max_acc = acc
state_dict = deepcopy(model.state_dict())
torch.save({'last_epoch': global_steps,
'model_state_dict': state_dict},
model_save_path)
結(jié)果
文章來源:http://www.zghlxwxcb.cn/news/detail-663158.html
參考資料
基于BERT預(yù)訓(xùn)練模型的中文文本分類任務(wù): https://mp.weixin.qq.com/s/bbeN95mlLaE05dFndUAxgA文章來源地址http://www.zghlxwxcb.cn/news/detail-663158.html
到了這里,關(guān)于[oneAPI] 基于BERT預(yù)訓(xùn)練模型的命名體識別任務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!