<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Bert4torch 快速入門實(shí)戰(zhàn)

          共 9678字,需瀏覽 20分鐘

           ·

          2022-08-06 23:26


          作者簡(jiǎn)介




          作者:Bo仔很忙??

          原文:https://zhuanlan.zhihu.com/p/486329434


          轉(zhuǎn)載者:楊夕

          推薦系統(tǒng) 百面百搭地址:

          https://github.com/km1994/RES-Interview-Notes

          NLP 百面百搭地址:

          https://github.com/km1994/NLP-Interview-Notes

          個(gè)人筆記:

          https://github.com/km1994/nlp_paper_study


          a5750f101d60029beb5280a5f7902dda.webp


          背景

          本人經(jīng)常會(huì)閱讀蘇神的科學(xué)空間網(wǎng)站,里面有很多對(duì)前言paper淺顯易懂的解釋,以及很多蘇神自己的創(chuàng)新實(shí)踐;并且基于bert4keras框架都有了相應(yīng)的代碼實(shí)現(xiàn)。但是由于本人主要用pytorch開(kāi)發(fā),因此參考bert4keras開(kāi)發(fā)了bert4torch項(xiàng)目,實(shí)現(xiàn)了bert4keras的主要功能。

          簡(jiǎn)介

          bert4torch是一個(gè)基于pytorch的訓(xùn)練框架,前期以效仿和實(shí)現(xiàn)bert4keras的主要功能為主,方便加載多類預(yù)訓(xùn)練模型進(jìn)行finetune,提供了中文注釋方便用戶理解模型結(jié)構(gòu)。主要是期望應(yīng)對(duì)新項(xiàng)目時(shí),可以直接調(diào)用不同的預(yù)訓(xùn)練模型直接finetune,或方便用戶基于bert進(jìn)行魔改,快速驗(yàn)證自己的idea;節(jié)省在github上clone各種項(xiàng)目耗時(shí)耗力,且本地文件各種copy的問(wèn)題。

          • pip安裝

          pip install bert4torch
          github鏈接https://github.com/Tongjilibo/bert4torch

          主要功能

          1、加載預(yù)訓(xùn)練權(quán)重(bert、roberta、albert、nezha、bart、RoFormer、ELECTRA、GPT、GPT2、T5)繼續(xù)進(jìn)行finetune

          4ca4002d8aea49beb44d2d1b1a83a704.webp

          目前支持的預(yù)訓(xùn)練模型一覽

          2、在bert基礎(chǔ)上靈活定義自己模型:主要是可以接在bert的[btz, seq_len, hdsz]的隱含層向量后做各種魔改

          3、調(diào)用方式和bert4keras基本一致,簡(jiǎn)潔高效

              model.fit(        train_dataloader,        steps_per_epoch=1000,        epochs=epochs,        callbacks=[evaluator]    )

          4、實(shí)現(xiàn)基于keras的訓(xùn)練進(jìn)度條動(dòng)態(tài)展示

          0f44cb7419ac8c2e1d4de6353e31a8e3.webp仿照keras的模型訓(xùn)練進(jìn)度條

          5、配合torchinfo,實(shí)現(xiàn)打印各層參數(shù)量功能

          265618d2c3cf767fcf4c54fcdc383196.webp打印參數(shù)

          6、結(jié)合logger,或者tensorboard可以在后臺(tái)打印日志

          支持在訓(xùn)練開(kāi)始/結(jié)束,batch開(kāi)始/結(jié)束,epoch的開(kāi)始/結(jié)束,記錄日志,寫(xiě)tensorboard等

          class Callback(object):    '''Callback基類    '''    def __init__(self):        pass    def on_train_begin(self, logs=None):        pass    def on_train_end(self, logs=None):        pass    def on_epoch_begin(self, global_step, epoch, logs=None):        pass    def on_epoch_end(self, global_step, epoch, logs=None):        pass    def on_batch_begin(self, global_step, batch, logs=None):        pass    def on_batch_end(self, global_step, batch, logs=None):        pass

          7、集成多個(gè)example,可以作為自己的訓(xùn)練框架,方便在同一個(gè)數(shù)據(jù)集上嘗試多種解決方案

          7e286326b47cef9ef057496c66a82b9b.webp實(shí)現(xiàn)多個(gè)example可供參考

          支持的預(yù)訓(xùn)練權(quán)重(bert4torch)


          d79eb6ee2f2befd9c967d3d087c1d634.webp

          實(shí)戰(zhàn)

          1. 建模流程示例

          # 建立分詞器tokenizer = Tokenizer(dict_path, do_lower_case=True)# 加載數(shù)據(jù)集,可以自己繼承Dataset來(lái)定義class MyDataset(ListDataset):    @staticmethod    def load_data(filenames):        """讀取文本文件,整理成需要的格式        """        D = []        return Ddef collate_fn(batch):    '''處理上述load_data得到的batch數(shù)據(jù),整理成對(duì)應(yīng)device上的Tensor    注意:返回值分為feature和label, feature可整理成list或tuple    '''    batch_token_ids, batch_segment_ids, batch_labels = [], [], []    return [batch_token_ids, batch_segment_ids], batch_labels.flatten()# 加載數(shù)據(jù)集train_dataloader = DataLoader(MyDataset('file_path'), batch_size=batch_size, shuffle=True, collate_fn=collate_fn) # 定義bert上的模型結(jié)構(gòu),以文本二分類為例class Model(BaseModel):    def __init__(self) -> None:        super().__init__()        self.bert = build_transformer_model(config_path, checkpoint_path, with_pool=True)        self.dropout = nn.Dropout(0.1)        self.dense = nn.Linear(768, 2)
          def forward(self, token_ids, segment_ids): # build_transformer_model得到的模型僅接受list/tuple傳參,因此入?yún)⒅挥幸粋€(gè)時(shí)候包裝成[token_ids] hidden_states, pooled_output = self.bert([token_ids, segment_ids]) output = self.dropout(pooled_output) output = self.dense(output) return outputmodel = Model().to(device)# 定義使用的loss和optimizer,這里支持自定義model.compile( loss=nn.CrossEntropyLoss(), # 可以自定義Loss optimizer=optim.Adam(model.parameters(), lr=2e-5), # 可以自定義優(yōu)化器 scheduler=None, # 可以自定義scheduler metrics=['accuracy'])# 定義評(píng)價(jià)函數(shù)def evaluate(data): total, right = 0., 0. for x_true, y_true in data: y_pred = model.predict(x_true).argmax(axis=1) total += len(y_true) right += (y_true == y_pred).sum().item() return right / totalclass Evaluator(Callback): """評(píng)估與保存,這里定義僅在epoch結(jié)束后調(diào)用 """ def __init__(self): self.best_val_acc = 0.
          def on_epoch_end(self, global_step, epoch, logs=None): val_acc = evaluate(valid_dataloader) if val_acc > self.best_val_acc: self.best_val_acc = val_acc model.save_weights('best_model.pt') print(f'val_acc: {val_acc:.5f}, best_val_acc: {self.best_val_acc:.5f}\n')if?__name__?==?'__main__': evaluator = Evaluator() model.fit(train_dataloader, epochs=20, steps_per_epoch=100, grad_accumulation_steps=2, callbacks=[evaluator])

          2. 主要模塊講解

          1) 數(shù)據(jù)處理部分

          a. 精簡(jiǎn)詞表,并建立分詞器

          token_dict, keep_tokens = load_vocab(    dict_path=dict_path,  # 詞典文件路徑    simplified=True,  # 過(guò)濾冗余部分token,如[unused1]    startswith=['[PAD]', '[UNK]', '[CLS]', '[SEP]'],  # 指定起始的token,如[UNK]從bert默認(rèn)的103位置調(diào)整到1)tokenizer?=?Tokenizer(token_dict,?do_lower_case=True)??#?若無(wú)需精簡(jiǎn),僅使用當(dāng)前行定義tokenizer即可

          b. 好用的小函數(shù)

          • text_segmentate(): 截?cái)嗫傞L(zhǎng)度至不超過(guò)maxlen, 接受多個(gè)sequence輸入,每次截?cái)嘧铋L(zhǎng)的句子,indices表示刪除的token位置

          • tokenizer.encode(): 把text轉(zhuǎn)成token_ids,默認(rèn)句首添加[CLS],句尾添加[SEP],返回token_ids和segment_ids,相當(dāng)于同時(shí)調(diào)用tokenizer.tokenize()tokenizer.tokens_to_ids()

          • tokenizer.decode(): 把token_ids轉(zhuǎn)成text,默認(rèn)會(huì)刪除[CLS], [SEP], [UNK]等特殊字符,相當(dāng)于調(diào)用tokenizer.ids_to_tokens()并做了一些后處理

          • sequence_padding: 將序列padding到同一長(zhǎng)度, 傳入一個(gè)元素為list, ndarray, tensor的list,返回ndarry或tensor

          2) 模型定義部分

          • 模型創(chuàng)建

          '''調(diào)用模型后,若設(shè)置with_pool,?with_nsp,?with_mlm,則返回值依次為[hidden_states,?pool_emb/nsp_emb,?mlm_scores],否則只返回hidden_states'''build_transformer_model(    config_path=config_path, # 模型的config文件地址    checkpoint_path=checkpoint_path, # 模型文件地址,默認(rèn)值None表示不加載預(yù)訓(xùn)練模型    model='bert', # 加載的模型結(jié)構(gòu),這里Model也可以基于nn.Module自定義后傳入    application='encoder',  # 模型應(yīng)用,支持encoder,lm和unilm格式    segment_vocab_size=2,  # type_token_ids數(shù)量,默認(rèn)為2,如不傳入segment_ids則需設(shè)置為0    with_pool=False,  # 是否包含Pool部分    with_nsp=False,  # 是否包含NSP部分    with_mlm=False,  # 是否包含MLM部分    return_model_config=False,  # 是否返回模型配置參數(shù)    output_all_encoded_layers=False,  # 是否返回所有hidden_state層)
          • 定義loss,optimizer,scheduler等

          '''定義使用的loss和optimizer,這里支持自定義'''model.compile(    loss=nn.CrossEntropyLoss(), # 可以自定義Loss    optimizer=optim.Adam(model.parameters(), lr=2e-5),  # 可以自定義優(yōu)化器    scheduler=None, # 可以自定義scheduler    adversarial_train={'name': 'fgm'},  # 訓(xùn)練trick方案設(shè)置,支持fgm, pgd, gradient_penalty, vat    metrics=['accuracy']  # loss等默認(rèn)打印的字段無(wú)需設(shè)置)
          • 自定義模型

          '''基于bert上層的各類魔改,如last2layer_average, token_first_last_average'''class Model(BaseModel):    # 需要繼承BaseModel    def __init__(self):        super().__init__()        self.bert = build_transformer_model(config_path, checkpoint_path)    def forward(self):        pass

          • 自定義訓(xùn)練過(guò)程

          '''自定義fit過(guò)程,適用于自帶fit()不滿足需求時(shí)'''class Model(BaseModel):    def fit(self, train_dataloader, steps_per_epoch, epochs):           train_dataloader = cycle(train_dataloader)        self.train()        for epoch in range(epochs):            for bti in range(steps_per_epoch):                train_X, train_y = next(train_dataloader)                output = self.forward(*train_X)                loss = self.criterion(output, train_y)                loss.backward()                self.optimizer.step()                self.optimizer.zero_grad()
          • 模型保存和加載

          '''prefix: 是否以原始的key來(lái)保存,如word_embedding原始key為bert.embeddings.word_embeddings.weight默認(rèn)為None表示不啟用, 若基于BaseModel自定義模型,需指定為bert模型對(duì)應(yīng)的成員變量名,直接使用設(shè)置為''主要是為了別的訓(xùn)練框架容易加載'''model.save_weights(save_path, prefix=None)model.load_weights(load_path, strict=True, prefix=None)
          • 加載transformers模型進(jìn)行訓(xùn)練

          from transformers import AutoModelForSequenceClassificationclass Model(BaseModel):    def __init__(self):        super().__init__()        self.bert = AutoModelForSequenceClassification.from_pretrained("file_path", num_labels=2)    def forward(self, token_ids, attention_mask, segment_ids):        output = self.bert(input_ids=token_ids, attention_mask=attention_mask, token_type_ids=segment_ids)        return output.logits

          3) 模型評(píng)估部分

          '''支持在多個(gè)位置執(zhí)行'''class Evaluator(Callback):    """評(píng)估與保存    """    def __init__(self):        self.best_val_acc = 0.    def on_train_begin(self, logs=None):  # 訓(xùn)練開(kāi)始時(shí)候        pass    def on_train_end(self, logs=None):  # 訓(xùn)練結(jié)束時(shí)候        pass    def on_batch_begin(self, global_step, batch, logs=None):  # batch開(kāi)始時(shí)候        pass    def on_batch_end(self, global_step, batch, logs=None):  # batch結(jié)束時(shí)候        # 可以設(shè)置每隔多少個(gè)step,后臺(tái)記錄log,寫(xiě)tensorboard等        # 盡量不要在batch_begin和batch_end中print,防止打斷進(jìn)度條功能        pass    def on_epoch_begin(self, global_step, epoch, logs=None):  # epoch開(kāi)始時(shí)候        pass    def on_epoch_end(self, global_step, epoch, logs=None):  # epoch結(jié)束時(shí)候        val_acc = evaluate(valid_dataloader)        if val_acc > self.best_val_acc:            self.best_val_acc = val_acc            model.save_weights('best_model.pt')        print(f'val_acc: {val_acc:.5f}, best_val_acc: {self.best_val_acc:.5f}\n')

          3. 其他特性講解

          1) 單機(jī)多卡訓(xùn)練

          a. 使用DataParallel

          '''DP有兩種方式,第一種是forward只計(jì)算logit,第二種是forward直接計(jì)算loss建議使用第二種,可以部分緩解負(fù)載不均衡的問(wèn)題'''from bert4torch.models import BaseModelDP# ===========處理數(shù)據(jù)和定義model===========model = BaseModelDP(model)  # 指定DP模式使用多gpumodel.compile(    loss=lambda x, _: x.mean(),  # 多個(gè)gpu計(jì)算的loss的均值    optimizer=optim.Adam(model.parameters(), lr=2e-5),  # 用足夠小的學(xué)習(xí)率)

          b. 使用DistributedDataParallel

          '''DDP使用torch.distributed.launch,從命令行啟動(dòng)'''# 需要定義命令行參數(shù)parser = argparse.ArgumentParser()parser.add_argument("--local_rank", type=int, default=-1)args = parser.parse_args()torch.cuda.set_device(args.local_rank)device = torch.device('cuda', args.local_rank)torch.distributed.init_process_group(backend='nccl')# ===========處理數(shù)據(jù)和定義model===========# 指定DDP模型使用多gpu, master_rank為指定用于打印訓(xùn)練過(guò)程的local_rankmodel = BaseModelDDP(    model, master_rank=0,     device_ids=[args.local_rank],     output_device=args.local_rank,     find_unused_parameters=False??)#?定義使用的loss和optimizer,這里支持自定義model.compile(loss=lambda x, _: x,  # 直接把forward計(jì)算的loss傳出來(lái)optimizer=optim.Adam(model.parameters(), lr=2e-5),  # 用足夠小的學(xué)習(xí)率)

          2) tensorboard保存訓(xùn)練過(guò)程

          from tensorboardX import SummaryWriterclass Evaluator(Callback):    """每隔多少個(gè)step評(píng)估并記錄tensorboard    """    def on_batch_end(self, global_step, batch, logs=None):        if global_step % 100 == 0:            writer.add_scalar(f"train/loss", logs['loss'], global_step)            val_acc = evaluate(valid_dataloader)            writer.add_scalar(f"valid/acc", val_acc, global_step)

          3) 打印訓(xùn)練參數(shù)

          from torchinfo import summarysummary(model, input_data=next(iter(train_dataloader))[0])


          瀏覽 128
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码乱伦网站 | 国内毛片毛片毛片毛片毛片毛片毛片 | 久久九九er精品在线 | 国产色亭亭视频 | 黄色录像视频大片 |