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

如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)

這篇具有很好參考價值的文章主要介紹了如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


摘要:如何使用 Pytorch(或Pytorchlightning) 和 huggingface Transformers 做文本摘要生成任務(wù),包括數(shù)據(jù)集的加載、模型的加載、模型的微調(diào)、模型的驗證、模型的保存、ROUGE指標(biāo)分?jǐn)?shù)的計算、loss的可視化。


? NLP 研 0 選手的學(xué)習(xí)筆記



一、需要的環(huán)境

python 需要 3.8+

numpy==1.19.2
pandas==1.3.4
torch>=1.7.0, !1.8.0(我的是1.11.0)
transformers==4.23.1
pytorch-lightning==1.5.10 (pip install pytorch-lightning==1.5.10)
scikit-learn==0.24.2 (pip install scikit-learn==0.24.2)
rouge==1.0.1
SentencePiece==0.1.97
nltk==3.8.1
rouge-score==0.1.2

文件相對地址mian.pytrain.csv 是必須要有的。mian.py 中寫入所有的代碼、train.csv 中裝的是訓(xùn)練集。這張圖里面,我沒有放測試集,但在 “五、項目鏈接” 中,我放了的。

如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)


二、任務(wù)說明

● 為什么要用 pytorch-lighting 呢?

pytorch-lighting(簡稱pl),它其實就是一個輕量級的 PyTorch 庫,用于高性能人工智能研究的輕量級 PyTorch 包裝器??s放你的模型,而不是樣板。

它可以清晰地抽象和自動化ML模型所附帶的所有日常樣板代碼,允許您專注于實際的ML部分(這些也往往是最有趣的部分)。除了自動化樣板代碼外,Lightning還可以作為一種樣式指南,用于構(gòu)建干凈且可復(fù)制的ML系統(tǒng)。

pytorch 和 pl 本質(zhì)上代碼是完全相同的。只不過pytorch需要自己造輪子(如model, dataloader, loss, train,test,checkpoint, save model等等都需要自己寫),而pl 把這些模塊都結(jié)構(gòu)化了(類似keras)。
————————————————
原文鏈接:pytorch-lightning入門(一)—— 初了解

● 我是基于 T5(text-to-text-transfer-transformer)模型的源代碼修改的,地址:https://github.com/Shivanandroy/simpleT5。主要修改點如下
??1. 取消了 checkpoint 保存機(jī)制,只保存最后一輪的模型和訓(xùn)練日志
??2. 加入早停機(jī)制,使得模型在訓(xùn)練過程中,若發(fā)現(xiàn) val_loss(驗證集的損失) 沒有下降,就及時停止訓(xùn)練(以防止過擬合)。
??3. 使用了 CNN/Daily Mail 的報刊新聞(一部分) 作為我的數(shù)據(jù)集,train.csv9000 個樣本(我將其以 9:1 的形式劃分成了訓(xùn)練集和驗證集),無測試集。
??4. 加入了 ROUGE 指標(biāo),主要在模型訓(xùn)練完后,對驗證集進(jìn)行 ROUGE 分?jǐn)?shù)計算。
??5. 將所有重要的英文注釋翻譯為中文,并加入詳細(xì)的注釋。

部分重要超參數(shù)列表如下

參數(shù)名 說明
batch_size 4 我用的 3060,12GB 顯存,跑不了多少…
max_epochs 10 最大訓(xùn)練輪數(shù)
source_max_token_len 768 最大文檔(source_text)長度,如果超過該長度,則截斷
target_max_token_len 64 最大摘要(target_text)長度,如果超過該長度,則截斷
precision 32 精度設(shè)置為全精度
early_stopping_patience_epochs 2 在第 2 輪結(jié)束時開始監(jiān)視 val_loss,如果 val_loss 沒有改善(即下降),則停止訓(xùn)練
num_beams 4 在進(jìn)行預(yù)測時 beams search 的數(shù)量(和 T5 論文中的一樣)
length_penalty 0.6 基于 beams search 生成所使用的長度的指數(shù)懲罰(和 T5 論文中的一樣)
learning_rate 0.0001 學(xué)習(xí)率

補充說明:我在代碼中設(shè)置了隨機(jī)種子(42),便于大家復(fù)現(xiàn)。


三、完整代碼

from abc import ABC
import pandas as pd
from sklearn.model_selection import train_test_split
from torch.utils.data import Dataset, DataLoader
import pytorch_lightning as pl
from torch.optim import AdamW
import numpy as np
import torch
from pytorch_lightning.callbacks.progress import TQDMProgressBar
from pytorch_lightning.callbacks.early_stopping import EarlyStopping
from rouge import Rouge
from transformers import (
    T5ForConditionalGeneration,
    PreTrainedTokenizer,
    T5TokenizerFast as T5Tokenizer,
)


class myDataModule(Dataset):
    """ Pytorch 類型的數(shù)據(jù)集類 """

    def __init__(
            self,
            data: pd.DataFrame,
            tokenizer: PreTrainedTokenizer,
            source_max_token_len: int = 512,
            target_max_token_len: int = 512,
    ):
        """
        為輸入數(shù)據(jù)初始化 PyTorch 數(shù)據(jù)集模塊
        參數(shù):
            data (pd.DataFrame): 輸入為 pandas dataframe 形式. Dataframe 必須有 2 列 --> "source_text" 和 "target_text"
            tokenizer (PreTrainedTokenizer): 一個預(yù)訓(xùn)練好的分詞器 (例如 T5Tokenizer, MT5Tokenizer 或 ByT5Tokenizer)
            source_max_token_len (int, optional): 源文本的最大 token 長度. 默認(rèn)值為 512.
            target_max_token_len (int, optional): 目標(biāo)文本的最大 token 長度. 默認(rèn)值為 512.
        """
        self.tokenizer = tokenizer
        self.data = data
        self.source_max_token_len = source_max_token_len
        self.target_max_token_len = target_max_token_len

    def __len__(self):
        """ 返回數(shù)據(jù)的長度 """
        return len(self.data)

    def __getitem__(self, index: int):
        """ 返回一個 batch_size 的 input, 以便之后輸入模型 """
        # 1. 獲取數(shù)據(jù)集中第 index 批次的數(shù)據(jù)
        data_row = self.data.iloc[index]
        # 2. 獲取源文檔
        source_text = data_row["source_text"]
        # 3. 對源文檔進(jìn)行分詞編碼
        source_text_encoding = self.tokenizer(
            source_text,
            max_length=self.source_max_token_len,
            padding="max_length",  # 如果文檔的長度未達(dá)到 max_length(即self.source_max_token_len), 就用<pad>填充滿
            truncation=True,  # 如果文檔的長度超過 max_length, 則截斷后面的文本, 只取前面的
            return_attention_mask=True,  # 要求返回 attention 的掩碼張亮
            add_special_tokens=True,  # 要求增加特殊的 token, 比如加入 <pad> 位
            return_tensors="pt",  # 以 pytorch 的 tensor 類型返回
        )
        # 4. 對目標(biāo)文檔(即摘要)進(jìn)行分詞編碼
        target_text_encoding = self.tokenizer(
            data_row["target_text"],
            max_length=self.target_max_token_len,
            padding="max_length",
            truncation=True,
            return_attention_mask=True,
            add_special_tokens=True,
            return_tensors="pt",
        )
        # 5. 獲取目標(biāo)文本(即摘要)的 token ids
        labels = target_text_encoding["input_ids"]
        # 6. 將摘要中 token id 為 0(即<pad>位) 的轉(zhuǎn)為 -100, 便于后期 "省略" 掉
        labels[labels == 0] = -100
        # 7. 以字典(dict)的形式返回這一批次的數(shù)據(jù)
        return dict(
            source_text_input_ids=source_text_encoding["input_ids"].flatten(),  # .flatten() 是為了
            source_text_attention_mask=source_text_encoding["attention_mask"].flatten(),
            labels=labels.flatten(),
            labels_attention_mask=target_text_encoding["attention_mask"].flatten(),
        )


class myLightningDataModule(pl.LightningDataModule, ABC):
    """ PyTorch Lightning 類型的數(shù)據(jù)集類, 它繼承了 "PyTorch 類型的數(shù)據(jù)集類" 的所有東西, 并附加了其他功能 """

    def __init__(
            self,
            train_df: pd.DataFrame,
            test_df: pd.DataFrame,
            tokenizer: PreTrainedTokenizer,
            batch_size: int = 4,
            source_max_token_len: int = 512,
            target_max_token_len: int = 512,
            num_workers: int = 4,  # 要為數(shù)據(jù)使用多少子進(jìn)程裝載。'0'表示將在主進(jìn)程中加載數(shù)據(jù)(默認(rèn)值:'0')
    ):
        """
        初始化 PyTorch Lightning 類型的數(shù)據(jù)模塊
        參數(shù):
            train_df (pd.DataFrame): training dataframe. Dataframe 必須有 2 列 --> "source_text" 和 "target_text"
            test_df (pd.DataFrame): validation dataframe. Dataframe 必須有 2 列 --> "source_text" 和 "target_text"
            tokenizer (PreTrainedTokenizer): 一個預(yù)訓(xùn)練好的分詞器 (例如 T5Tokenizer, MT5Tokenizer 或 ByT5Tokenizer)
            batch_size (int, optional): batch size. 默認(rèn)為 4.
            source_max_token_len (int, optional): 源文本的最大 token 長度. 默認(rèn)值為 512.
            target_max_token_len (int, optional): 目標(biāo)文本的最大 token 長度. 默認(rèn)值為 512.
        """
        super().__init__()
        self.train_df = train_df
        self.test_df = test_df
        self.batch_size = batch_size
        self.tokenizer = tokenizer
        self.source_max_token_len = source_max_token_len
        self.target_max_token_len = target_max_token_len
        self.num_workers = num_workers
        self.train_dataset = None
        self.test_dataset = None

    def setup(self, stage=None):
        self.train_dataset = myDataModule(
            self.train_df,
            self.tokenizer,
            self.source_max_token_len,
            self.target_max_token_len,
        )
        self.test_dataset = myDataModule(
            self.test_df,
            self.tokenizer,
            self.source_max_token_len,
            self.target_max_token_len,
        )

    def train_dataloader(self):
        """ 訓(xùn)練集 dataloader """
        return DataLoader(
            self.train_dataset,
            batch_size=self.batch_size,
            shuffle=True,  # 隨機(jī)打亂訓(xùn)練集
            num_workers=self.num_workers,
        )

    def val_dataloader(self):
        """ 驗證集 dataloader """
        return DataLoader(
            self.test_dataset,
            batch_size=self.batch_size,
            shuffle=False,
            num_workers=self.num_workers,
        )

    def test_dataloader(self):
        """ 測試集 dataloader """
        return DataLoader(
            self.test_dataset,
            batch_size=self.batch_size,
            shuffle=False,
            num_workers=self.num_workers,
        )


class myLightningModel(pl.LightningModule, ABC):
    """ PyTorch Lightning 模型類 """

    def __init__(
            self,
            tokenizer,
            model,
            output_dir: str = "outputs",
            save_only_last_epoch: bool = False,
    ):
        """
        初始化一個 PyTorch Lightning 模型
        Args:
            tokenizer : T5/MT5/ByT5 分詞器
            pretrained_model : T5/MT5/ByT5 的預(yù)訓(xùn)練模型
            output_dir (str, optional): 保存模型檢查點的輸出目錄, 默認(rèn)為 "outputs"
            save_only_last_epoch (bool, optional): 如果為 True, 則只保存最后一個 epoch, 否則將為每個 epoch 保存模型
        """
        super().__init__()
        self.model = model
        self.tokenizer = tokenizer
        self.output_dir = output_dir
        self.average_training_loss = None  # 訓(xùn)練時的平均 loss
        self.average_validation_loss = None  # 驗證時的平均 loss
        self.save_only_last_epoch = save_only_last_epoch

    def forward(self, input_ids, attention_mask, decoder_attention_mask, labels=None):
        """ forward step """
        output = self.model(
            input_ids,
            attention_mask=attention_mask,
            labels=labels,
            decoder_attention_mask=decoder_attention_mask,
        )
        return output.loss, output.logits  # loss 的計算為 = CrossEntropyLoss(ignore_index=-100)

    def training_step(self, batch, batch_size):  # 自動打開模型的 train() 模型
        """ 當(dāng)用訓(xùn)練集訓(xùn)練模型時, 執(zhí)行該代碼 """
        input_ids = batch["source_text_input_ids"]
        attention_mask = batch["source_text_attention_mask"]
        labels = batch["labels"]
        labels_attention_mask = batch["labels_attention_mask"]

        loss, outputs = self(  # 直接調(diào)用 forward()  源代碼只有 self
            input_ids=input_ids,
            attention_mask=attention_mask,
            decoder_attention_mask=labels_attention_mask,
            labels=labels,
        )

        self.log(  # 寫入日志
            "train_loss", loss, prog_bar=True, logger=True, on_epoch=True, on_step=True
        )
        return loss

    def validation_step(self, batch, batch_size):  # 自動打開模型的 eval() 模型
        """ 當(dāng)用驗證集測試模型時, 執(zhí)行該代碼 """
        input_ids = batch["source_text_input_ids"]
        attention_mask = batch["source_text_attention_mask"]
        labels = batch["labels"]
        labels_attention_mask = batch["labels_attention_mask"]

        loss, outputs = self(
            input_ids=input_ids,
            attention_mask=attention_mask,
            decoder_attention_mask=labels_attention_mask,
            labels=labels,
        )

        self.log(
            "val_loss", loss, prog_bar=True, logger=True, on_epoch=True, on_step=True
        )
        # return {'loss': loss, 'input_ids': input_ids, 'labels': labels}  # 因為在驗證集測試結(jié)束時什么都不做, 故不返回東西

    def test_step(self, batch, batch_size):  # 自動打開模型的 eval() 模型. 因為我沒有放入測試集進(jìn)來, 所以不會執(zhí)行該段代碼
        """ 當(dāng)用測試集測試模型時, 執(zhí)行該代碼 """
        input_ids = batch["source_text_input_ids"]
        attention_mask = batch["source_text_attention_mask"]
        labels = batch["labels"]
        labels_attention_mask = batch["labels_attention_mask"]

        loss, outputs = self(
            input_ids=input_ids,
            attention_mask=attention_mask,
            decoder_attention_mask=labels_attention_mask,
            labels=labels,
        )

        self.log("test_loss", loss, prog_bar=True, logger=True)
        return loss

    def configure_optimizers(self):  # 在該類初始化時即被調(diào)用
        """ 配置優(yōu)化器(optimizers) """
        return AdamW(self.parameters(), lr=0.0001)

    def training_epoch_end(self, training_step_outputs):
        """ 在每一輪訓(xùn)練結(jié)束時保存訓(xùn)練了的分詞器和模型 """
        self.average_training_loss = np.round(
            # torch.stack(): 把多個 2 維的張量湊成一個3維的張量; 多個 3 維的湊成一個4維的張量...以此類推, 也就是在增加新的維度進(jìn)行堆疊.
            torch.mean(torch.stack([x["loss"] for x in training_step_outputs])).item(),
            4,  # 小數(shù)位數(shù)后保留 4 位
        )
        path = f"{self.output_dir}/simple_T5"
        if self.save_only_last_epoch:
            if self.current_epoch == self.trainer.max_epochs - 1:
                self.tokenizer.save_pretrained(path)  # 保存分詞器到路徑 path 底下
                self.model.save_pretrained(path)  # 保存模型到路徑 path 底下
        else:
            self.tokenizer.save_pretrained(path)
            self.model.save_pretrained(path)

    def validation_epoch_end(self, validation_step_outputs):
        """ 在每一輪驗證集測試結(jié)束時做點什么呢? """
        pass


class myModel_for_Train:
    """ 自定義的 T5 模型類 """

    def __init__(self) -> None:
        """ 初始化自定義的模型類 """
        self.model = None
        self.T5_Model = None
        self.tokenizer = None
        self.device = None
        self.data_module = None

    def from_pretrained(self, model_name="t5-base") -> None:
        """
        加載預(yù)訓(xùn)練 T5 模型進(jìn)行訓(xùn)練/微調(diào)
        參數(shù):
            model_name (str, optional): 確切的模型體系結(jié)構(gòu)名稱,"t5-base" 或 "t5-large". 默認(rèn)為 "t5-base".
        """
        self.tokenizer = T5Tokenizer.from_pretrained(f"{model_name}")
        self.model = T5ForConditionalGeneration.from_pretrained(
            f"{model_name}", return_dict=True  # 是否返回一個 ~utils.ModelOutput類 而不是普通的元組
        )

    def train(
            self,
            train_df: pd.DataFrame,
            eval_df: pd.DataFrame,
            source_max_token_len: int = 512,
            target_max_token_len: int = 512,
            batch_size: int = 8,
            max_epochs: int = 5,
            use_gpu: bool = True,
            output_dir: str = "outputs",
            early_stopping_patience_epochs: int = 2,  # 0 表示禁用提前停止功能
            precision=32,
            logger="default",
            dataloader_num_workers: int = 2,
            save_only_last_epoch: bool = False,  # 不設(shè)置只保留最后一輪, 而是保留在驗證集上效果最好的一輪
    ):
        """
        在自定義數(shù)據(jù)集上訓(xùn)練 T5 模型
        參數(shù):
            train_df (pd.DataFrame): training dataframe. Dataframe 必須有 2 列 --> "source_text" 和 "target_text"
            eval_df ([type], optional): validation dataframe. Dataframe 必須有 2 列 --> "source_text" 和 "target_text"
            source_max_token_len (int, optional): 源文本的最大 token 長度. 默認(rèn)值為 512.
            target_max_token_len (int, optional): 目標(biāo)文本的最大 token 長度. 默認(rèn)值為 512.
            batch_size (int, optional): batch size. 默認(rèn)值為 8.
            max_epochs (int, optional): 最大的 epochs 值. 默認(rèn)為 5.
            use_gpu (bool, optional): 如果為True, 則模型使用 gpu 進(jìn)行訓(xùn)練. 默認(rèn)為 True.
            output_dir (str, optional): 保存模型 checkpoints 的輸出目錄. 默認(rèn)為 "outputs".
            early_stopping_patience_epochs (int, optional): 在 epoch 結(jié)束時監(jiān)視 val_loss, 如果 val_loss 在指定的 epoch 數(shù)之后沒有改善(即下降),
            則停止訓(xùn)練. 若設(shè)置 0 表示禁用提前停止. 默認(rèn)為 0(禁用)
            precision (int, optional): 設(shè)置精度訓(xùn)練-雙精度(64), 全精度(32)或半精度(16). 默認(rèn)值為 32.
            logger (pytorch_lightning.loggers) : PyTorch Lightning支持的任何記錄器. 默認(rèn)為 "default". 如果為 "default",
            則使用 pytorch lightning default logger, 用于記錄訓(xùn)練過程.
            dataloader_num_workers (int, optional): 設(shè)置加載 train/test/val dataloader 的進(jìn)程數(shù)量
            save_only_last_epoch (bool, optional): 如果為 True, 則僅保存最后一個 epoch, 否則將保存每個 epoch 的分詞器和模型
        """
        self.data_module = myLightningDataModule(
            train_df=train_df,
            test_df=eval_df,
            tokenizer=self.tokenizer,
            batch_size=batch_size,
            source_max_token_len=source_max_token_len,
            target_max_token_len=target_max_token_len,
            num_workers=dataloader_num_workers,
        )

        self.T5_Model = myLightningModel(
            tokenizer=self.tokenizer,
            model=self.model,
            output_dir=output_dir,  # 保存 tokenizer 和 model 的路徑
            save_only_last_epoch=save_only_last_epoch,  # 只保存最后一輪的 checkpoint
        )

        # 添加回調(diào)方法, 用于顯示模型訓(xùn)練的進(jìn)度, 更新頻率為 5
        callbacks = [TQDMProgressBar(refresh_rate=5)]

        if early_stopping_patience_epochs > 0:
            early_stop_callback = EarlyStopping(
                monitor="val_loss",
                min_delta=0.00,
                patience=early_stopping_patience_epochs,
                verbose=True,
                mode="min",
            )
            callbacks.append(early_stop_callback)

        # 如果有 gpu, 則添加
        gpus = 1 if use_gpu else 0

        # 添加 logger(日志器)
        loggers = True if logger == "default" else logger

        # prepare trainer(訓(xùn)練器)
        trainer = pl.Trainer(
            default_root_dir='./',  # 日志 和 checkpoint 的路徑
            logger=loggers,
            enable_checkpointing=False,  # 不保存 checkpoint
            callbacks=callbacks,
            max_epochs=max_epochs,
            gpus=gpus,
            precision=precision,
            log_every_n_steps=1,  # 每訓(xùn)練 1 步(step)就記錄一下日志.
        )

        # fit trainer(訓(xùn)練器)
        trainer.fit(self.T5_Model, self.data_module)

    def load_model(
            self,
            model_dir: str = "outputs",
            use_gpu: bool = False
    ):
        """
        加載某一個 checkpoint, 即加載模型
        參數(shù):
            model_type (str, optional): "t5" 或 "mt5". 默認(rèn)為 "t5".
            model_dir (str, optional): 模型目錄的路徑. 默認(rèn)為 "outputs".
            use_gpu (bool, optional): 如果為 True, 模型使用 gpu 進(jìn)行推理/預(yù)測. 默認(rèn)為 True.
        """

        self.model = T5ForConditionalGeneration.from_pretrained(f"{model_dir}")
        self.tokenizer = T5Tokenizer.from_pretrained(f"{model_dir}")

        if use_gpu:
            if torch.cuda.is_available():
                self.device = torch.device("cuda")
            else:
                raise "exception ---> no gpu found. set use_gpu=False, to use CPU"
        else:
            self.device = torch.device("cpu")

    def predict(
            self,
            source_text: str,
            max_length: int = 512,
            num_return_sequences: int = 1,
            num_beams: int = 4,  # 按照 t5 論文里寫的來
            top_k: int = 50,
            top_p: float = 0.95,
            # do_sample: bool = True,
            repetition_penalty: float = 2.5,
            length_penalty: float = 0.6,  # 按照 t5 論文里寫的來
            early_stopping: bool = True,
            skip_special_tokens: bool = True,
            clean_up_tokenization_spaces: bool = True,
    ):
        """
        生成 T5 模型的預(yù)測(文本)
        參數(shù):
            source_text (str): 任何用于生成預(yù)測的文本, 即源文本
            max_length (int, optional): 預(yù)測的最大 token 長度. 默認(rèn)值為 512.
            num_return_sequences (int, optional): 要返回的預(yù)測數(shù). 默認(rèn)值為 1.
            num_beams (int, optional): beams 搜索的數(shù)量. 默認(rèn)值為 2.
            top_k (int, optional): 用于 top-k 篩選的最高概率詞匯表 tokens 的數(shù)量. 默認(rèn)值為 50.
            top_p (float, optional): 如果設(shè)置為 float < 1, 那只有概率加起來等于 top_p 或更高的最可能 token 的最小集被保留用于生成. 默認(rèn)值為 0.95.
            do_sample (bool, optional): 是否使用抽樣; 否則使用貪婪解碼.默認(rèn)值為 True.
            repetition_penalty (float, optional): 重復(fù)懲罰的參數(shù). 1.0 意味著沒有懲罰. 更多細(xì)節(jié)請參見[本文]
            (https://arxiv.org/pdf/1909.05858.pdf)。默認(rèn)值為 2.5.
            length_penalty (float, optional): 基于 beam 生成所使用的長度的指數(shù)懲罰. length_penalty > 0.0 表示促進(jìn)更長的序列,
            而 length_penalty < 0.0 表示鼓勵較短的序列. 默認(rèn)值為 1.0.
            early_stopping (bool, optional): 是否在每批至少有 num_beams 條語句完成時停止 beam search. 默認(rèn)值為 True.
            skip_special_tokens (bool, optional): 是否跳過特殊的 token, 例如 <pad>, 默認(rèn)值為 True.
            clean_up_tokenization_spaces (bool, optional): 是否清理 tokens 的空間. 默認(rèn)值為 True.
        返回:
            list[str]: 返回預(yù)測的文本, 即摘要
        """
        input_ids = self.tokenizer.encode(
            source_text,
            return_tensors="pt",
            add_special_tokens=True
        )
        if torch.cuda.is_available():
            self.device = torch.device("cuda")
            self.model = self.model.to(self.device)
            input_ids = input_ids.to(self.device)  # 放入 gpu
        generated_ids = self.model.generate(
            input_ids=input_ids,
            num_beams=num_beams,
            max_length=max_length,
            repetition_penalty=repetition_penalty,
            length_penalty=length_penalty,
            early_stopping=early_stopping,
            top_k=top_k,
            top_p=top_p,
            num_return_sequences=num_return_sequences,
        )

        predictions_text = [
            self.tokenizer.decode(
                every_ids,
                skip_special_tokens=skip_special_tokens,
                clean_up_tokenization_spaces=clean_up_tokenization_spaces,
            )
            for every_ids in generated_ids
        ]
        return predictions_text


if __name__ == '__main__':
    torch.cuda.empty_cache()
    pl.seed_everything(42)  # 設(shè)置隨機(jī)種子, 方便復(fù)現(xiàn)
    train_data_path = "train.csv"
    t5_train_df = pd.read_csv(train_data_path, sep='\t')
    print('顯示前 5 個樣例:\n', t5_train_df.head(), '\n總的新聞和摘要對數(shù)為::', len(t5_train_df))

    # T5 模型要求數(shù)據(jù)幀(dataframe)有2列: "source_text" 和 "target_text"
    t5_train_df = t5_train_df.rename(columns={"summary": "target_text", "document": "source_text"})
    t5_train_df = t5_train_df[['source_text', 'target_text']]

    # T5 模型需要一個與任務(wù)相關(guān)的前綴(prefix): 因為它是一個摘要任務(wù), 我們將添加一個前綴 "summary:"
    t5_train_df['source_text'] = "summarize: " + t5_train_df['source_text']
    print('顯示新改造的所有(新聞和摘要對)樣例:\n', t5_train_df)  # 平均的文檔長度為 1212, 摘要長度為 82

    t5_train_df, t5_valid_df = train_test_split(t5_train_df, test_size=0.1)
    print(t5_train_df.shape, t5_valid_df.shape)
    
	# ****************  以下是模型的訓(xùn)練代碼  ****************
    t5_model = myModel_for_Train()
    t5_model.from_pretrained(model_name="t5-base")
    t5_model.train(
        train_df=t5_train_df,
        eval_df=t5_valid_df,
        source_max_token_len=768,
        target_max_token_len=64,
        batch_size=4,
        max_epochs=10,
        use_gpu=True,
    )
    print('模型已經(jīng)訓(xùn)練好了!')

四、訓(xùn)練結(jié)果

● 通過在 Anaconda Prompt (Anaconda3) 終端,對應(yīng)的環(huán)境里面輸入 tensorboard --logdir=你的events.out.tfevents文件路徑,然后再用瀏覽器打開 http://localhost:6006/ 網(wǎng)址。

比如我的 events.out.tfevents 文件路徑是:
tensorboard --logdir=C:\Users\xxx\Desktop\simpleT5-main\t5_summary_test\lightning_logs\version_0

顯示訓(xùn)練過程類似如下:可見,當(dāng) val_lossstep=100 時達(dá)到最小,即保存此時刻的模型(:此圖不是上述代碼的結(jié)果,上述結(jié)果的 val_loss 一直在上升…,就不太好看,所以我隨便找了一個訓(xùn)練過程)。

如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)

● 在 Pycharm 中的終端,我截了部分輸出圖如下:

如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)

● 然后,我對驗證集進(jìn)行 ROUGE 分?jǐn)?shù)計算:

if __name__ == '__main__':
    ...
    ...
    ...
    
    # ****************  以下是驗證集的Rouge評測和生成測試  ****************
    test_t5_model = myModel_for_Train()
    test_t5_model.load_model("outputs/simple_T5", use_gpu=True)
    print('模型已經(jīng)加載好了!')
    # 對驗證集進(jìn)行 ROUGE 分?jǐn)?shù)計算
    my_rouge = Rouge()
    rouge_1, rouge_2, rouge_l_f1, rouge_l_p, rouge_l_r = 0, 0, 0, 0, 0
    for ind in range(len(t5_valid_df)):
        input_text = t5_valid_df.iloc[ind]['source_text']
        output_text = test_t5_model.predict(input_text)
        label_text = t5_valid_df.iloc[ind]['target_text']
        result = my_rouge.get_scores(output_text, [label_text], avg=True)  # 取一個 batch 的平均
        rouge_1 += result['rouge-1']['f']
        rouge_2 += result['rouge-2']['f']
        rouge_l_f1 += result['rouge-l']['f']
        rouge_l_p += result['rouge-l']['p']
        rouge_l_r += result['rouge-l']['r']
        # print(ind, rouge_1 / (ind + 1), rouge_2 / (ind + 1), rouge_l_f1 / (ind + 1), rouge_l_p / (ind + 1),
        #       rouge_l_r / (ind + 1))
    print('驗證集平均的 Rouge_1: {}, Rouge_2: {}, Rouge_l_f1: {}, Rouge_l_p: {}, Rouge_l_r: {}'.format(
        rouge_1 / len(t5_valid_df), rouge_2 / len(t5_valid_df), rouge_l_f1 / len(t5_valid_df),
        rouge_l_p / len(t5_valid_df), rouge_l_r / len(t5_valid_df)))

    text_to_summarize = """summarize: Rahul Gandhi has replied to Goa CM Manohar Parrikar's letter,
    which accused the Congress President of using his "visit to an ailing man for political gains".
    "He's under immense pressure from the PM after our meeting and needs to demonstrate his loyalty by attacking me,"
    Gandhi wrote in his letter. Parrikar had clarified he didn't discuss Rafale deal with Rahul.
    """
    print('生成的摘要為:', test_t5_model.predict(text_to_summarize))

● 運行結(jié)果如下:

驗證集平均的 Rouge_1: 0.3369, Rouge_2: 0.1432, Rouge_l_f1: 0.3158, Rouge_l_p: 0.4136, Rouge_l_r: 0.2692
生成的摘要為:['Goa CM Manohar Parrikar accuses the Congress president of using his visit to an ailing man for political gains. Gandhi says he needs to demonstrate his loyalty by attacking me.']

● 如果加入 scheduler(即把余弦學(xué)習(xí)率加入進(jìn) configure_optimizers() 中),結(jié)果會更好一點:

 def configure_optimizers(self):  # 在該類初始化時即被調(diào)用
      """ 配置優(yōu)化器(optimizers) """
      optimizer = AdamW(self.parameters(), lr=0.0001)
      scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10, eta_min=0)  # T_max表示半個周期的大小
      return {
              "optimizer": optimizer,
              "lr_scheduler": {"scheduler": scheduler}
          }
      # return AdamW(self.parameters(), lr=0.0001)
      
驗證集平均的 Rouge_1: 0.4199, Rouge_2: 0.2320, Rouge_l_f1: 0.4033, Rouge_l_p: 0.5157, Rouge_l_r: 0.3468


五、項目鏈接

● 啊哈,2023-3-15 寫的文章,到了 2023-7-9 才把項目鏈接掛到 github 上,大伙久等了??

項目鏈接:https://github.com/Wangdoudou8/text-summarization-csdn/tree/main


六、補充說明

● 若有寫得不對的地方,或有疑問,歡迎評論交流。


?? ?? ??文章來源地址http://www.zghlxwxcb.cn/news/detail-448112.html

到了這里,關(guān)于如何用pytorch做文本摘要生成任務(wù)(加載數(shù)據(jù)集、T5 模型參數(shù)、微調(diào)、保存和測試模型,以及ROUGE分?jǐn)?shù)計算)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • pytorch-textsummary,中文文本摘要實踐

    pytorch-textsummary是一個以pytorch和transformers為基礎(chǔ),專注于中文文本摘要的輕量級自然語言處理工具,支持抽取式摘要等。 數(shù)據(jù) 使用方式 paper 參考 pytorch-textsummary: https://github.com/yongzhuo/Pytorch-NLU/pytorch_textsummary 免責(zé)聲明:以下數(shù)據(jù)集由公開渠道收集而成, 只做匯總說明; 科學(xué)研究

    2024年02月21日
    瀏覽(27)
  • 深度解析NLP文本摘要技術(shù):定義、應(yīng)用與PyTorch實戰(zhàn)

    深度解析NLP文本摘要技術(shù):定義、應(yīng)用與PyTorch實戰(zhàn)

    在本文中,我們深入探討了自然語言處理中的文本摘要技術(shù),從其定義、發(fā)展歷程,到其主要任務(wù)和各種類型的技術(shù)方法。文章詳細(xì)解析了抽取式、生成式摘要,并為每種方法提供了PyTorch實現(xiàn)代碼。最后,文章總結(jié)了摘要技術(shù)的意義和未來的挑戰(zhàn),強調(diào)了其在信息過載時代的

    2024年02月05日
    瀏覽(27)
  • 【文本摘要(2)】pytorch之Seq2Seq

    【文本摘要(2)】pytorch之Seq2Seq

    改廢了兩個代碼后,又找到了一個文本摘要代碼 終于跑起來了 改廢的兩個代碼: 一個是機(jī)器翻譯改文本摘要,結(jié)果沒跑起來。。。 一個是英文文本摘要改中文文本摘要,預(yù)測的摘要全是,,,這種 代碼參考: https://github.com/jasoncao11/nlp-notebook/tree/master/4-2.Seq2seq_Att 跪謝大佬

    2024年02月03日
    瀏覽(49)
  • 開啟想象翅膀:輕松實現(xiàn)文本生成模型的創(chuàng)作應(yīng)用,支持LLaMA、ChatGLM、UDA、GPT2、Seq2Seq、BART、T5、SongNet等模型,開箱即用

    開啟想象翅膀:輕松實現(xiàn)文本生成模型的創(chuàng)作應(yīng)用,支持LLaMA、ChatGLM、UDA、GPT2、Seq2Seq、BART、T5、SongNet等模型,開箱即用

    TextGen 實現(xiàn)了多種文本生成模型,包括:LLaMA、ChatGLM、UDA、GPT2、Seq2Seq、BART、T5、SongNet等模型,開箱即用。 [2023/06/15] v1.0.0版本: 新增ChatGLM/LLaMA/Bloom模型的多輪對話微調(diào)訓(xùn)練,并發(fā)布醫(yī)療問診LoRA模型shibing624/ziya-llama-13b-medical-lora。詳見Release-v1.0.0 [2023/06/02] v0.2.7版本: 新增ChatG

    2024年02月13日
    瀏覽(19)
  • 基于PyTorch使用LSTM實現(xiàn)新聞文本分類任務(wù)

    基于PyTorch使用LSTM實現(xiàn)新聞文本分類任務(wù)

    PyTorch深度學(xué)習(xí)項目實戰(zhàn)100例 https://weibaohang.blog.csdn.net/article/details/127154284?spm=1001.2014.3001.5501 基于PyTorch使用LSTM實現(xiàn)新聞文本分類任務(wù)的概況如下: 任務(wù)描述:新聞文本分類是一種常見的自然語言處理任務(wù),旨在將新聞文章分為不同的類別,如政治、體育、科技等。 方法:使

    2024年02月09日
    瀏覽(23)
  • transformer模型,文本生成任務(wù)。 self-attention結(jié)構(gòu)

    transformer模型,文本生成任務(wù)。 self-attention結(jié)構(gòu)

    大家好,好久不見,終于又有機(jī)會來學(xué)習(xí)深度學(xué)習(xí)了, 這次我們通過全球人工智能大賽算法挑戰(zhàn)賽的賽道一來學(xué)習(xí)。 2023全球人工智能技術(shù)創(chuàng)新大賽 - 算法挑戰(zhàn)賽 賽道一的任務(wù)是? 通過醫(yī)療圖像的文字描述來生成醫(yī)生的診斷描述。 這是一個典型的文本生成任務(wù), 因此transf

    2023年04月09日
    瀏覽(47)
  • 【多模態(tài)】5、BLIP | 統(tǒng)一理解與生成任務(wù) 為圖像生成更高質(zhì)量的文本描述

    【多模態(tài)】5、BLIP | 統(tǒng)一理解與生成任務(wù) 為圖像生成更高質(zhì)量的文本描述

    論文:BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation 代碼:https://github.com/salesforce/BLIP 線上體驗:https://huggingface.co/spaces/Salesforce/BLIP 出處:ICML 2022 | Salesforce Research 時間:2022.02 貢獻(xiàn): 提出了一個可以聯(lián)合訓(xùn)練理解和生成任務(wù)的多模態(tài)混合模

    2024年02月16日
    瀏覽(103)
  • 【AIGC】8、BLIP | 統(tǒng)一理解與生成任務(wù) 為圖像生成更高質(zhì)量的文本描述

    【AIGC】8、BLIP | 統(tǒng)一理解與生成任務(wù) 為圖像生成更高質(zhì)量的文本描述

    論文:BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation 代碼:https://github.com/salesforce/BLIP 線上體驗:https://huggingface.co/spaces/Salesforce/BLIP 出處:ICML 2022 | Salesforce Research 時間:2022.02 貢獻(xiàn): 提出了一個可以聯(lián)合訓(xùn)練理解和生成任務(wù)的多模態(tài)混合模

    2024年02月09日
    瀏覽(233)
  • 【古詩生成AI實戰(zhàn)】之三——任務(wù)加載器與預(yù)處理器

    【古詩生成AI實戰(zhàn)】之三——任務(wù)加載器與預(yù)處理器

    ??本章內(nèi)容屬于 數(shù)據(jù)處理階段 ,將分別介紹任務(wù)加載器 task 和預(yù)處理器 processor 。 ??在深入探討數(shù)據(jù)處理的具體步驟之前,讓我們先了解一下我們將要使用的數(shù)據(jù)集的形式。 ??本項目采用的是七絕數(shù)據(jù)集,總計83072條古詩,其形式如下: ??實際上我們只需要古詩的

    2024年02月02日
    瀏覽(38)
  • 深度學(xué)習(xí)實戰(zhàn)29-AIGC項目:利用GPT-2(CPU環(huán)境)進(jìn)行文本續(xù)寫與生成歌詞任務(wù)

    大家好,我是微學(xué)AI,今天給大家介紹一下深度學(xué)習(xí)實戰(zhàn)29-AIGC項目:利用GPT-2(CPU環(huán)境)進(jìn)行文本續(xù)寫與生成歌詞任務(wù)。在大家沒有GPU算力的情況,大模型可能玩不動,推理速度慢,那么我們怎么才能跑去生成式的模型呢,我們可以試一下GPT-2完成一些簡單的任務(wù),讓大家在CPU環(huán)

    2024年02月08日
    瀏覽(25)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包