标題選的好,紳士少不了。标題與文章的點選量有很大的聯系,一個好的标題能夠帶來更多的讀者。标題是潛在觀衆在決定是否閱讀的文章之前首先看到的内容。作為一名資料科學家,我決定制作一個模型來幫助我使用 GPT2 生成這些标題。
資料
我制作了一個 csv 檔案,其中包含我在 Medium.com 網站上使用 Parsehub 抓取的各種标簽中最好的資料科學文章。csv 檔案包含有關文章标題、使用的标簽、作者、點在人數、回複數量等資訊。該資料集可在 Kaggle 上獲得,稱為 Medium-Search-Dataset。
任務
我的任務是制作一個文本生成器來生成連貫的文章标題。我将使用 Transformers 庫進行預處理和模型建構,然後我将使用 PyTorch Lightning 微調模型。
安裝Transformers
使用以下指令安裝 Transformers。
pip install transformers
複制
你可以在 Kaggle 和 Github 上檢視完整的代碼(連結最後提供)。我建議在 Kaggle 而不是本地機器運作這個 notebook,因為 Kaggle 已經在環境中安裝了大部分依賴項。Pytorch Lightning 将用作包裝類以加快模型建構。
運作下面的單元格以確定安裝了所有必需的包。如果你沒有安裝所有的包,它會抛出一個錯誤。
from transformers import GPT2LMHeadModel, GPT2Tokenizer,AdamW
import pandas as pd
from torch.utils.data import Dataset , DataLoader
import pytorch_lightning as pl
from sklearn.model_selection import train_test_split
複制
資料
df = pd.read_csv("../input/mediumsearchdataset/Train.csv")
df
複制

我将下載下傳 GPT2-large 。它的大小為 3 GB,這就是為什麼我建議使用像 Kaggle 這樣的遠端筆記本。
tokenizer = GPT2Tokenizer.from_pretrained("gpt2-large")
gpt2 = GPT2LMHeadModel.from_pretrained("gpt2-large")
複制
在微調前可以測試 一下GPT2的模型
tokenizer.pad_token = tokenizer.eos_token
prompt = tokenizer.encode("machine learning", max_length = 30 , padding = "max_length" , truncation = True , return_tensors = "pt")
output = gpt2.generate(prompt,do_sample = True, max_length = 100,top_k = 10, temperature = 0.8)
tokenizer.decode(output[0] , skip_special_tokens = True)
複制
正如我們所看到的,該模型确實在我們輸入的“機器學習”上生成文本,但是它生成的與标題差的太多了。在以下部分中,我們将微調模型以生成更好的文本。
下面我們要自定義一個資料集,它将建立标記化的标題并将其發送到資料集。
class TitleDataset(Dataset):
def __init__(self,titles):
self.tokenizer = tokenizer
self.titles = titles
def __len__(self):
return len(self.titles)
def __getitem__(self,index):
title = self.titles[index]
title_token = tokenizer.encode(title , max_length = 30 , padding = "max_length" , truncation = True, return_tensors = "pt").reshape(-1)
return title_token
#sanity check
dset = TitleDataset(df["post_name"].values)
title = next(iter(DataLoader(dset , batch_size = 1,shuffle = True)))
display(title)
複制
class Quadratic_Module(pl.LightningDataModule):
def __init__(self):
super().__init__()
self.train_dataset = Quadratic_Dataset(path = train_df["id"].values , targets = train_df[["a_","b_", "c_"]].values)
self.test_dataset = Quadratic_Dataset(path = test_df["id"].values , targets = test_df[["a_","b_" , "c_"]].values)
self.val_dataset = Quadratic_Dataset(path = val_df["id"].values , targets = val_df[["a_","b_" , "c_"]].values)
self.predictions = Quadratic_Dataset(path = test_df["id"].values , targets = None)def prepare_data(self) :
pass
def train_dataloader(self):
return DataLoader(self.train_dataset , batch_size = 32 , shuffle = True)def test_dataloader(self):
return DataLoader(self.test_dataset , batch_size = 32 , shuffle = False)def val_dataloader(self):
return DataLoader(self.val_dataset , batch_size = 32 , shuffle = False)
def predict_dataloader(self):
return DataLoader(self.predictions , batch_size = 1 , shuffle = False)
複制
以上是資料讀取的一些輔助函數,幫助我們生成dataloader
當文本傳遞給 GPT2 時,它會傳回輸出 logits 和模型的損失,因為pytorch lighting是這樣要求的。
class TitleGenerator(pl.LightningModule):
def __init__(self):
super().__init__()
self.neural_net = gpt2_model
def forward(self,x):
return self.neural_net(x , labels = x)
def configure_optimizers(self):
return AdamW(self.parameters(), 1e-4)
def training_step(self,batch,batch_idx):
x= batch
output = self(x)
return output.loss
def test_step(self,batch,batch_idx):
x= batch
output = self(x)
return output.loss
def validation_step(self,batch,batch_idx):
x= batch
output = self(x)
return output.loss
複制
訓練
微調 GPT2 模型需要很長時間我建議使用 GPU(如果可用)。Lightning 允許我們在訓練器中聲明 GPU,同時處理其餘部分。6輪訓練應該需要大約 30 分鐘。
from pytorch_lightning import Trainer
model = TitleGenerator()
module = TitleDataModule()
trainer = Trainer(max_epochs = 6,gpus = 1)
trainer.fit(model,module)
複制
訓練完成後可以進行測試和預測
如果你計劃将代碼部署到生産中,我不建議這樣做,因為它可能會導緻錯誤。以下代碼是改變原始模型權重的快速的方法,但是她會有一些問題。
raw_text = ["The" ,"machine Learning" , "A" , "Data science" , "AI" , "A" , "The" , "Why" , "how"]
for x in raw_text:
prompts = tokenizer.encode(x , return_tensors = "pt")
outputs = gpt2.generate(prompt,do_sample = True, max_length = 32,top_k = 10, temperature = 0.8)
display(tokenizer.decode(outputs[0] , skip_special_tokens = True))
複制
最後說明
我會将該模型部署為 API,但該模型超過 3 GB,将其托管在網站上确實沒有意義。你也可以嘗試在微調後将模型上傳到 Huggingface hub上。
代碼位址在這裡:https://github.com/Aristotle609/Medium-Title-Generator
或者直接fork這個kaggle的代碼:https://www.kaggle.com/aristotle609/medium-titles-generator
本文作者:Aristotle Fernandes