моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Оглавление
3. Оцените PEGASUS на наборе данных CNN/DailyMail.
1. Оцените производительность PEGASUS на SAMSum.
AGI, или Общий Искусственный Интеллект, — это система искусственного интеллекта с уровнем человеческого интеллекта. Он может не только выполнять конкретные задачи, но также понимать, изучать и применять знания для решения широкого круга задач, обладая высокой автономностью и адаптивностью. Возможности AGI включают, помимо прочего, самообучение, самосовершенствование, саморегулирование и способность решать различные сложные проблемы без вмешательства человека.
- Возможности AGI очень широки:
Междоменное выполнение задач: AGI может обрабатывать задачи в нескольких доменах и не ограничивается конкретными сценариями приложений.
Автономное обучение и адаптация: AGI может учиться на опыте и адаптироваться к новым условиям и ситуациям.
Креативное мышление: AGI способен мыслить инновационно и предлагать новые решения.
Социальное взаимодействие: AGI способен к сложным социальным взаимодействиям с людьми и понимает эмоциональные и социальные сигналы.
- Что касается будущих перспектив развития AGI, то он считается одной из конечных целей исследований в области искусственного интеллекта и имеет огромный потенциал для изменений:
Технологические инновации. С развитием таких технологий, как машинное обучение и нейронные сети, реализация AGI может стать все ближе.
Междисциплинарная интеграция. Внедрение AGI требует интеграции знаний из нескольких дисциплин, таких как информатика, нейробиология и психология.
Этические и социальные соображения. Развитие AGI требует рассмотрения этических и социальных вопросов, таких как конфиденциальность, безопасность и занятость.
Расширенные возможности обучения и адаптации. Будущие системы AGI могут использовать передовые алгоритмы для изучения окружающей среды и оптимизации поведения.
Мультимодальное взаимодействие: AGI будет иметь множество методов восприятия и взаимодействия для взаимодействия с людьми и другими системами.
Hugging Face, одно из самых популярных сообществ и платформ машинного обучения с открытым исходным кодом в мире, играет важную роль в эпоху AGI. Он предоставляет богатые ресурсы предварительно обученных моделей и наборов данных, способствуя развитию области машинного обучения. Hugging Face отличается простотой использования и открытостью. Благодаря библиотеке Transformers он предоставляет пользователям удобный способ обработки текста. С развитием технологии искусственного интеллекта сообщество Hugging Face продолжит играть важную роль в продвижении разработки и применения технологий искусственного интеллекта, особенно в разработке мультимодальных технологий искусственного интеллекта. Сообщество Hugging Face будет расширять разнообразие своих моделей. и наборы данных, включая мультимодальные данные, такие как изображения, аудио и видео.
- В эпоху AGI «Обнимающее лицо» может использоваться следующими способами:
Обмен моделями: Hugging Face, являясь платформой для обмена моделями, продолжит способствовать обмену и сотрудничеству передовых моделей AGI.
Экосистема с открытым исходным кодом. Экосистема с открытым исходным кодом Hugging Face поможет ускорить развитие и внедрение инноваций в области AGI.
Инструменты и услуги. Предоставляйте множество инструментов и услуг для поддержки разработчиков и исследователей в их исследованиях и приложениях в области искусственного интеллекта.
Этика и социальная ответственность: Hugging Face фокусируется на этике искусственного интеллекта и будет способствовать разработке и применению ответственных моделей AGI для обеспечения технологического прогресса при соблюдении этических стандартов.
AGI, как передовая форма искусственного интеллекта будущего, имеет широкие перспективы применения, и Hugging Face, как сообщество с открытым исходным кодом, будет играть ключевую роль в продвижении разработки и применения AGI.
(Примечание. Для запуска следующего кода может потребоваться научный доступ к Интернету)
Возможно, вам пришлось резюмировать документ, включая исследовательскую статью, отчет о финансовых доходах или серию электронных писем. Если задуматься, для этого требуется целый ряд способностей, включая понимание развернутого контента, его рассуждение, а затем создание беглого текста, охватывающего основные темы исходного документа. Более того, точное изложение новостной статьи сильно отличается от краткого изложения юридического контракта и, следовательно, требует сложных возможностей обобщения предметной области. По этим причинам обобщение текста (технический термин — обобщение текста) является сложной задачей для моделей нейронного языка, включая модели Transformer. Несмотря на эти проблемы, обобщение текста может значительно ускорить рабочий процесс экспертов в предметной области. Компании могут использовать обобщение текста для сжатия внутренних знаний, обобщения контрактов, автоматического создания контента для публикации в социальных сетях и т. д. Поэтому задача НЛП по резюмированию текста является ценной.
Чтобы помочь вам понять проблемы, в этом разделе рассматривается, как использовать предварительно обученные модели Transformer для суммирования текста. Суммирование — это классическая задача последовательного преобразования (seq2seq), для которой требуется входной и целевой текст.
Обобщение текста — это задача обработки естественного языка, цель которой — извлечь краткую и важную информацию из длинного текста и создать короткую версию. Реферирование текста можно разделить на два основных типа: экстрактивное реферирование и генеративное реферирование.
- Извлекательное резюме
Экстрактивное реферирование выбирает важные предложения или абзацы в исходном тексте и непосредственно извлекает это содержимое в виде резюме. Этот метод не меняет структуру слов и предложений в исходном тексте.
Принцип реализации:
- Извлечение признаков: во-первых, необходимо извлечь различные характеристики текста, такие как частота слов, положение предложения, ключевые слова, именованные объекты и т. д.
- Оценка важности: на основе извлеченных функций для каждого предложения рассчитывается оценка, чтобы определить его важность.
- Выбор предложения: на основе оценки важности для построения резюме выбираются наиболее важные предложения.
сложность:
- Измерение важности: как точно измерить относительную важность предложений.
- Устранение избыточности: избегайте выбора предложений с повторяющимся содержанием.
Метод реализации:
- Подход, основанный на правилах: для выбора предложений используются заранее определенные правила и статистические методы.
- Метод машинного обучения: используйте алгоритмы обучения с учителем, чтобы научиться выбирать важные предложения на основе обучающих данных.
- Генеративное обобщение
Генеративное обобщение работает путем понимания исходного текста и создания новых предложений для обобщения его содержания. Такой подход создает более естественное и связное резюме, но при этом является более сложным.
Принцип реализации:
- Архитектура кодировщика-декодера: использует модель «последовательность-последовательность» (Seq2Seq), где кодер кодирует входной текст в векторы контекста, а декодер генерирует сводки на основе векторов контекста.
- Механизм внимания: в процессе декодирования модель может фокусироваться на различных частях входного текста, чтобы генерировать более релевантный контент.
- Предварительно обученная модель. Используйте предварительно обученные языковые модели (такие как BERT, GPT и т. д.) для улучшения качества создаваемых сводок.
сложность:
- Согласованность содержания. Создаваемое резюме должно поддерживать логическую последовательность и избегать разрывов содержания.
- Целостность информации: гарантирует, что созданное резюме содержит ключевую информацию из исходного текста.
- Сложность модели: генерирующие сводные модели обычно более сложны, чем извлекающие сводные модели, и требуют больше вычислительных ресурсов и обучающих данных.
Метод реализации:
- Классическая модель Seq2Seq: например, модель кодера-декодера на основе LSTM.
- Предварительно обученные модели трансформаторов: такие как BERTSUM, T5, BART и т. д.
- Обобщение текста в Hugging Face
Hugging Face предоставляет множество предварительно обученных моделей и инструментов для простой реализации задач по обобщению текста. Ниже приведены некоторые часто используемые модели реферирования текста и способы их использования:
- Суммирование с использованием предварительно обученных моделей
Ниже приведен пример кода для суммирования текста с использованием модели BART, предоставленной 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)
- Поддерживаемые сводные модели
Hugging Face предоставляет множество предварительно обученных моделей для обобщения текста, включая, помимо прочего:
- БАРТ (facebook/bart-large-cnn)
- T5 (t5-маленький, t5-основание, t5-большой, t5-3b, t5-11b)
- ПЕГАС (google/pegasus-xsum, google/pegasus-cnn_dailymail)
- Обучите свою собственную сводную модель
Если вам нужно лучше адаптироваться к задачам обобщения текста, специфичным для предметной области, вы можете точно настроить предварительно обученную модель, используя собственный набор данных. Вот простой пример тонкой настройки:
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()Резюмирование текста — это сложная и трудная задача обработки естественного языка. Используя предварительно обученные модели и инструменты Hugging Face, можно значительно упростить процесс суммирования текста. Пользователи могут выбрать подходящую модель в соответствии с конкретными потребностями и настроить ее для получения наилучшего суммарного эффекта.
В этом разделе мы создадим нашу собственную модель кодировщика-декодера для сжатия разговоров нескольких человек в краткие сводки. Но перед этим давайте взглянем на классический набор данных в области обобщения: корпус CNN/DailyMail.
Теперь у нас есть все необходимое для полной оценки модели: у нас есть набор данных тестового набора CNN/DailyMail, метрика ROUGE для оценки и сводная модель.
- # 导入所需的库
- 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"]
Нам просто нужно собрать кусочки воедино. Сначала мы оцениваем производительность эталонной модели из трех предложений:
- # 定义一个函数,用于评估基线模型生成的摘要
- 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
Затем мы применяем функцию к подмножеству данных. Поскольку тестовая часть набора данных CNN/DailyMail содержит около 10 000 выборок, создание резюме всех этих статей занимает много времени. Вспомним главу 5, что каждый сгенерированный токен необходимо пройти через модель. Для генерации 100 токенов на выборку потребуется 1 миллион проходов вперед, и если бы мы использовали поиск по лучам, это число также нужно было бы умножить на количество лучей. Чтобы ускорить расчет, мы разделим тестовый набор на части и в конечном итоге используем 1000 образцов для оценки. Таким образом, мы можем завершить оценку модели PEGASUS менее чем за час на одном графическом процессоре и получить стабильные оценки:
- # 从测试集中随机抽取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
результат операции:
румяна1 | румяна2 | rougeL | rougeLsum | |
базовый уровень | 0.38928 | 0.171296 | 0.245061 | 0.354239 |
Результаты в основном хуже, чем в предыдущем примере, но все же лучше, чем у GPT-2! Теперь мы следуем той же схеме для оценки модели 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
Давайте подробно объясним этот оценочный код. Сначала мы разбиваем набор данных на более мелкие пакеты, чтобы их можно было обрабатывать одновременно. Затем для каждой партии мы токенизируем входные статьи и передаем их в функцию генерации() для создания сводок с использованием лучевого поиска. Мы используем те же параметры генерации, что и в статье. Новая длина штрафного параметра гарантирует, что модель не будет генерировать слишком длинные последовательности.Наконец, мы декодируем сгенерированный текст, заменяя<n> токены и добавьте декодированный текст в метрику вместе с ссылочным текстом. Наконец, мы вычисляем и возвращаем оценку ROUGE. Теперь мы снова используем класс AutoModelForSeq2SeqLM для задачи генерации seq2seq, чтобы загрузить модель и оценить ее:
- # 从 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"])
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, результаты работы для справки с использованием примеров следующие)
румяна1 | румяна2 | rougeL | rougeLsum | |
пегас | 0.43438 | 0.210883 | 0.307195 | 0.373231 |
Эти цифры очень близки к результатам, приведенным в статье. Здесь важно отметить, что потери и точность каждого токена в некоторой степени не связаны с показателем ROUGE. Потери не зависят от стратегии декодирования, тогда как показатель ROUGE сильно связан.
Поскольку ROUGE и BLEU обеспечивают лучшие потери или точность, чем человеческая оценка, вам следует сосредоточиться на них при построении моделей генерации текста, а также тщательно изучить и выбрать стратегии декодирования. Однако эти показатели далеки от совершенства, поэтому всегда следует учитывать человеческую оценку.
Теперь, когда у нас есть функция оценки, мы можем обучить нашу собственную сводную модель.
На этом этапе мы рассмотрели множество деталей суммирования и оценки текста, теперь мы используем эти знания для обучения пользовательской модели суммирования текста! Для нашего специального приложения мы будем использовать набор данных SAMSum, разработанный Samsung (часттпс://ореял.лу/н1ггд ), этот набор данных содержит серию разговоров и кратких обзоров. Эти разговоры могут отражать взаимодействие между клиентами и колл-центрами, создавая точные сводные данные, которые помогают улучшить обслуживание клиентов и выявить общие закономерности в запросах клиентов. Давайте сначала загрузим набор данных и просмотрим образец:
- # 从 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"])
(Примечание: вам может потребоваться установить py7zr, pip install py7zr)
результат операции:
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.
Разговоры выглядят так же, как если бы вы общались с помощью текстовых сообщений или WhatsApp, включая смайлы и заполнители для GIF-файлов. Поле диалога содержит полный текст, а поле сводки представляет собой краткое изложение диалога. Может ли модель, настроенная на наборе данных CNN/DailyMail, обрабатывать этот набор данных? Давайте взглянем!
Сначала мы запустим тот же процесс генерации сводки, используя PEGASUS, чтобы увидеть результат. Мы можем повторно использовать код, сгенерированный сводкой CNN/DailyMail:
- # 使用已加载的summarization管道对测试集中的第一个对话样本进行摘要
- pipe_out = pipe(dataset_samsum["test"][0]["dialogue"])
-
- # 打印生成的摘要标题
- print("Summary:")
-
- # 打印生成的摘要文本,并将每个句子的句号后面的空格替换为换行符
- # 这行代码会输出生成的摘要,其中 ". " 替换为 ".n" 使其更易读
- print(pipe_out[0]["summary_text"].replace(" .", ".n"))
результат операции:
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"
Мы видим, что модель в основном пытается подвести итог, извлекая ключевые предложения из разговора. Это может относительно хорошо работать с набором данных CNN/DailyMail, но в SAMSum сводка более абстрактна, и эффект не обязательно хороший. Мы можем подтвердить это, проведя полную оценку ROUGE на тестовом наборе:
- # 使用评估函数 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"])
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, результаты работы для справки с использованием примеров следующие)
румяна1 | румяна2 | rougeL | rougeLsum | |
пегас | 0.29617 | 0.087803 | 0.229604 | 0.229514 |
Хотя результаты невелики, это не является неожиданным, поскольку они далеки от распространения данных CNN/DailyMail. Тем не менее, настройка процесса оценки до обучения имеет два преимущества: мы можем напрямую использовать показатели для измерения успеха обучения, и у нас есть хороший базовый уровень. Точная настройка модели в нашем наборе данных должна немедленно улучшить метрику ROUGE. Если улучшения не происходит, мы знаем, что с нашим циклом обучения что-то не так.
Прежде чем мы приступим к обучению на данных, мы кратко рассмотрим распределения входных и выходных длин:
- # 编码训练集中的对话文本和摘要,并计算其长度
- 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()
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, результаты работы для справки с использованием примеров следующие)
Мы видим, что большинство разговоров намного короче, чем статьи CNN/DailyMail, и содержат от 100 до 200 токенов в каждом. Аналогичным образом, резюме намного короче, от 20 до 40 токенов (такой же длины, как средний твит).
Давайте сначала запомним эти результаты, мы воспользуемся ими позже. Во-первых, нам нужно токенизировать набор данных. Максимальную длину диалога и аннотации мы установили на 1024 и 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)
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
На этапе токенизации есть новая вещь: контекст tokenizer.as_target_tokenizer(). Некоторым моделям требуются специальные токены на входе декодера, поэтому важно разделить этапы токенизации для входов кодера и декодера. В операторе with (называемом менеджером контекста) токенизатор знает, что он выполняет токенизацию для декодера.
Теперь нам нужно создать органайзер данных. В большинстве случаев мы можем использовать сортировщик по умолчанию, который собирает все тензоры в пакет и просто складывает их. Для задачи суммирования нам нужно не только сложить входные данные, но и подготовить целевые значения на стороне декодера. PEGASUS представляет собой преобразователь кодер-декодер и поэтому имеет классическую архитектуру seq2seq. В настройке seq2seq общий подход заключается в применении принудительного воздействия преподавателя в декодере. При использовании этой стратегии декодер получает входные токены (так же, как модель только для декодера, например GPT-2), которые в дополнение к выходным данным кодера сдвигаются на одну позицию вправо за счет аннотации. Следовательно, при прогнозировании следующего токена декодер получит на вход истинное значение, сдвинутое на одну позицию вправо, как показано в следующей таблице:
- # 示例文本序列和标签生成过程
- 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')
результат операции:
шаг | декодер_вход | этикетка |
1 | [ПАД] | Трансформеры |
2 | [ПАД, Трансформеры] | являются |
3 | [PAD, Трансформеры, есть] | потрясающий |
4 | [PAD, Трансформеры, это, потрясающе] | для |
5 | [PAD, Трансформеры, это, потрясающе, для] | текст |
6 | [PAD, Трансформеры, потрясающие, для, текста] | резюмирование |
Мы перемещаем его на одну позицию вправо, чтобы декодер видел только предыдущую правильную аннотацию, а не текущие или будущие аннотации. Достаточно простого сдвига, потому что декодер имеет замаскированный механизм самоконтроля, который маскирует все текущие и будущие входные данные.
Поэтому при подготовке пакета мы задаем вход декодеру, перемещая аннотацию на одну позицию вправо. После этого мы гарантируем, что токены-заполнители в функции потерь игнорируются, установив для них значение -100 в аннотации. На самом деле нам не нужно выполнять эти шаги вручную, поскольку DataCollatorForSeq2Seq делает все это за нас:
- # 导入 Seq2Seq 数据集整理器模块
- from transformers import DataCollatorForSeq2Seq
-
- # 创建 Seq2Seq 数据集整理器实例
- seq2seq_data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
Затем, как обычно, настраиваем TrainingArguments для обучения:
- # 导入训练参数和训练器模块
- 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 # 梯度累积步数
- )
Отличие от предыдущих настроек в том, что на этот раз появился новый параметрgradient_accumulation_steps. Поскольку модель очень большая, нам необходимо установить размер пакета равным 1. Однако слишком малые размеры пакетов могут повлиять на сходимость. Чтобы решить эту проблему, мы можем использовать хитрый трюк, называемый накоплением градиента. Как следует из названия, вместо вычисления градиентов для всей партии сразу мы вычисляем и агрегируем градиенты по партиям. Когда мы агрегируем достаточное количество градиентов, мы запускаем этап оптимизации. Естественно, это медленнее, чем выполнение всего этого за один раз, но это экономит нам много памяти графического процессора.
Теперь мы входим в Hugging Face, чтобы после тренировки отправить модель в Hub:
- from huggingface_hub import notebook_login
-
- notebook_login()
результат операции:
Теперь у нас есть все необходимое для инициализации трейнера, включая модель, токенизатор, параметры обучения, организаторы данных, а также наборы данных для обучения и оценки:
- 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"] # 评估数据集
- )
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto)
Мы готовы тренироваться. После завершения обучения мы можем запустить функцию оценки непосредственно на тестовом наборе, чтобы увидеть, как работает модель:
- 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"])
результат операции:
(Временно об ошибке сообщается здесь:
TypeError: Couldn't build proto file into descriptor pool: duplicate file name sentencepiece_model.proto
, результаты работы для справки с использованием примеров следующие)
румяна1 | румяна2 | rougeL | rougeLsum | |
пегас | 0.42761 | 0.200571 | 0.340648 | 0.340738 |
Мы видим, что оценка ROUGE значительно улучшилась по сравнению с моделью без тонкой настройки, поэтому, хотя предыдущая модель также была обучена для генерации сводок, она не адаптировалась должным образом к новой области. Давайте отправим нашу модель в Hub:
- # 将训练完成的模型推送到 Hub 上
- trainer.push_to_hub("Training complete!")
Далее мы будем использовать эту модель для создания некоторых сводок.
Вы также можете оценить сгенерированные результаты в рамках цикла обучения: используйте расширение TrainingArguments под названием Seq2SeqTrainingArguments и укажите Predict_with_generate=True. Передайте это специальному тренеру под названием Seq2SeqTrainer, который использует функцию генерации() вместо прямого прохода модели для создания прогнозов для оценки. Попробуйте!
Глядя на потери и баллы ROUGE, кажется, что модель демонстрирует значительное улучшение по сравнению с исходной моделью, обученной только на CNN/DailyMail. Сводная информация, созданная на основе одного образца в тестовом наборе, выглядит следующим образом:
- 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"])
результат операции:
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.
Это очень похоже на справочное резюме. Похоже, модель научилась синтезировать разговоры в краткое изложение, а не просто извлекать отрывки. Теперь последний тест: как модель работает с пользовательскими входными данными?
- # 自定义对话示例
- 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"])
результат операции:
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.
Сгенерированное пользовательское резюме беседы имеет смысл. Он хорошо суммирует то, о чем все участники дискуссии хотели вместе написать книгу, а не просто извлекает одно предложение. Например, он объединяет строки 3 и 4 в одну логическую комбинацию.