le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Sommario
3. Valutare PEGASUS sul set di dati CNN/DailyMail
4. Modello di sintesi formativa
1. Valutare le prestazioni di PEGASUS su SAMSum
3. Genera riepilogo della conversazione
AGI, o Artificial General Intelligence, è un sistema di intelligenza artificiale con livelli di intelligenza umana. Non solo può svolgere compiti specifici, ma anche comprendere, apprendere e applicare la conoscenza per risolvere un'ampia gamma di problemi, con elevata autonomia e adattabilità. Le capacità dell'AGI includono, ma non sono limitate, all'autoapprendimento, all'automiglioramento, all'autoadattamento e alla capacità di risolvere vari problemi complessi senza l'intervento umano.
- Ciò che l’AGI può fare è molto ampio:
Esecuzione di attività tra domini: AGI può gestire attività in più domini e non è limitata a scenari applicativi specifici.
Apprendimento e adattamento autonomi: l’AGI può imparare dall’esperienza e adattarsi a nuovi ambienti e situazioni.
Pensiero creativo: AGI è in grado di pensare in modo innovativo e trovare nuove soluzioni.
Interazione sociale: l'AGI è capace di interazioni sociali complesse con gli esseri umani e comprende i segnali emotivi e sociali.
- Per quanto riguarda le prospettive di sviluppo futuro dell’AGI, è considerato uno degli obiettivi finali della ricerca sull’intelligenza artificiale e presenta un enorme potenziale di cambiamento:
Innovazione tecnologica: con il progresso di tecnologie come l’apprendimento automatico e le reti neurali, la realizzazione dell’AGI potrebbe essere sempre più vicina.
Integrazione interdisciplinare: l’implementazione dell’AGI richiede l’integrazione della conoscenza di più discipline come l’informatica, le neuroscienze e la psicologia.
Considerazioni etiche e sociali: lo sviluppo dell’AGI richiede la considerazione di questioni etiche e sociali come la privacy, la sicurezza e l’occupazione.
Capacità di apprendimento e adattamento migliorate: i futuri sistemi AGI potrebbero utilizzare algoritmi avanzati per apprendere dall’ambiente e ottimizzare il comportamento.
Interazione multimodale: l'AGI avrà molteplici metodi di percezione e interazione per interagire con gli esseri umani e altri sistemi.
Essendo una delle comunità e piattaforme di machine learning open source più popolari al mondo, Hugging Face svolge un ruolo importante nell'era AGI. Fornisce ricche risorse di modelli e set di dati preaddestrati, promuovendo lo sviluppo del campo dell'apprendimento automatico. Hugging Face è caratterizzato da facilità d'uso e apertura. Attraverso la sua libreria Transformers, fornisce agli utenti un modo conveniente per i modelli di elaborare il testo. Con lo sviluppo della tecnologia AI, la comunità Hugging Face continuerà a svolgere un ruolo importante nel promuovere lo sviluppo e l'applicazione della tecnologia AI, in particolare nello sviluppo della tecnologia AI multimodale. La comunità Hugging Face amplierà la diversità dei suoi modelli e set di dati, inclusi dati multimodali come immagini, audio e video.
- Nell’era dell’AGI, Hugging Face potrebbe entrare in gioco nei seguenti modi:
Condivisione di modelli: come piattaforma di condivisione di modelli, Hugging Face continuerà a promuovere la condivisione e la collaborazione di modelli AGI avanzati.
Ecosistema open source: l’ecosistema open source di Hugging Face contribuirà ad accelerare lo sviluppo e l’innovazione della tecnologia AGI.
Strumenti e servizi: fornire una vasta gamma di strumenti e servizi per supportare sviluppatori e ricercatori nella loro ricerca e applicazioni nel campo AGI.
Etica e responsabilità sociale: Hugging Face si concentra sull’etica dell’IA e promuoverà lo sviluppo e l’applicazione di modelli AGI responsabili per garantire il progresso tecnologico nel rispetto degli standard etici.
L’AGI, in quanto forma avanzata di intelligenza artificiale del futuro, ha ampie prospettive di applicazione e Hugging Face, in quanto comunità open source, svolgerà un ruolo chiave nel promuovere lo sviluppo e l’applicazione dell’AGI.
(Nota: il seguente codice potrebbe richiedere l'accesso scientifico a Internet per essere eseguito)
Potresti aver dovuto riassumere un documento, incluso un articolo di ricerca, un rapporto sui guadagni finanziari o una serie di e-mail. Se ci pensi, ciò richiede una serie di abilità, tra cui la comprensione di contenuti di lunga durata, il ragionamento sul contenuto e quindi la produzione di un testo fluido che comprenda i temi principali del documento originale. Inoltre, riassumere accuratamente un articolo di notizie è molto diverso dal riassumere un contratto legale e quindi richiede complesse capacità di generalizzazione del dominio. Per questi motivi, riassumere il testo (il termine tecnico è riepilogo del testo) è un compito difficile per i modelli del linguaggio neurale, inclusi i modelli Transformer. Nonostante queste sfide, il riepilogo del testo può accelerare in modo significativo il flusso di lavoro degli esperti del settore. Le aziende possono utilizzare il riepilogo del testo per condensare la conoscenza interna, riassumere i contratti, generare automaticamente contenuti di pubblicazione sui social media, ecc. Pertanto il compito della PNL di riepilogo del testo è prezioso.
Per aiutarti a comprendere le sfide, questa sezione esplora come sfruttare i modelli preaddestrati di Transformer per il riepilogo del testo. Il riepilogo è una classica attività da sequenza a sequenza (seq2seq) che richiede testo di input e testo di destinazione.
Il riepilogo del testo è un'attività di elaborazione del linguaggio naturale il cui obiettivo è estrarre informazioni concise e importanti da un testo lungo e generare una versione breve. Il riepilogo del testo può essere suddiviso in due tipologie principali: riepilogo estrattivo e riepilogo generativo.
- Riepilogo estrattivo
Il riepilogo estrattivo seleziona frasi o paragrafi importanti nel testo originale ed estrae direttamente questi contenuti come riassunti. Questo metodo non modifica le parole e la struttura della frase nel testo originale.
Principio di attuazione:
- Estrazione delle caratteristiche: innanzitutto è necessario estrarre varie caratteristiche del testo, come la frequenza delle parole, la posizione della frase, le parole chiave, le entità denominate, ecc.
- Punteggio di importanza: in base alle caratteristiche estratte, viene calcolato un punteggio per ogni frase per determinarne l'importanza.
- Selezione delle frasi: in base al punteggio di importanza, vengono selezionate le frasi più importanti per costruire il riassunto.
difficoltà:
- Misurazione dell'importanza: come misurare accuratamente l'importanza relativa delle frasi.
- Eliminazione della ridondanza: evitare di selezionare frasi con contenuti ripetuti.
Metodo per realizzare:
- Approccio basato su regole: utilizza regole predefinite e metodi statistici per selezionare le frasi.
- Metodo di apprendimento automatico: utilizza algoritmi di apprendimento supervisionato per imparare a selezionare frasi importanti in base ai dati di addestramento.
- Riepilogo generativo
Il riepilogo generativo funziona comprendendo il testo originale e generando nuove frasi per riassumerne il contenuto. Questo approccio crea una sintesi più naturale e coerente, ma è anche più complessa.
Principio di attuazione:
- Architettura codificatore-decodificatore: utilizza un modello sequenza-sequenza (Seq2Seq), in cui il codificatore codifica il testo di input in vettori di contesto e il decodificatore genera riepiloghi basati sui vettori di contesto.
- Meccanismo di attenzione: durante il processo di decodifica, il modello può concentrarsi su diverse parti del testo di input per generare contenuti più pertinenti.
- Modello preaddestrato: utilizza modelli linguistici preaddestrati (come BERT, GPT e così via) per migliorare la qualità dei riepiloghi generati.
difficoltà:
- Coerenza del contenuto: il riepilogo generato deve mantenere la coerenza logica ed evitare interruzioni del contenuto.
- Integrità delle informazioni: garantisce che il riepilogo generato contenga le informazioni chiave del testo originale.
- Complessità del modello: i modelli di riepilogo generativi sono generalmente più complessi dei modelli di riepilogo estrattivi e richiedono più risorse di calcolo e dati di addestramento.
Metodo per realizzare:
- Modello Seq2Seq classico: come il modello encoder-decoder basato su LSTM.
- Modelli di Transformer pre-addestrati: come BERTSUM, T5, BART, ecc.
- Riepilogo del testo in Hugging Face
Hugging Face fornisce una varietà di modelli e strumenti preaddestrati per implementare facilmente attività di riepilogo del testo. Di seguito sono riportati alcuni modelli di riepilogo del testo comunemente utilizzati e come utilizzarli:
- Riepilogo utilizzando modelli preaddestrati
Di seguito è riportato un codice di esempio per il riepilogo del testo utilizzando il modello BART fornito da Hugging Face:
from transformers import BartForConditionalGeneration, BartTokenizer # 加载预训练的BART模型和对应的tokenizer model_name = "facebook/bart-large-cnn" model = BartForConditionalGeneration.from_pretrained(model_name) tokenizer = BartTokenizer.from_pretrained(model_name) # 输入文本 input_text = """Your text to summarize goes here.""" # 对输入文本进行tokenize,并添加必要的模型输入 inputs = tokenizer([input_text], max_length=1024, return_tensors='pt') # 使用模型生成摘要 summary_ids = model.generate(inputs['input_ids'], num_beams=4, max_length=150, early_stopping=True) # 将生成的token序列转换回文本 summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True) print(summary)
- Modelli di riepilogo supportati
Hugging Face fornisce una varietà di modelli preaddestrati per il riepilogo del testo, inclusi ma non limitati a:
- BART (facebook/bart-large-cnn)
- T5 (t5-piccolo, t5-base, t5-grande, t5-3b, t5-11b)
- PEGASO (google/pegasus-xsum, google/pegasus-cnn_dailymail)
- Addestra il tuo modello di riepilogo
Se è necessario adattarsi meglio alle attività di riepilogo del testo specifiche del dominio, è possibile ottimizzare il modello preaddestrato utilizzando il proprio set di dati. Ecco un semplice esempio di messa a punto:
from transformers import Trainer, TrainingArguments, BartForConditionalGeneration, BartTokenizer from datasets import load_dataset # 加载数据集 dataset = load_dataset("cnn_dailymail", "3.0.0") # 加载预训练的BART模型和tokenizer model_name = "facebook/bart-large-cnn" model = BartForConditionalGeneration.from_pretrained(model_name) tokenizer = BartTokenizer.from_pretrained(model_name) # 数据预处理 def preprocess_function(examples): inputs = [doc for doc in examples['article']] model_inputs = tokenizer(inputs, max_length=1024, truncation=True) # 设定摘要作为目标 with tokenizer.as_target_tokenizer(): labels = tokenizer(examples['highlights'], max_length=150, truncation=True) model_inputs['labels'] = labels['input_ids'] return model_inputs tokenized_dataset = dataset.map(preprocess_function, batched=True) # 定义训练参数 training_args = TrainingArguments( output_dir="./results", evaluation_strategy="epoch", learning_rate=2e-5, per_device_train_batch_size=4, per_device_eval_batch_size=4, num_train_epochs=3, weight_decay=0.01, ) # 使用Trainer进行训练 trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset["train"], eval_dataset=tokenized_dataset["validation"], ) trainer.train()Il riepilogo del testo è un compito complesso e impegnativo di elaborazione del linguaggio naturale. Utilizzando i modelli e gli strumenti pre-addestrati forniti da Hugging Face, il processo di implementazione del riepilogo del testo può essere notevolmente semplificato. Gli utenti possono selezionare il modello appropriato in base alle esigenze specifiche e perfezionarlo per ottenere il miglior effetto di sintesi.
In questa sezione costruiremo il nostro modello di codificatore-decodificatore per comprimere le conversazioni tra più persone in riepiloghi concisi. Ma prima diamo un'occhiata a un classico set di dati nel campo della sintesi: il corpus CNN/DailyMail.
Ora le condizioni sono complete per valutare completamente il modello: abbiamo il set di dati del set di test CNN/DailyMail, la metrica ROUGE per la valutazione e un modello di riepilogo.
- # 导入所需的库
- import matplotlib.pyplot as plt # 导入 matplotlib.pyplot,用于绘制图形
- import pandas as pd # 导入 pandas,用于数据处理
- from datasets import load_dataset, load_metric # 从 datasets 库中导入 load_dataset 和 load_metric 函数
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer # 从 transformers 库中导入 AutoModelForSeq2SeqLM 和 AutoTokenizer
-
- # 加载 CNN/DailyMail 数据集,版本为 3.0.0
- dataset = load_dataset("cnn_dailymail", "3.0.0")
-
- # 加载 ROUGE 评价指标,用于计算文本摘要的质量
- rouge_metric = load_metric("rouge", cache_dir=None)
-
- # 定义要计算的 ROUGE 分数的名称列表
- rouge_names = ["rouge1", "rouge2", "rougeL", "rougeLsum"]
Dobbiamo solo mettere insieme i pezzi. Innanzitutto, valutiamo le prestazioni del modello benchmark a tre frasi:
- # 定义一个函数,用于评估基线模型生成的摘要
- def evaluate_summaries_baseline(dataset, metric, column_text="article", column_summary="highlights"):
- # 使用 three_sentence_summary 函数对数据集中的每篇文章生成摘要
- summaries = [three_sentence_summary(text) for text in dataset[column_text]]
-
- # 将生成的摘要和参考摘要添加到评价指标中
- metric.add_batch(predictions=summaries, references=dataset[column_summary])
-
- # 计算评价指标的分数
- score = metric.compute()
-
- # 返回评价指标的分数
- return score
Applichiamo quindi la funzione a un sottoinsieme di dati. Poiché la parte di test del set di dati CNN/DailyMail contiene circa 10.000 campioni, generare riepiloghi di tutti questi articoli richiede molto tempo. Ricordiamo dal Capitolo 5 che ogni token generato deve essere inoltrato attraverso il modello. La generazione di 100 token per campione richiederebbe 1 milione di passaggi in avanti e, se utilizzassimo la ricerca dei raggi, anche questo numero dovrebbe essere moltiplicato per il numero di raggi. Per velocizzare il calcolo, sottocampioneremo il set di test e infine utilizzeremo 1000 campioni per la valutazione. In questo modo possiamo completare la valutazione del modello PEGASUS in meno di un'ora su una singola GPU e ottenere stime di punteggio stabili:
- # 从测试集中随机抽取1000条样本,用于评估
- test_sampled = dataset["test"].shuffle(seed=42).select(range(1000))
-
- # 使用基线模型生成摘要并评估其质量
- score = evaluate_summaries_baseline(test_sampled, rouge_metric)
-
- # 将评价指标的分数存储在字典中
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将评价指标的分数转换为DataFrame格式,并转置以便显示
- pd.DataFrame.from_dict(rouge_dict, orient="index", columns=["baseline"]).T
risultato dell'operazione:
rosso1 | rosso2 | rossoL | rossoLsomma | |
linea di base | 0.38928 | 0.171296 | 0.245061 | 0.354239 |
I punteggi sono per lo più peggiori rispetto all'esempio precedente, ma comunque migliori di quelli ottenuti da GPT-2! Ora seguiamo lo stesso schema per valutare il modello PEGASUS:
- # 导入 tqdm 模块,用于显示进度条
- from tqdm import tqdm
- # 导入 torch 模块,用于使用 GPU 或 CPU 进行计算
- import torch
-
- # 设置设备为 GPU(如果可用)或 CPU
- device = "cuda" if torch.cuda.is_available() else "cpu"
-
- def chunks(list_of_elements, batch_size):
- """将 list_of_elements 按 batch_size 切分成多个小块"""
- for i in range(0, len(list_of_elements), batch_size):
- yield list_of_elements[i : i + batch_size]
-
- def evaluate_summaries_pegasus(dataset, metric, model, tokenizer,
- batch_size=16, device=device,
- column_text="article",
- column_summary="highlights"):
- """评估使用 Pegasus 模型生成的摘要"""
-
- # 将文章和摘要分别按 batch_size 切分成多个小块
- article_batches = list(chunks(dataset[column_text], batch_size))
- target_batches = list(chunks(dataset[column_summary], batch_size))
-
- # 使用 tqdm 显示进度条,遍历每个文章批次和相应的摘要批次
- for article_batch, target_batch in tqdm(
- zip(article_batches, target_batches), total=len(article_batches)):
-
- # 对文章批次进行标记,将其转换为模型输入的张量
- inputs = tokenizer(article_batch, max_length=1024, truncation=True,
- padding="max_length", return_tensors="pt")
-
- # 使用 Pegasus 模型生成摘要
- summaries = model.generate(input_ids=inputs["input_ids"].to(device),
- attention_mask=inputs["attention_mask"].to(device),
- length_penalty=0.8, num_beams=8, max_length=128)
-
- # 解码生成的摘要,将其从张量转换为字符串
- decoded_summaries = [tokenizer.decode(s, skip_special_tokens=True,
- clean_up_tokenization_spaces=True)
- for s in summaries]
- decoded_summaries = [d.replace("", " ") for d in decoded_summaries]
-
- # 将生成的摘要和目标摘要添加到评价指标中
- metric.add_batch(predictions=decoded_summaries, references=target_batch)
-
- # 计算评价指标分数
- score = metric.compute()
- return score
Spieghiamo questo codice di valutazione in dettaglio. Innanzitutto, dividiamo il set di dati in lotti più piccoli in modo che possano essere elaborati simultaneamente. Quindi, per ciascun batch, tokenizziamo gli articoli di input e li inseriamo nella funzione generate() per generare riepiloghi utilizzando la ricerca travi. Usiamo gli stessi parametri di generazione del documento. La nuova lunghezza del parametro di penalità garantisce che il modello non generi sequenze troppo lunghe.Infine, decodifichiamo il testo risultante, sostituendolo<n> token e aggiungi il testo decodificato alla metrica insieme al testo di riferimento. Infine, calcoliamo e restituiamo il punteggio ROUGE. Ora utilizziamo nuovamente la classe AutoModelForSeq2SeqLM per l'attività di generazione di seq2seq per caricare il modello e valutarlo:
- # 从 transformers 库中导入用于序列到序列任务的模型和标记器
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
-
- # 设置模型检查点名称,使用 Google 的 PEGASUS 模型,预训练于 CNN/DailyMail 数据集
- model_ckpt = "google/pegasus-cnn_dailymail"
-
- # 从预训练的模型检查点中加载标记器和模型,并将模型移动到指定的设备(CPU 或 GPU)
- tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
- model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)
-
- # 使用评估函数 evaluate_summaries_pegasus 评估 PEGASUS 模型生成的摘要
- # 输入参数包括测试数据、ROUGE 评价指标、模型、标记器和批处理大小
- score = evaluate_summaries_pegasus(test_sampled, rouge_metric,
- model, tokenizer, batch_size=8)
-
- # 从评估结果中提取 ROUGE 分数,将其转换为字典格式,其中键为 ROUGE 指标名称,值为 F-measure 分数
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将 ROUGE 分数字典转换为 pandas 数据框,并以 "pegasus" 作为索引
- pd.DataFrame(rouge_dict, index=["pegasus"])
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, i risultati correnti per riferimento utilizzando gli esempi sono i seguenti)
rosso1 | rosso2 | rossoL | rossoLsomma | |
pegaso | 0.43438 | 0.210883 | 0.307195 | 0.373231 |
Questi numeri sono molto vicini ai risultati del documento. La cosa importante da notare qui è che la perdita e la precisione di ciascun token sono in qualche modo disaccoppiate dal punteggio ROUGE. La perdita è indipendente dalla strategia di decodifica, mentre il punteggio ROUGE è fortemente accoppiato.
Poiché ROUGE e BLEU raggiungono una migliore perdita o accuratezza rispetto alla valutazione umana, è necessario concentrarsi su di essi quando si costruiscono modelli di generazione del testo ed esplorare e selezionare attentamente le strategie di decodifica. Tuttavia, questi parametri sono lungi dall’essere perfetti, quindi la valutazione umana dovrebbe sempre essere presa in considerazione.
Ora che abbiamo la funzione di valutazione, possiamo addestrare il nostro modello di riepilogo.
A questo punto, abbiamo esaminato molti dettagli del riepilogo e della valutazione del testo, ora utilizziamo queste conoscenze per addestrare un modello di riepilogo del testo personalizzato! Per la nostra applicazione personalizzata, utilizzeremo il set di dati SAMSum sviluppato da Samsung (HTTPS://loReioool.le/N1GGQ ), questo set di dati contiene una serie di conversazioni e brevi riassunti. Queste conversazioni possono rappresentare le interazioni tra clienti e call center, generando riepiloghi accurati per aiutare a migliorare il servizio clienti e rilevare modelli comuni nelle richieste dei clienti. Carichiamo innanzitutto il set di dati e visualizziamo un esempio:
- # 从 datasets 库中导入用于加载数据集的函数
- from datasets import load_dataset
-
- # 加载 SamSum 数据集,该数据集包含对话和相应的摘要
- dataset_samsum = load_dataset("samsum",trust_remote_code=True)
-
- # 获取数据集的每个划分(训练集、验证集、测试集)的长度,并存储在列表 split_lengths 中
- split_lengths = [len(dataset_samsum[split]) for split in dataset_samsum]
-
- # 打印每个数据集划分的长度
- print(f"Split lengths: {split_lengths}")
-
- # 打印训练集中列的名称(特征)
- print(f"Features: {dataset_samsum['train'].column_names}")
-
- # 打印测试集中第一个对话样本
- print("nDialogue:")
- print(dataset_samsum["test"][0]["dialogue"])
-
- # 打印测试集中第一个对话样本的摘要
- print("nSummary:")
- print(dataset_samsum["test"][0]["summary"])
(Nota: potrebbe essere necessario installare py7zr, pip install py7zr)
risultato dell'operazione:
Split lengths: [14732, 819, 818] Features: ['id', 'dialogue', 'summary'] Dialogue: Hannah: Hey, do you have Betty's number? Amanda: Lemme check Hannah: <file_gif> Amanda: Sorry, can't find it. Amanda: Ask Larry Amanda: He called her last time we were at the park together Hannah: I don't know him well Hannah: <file_gif> Amanda: Don't be shy, he's very nice Hannah: If you say so.. Hannah: I'd rather you texted him Amanda: Just text him 🙂 Hannah: Urgh.. Alright Hannah: Bye Amanda: Bye bye Summary: Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry.
Le conversazioni sembrano proprio come se chattassi tramite SMS o WhatsApp, inclusi emoji e segnaposto per GIF. Il campo dialogo contiene il testo completo, mentre il campo riepilogo è un riassunto del dialogo. Un modello messo a punto sul set di dati CNN/DailyMail può gestire questo set di dati? Diamo un'occhiata!
Innanzitutto, eseguiremo lo stesso processo di generazione del riepilogo utilizzando PEGASUS per vedere l'output. Possiamo riutilizzare il codice generato dal riepilogo CNN/DailyMail:
- # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
- pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
-
- # 打印生成的摘要标题
- print("Summary:")
-
- # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
- # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
- print(pipe_out[0]["summary_text"].replace(" .", ".n"))
risultato dell'operazione:
Summary: Hannah asks Amanda for Betty's number. Amanda can't find it. Hannah asks Larry. Amanda asks Larry to text him. Hannah says she'll text him back. Hannah calls it a day and says she's going to go home. Hannah: "Bye bye"
Possiamo vedere che il modello cerca principalmente di riassumere estraendo frasi chiave nella conversazione. Questo potrebbe funzionare relativamente bene sul set di dati CNN/DailyMail, ma in SAMSum il riepilogo è più astratto e l'effetto potrebbe non essere buono. Possiamo confermarlo eseguendo la valutazione ROUGE completa sul set di test:
- # 使用评估函数 evaluate_summaries_pegasus 对 SamSum 数据集的测试集进行摘要生成评估
- # 传入的参数包括数据集、评价指标、模型、tokenizer、文本列名、摘要列名和批量大小
- score = evaluate_summaries_pegasus(dataset_samsum["test"], rouge_metric, model,
- tokenizer, column_text="dialogue",
- column_summary="summary", batch_size=8)
-
- # 创建一个字典 rouge_dict,用于存储 ROUGE 评分的中值 F-measure 值
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 将 ROUGE 评分字典转换为 Pandas 数据框,并以 "pegasus" 为索引
- pd.DataFrame(rouge_dict, index=["pegasus"])
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, i risultati correnti per riferimento utilizzando gli esempi sono i seguenti)
rosso1 | rosso2 | rossoL | rossoLsomma | |
pegaso | 0.29617 | 0.087803 | 0.229604 | 0.229514 |
Anche se i risultati non sono eccezionali, non è inaspettato in quanto è molto lontano dalla distribuzione dei dati CNN/DailyMail. Tuttavia, impostare il processo di valutazione prima della formazione presenta due vantaggi: possiamo utilizzare direttamente i parametri per misurare il successo della formazione e abbiamo una buona base di partenza. La messa a punto del modello sul nostro set di dati dovrebbe migliorare immediatamente la metrica ROUGE, se non ci sono miglioramenti allora sappiamo che c'è qualcosa di sbagliato nel nostro ciclo di addestramento.
Prima di allenarci sui dati, diamo una rapida occhiata alle distribuzioni della lunghezza di input e output:
- # 编码训练集中的对话文本和摘要,并计算其长度
- d_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["dialogue"]]
- s_len = [len(tokenizer.encode(s)) for s in dataset_samsum["train"]["summary"]]
-
- # 创建一个包含两个子图的图形对象
- fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), sharey=True)
-
- # 绘制对话文本的长度分布直方图
- axes[0].hist(d_len, bins=20, color="C0", edgecolor="C0")
- axes[0].set_title("Dialogue Token Length")
- axes[0].set_xlabel("Length")
- axes[0].set_ylabel("Count")
-
- # 绘制摘要的长度分布直方图
- axes[1].hist(s_len, bins=20, color="C0", edgecolor="C0")
- axes[1].set_title("Summary Token Length")
- axes[1].set_xlabel("Length")
-
- # 调整子图布局,使其更加紧凑
- plt.tight_layout()
-
- # 显示绘制的图形
- plt.show()
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, i risultati correnti per riferimento utilizzando gli esempi sono i seguenti)
Possiamo vedere che la maggior parte delle conversazioni sono molto più brevi degli articoli della CNN/DailyMail, con circa 100-200 token ciascuna. Allo stesso modo, i riassunti sono molto più brevi, dai 20 ai 40 token (la stessa lunghezza di un tweet medio).
Ricordiamo prima questi risultati, li useremo in seguito. Innanzitutto, dobbiamo tokenizzare il set di dati. Impostiamo la lunghezza massima del dialogo e del riassunto rispettivamente su 1024 e 128:
- def convert_examples_to_features(example_batch):
- """
- 将示例批处理转换为模型输入特征。
-
- Args:
- - example_batch (dict): 包含对话和摘要的示例批处理字典。
-
- Returns:
- - dict: 包含转换后特征的字典,包括输入编码和目标编码。
- """
- # 对对话文本进行编码处理,生成输入编码
- input_encodings = tokenizer(example_batch["dialogue"], max_length=1024,
- truncation=True)
-
- # 使用目标编码器处理摘要文本,生成目标编码
- with tokenizer.as_target_tokenizer():
- target_encodings = tokenizer(example_batch["summary"], max_length=128,
- truncation=True)
-
- # 返回包含输入编码、目标标签和注意力掩码的字典
- return {
- "input_ids": input_encodings["input_ids"],
- "attention_mask": input_encodings["attention_mask"],
- "labels": target_encodings["input_ids"]
- }
-
- # 使用 map 方法将 SamSum 数据集转换为 PyTorch 格式
- dataset_samsum_pt = dataset_samsum.map(convert_examples_to_features,
- batched=True)
-
- # 设置数据集格式为 Torch 张量类型,并指定列名
- columns = ["input_ids", "labels", "attention_mask"]
- dataset_samsum_pt.set_format(type="torch", columns=columns)
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
C'è una novità nella fase di tokenizzazione: il contesto tokenizer.as_target_tokenizer(). Alcuni modelli richiedono token speciali nell'ingresso del decodificatore, quindi è importante separare le fasi di tokenizzazione per gli ingressi del codificatore e del decodificatore. All'interno di un'istruzione with (chiamata gestore di contesto), il tokenizzatore sa che sta tokenizzando per il decodificatore.
Ora dobbiamo creare l'organizzatore dei dati. Nella maggior parte dei casi possiamo utilizzare il raccoglitore predefinito, che raccoglie tutti i tensori in un batch e li impila semplicemente. Per l'attività di riepilogo, non dobbiamo solo impilare gli input, ma anche preparare gli obiettivi sul lato del decodificatore. PEGASUS è un trasformatore encoder-decoder e quindi ha un'architettura classica seq2seq. In un'impostazione seq2seq, un approccio comune consiste nell'applicare la forzatura dell'insegnante nel decodificatore. Quando si utilizza questa strategia, il decodificatore riceve token di input (come un modello solo decodificatore come GPT-2), che vengono spostati di una posizione a destra dall'annotazione, oltre all'output del codificatore. Pertanto, nel prevedere il token successivo, il decodificatore otterrà come input il valore vero spostato di una posizione a destra, come mostrato nella tabella seguente:
- # 示例文本序列和标签生成过程
- text = ['PAD', 'Transformers', 'are', 'awesome', 'for', 'text', 'summarization']
-
- # 初始化存储每步结果的列表
- rows = []
-
- # 循环生成每步的数据行
- for i in range(len(text)-1):
- rows.append({
- 'step': i+1, # 步骤号,从1开始
- 'decoder_input': text[:i+1], # 解码器输入序列,从文本开始到当前位置
- 'label': text[i+1] # 标签,当前位置的下一个词
- })
-
- # 创建数据帧,并以步骤号作为索引
- pd.DataFrame(rows).set_index('step')
risultato dell'operazione:
fare un passo | decodificatore_input | etichetta |
1 | [PANNELLO] | Trasformatori |
2 | [PAD, Trasformatori] | Sono |
3 | [PAD, Transformers, sono] | Eccezionale |
4 | [PAD, Transformers, sono fantastici] | per |
5 | [PAD, Transformers, sono, fantastici, per] | testo |
6 | [PAD, Transformers, sono, fantastici, per, testo] | riassunto |
Lo spostiamo di una posizione a destra in modo che il decodificatore veda solo l'annotazione corretta precedente, non le annotazioni attuali o future. Il semplice spostamento è sufficiente perché il decodificatore ha un meccanismo di auto-attenzione mascherato che maschera tutti gli input attuali e futuri.
Pertanto, durante la preparazione del batch, impostiamo l'ingresso al decodificatore spostando l'annotazione di una posizione a destra. Successivamente, ci assicuriamo che i token di riempimento nella funzione di perdita vengano ignorati impostandoli su -100 nell'annotazione. In realtà, non dobbiamo eseguire questi passaggi manualmente perché DataCollatorForSeq2Seq fa tutto per noi:
- # 导入 Seq2Seq 数据集整理器模块
- from transformers import DataCollatorForSeq2Seq
-
- # 创建 Seq2Seq 数据集整理器实例
- seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
Quindi, come al solito, impostiamo un TrainingArguments per la formazione:
- # 导入训练参数和训练器模块
- from transformers import TrainingArguments, Trainer
-
- # 定义训练参数
- training_args = TrainingArguments(
- output_dir='pegasus-samsum', # 模型输出目录
- num_train_epochs=1, # 训练的轮数
- warmup_steps=500, # 学习率预热步数
- per_device_train_batch_size=1, # 每个设备的训练批次大小
- per_device_eval_batch_size=1, # 每个设备的评估批次大小
- weight_decay=0.01, # 权重衰减率
- logging_steps=10, # 训练日志记录步数
- push_to_hub=True, # 是否推送到模型中心
- evaluation_strategy='steps', # 评估策略
- eval_steps=500, # 评估步数间隔
- save_steps=1e6, # 模型保存步数间隔
- gradient_accumulation_steps=16 # 梯度累积步数
- )
La differenza rispetto alle impostazioni precedenti è che questa volta c'è un nuovo parametro gradient_accumulation_steps. Poiché il modello è molto grande, dobbiamo impostare la dimensione del batch su 1. Tuttavia, dimensioni batch troppo piccole possono influire sulla convergenza. Per risolvere questo problema, possiamo usare un trucco intelligente chiamato accumulo del gradiente. Come suggerisce il nome, invece di calcolare i gradienti per l'intero batch in una volta, calcoliamo e aggreghiamo i gradienti in batch. Quando abbiamo aggregato abbastanza gradienti, eseguiamo una fase di ottimizzazione. Questo è naturalmente più lento che fare tutto in una volta, ma ci fa risparmiare molta memoria della GPU.
Ora accediamo a Hugging Face in modo da poter inviare il modello all'Hub dopo l'addestramento:
- from huggingface_hub import notebook_login
-
- notebook_login()
risultato dell'operazione:
Ora abbiamo tutto ciò di cui abbiamo bisogno per inizializzare il trainer, inclusi modello, tokenizzatore, parametri di addestramento, organizzatori di dati e set di dati di addestramento e valutazione:
- from transformers import TrainingArguments, Trainer
-
- # 创建一个 Trainer 实例用于训练序列到序列模型。
- trainer = Trainer(
- model=model, # 要训练的序列到序列模型
- args=training_args, # 定义的训练参数
- tokenizer=tokenizer, # 用于预处理输入数据的分词器
- data_collator=seq2seq_data_collator, # 用于批处理数据的数据整理器
- train_dataset=dataset_samsum_pt["train"], # 训练数据集
- eval_dataset=dataset_samsum_pt["validation"] # 评估数据集
- )
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Siamo pronti per allenarci. Una volta completato l'addestramento, possiamo eseguire la funzione di valutazione direttamente sul set di test per vedere come si è comportato il modello:
- from transformers import TrainingArguments, Trainer
-
- # 开始训练模型
- trainer.train()
-
- # 使用评估函数评估 Pegasus 模型的摘要质量
- score = evaluate_summaries_pegasus(
- dataset_samsum["test"], rouge_metric, trainer.model, tokenizer,
- batch_size=2, column_text="dialogue", column_summary="summary")
-
- # 提取 ROUGE 指标结果
- rouge_dict = dict((rn, score[rn].mid.fmeasure) for rn in rouge_names)
-
- # 创建 DataFrame 显示 ROUGE 指标
- pd.DataFrame(rouge_dict, index=[f"pegasus"])
risultato dell'operazione:
(Temporaneamente l'errore viene segnalato qui:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, i risultati correnti per riferimento utilizzando gli esempi sono i seguenti)
rosso1 | rosso2 | rossoL | rossoLsomma | |
pegaso | 0.42761 | 0.200571 | 0.340648 | 0.340738 |
Possiamo vedere che il punteggio ROUGE è significativamente migliorato rispetto al modello senza messa a punto, quindi sebbene il modello precedente fosse stato addestrato anche per la generazione di riepilogo, non si adattava bene al nuovo dominio. Spostiamo il nostro modello su Hub:
- # 将训练完成的模型推送到 Hub 上
- trainer.push_to_hub("Training complete!")
Successivamente utilizzeremo questo modello per generare alcuni riepiloghi per noi.
È inoltre possibile valutare i risultati generati come parte di un ciclo di training: utilizzare l'estensione TrainingArguments denominata Seq2SeqTrainingArguments e specificare predit_with_generate=True. Passalo a un Trainer dedicato chiamato Seq2SeqTrainer, che utilizza la funzione generate() invece di un passaggio in avanti del modello per creare previsioni per la valutazione. Provaci!
Osservando la perdita e i punteggi ROUGE, il modello sembra mostrare un miglioramento significativo rispetto al modello originale addestrato solo su CNN/DailyMail. Un riepilogo generato da un campione nel set di test è simile al seguente:
- import transformers
-
- # 设置transformers的日志级别为错误,以减少输出日志
- transformers.logging.set_verbosity_error()
-
- # 定义生成摘要时的参数
- gen_kwargs = {"length_penalty": 0.8, "num_beams": 8, "max_length": 128}
-
- # 从测试集中选择一个示例
- sample_text = dataset_samsum["test"][0]["dialogue"]
- reference = dataset_samsum["test"][0]["summary"]
-
- # 使用预训练的pegasus-samsum模型创建摘要管道
- pipe = pipeline("summarization", model="transformersbook/pegasus-samsum")
-
- # 输出对话和参考摘要
- print("Dialogue:")
- print(sample_text)
- print("nReference Summary:")
- print(reference)
-
- # 使用模型生成摘要并输出
- print("nModel Summary:")
- print(pipe(sample_text, **gen_kwargs)[0]["summary_text"])
risultato dell'operazione:
Dialogue: Hannah: Hey, do you have Betty's number? Amanda: Lemme check Hannah: <file_gif> Amanda: Sorry, can't find it. Amanda: Ask Larry Amanda: He called her last time we were at the park together Hannah: I don't know him well Hannah: <file_gif> Amanda: Don't be shy, he's very nice Hannah: If you say so.. Hannah: I'd rather you texted him Amanda: Just text him 🙂 Hannah: Urgh.. Alright Hannah: Bye Amanda: Bye bye Reference Summary: Hannah needs Betty's number but Amanda doesn't have it. She needs to contact Larry. Model Summary: Amanda can't find Betty's number. Larry called Betty last time they were at the park together. Hannah wants Amanda to text Larry instead of calling Betty.
Questo è molto simile a un riepilogo di riferimento. Sembra che il modello abbia imparato a sintetizzare le conversazioni in riassunti invece di limitarsi a estrarne i passaggi. Passiamo ora al test finale: come si comporta il modello sugli input personalizzati?
- # 自定义对话示例
- custom_dialogue = """
- Thom: Hi guys, have you heard of transformers?
- Lewis: Yes, I used them recently!
- Leandro: Indeed, there is a great library by Hugging Face.
- Thom: I know, I helped build it ;)
- Lewis: Cool, maybe we should write a book about it. What do you think?
- Leandro: Great idea, how hard can it be?!
- Thom: I am in!
- Lewis: Awesome, let's do it together!
- """
-
- # 使用预训练的pegasus-samsum模型生成摘要,并输出摘要结果
- print(pipe(custom_dialogue, **gen_kwargs)[0]["summary_text"])
risultato dell'operazione:
Thom and Lewis wanted to write a book about transformers. They came up with the idea with the help of Hugging Face's Leandro. The book will be called "Transformers: The Power of Transformers" and will be published in 2015. The project is currently in the planning stages.
Il riepilogo della conversazione personalizzata generato ha senso. Fa un buon lavoro nel riassumere ciò di cui tutti i partecipanti alla discussione volevano scrivere un libro insieme, piuttosto che limitarsi a estrarre una singola frase. Ad esempio, combina le righe 3 e 4 in un'unica combinazione logica.