国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

猿創(chuàng)征文|信息抽?。?)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取

這篇具有很好參考價(jià)值的文章主要介紹了猿創(chuàng)征文|信息抽?。?)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1 前言

猿創(chuàng)征文|信息抽?。?)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取

論文參考:
1 Neural Architectures for Named Entity Recognition
2 Attention is all you need
3 BERT: Pre-training of Deep Bidirectional Transformers for
Language Understanding
4 Bidirectional LSTM-CRF Models for Sequence Tagging
使用數(shù)據(jù)集:
https://www.datafountain.cn/competitions/529/ranking
Tips:文章可能存在一些漏洞,歡迎留言指出

2 數(shù)據(jù)準(zhǔn)備

使用了transformers和seqeval庫
安裝方法:
huggingface-transformers

conda install -c huggingface transformers

seqeval

pip install seqeval -i https://pypi.tuna.tsinghua.edu.cn/simple

代碼

import pandas as pd
import torch
from torch import optim
from torch.utils.data import DataLoader
from tqdm import tqdm
from bert_bilstm_crf import Bert_BiLSTM_CRF, NerDataset, NerDatasetTest
from bert_crf import Bert_CRF
from transformers import AutoTokenizer, BertTokenizer
from seqeval.metrics import f1_score

# 路徑
TRAIN_PATH = './dataset/train_data_public.csv'
TEST_PATH = './dataset/test_public.csv'
MODEL_PATH1 = './model/bert_bilstm_crf.pkl'
MODEL_PATH2 = '../model/bert_crf.pkl'

# 超參數(shù)
MAX_LEN = 64
BATCH_SIZE = 16
EPOCH = 5

# 預(yù)設(shè)
# 設(shè)備
DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu"
# tag2index
tag2index = {
    "O": 0,  # 其他
    "B-BANK": 1, "I-BANK": 2,  # 銀行實(shí)體
    "B-PRODUCT": 3, "I-PRODUCT": 4,  # 產(chǎn)品實(shí)體
    "B-COMMENTS_N": 5, "I-COMMENTS_N": 6,  # 用戶評(píng)論,名詞
    "B-COMMENTS_ADJ": 7, "I-COMMENTS_ADJ": 8  # 用戶評(píng)論,形容詞
}
index2tag = {v: k for k, v in tag2index.items()}

3 數(shù)據(jù)預(yù)處理

== 流程==

  1. 使用 s e r i e s . a p p l y ( l i s t ) \textcolor{red}{series.apply(list)} series.apply(list)函數(shù)將str轉(zhuǎn)化為list格式
  2. 加載bert預(yù)訓(xùn)練tokenizer,使用 e n c o d e _ p l u s \textcolor{red}{encode\_plus} encode_plus函數(shù)對每一個(gè)text進(jìn)行encode
  3. 如果是訓(xùn)練集,則執(zhí)行如下操作:首先按照空格將每一個(gè)tag分割,并轉(zhuǎn)化為索引列表,對每一個(gè)index_list,按照長度大于MAX_LEN裁剪,小于MAX_LEN填充的規(guī)則,合并為一個(gè)list,最后轉(zhuǎn)化為tensor格式

代碼

# 預(yù)處理
def data_preprocessing(dataset, is_train):
    # 數(shù)據(jù)str轉(zhuǎn)化為list
    dataset['text_split'] = dataset['text'].apply(list)
    # token
    tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
    texts = dataset['text_split'].array.tolist()
    token_texts = []
    for text in tqdm(texts):
        tokenized = tokenizer.encode_plus(text=text,
                                          max_length=MAX_LEN,
                                          return_token_type_ids=True,
                                          return_attention_mask=True,
                                          return_tensors='pt',
                                          padding='max_length',
                                          truncation=True)
        token_texts.append(tokenized)

    # 訓(xùn)練集有tag,測試集沒有tag
    tags = None
    if is_train:
        dataset['tag'] = dataset['BIO_anno'].apply(lambda x: x.split(sep=' '))
        tags = []
        for tag in tqdm(dataset['tag'].array.tolist()):
            index_list = [0] + [tag2index[t] for t in tag] + [0]
            if len(index_list) < MAX_LEN:  # 填充
                pad_length = MAX_LEN - len(index_list)
                index_list += [tag2index['O']] * pad_length
            if len(index_list) > MAX_LEN:  # 裁剪
                index_list = index_list[:MAX_LEN-1] + [0]
            tags.append(index_list)
        tags = torch.LongTensor(tags)

    return token_texts, tags

4 Bert-BiLSTM-CRF模型

猿創(chuàng)征文|信息抽?。?)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取
相對于Bert-CRF,中間添加了雙向LSTM層。相對BiLSTM-CRF,相當(dāng)于前面的word_embedding層替換為了bert預(yù)訓(xùn)練模型。
代碼

import torch
from torch import nn
from torchcrf import CRF
from transformers import BertModel
from torch.utils.data import Dataset


class Bert_BiLSTM_CRF(nn.Module):
    def __init__(self, tag2index):
        super(Bert_BiLSTM_CRF, self).__init__()
        self.tagset_size = len(tag2index)

        # bert層
        self.bert = BertModel.from_pretrained('bert-base-chinese')
        # config = self.bert.config
        # lstm層
        self.lstm = nn.LSTM(input_size=768, hidden_size=128, num_layers=1, batch_first=True, bidirectional=True)
        # dropout層
        self.dropout = nn.Dropout(p=0.1)
        # Dense層
        self.dense = nn.Linear(in_features=256, out_features=self.tagset_size)
        # CRF層
        self.crf = CRF(num_tags=self.tagset_size)

        # 隱藏層
        self.hidden = None

    # 負(fù)對數(shù)似然損失函數(shù)
    def neg_log_likelihood(self, emissions, tags=None, mask=None, reduction=None):
        return -1 * self.crf(emissions=emissions, tags=tags, mask=mask, reduction=reduction)

    def forward(self, token_texts, tags):
        """
        token_texts:{"input_size": tensor,  [batch, 1, seq_len]->[batch, seq_len]
                    "token_type_ids": tensor,  [batch, 1, seq_len]->[batch, seq_len]
                     "attention_mask": tensor  [batch, 1, seq_len]->[batch, seq_len]->[seq_len, batch]
                     }
        tags:  [batch, seq_len]->[seq_len, batch]
        bert_out:  [batch, seq_len, hidden_size(768)]->[seq_len, batch, hidden_size]
        self.hidden:  [num_layers * num_directions, hidden_size(128)]
        out:  [seq_len, batch, hidden_size * 2(256)]
        lstm_feats:  [seq_len, batch, tagset_size]
        loss:  tensor
        predictions:  [batch, num]
        """
        texts, token_type_ids, masks = token_texts['input_ids'], token_texts['token_type_ids'], token_texts['attention_mask']
        texts = texts.squeeze(1)
        token_type_ids = token_type_ids.squeeze(1)
        masks = masks.squeeze(1)
        bert_out = self.bert(input_ids=texts, attention_mask=masks, token_type_ids=token_type_ids)[0]
        bert_out = bert_out.permute(1, 0, 2)
        # 檢測設(shè)備
        device = bert_out.device
        # 初始化隱藏層參數(shù)
        self.hidden = (torch.randn(2, bert_out.size(0), 128).to(device),
                       torch.randn(2, bert_out.size(0), 128).to(device))
        out, self.hidden = self.lstm(bert_out, self.hidden)
        lstm_feats = self.dense(out)

        # 格式轉(zhuǎn)換
        masks = masks.permute(1, 0)
        masks = masks.clone().detach().bool()
        # masks = torch.tensor(masks, dtype=torch.uint8)
        # 計(jì)算損失值和預(yù)測值
        if tags is not None:
            tags = tags.permute(1, 0)
            loss = self.neg_log_likelihood(lstm_feats, tags, masks, 'mean')
            predictions = self.crf.decode(emissions=lstm_feats, mask=masks)  # [batch, 任意數(shù)]
            return loss, predictions
        else:
            predictions = self.crf.decode(emissions=lstm_feats, mask=masks)
            return predictions

Dataset

class NerDataset(Dataset):
    def __init__(self, token_texts, tags):
        super(NerDataset, self).__init__()
        self.token_texts = token_texts
        self.tags = tags

    def __getitem__(self, index):
        return {
            "token_texts": self.token_texts[index],
            "tags": self.tags[index] if self.tags is not None else None,
        }

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


class NerDatasetTest(Dataset):
    def __init__(self, token_texts):
        super(NerDatasetTest, self).__init__()
        self.token_texts = token_texts

    def __getitem__(self, index):
        return {
            "token_texts": self.token_texts[index],
            "tags": 0
        }

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

前向傳播分析
token_texts:{
“input_size”: tensor, [batch, 1, seq_len]->[batch, seq_len]
“token_type_ids”: tensor, [batch, 1, seq_len]->[batch, seq_len]
“attention_mask”: tensor [batch, 1, seq_len]->[batch, seq_len]->[seq_len, batch]
}
tags: [batch, seq_len]->[seq_len, batch]
bert_out: [batch, seq_len, hidden_size(768)]->[seq_len, batch, hidden_size]
self.hidden: [num_layers * num_directions, hidden_size(128)]
out: [seq_len, batch, hidden_size * 2(256)]
lstm_feats: [seq_len, batch, tagset_size]
loss: tensor
predictions: [batch, num]

5 Bert-CRF模型

猿創(chuàng)征文|信息抽取(2)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取

from torch import nn
from torchcrf import CRF
from transformers import BertModel


class Bert_CRF(nn.Module):
    def __init__(self, tag2index):
        super(Bert_CRF, self).__init__()
        self.tagset_size = len(tag2index)

        # bert層
        self.bert = BertModel.from_pretrained('bert-base-chinese')
        # dense層
        self.dense = nn.Linear(in_features=768, out_features=self.tagset_size)
        # CRF層
        self.crf = CRF(num_tags=self.tagset_size)

        # 隱藏層
        self.hidden = None

    def neg_log_likelihood(self, emissions, tags=None, mask=None, reduction=None):
        return -1 * self.crf(emissions=emissions, tags=tags, mask=mask, reduction=reduction)

    def forward(self, token_texts, tags):
        """
        token_texts:{"input_size": tensor,  [batch, 1, seq_len]->[batch, seq_len]
                    "token_type_ids": tensor,  [batch, 1, seq_len]->[batch, seq_len]
                     "attention_mask": tensor  [batch, 1, seq_len]->[batch, seq_len]->[seq_len, batch]
                     }
        tags:  [batch, seq_len]->[seq_len, batch]
        bert_out:  [batch, seq_len, hidden_size(768)]->[seq_len, batch, hidden_size]
        feats:  [seq_len, batch, tagset_size]
        loss:  tensor
        predictions:  [batch, num]
        """
        texts, token_type_ids, masks = token_texts.values()
        texts = texts.squeeze(1)
        token_type_ids = token_type_ids.squeeze(1)
        masks = masks.squeeze(1)
        bert_out = self.bert(input_ids=texts, attention_mask=masks, token_type_ids=token_type_ids)[0]
        bert_out = bert_out.permute(1, 0, 2)
        feats = self.dense(bert_out)

        # 格式轉(zhuǎn)換
        masks = masks.permute(1, 0)
        masks = masks.clone().detach().bool()
        # 計(jì)算損失之和預(yù)測值
        if tags is not None:
            tags = tags.permute(1, 0)
            loss = self.neg_log_likelihood(feats, tags, masks, 'mean')
            predictions = self.crf.decode(emissions=feats, mask=masks)
            return loss, predictions
        else:
            predictions = self.crf.decode(emissions=feats, mask=masks)
            return predictions

前向傳播分析
token_texts:{
“input_size”: tensor, [batch, 1, seq_len]->[batch, seq_len]
“token_type_ids”: tensor, [batch, 1, seq_len]->[batch, seq_len]
“attention_mask”: tensor [batch, 1, seq_len]->[batch, seq_len]->[seq_len, batch]
}
tags: [batch, seq_len]->[seq_len, batch]
bert_out: [batch, seq_len, hidden_size(768)]->[seq_len, batch, hidden_size]
feats: [seq_len, batch, tagset_size]
loss: tensor
predictions: [batch, num]

6 模型訓(xùn)練

# 訓(xùn)練
def train(train_dataloader, model, optimizer, epoch):
    for i, batch_data in enumerate(train_dataloader):
        token_texts = batch_data['token_texts'].to(DEVICE)
        tags = batch_data['tags'].to(DEVICE)
        loss, predictions = model(token_texts, tags)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if i % 200 == 0:
            micro_f1 = get_f1_score(tags, predictions)
            print(f'Epoch:{epoch} | i:{i} | loss:{loss.item()} | Micro_F1:{micro_f1}')

7 結(jié)果評(píng)估

# 計(jì)算f1值
def get_f1_score(tags, predictions):
    tags = tags.to('cpu').data.numpy().tolist()
    temp_tags = []
    final_tags = []
    for index in range(BATCH_SIZE):
        # predictions先去掉頭,再去掉尾
        predictions[index].pop()
        length = len(predictions[index])
        temp_tags.append(tags[index][1:length])
        predictions[index].pop(0)
        # 格式轉(zhuǎn)化,轉(zhuǎn)化為List(str)
        temp_tags[index] = [index2tag[x] for x in temp_tags[index]]
        predictions[index] = [index2tag[x] for x in predictions[index]]
        final_tags.append(temp_tags[index])

    f1 = f1_score(final_tags, predictions, average='micro')
    return f1

Bert-BiLSTM-CRF

GPU_NAME:NVIDIA GeForce RTX 3060 Laptop GPU | Memory_Allocated:413399040
Epoch:0 | i:0 | loss:58.75139236450195 | Micro_F1:0.0
Epoch:0 | i:200 | loss:26.20857048034668 | Micro_F1:0.0
Epoch:0 | i:400 | loss:18.385879516601562 | Micro_F1:0.0
Epoch:1 | i:0 | loss:20.496620178222656 | Micro_F1:0.0
Epoch:1 | i:200 | loss:15.421577453613281 | Micro_F1:0.0
Epoch:1 | i:400 | loss:11.486358642578125 | Micro_F1:0.0
Epoch:2 | i:0 | loss:14.486601829528809 | Micro_F1:0.0
Epoch:2 | i:200 | loss:10.369649887084961 | Micro_F1:0.18867924528301888
Epoch:2 | i:400 | loss:8.056020736694336 | Micro_F1:0.5652173913043479
Epoch:3 | i:0 | loss:14.958343505859375 | Micro_F1:0.41025641025641024
Epoch:3 | i:200 | loss:9.968450546264648 | Micro_F1:0.380952380952381
Epoch:3 | i:400 | loss:8.947534561157227 | Micro_F1:0.5614035087719299
Epoch:4 | i:0 | loss:9.189300537109375 | Micro_F1:0.5454545454545454
Epoch:4 | i:200 | loss:8.673486709594727 | Micro_F1:0.43999999999999995
Epoch:4 | i:400 | loss:6.431578636169434 | Micro_F1:0.6250000000000001

Bert-CRF

GPU_NAME:NVIDIA GeForce RTX 3060 Laptop GPU | Memory_Allocated:409739264
Epoch:0 | i:0 | loss:57.06057357788086 | Micro_F1:0.0
Epoch:0 | i:200 | loss:12.05904483795166 | Micro_F1:0.0
Epoch:0 | i:400 | loss:13.805888175964355 | Micro_F1:0.39393939393939387
Epoch:1 | i:0 | loss:9.807424545288086 | Micro_F1:0.4905660377358491
Epoch:1 | i:200 | loss:8.098043441772461 | Micro_F1:0.509090909090909
Epoch:1 | i:400 | loss:7.059831619262695 | Micro_F1:0.611111111111111
Epoch:2 | i:0 | loss:6.629759788513184 | Micro_F1:0.6133333333333333
Epoch:2 | i:200 | loss:3.593130350112915 | Micro_F1:0.6896551724137931
Epoch:2 | i:400 | loss:6.8786163330078125 | Micro_F1:0.6666666666666666
Epoch:3 | i:0 | loss:5.009466648101807 | Micro_F1:0.6969696969696969
Epoch:3 | i:200 | loss:2.9549810886383057 | Micro_F1:0.8450704225352113
Epoch:3 | i:400 | loss:3.3801448345184326 | Micro_F1:0.868421052631579
Epoch:4 | i:0 | loss:5.864352226257324 | Micro_F1:0.626865671641791
Epoch:4 | i:200 | loss:3.308518409729004 | Micro_F1:0.7666666666666667
Epoch:4 | i:400 | loss:4.221902847290039 | Micro_F1:0.7000000000000001

分析
進(jìn)行了5個(gè)epoch的訓(xùn)練
數(shù)據(jù)集比較小,只有7000多條數(shù)據(jù),因此兩個(gè)模型效果擬合效果相對BiLSTM+CRF模型提升不大。而添加了雙向LSTM層之后,模型效果反而有所下降。

8 訓(xùn)練集流水線

注意學(xué)習(xí)率要設(shè)置小一點(diǎn)(小于1e-5),否則預(yù)測結(jié)果均為0,不收斂。

def execute():
    # 加載訓(xùn)練集
    train_dataset = pd.read_csv(TRAIN_PATH, encoding='utf8')
    # 數(shù)據(jù)預(yù)處理
    token_texts, tags = data_preprocessing(train_dataset, is_train=True)
    # 數(shù)據(jù)集裝載
    train_dataset = NerDataset(token_texts, tags)
    train_dataloader = DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4)
    # 構(gòu)建模型
    # model = Bert_BiLSTM_CRF(tag2index=tag2index).to(DEVICE)
    model = Bert_CRF(tag2index=tag2index).to(DEVICE)
    optimizer = optim.AdamW(model.parameters(), lr=1e-6)
    print(f"GPU_NAME:{torch.cuda.get_device_name()} | Memory_Allocated:{torch.cuda.memory_allocated()}")
    # 模型訓(xùn)練
    for i in range(EPOCH):
        train(train_dataloader, model, optimizer, i)

    # 保存模型
    torch.save(model.state_dict(), MODEL_PATH2)

9 測試集流水線

# 測試集預(yù)測實(shí)體標(biāo)簽
def test():
    # 加載數(shù)據(jù)集
    test_dataset = pd.read_csv(TEST_PATH, encoding='utf8')
    # 數(shù)據(jù)預(yù)處理
    token_texts, _ = data_preprocessing(test_dataset, is_train=False)
    # 裝載測試集
    dataset_test = NerDatasetTest(token_texts)
    test_dataloader = DataLoader(dataset=dataset_test, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)
    # 構(gòu)建模型
    # model = Bert_BiLSTM_CRF(tag2index).to(DEVICE)
    model = Bert_CRF(tag2index).to(DEVICE)
    model.load_state_dict(torch.load(MODEL_PATH2))
    # 模型預(yù)測
    model.eval()
    predictions_list = []
    with torch.no_grad():
        for i, batch_data in enumerate(test_dataloader):
            token_texts = batch_data['token_texts'].to(DEVICE)
            predictions = model(token_texts, None)
            predictions_list.extend(predictions)
    print(len(predictions_list))
    print(len(test_dataset['text']))

    # 將預(yù)測結(jié)果轉(zhuǎn)換為文本格式
    entity_tag_list = []
    index2tag = {v: k for k, v in tag2index.items()}  # 反轉(zhuǎn)字典
    for i, (text, predictions) in enumerate(zip(test_dataset['text'], predictions_list)):
        # 刪除首位和最后一位
        predictions.pop()
        predictions.pop(0)
        text_entity_tag = []
        for c, t in zip(text, predictions):
            if t != 0:
                text_entity_tag.append(c + index2tag[t])
        entity_tag_list.append(" ".join(text_entity_tag))  # 合并為str并加入列表中

    print(len(entity_tag_list))
    result_df = pd.DataFrame(data=entity_tag_list, columns=['result'])
    result_df.to_csv('./data/result_df3.csv')

猿創(chuàng)征文|信息抽取(2)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取
結(jié)果好像存在一些問題。。。

10 記錄遇到的一些坑

(1)模型預(yù)測結(jié)果全為O
原因:按照之前的模型,AdamW優(yōu)化器學(xué)習(xí)率設(shè)置0.001,學(xué)習(xí)率過高,導(dǎo)致梯度下降過程中落入了局部最低點(diǎn)。
解決方法:重新設(shè)置學(xué)習(xí)率為1e-6
(2)transformers的AdamW顯示過期
解決方法:直接使用torch.optim的AdamW即可
(3)transformers庫在ubuntu上無法使用
原因:缺少依賴
解決方法:

apt-get update
apt-get install libssl1.0.0 libssl-dev

使用此代碼在服務(wù)器終端上跑完后,仍會(huì)報(bào)錯(cuò),原因未知,暫時(shí)用os.system()嵌入到代碼中,在windows系統(tǒng)中無此報(bào)錯(cuò)。
(4)筆記本(聯(lián)想R7000P2021)運(yùn)行代碼溫度過高(最高95度)
解決方法:先用均衡模式(CPU不睿頻)跑,溫度只有六七十度,然后開啟野獸模式跑一段時(shí)間,溫度高了再切換為均衡模式。文章來源地址http://www.zghlxwxcb.cn/news/detail-429090.html

11 完整代碼

import pandas as pd
import torch
from torch import optim
from torch.utils.data import DataLoader
from tqdm import tqdm
from bert_bilstm_crf import Bert_BiLSTM_CRF, NerDataset, NerDatasetTest
from bert_crf import Bert_CRF
from transformers import AutoTokenizer, BertTokenizer
from seqeval.metrics import f1_score

# 路徑
TRAIN_PATH = './dataset/train_data_public.csv'
TEST_PATH = './dataset/test_public.csv'
MODEL_PATH1 = './model/bert_bilstm_crf.pkl'
MODEL_PATH2 = '../model/bert_crf.pkl'

# 超參數(shù)
MAX_LEN = 64
BATCH_SIZE = 16
EPOCH = 5

# 預(yù)設(shè)
# 設(shè)備
DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu"
# tag2index
tag2index = {
    "O": 0,  # 其他
    "B-BANK": 1, "I-BANK": 2,  # 銀行實(shí)體
    "B-PRODUCT": 3, "I-PRODUCT": 4,  # 產(chǎn)品實(shí)體
    "B-COMMENTS_N": 5, "I-COMMENTS_N": 6,  # 用戶評(píng)論,名詞
    "B-COMMENTS_ADJ": 7, "I-COMMENTS_ADJ": 8  # 用戶評(píng)論,形容詞
}
index2tag = {v: k for k, v in tag2index.items()}


# 訓(xùn)練
def train(train_dataloader, model, optimizer, epoch):
    for i, batch_data in enumerate(train_dataloader):
        token_texts = batch_data['token_texts'].to(DEVICE)
        tags = batch_data['tags'].to(DEVICE)
        loss, predictions = model(token_texts, tags)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if i % 200 == 0:
            micro_f1 = get_f1_score(tags, predictions)
            print(f'Epoch:{epoch} | i:{i} | loss:{loss.item()} | Micro_F1:{micro_f1}')


# 計(jì)算f1值
def get_f1_score(tags, predictions):
    tags = tags.to('cpu').data.numpy().tolist()
    temp_tags = []
    final_tags = []
    for index in range(BATCH_SIZE):
        # predictions先去掉頭,再去掉尾
        predictions[index].pop()
        length = len(predictions[index])
        temp_tags.append(tags[index][1:length])
        predictions[index].pop(0)
        # 格式轉(zhuǎn)化,轉(zhuǎn)化為List(str)
        temp_tags[index] = [index2tag[x] for x in temp_tags[index]]
        predictions[index] = [index2tag[x] for x in predictions[index]]
        final_tags.append(temp_tags[index])

    f1 = f1_score(final_tags, predictions, average='micro')
    return f1


# 預(yù)處理
def data_preprocessing(dataset, is_train):
    # 數(shù)據(jù)str轉(zhuǎn)化為list
    dataset['text_split'] = dataset['text'].apply(list)
    # token
    tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
    texts = dataset['text_split'].array.tolist()
    token_texts = []
    for text in tqdm(texts):
        tokenized = tokenizer.encode_plus(text=text,
                                          max_length=MAX_LEN,
                                          return_token_type_ids=True,
                                          return_attention_mask=True,
                                          return_tensors='pt',
                                          padding='max_length',
                                          truncation=True)
        token_texts.append(tokenized)

    # 訓(xùn)練集有tag,測試集沒有tag
    tags = None
    if is_train:
        dataset['tag'] = dataset['BIO_anno'].apply(lambda x: x.split(sep=' '))
        tags = []
        for tag in tqdm(dataset['tag'].array.tolist()):
            index_list = [0] + [tag2index[t] for t in tag] + [0]
            if len(index_list) < MAX_LEN:  # 填充
                pad_length = MAX_LEN - len(index_list)
                index_list += [tag2index['O']] * pad_length
            if len(index_list) > MAX_LEN:  # 裁剪
                index_list = index_list[:MAX_LEN-1] + [0]
            tags.append(index_list)
        tags = torch.LongTensor(tags)

    return token_texts, tags


# 執(zhí)行流水線
def execute():
    # 加載訓(xùn)練集
    train_dataset = pd.read_csv(TRAIN_PATH, encoding='utf8')
    # 數(shù)據(jù)預(yù)處理
    token_texts, tags = data_preprocessing(train_dataset, is_train=True)
    # 數(shù)據(jù)集裝載
    train_dataset = NerDataset(token_texts, tags)
    train_dataloader = DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4)
    # 構(gòu)建模型
    # model = Bert_BiLSTM_CRF(tag2index=tag2index).to(DEVICE)
    model = Bert_CRF(tag2index=tag2index).to(DEVICE)
    optimizer = optim.AdamW(model.parameters(), lr=1e-6)
    print(f"GPU_NAME:{torch.cuda.get_device_name()} | Memory_Allocated:{torch.cuda.memory_allocated()}")
    # 模型訓(xùn)練
    for i in range(EPOCH):
        train(train_dataloader, model, optimizer, i)

    # 保存模型
    torch.save(model.state_dict(), MODEL_PATH2)


# 測試集預(yù)測實(shí)體標(biāo)簽
def test():
    # 加載數(shù)據(jù)集
    test_dataset = pd.read_csv(TEST_PATH, encoding='utf8')
    # 數(shù)據(jù)預(yù)處理
    token_texts, _ = data_preprocessing(test_dataset, is_train=False)
    # 裝載測試集
    dataset_test = NerDatasetTest(token_texts)
    test_dataloader = DataLoader(dataset=dataset_test, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)
    # 構(gòu)建模型
    model = Bert_BiLSTM_CRF(tag2index).to(DEVICE)
    model.load_state_dict(torch.load(MODEL_PATH2))
    # 模型預(yù)測
    model.eval()
    predictions_list = []
    with torch.no_grad():
        for i, batch_data in enumerate(test_dataloader):
            token_texts = batch_data['token_texts'].to(DEVICE)
            predictions = model(token_texts, None)
            predictions_list.extend(predictions)
    print(len(predictions_list))
    print(len(test_dataset['text']))

    # 將預(yù)測結(jié)果轉(zhuǎn)換為文本格式
    entity_tag_list = []
    index2tag = {v: k for k, v in tag2index.items()}  # 反轉(zhuǎn)字典
    for i, (text, predictions) in enumerate(zip(test_dataset['text'], predictions_list)):
        # 刪除首位和最后一位
        predictions.pop()
        predictions.pop(0)
        text_entity_tag = []
        for c, t in zip(text, predictions):
            if t != 0:
                text_entity_tag.append(c + index2tag[t])
        entity_tag_list.append(" ".join(text_entity_tag))  # 合并為str并加入列表中

    print(len(entity_tag_list))
    result_df = pd.DataFrame(data=entity_tag_list, columns=['result'])
    result_df.to_csv('./data/result_df3.csv')


if __name__ == '__main__':
    execute()
    test()

到了這里,關(guān)于猿創(chuàng)征文|信息抽取(2)——pytorch實(shí)現(xiàn)Bert-BiLSTM-CRF、Bert-CRF模型進(jìn)行實(shí)體抽取的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 猿創(chuàng)征文|【HTML】標(biāo)簽學(xué)習(xí)之路

    猿創(chuàng)征文|【HTML】標(biāo)簽學(xué)習(xí)之路

    ?? 目錄 一、HTML語法規(guī)范 1.基本語法概述 2.標(biāo)簽關(guān)系 二、HTML基本結(jié)構(gòu)標(biāo)簽 1.第一個(gè)HTML頁面 2.HTML基本結(jié)構(gòu)標(biāo)簽總結(jié) 1.基本語法概述 html是由尖括號(hào)包圍的,列如: html 。 html標(biāo)簽通常是成對出現(xiàn)的,列如:html和/html,我們稱為 雙標(biāo)簽 。標(biāo)簽對里的第一個(gè)標(biāo)簽是開始標(biāo)

    2024年01月16日
    瀏覽(25)
  • 猿創(chuàng)征文|ZooKeeper(偽)集群搭建

    猿創(chuàng)征文|ZooKeeper(偽)集群搭建

    前言:zookeeper作為一款分布式協(xié)調(diào)中間件,其重要性不言而喻,因此需要保證其高可用性。所以一般都會(huì)搭建zookeeper集群,今天葉秋帶領(lǐng)大家在一臺(tái)服務(wù)器上搭建偽集群。 目錄 1、 搭建要求 2、 準(zhǔn)備工作 3、 配置集群 ?4 啟動(dòng)集群 ?5 模擬集群異常 1、 搭建要求 真實(shí)的集群是

    2024年02月01日
    瀏覽(30)
  • 猿創(chuàng)征文| redis基本數(shù)據(jù)類型

    猿創(chuàng)征文| redis基本數(shù)據(jù)類型

    ??個(gè)人主頁:不斷前進(jìn)的皮卡丘 ??博客描述:夢想也許遙不可及,但重要的是追夢的過程,用博客記錄自己的成長,記錄自己一步一步向上攀登的印記 ??個(gè)人專欄:微服務(wù)專欄 ??redis常見的操作命令:http://www.redis.cn/commands.html 命令 功能 keys * 查看當(dāng)前庫的所有key exists key 判斷

    2023年04月08日
    瀏覽(18)
  • 以太坊是什么?|猿創(chuàng)征文

    以太坊是什么?|猿創(chuàng)征文

    以太坊是一個(gè)可編程、可視化、更易用的區(qū)塊鏈,它允許任何人編寫智能合約和發(fā)行代幣。 在以太坊(Ethereum)出現(xiàn)之前,各種區(qū)塊鏈應(yīng)用的功能非常有限,例如,比特幣和其他加密貨幣都只是純粹的數(shù)字貨幣。 以太坊(Ethereum)創(chuàng)始人Vitalik Buterin將以太坊(Ethereum)設(shè)想為開發(fā)人員

    2024年02月02日
    瀏覽(23)
  • 猿創(chuàng)征文|【深度學(xué)習(xí)前沿應(yīng)用】文本生成

    猿創(chuàng)征文|【深度學(xué)習(xí)前沿應(yīng)用】文本生成

    作者簡介 :在校大學(xué)生一枚,C/C++領(lǐng)域新星創(chuàng)作者,華為云享專家,阿里云專家博主,騰云先鋒(TDP)成員,云曦智劃項(xiàng)目總負(fù)責(zé)人,全國高等學(xué)校計(jì)算機(jī)教學(xué)與產(chǎn)業(yè)實(shí)踐資源建設(shè)專家委員會(huì)(TIPCC)志愿者,以及編程愛好者,期待和大家一起學(xué)習(xí),一起進(jìn)步~ . 博客主頁 :

    2024年02月06日
    瀏覽(17)
  • 猿創(chuàng)征文|“云“創(chuàng)新展望:數(shù)據(jù)之浩瀚

    猿創(chuàng)征文|“云“創(chuàng)新展望:數(shù)據(jù)之浩瀚

    ??wei_shuo的個(gè)人主頁 ??wei_shuo的學(xué)習(xí)社區(qū) ??Hello World ! AWS亞馬遜云科技提供全球覆蓋廣泛、服務(wù)深入的云平臺(tái),全球數(shù)據(jù)中心提供超過 200 項(xiàng)功能齊全的服務(wù) 連續(xù) 11 年被 Gartner 評(píng)為\\\"全球云計(jì)算領(lǐng)導(dǎo)者\(yùn)\\" ;2021 年全新 Gartner 魔力象限中被評(píng)為\\\"云基礎(chǔ)設(shè)施與平臺(tái)服務(wù)(Iaas Pa

    2023年04月24日
    瀏覽(23)
  • 猿創(chuàng)征文|我的技術(shù)成長之路&&C++

    猿創(chuàng)征文|我的技術(shù)成長之路&&C++

    ?作者簡介:C/C++領(lǐng)域新星創(chuàng)作者,CSDN內(nèi)容合伙人,新晉萬粉博主,大三學(xué)生 這個(gè)世界熙熙攘攘,少有人給靈魂拋光 ??讀者朋友們大家好,借著本次猿創(chuàng)征文活動(dòng)我將分享一下自己的C++技術(shù)的成長之路。身為計(jì)科專業(yè)的學(xué)生,我接觸的第一門編程語言是C語言,打印的第一

    2024年02月06日
    瀏覽(20)
  • 猿創(chuàng)征文 | Solidity 智能合約技術(shù)成長之路

    猿創(chuàng)征文 | Solidity 智能合約技術(shù)成長之路

    Solidity 是鏈上智能合約的開發(fā)語言,鏈上智能合約相當(dāng)于傳統(tǒng)行業(yè)的后端,鏈上應(yīng)用基本都是由合約 + 前端組成的,雖然不推薦,但部分鏈上應(yīng)用也會(huì)加入后端進(jìn)行數(shù)據(jù)存儲(chǔ),以降低用戶的使用成本。 Solidity 這門開發(fā)語言并不復(fù)雜,只需要您稍微有一點(diǎn)兒編程基礎(chǔ),英文詞匯

    2024年01月23日
    瀏覽(23)
  • 猿創(chuàng)征文|Hadoop大數(shù)據(jù)技術(shù)綜合實(shí)驗(yàn)

    猿創(chuàng)征文|Hadoop大數(shù)據(jù)技術(shù)綜合實(shí)驗(yàn)

    當(dāng)前互聯(lián)網(wǎng)應(yīng)用中,萬維網(wǎng)(World Wide Web)應(yīng)用占據(jù)了絕大部分的份額。萬維網(wǎng)應(yīng)用對外提供服務(wù)需要架設(shè)Web服務(wù)器軟件。典型的Web服務(wù)器軟件有Apache、Nginx等。Web服務(wù)器軟件在運(yùn)行過程中會(huì)寫入各種日志到磁盤文件中。例如,Apache Web服務(wù)器軟件運(yùn)行過程中,會(huì)產(chǎn)生access.log文

    2024年02月03日
    瀏覽(31)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包