diff --git a/chapters/ru/chapter0/1.mdx b/chapters/ru/chapter0/1.mdx index 6e42a9fc7..72fce3460 100644 --- a/chapters/ru/chapter0/1.mdx +++ b/chapters/ru/chapter0/1.mdx @@ -1,6 +1,6 @@ # Введение -Добро пожаловать на курс от Hugging Face! Это введение поможет настроить рабочее окружение. Если вы только начинаете курс, мы рекомендуем сначала заглянуть в [Главу 1](/course/ru/chapter1), затем вернуться и настроить среду, чтобы попробовать запустить код самостоятельно. +Добро пожаловать на курс от Hugging Face! Это введение поможет настроить рабочее окружение. Если вы только начинаете курс, мы рекомендуем сначала заглянуть в [Главу 1](../chapter1/1), затем вернуться и настроить среду, чтобы попробовать запустить код самостоятельно. Все библиотеки, которые мы будем использовать в этом курсе, доступны в качестве Python-пакетов. В этом уроке мы покажем, как установить окружение и необходимые библиотеки. diff --git a/chapters/ru/chapter2/1.mdx b/chapters/ru/chapter2/1.mdx index 47421460e..ce2dbae74 100644 --- a/chapters/ru/chapter2/1.mdx +++ b/chapters/ru/chapter2/1.mdx @@ -5,7 +5,7 @@ classNames="absolute z-10 right-0 top-0" /> -Как вы могли заметить в [Главе 1](/course/chapter1), модели трансформеров обычно бывают очень большие. Обучение и развертывание таких моделей с миллионами и даже десятками *миллиардов* параметров является сложной задачей. Кроме того, новые модели выпускаются почти ежедневно, и каждая из них имеет собственную реализацию, опробовать их все — непростая задача. +Как вы могли заметить в [Главе 1](../chapter1/1), модели трансформеров обычно бывают очень большие. Обучение и развертывание таких моделей с миллионами и даже десятками *миллиардов* параметров является сложной задачей. Кроме того, новые модели выпускаются почти ежедневно, и каждая из них имеет собственную реализацию, опробовать их все — непростая задача. Библиотека 🤗 Transformers была создана для решения этой проблемы. Её цель — предоставить единый API, с помощью которого можно загружать, обучать и сохранять любую модель трансформера. Основными функциями библиотеки являются: @@ -15,7 +15,7 @@ Последняя особенность сильно отличает библиотеку 🤗 Transformers от других библиотек машинного обучения. Модели не строятся на модулях, которые являются общими для всех файлов; вместо этого каждая модель имеет свои собственные слои. Это не только делает модели более доступными и понятными, но и позволяет легко экспериментировать с одной моделью, не затрагивая другие. -Эта глава начнается со сквозного примера, в котором мы используем модель и токенизатор вместе, чтобы воспроизвести функцию `pipeline()` представленную в [Главе 1](/course/chapter1). Далее мы обсудим API модели: углубимся в классы модели и конфигурации и покажем, как загружать модель и как она обрабатывает числовые входные данные для получения прогнозов. +Эта глава начнается со сквозного примера, в котором мы используем модель и токенизатор вместе, чтобы воспроизвести функцию `pipeline()` представленную в [Главе 1](../chapter1/1). Далее мы обсудим API модели: углубимся в классы модели и конфигурации и покажем, как загружать модель и как она обрабатывает числовые входные данные для получения прогнозов. Затем мы рассмотрим API токенизатора, который является другим основным компонентом функции `pipeline()`. Токенизаторы берут на себя первый и последний этапы обработки, обрабатывая преобразование текста в числовые входные данные для нейронной сети и обратное преобразование в текст, когда это необходимо. Наконец, мы покажем вам, как обработывается передача нескольких предложений в модель с помощью подготовленных пакетов, а затем завершим все это более детальным рассмотрением высокоуровневой функции `tokenizer()`. diff --git a/chapters/ru/chapter2/2.mdx b/chapters/ru/chapter2/2.mdx index ff5c6a630..3960afe39 100644 --- a/chapters/ru/chapter2/2.mdx +++ b/chapters/ru/chapter2/2.mdx @@ -32,7 +32,7 @@ {/if} -Давайте начнем с готового примера, взглянув на то, что происходило за кулисами, когда мы выполняли следующий код в [Главе 1](/course/chapter1): +Давайте начнем с готового примера, взглянув на то, что происходило за кулисами, когда мы выполняли следующий код в [Главе 1](../chapter1/1): ```python from transformers import pipeline @@ -53,7 +53,7 @@ classifier( {'label': 'NEGATIVE', 'score': 0.9994558095932007}] ``` -Как мы уже увидели в [Главе 1](/course/chapter1), данный конвейер включает в себя три шага: предварительная обработка, передача входных данных через модель и постобработка: +Как мы уже увидели в [Главе 1](../chapter1/1), данный конвейер включает в себя три шага: предварительная обработка, передача входных данных через модель и постобработка:
Полный конвейер NLP: токенизация текста, преобразование в идентификаторы и вывод с помощью модели Transformer и слоя 'head' модели. @@ -176,7 +176,7 @@ model = TFAutoModel.from_pretrained(checkpoint) Если вы пока не понимаете в чем смысл, не беспокойтесь об этом. Мы объясним все это позже. -Хотя эти скрытые состояния могут быть полезны сами по себе, они обычно являются входными данными для другой части модели, известной как слой *head*. В [Главе 1](/course/chapter1) разные задачи могли бы выполняться с одной и той же архитектурой, но с каждой из этих задач будет связан отдельный слой "head". +Хотя эти скрытые состояния могут быть полезны сами по себе, они обычно являются входными данными для другой части модели, известной как слой *head*. В [Главе 1](../chapter1/1) разные задачи могли бы выполняться с одной и той же архитектурой, но с каждой из этих задач будет связан отдельный слой "head". ### Многомерный вектор, что это? diff --git a/chapters/ru/chapter2/3.mdx b/chapters/ru/chapter2/3.mdx index 41d226813..b7e941ac4 100644 --- a/chapters/ru/chapter2/3.mdx +++ b/chapters/ru/chapter2/3.mdx @@ -112,7 +112,7 @@ model = TFBertModel(config) ``` {/if} -Модель можно использовать в этом состоянии, но она будет выводить тарабарщину; сначала ее нужно обучить. Мы могли бы обучить модель с нуля для решения поставленной задачи, но, как вы видели в [Главе 1](/course/chapter1), это потребовало бы много времени и большого количества данных, а также имело бы значительное воздействие на окружающую среду. Чтобы избежать ненужных и дублирующих усилий, крайне важно иметь возможность делиться и повторно использовать модели, которые уже были обучены. +Модель можно использовать в этом состоянии, но она будет выводить тарабарщину; сначала ее нужно обучить. Мы могли бы обучить модель с нуля для решения поставленной задачи, но, как вы видели в [Главе 1](../chapter1/1), это потребовало бы много времени и большого количества данных, а также имело бы значительное воздействие на окружающую среду. Чтобы избежать ненужных и дублирующих усилий, крайне важно иметь возможность делиться и повторно использовать модели, которые уже были обучены. Загрузить уже обученную модель Transformer очень просто — мы можем сделать это с помощью метода `from_pretrained()`: diff --git a/chapters/ru/chapter3/1.mdx b/chapters/ru/chapter3/1.mdx index 476152eb3..953a2bd45 100644 --- a/chapters/ru/chapter3/1.mdx +++ b/chapters/ru/chapter3/1.mdx @@ -7,7 +7,7 @@ classNames="absolute z-10 right-0 top-0" /> -В [главе 2](/course/ru/chapter2) мы увидели, как можно использовать токенизаторы и предобученные модели для построения предсказаний. Но что если мы хотим дообучить предобученную модель на собственном датасете? Это и есть тема данной главы! Мы изучим: +В [главе 2](../chapter2/1) мы увидели, как можно использовать токенизаторы и предобученные модели для построения предсказаний. Но что если мы хотим дообучить предобученную модель на собственном датасете? Это и есть тема данной главы! Мы изучим: {#if fw === 'pt'} * Как подготовить большой датасет из Model Hub diff --git a/chapters/ru/chapter3/2.mdx b/chapters/ru/chapter3/2.mdx index dc8c83f24..4c791b475 100644 --- a/chapters/ru/chapter3/2.mdx +++ b/chapters/ru/chapter3/2.mdx @@ -23,7 +23,7 @@ {/if} {#if fw === 'pt'} -Продолжим с примером из [предыдущей главы](/course/ru/chapter2), вот как мы будем обучать классификатор последовательности на одном батче с помощью PyTorch: +Продолжим с примером из [предыдущей главы](../chapter2/1), вот как мы будем обучать классификатор последовательности на одном батче с помощью PyTorch: ```python import torch @@ -48,7 +48,7 @@ loss.backward() optimizer.step() ``` {:else} -Continuing with the example from the [previous chapter](/course/ru/chapter2), вот как мы будем обучать классификатор последовательности на одном батче с помощью TensorFlow: +Continuing with the example from the [previous chapter](../chapter2/1), вот как мы будем обучать классификатор последовательности на одном батче с помощью TensorFlow: ```python import tensorflow as tf @@ -159,7 +159,7 @@ raw_train_dataset.features {/if} -Чтобы предобработать датасет, нам необходимо конвертировать текст в числа, которые может обработать модель. Как вы видели в [предыдущей главе](/course/ru/chapter2), это делается с помощью токенайзера. Мы можем подать на вход токенайзеру одно или список предложений, т.е. можно токенизировать предложения попарно таким образом: +Чтобы предобработать датасет, нам необходимо конвертировать текст в числа, которые может обработать модель. Как вы видели в [предыдущей главе](../chapter2/1), это делается с помощью токенайзера. Мы можем подать на вход токенайзеру одно или список предложений, т.е. можно токенизировать предложения попарно таким образом: ```py from transformers import AutoTokenizer @@ -185,7 +185,7 @@ inputs } ``` -Мы уже обсуждали ключи `input_ids` и `attention_mask` в [главе 2](/course/ru/chapter2), но не упоминали о `token_type_ids`. В этом примере мы указываем модели какая часть входных данных является первым предложением, а какая вторым. +Мы уже обсуждали ключи `input_ids` и `attention_mask` в [главе 2](../chapter2/1), но не упоминали о `token_type_ids`. В этом примере мы указываем модели какая часть входных данных является первым предложением, а какая вторым. @@ -216,13 +216,13 @@ tokenizer.convert_ids_to_tokens(inputs["input_ids"]) Обратите внимание, что если вы выберете другой чекпоинт, `token_type_ids` необязательно будут присутствовать в ваших токенизированных входных данных (например, они не возвращаются, если вы используете модель DistilBERT). Они возвращаются только тогда, когда модель будет знать, что с ними делать, потому что она видела их во время предобучения. -В данном случае BERT был обучен с информацией о идентификаторах типов токенов, и помимо задачи маскированной языковой модели, о которой мы говорили в [главе 1](/course/ru/chapter1), он может решать еще одну задачу: предсказание следующего предложения (_next sentence prediction_). Суть этой задачи - смоделировать связь между предложениями. +В данном случае BERT был обучен с информацией о идентификаторах типов токенов, и помимо задачи маскированной языковой модели, о которой мы говорили в [главе 1](../chapter1/1), он может решать еще одну задачу: предсказание следующего предложения (_next sentence prediction_). Суть этой задачи - смоделировать связь между предложениями. В этой задаче модели на вход подаются пары предложений (со случайно замаскированными токенами), от модели требуется предсказать, является ли следующее предложение продолжением текущего. Чтобы задача не была слишком тривиальной, половина времени модель обучается на соседних предложениях из одного документа, другую половину на парах предложений, взятых из разных источников. В общем случае вам не нужно беспокоиться о наличии `token_type_ids` в ваших токенизированных данных: пока вы используете одинаковый чекпоинт и для токенизатора, и для модели – токенизатор будет знать, как нужно обработать данные. -Теперь мы знаем, что токенизатор может подготовить сразу пару предложений, а значит мы можем использовать его для целого датасета: так же как и в [предыдущей главе](/course/ru/chapter2) можно подать на вход токенизатору список первых предложений и список вторых предложений. Это также сработает и для механизмов дополнения (padding) и усечения до максимальной длины (truncation) - об этом мы говорили в [главе 2](/course/chapter2). Итак, один из способов предобработать обучающий датасет такой: +Теперь мы знаем, что токенизатор может подготовить сразу пару предложений, а значит мы можем использовать его для целого датасета: так же как и в [предыдущей главе](../chapter2/1) можно подать на вход токенизатору список первых предложений и список вторых предложений. Это также сработает и для механизмов дополнения (padding) и усечения до максимальной длины (truncation) - об этом мы говорили в [главе 2](../chapter2). Итак, один из способов предобработать обучающий датасет такой: ```py tokenized_dataset = tokenizer( diff --git a/chapters/ru/chapter3/3.mdx b/chapters/ru/chapter3/3.mdx index 8da9c30d1..4f00a73b3 100644 --- a/chapters/ru/chapter3/3.mdx +++ b/chapters/ru/chapter3/3.mdx @@ -45,11 +45,11 @@ training_args = TrainingArguments("test-trainer") -💡 Если вы хотите автоматически загружать модель на Hub во время обучения, передайте аргумент `push_to_hub=True` в `TrainingArguments`. Мы больше узнаем об этом в главе [Chapter 4](/course/chapter4/3). +💡 Если вы хотите автоматически загружать модель на Hub во время обучения, передайте аргумент `push_to_hub=True` в `TrainingArguments`. Мы больше узнаем об этом в [главе 4](../chapter4/3). -Второй шаг – задание модели. Так же, как и в [предыдущей главе](/course/chapter2), мы будем использовать класс `AutoModelForSequenceClassification` с двумя лейблами: +Второй шаг – задание модели. Так же, как и в [предыдущей главе](../chapter2/1), мы будем использовать класс `AutoModelForSequenceClassification` с двумя лейблами: ```py from transformers import AutoModelForSequenceClassification @@ -57,7 +57,7 @@ from transformers import AutoModelForSequenceClassification model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2) ``` -После создания экземпляра предобученной модели будет распечатано предупреждение (в [главе 2](/course/chapter2) мы с таким не сталкивались). Это происходит потому, что BERT не был предобучен для задачи классификации пар предложений, его последний слой не будет использован, вместо него будет добавлен слой, позволяющий работать с такой задачей. Предупреждения сообщают, что некоторые веса не будут использованы (как раз тех слоев, которые не будут использоваться) и для новых будут инициализированы случайные веса. В заключении предлагается обучить модель, что мы и сделаем прямо сейчас. +После создания экземпляра предобученной модели будет распечатано предупреждение (в [главе 2](../chapter2/1) мы с таким не сталкивались). Это происходит потому, что BERT не был предобучен для задачи классификации пар предложений, его последний слой не будет использован, вместо него будет добавлен слой, позволяющий работать с такой задачей. Предупреждения сообщают, что некоторые веса не будут использованы (как раз тех слоев, которые не будут использоваться) и для новых будут инициализированы случайные веса. В заключении предлагается обучить модель, что мы и сделаем прямо сейчас. После того, как мы загрузили модель, мы можем определить `Trainer` и передать туда нужные объекты: `model`, `training_args`, обучающую и валидационную выборки, `data_collator` и `tokenizer` @@ -105,7 +105,7 @@ print(predictions.predictions.shape, predictions.label_ids.shape) Результат функции `predict()` - другой именованный кортеж с полями `predictions`, `label_ids` и `metrics`. Поле `metrics` будет содержать значение лосса на нашем датасете и значения метрик. После реализации функции `compute_metrics()` и передачи ее в `Trainer` поле `metrics` также будет содержать результат функции `compute_metrics()`. -Как можно заметить, `predictions` - массив 408 х 2 (408 - число элементов в датасете, который мы использовали). Это логиты для каждого элемента нашего датасета, переданного в `predict()` (как вы видели в [предыдущей главе](/course/chapter2) все модели Трансформеров возвращают логиты). Чтобы превратить их в предсказания и сравнить с нашими лейблами, нам необходимо узнать индекс максимального элемента второй оси: +Как можно заметить, `predictions` - массив 408 х 2 (408 - число элементов в датасете, который мы использовали). Это логиты для каждого элемента нашего датасета, переданного в `predict()` (как вы видели в [предыдущей главе](../chapter2/1) все модели Трансформеров возвращают логиты). Чтобы превратить их в предсказания и сравнить с нашими лейблами, нам необходимо узнать индекс максимального элемента второй оси: ```py import numpy as np diff --git a/chapters/ru/chapter3/3_tf.mdx b/chapters/ru/chapter3/3_tf.mdx index 92b68b191..bbe24dee5 100644 --- a/chapters/ru/chapter3/3_tf.mdx +++ b/chapters/ru/chapter3/3_tf.mdx @@ -58,7 +58,7 @@ tf_validation_dataset = tokenized_datasets["validation"].to_tf_dataset( -Как и в [предыдущей главе](/course/ru/chapter2), мы будем использовать класс `TFAutoModelForSequenceClassification` с двумя метками: +Как и в [предыдущей главе](../chapter2/1), мы будем использовать класс `TFAutoModelForSequenceClassification` с двумя метками: ```py from transformers import TFAutoModelForSequenceClassification @@ -66,7 +66,7 @@ from transformers import TFAutoModelForSequenceClassification model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2) ``` -Вы заметите, что в отличие от [Главы 2](/course/ru/chapter2), вы получаете предупреждение после создания экземпляра этой предварительно обученной модели. Это связано с тем, что BERT не был предварительно обучен классификации пар предложений, поэтому последний слой предварительно обученной модели был отброшен, а вместо него был вставлен новый слой, подходящий для классификации последовательностей. Предупреждения указывают на то, что некоторые веса не использовались (те, которые соответствуют удаленным слоям), а некоторые другие были инициализированы случайным образом (те, что для новых слоев). В заключение предлагается обучить модель, что мы и собираемся сделать сейчас. +Вы заметите, что в отличие от [Главы 2](../chapter2/1), вы получаете предупреждение после создания экземпляра этой предварительно обученной модели. Это связано с тем, что BERT не был предварительно обучен классификации пар предложений, поэтому последний слой предварительно обученной модели был отброшен, а вместо него был вставлен новый слой, подходящий для классификации последовательностей. Предупреждения указывают на то, что некоторые веса не использовались (те, которые соответствуют удаленным слоям), а некоторые другие были инициализированы случайным образом (те, что для новых слоев). В заключение предлагается обучить модель, что мы и собираемся сделать сейчас. Чтобы точно настроить модель в нашем наборе данных, нам просто нужно вызвать `compile()` у нашей модели, а затем передать наши данные в метод `fit()`. Это запустит процесс fine tuning (который должен занять пару минут на графическом процессоре) и сообщит о значениях функции потерь при обучении, а также о значениях функции потерь на валидации. @@ -147,7 +147,7 @@ model.fit(tf_train_dataset, validation_data=tf_validation_dataset, epochs=3) -💡 Если вы хотите автоматически загружать свою модель на Hub во время обучения, вы можете передать `PushToHubCallback` в метод `model.fit()`. Мы узнаем об этом больше в [Chapter 4](/course/chapter4/3). +💡 Если вы хотите автоматически загружать свою модель на Hub во время обучения, вы можете передать `PushToHubCallback` в метод `model.fit()`. Мы узнаем об этом больше в [Главе 4](../chapter4/3). @@ -188,4 +188,4 @@ metric.compute(predictions=class_preds, references=raw_datasets["validation"]["l Точные результаты, которые вы получите, могут отличаться, так как случайная инициализация параметров выходных слоев модели может изменить показатели. Здесь мы видим, что наша модель имеет точность 85,78% на валидационном наборе и оценку F1 89,97. Это две метрики, используемые для оценки результатов датасета MRPC для теста GLUE. В таблице в [документации BERT] (https://arxiv.org/pdf/1810.04805.pdf) сообщается о балле F1 88,97% для базовой модели. Это была модель, которая не чувствительна к регистру текста, в то время как сейчас мы используем модель, учитывающую регистр, что и объясняет лучший результат. -На этом введение в fine tuning с помощью Keras API завершено. Пример выполнения этого для наиболее распространенных задач NLP будет дан в [Главе 7](/course/ru/chapter7). Если вы хотите отточить свои навыки работы с Keras API, попробуйте точно настроить модель в наборе данных GLUE SST-2, используя обработку данных, которую вы выполнили в разделе 2. +На этом введение в fine tuning с помощью Keras API завершено. Пример выполнения этого для наиболее распространенных задач NLP будет дан в [Главе 7](../chapter7). Если вы хотите отточить свои навыки работы с Keras API, попробуйте точно настроить модель в наборе данных GLUE SST-2, используя обработку данных, которую вы выполнили в разделе 2. diff --git a/chapters/ru/chapter4/3.mdx b/chapters/ru/chapter4/3.mdx index d737fd07a..3a7fbf507 100644 --- a/chapters/ru/chapter4/3.mdx +++ b/chapters/ru/chapter4/3.mdx @@ -50,7 +50,7 @@ Простейший путь загрузки файлов на Hub – `push_to_hub` API. -Перед тем, как пойдем дальше, необходимо сгенерировать токен аутентификации. Это необходимо сделать для того, чтобы `huggingface_hub` API «узнал» вас и предоставил вам необходимые права на запись. Убедитесь, что вы находитесь в окружении, в котором установлена библиотека `transformers` (см. [Установка](/course/ru/chapter0)). Если вы работаете в Jupyter'е, вы можете использовать следующую функцию для авторизации: +Перед тем, как пойдем дальше, необходимо сгенерировать токен аутентификации. Это необходимо сделать для того, чтобы `huggingface_hub` API «узнал» вас и предоставил вам необходимые права на запись. Убедитесь, что вы находитесь в окружении, в котором установлена библиотека `transformers` (см. [Установка](../chapter0)). Если вы работаете в Jupyter'е, вы можете использовать следующую функцию для авторизации: ```python from huggingface_hub import notebook_login diff --git a/chapters/ru/chapter5/1.mdx b/chapters/ru/chapter5/1.mdx index ff8429d6a..911a94fa8 100644 --- a/chapters/ru/chapter5/1.mdx +++ b/chapters/ru/chapter5/1.mdx @@ -1,6 +1,6 @@ # Введение -В [главе 3](/course/ru/chapter3) вы поверхностно ознакомились с библиотекой 🤗 Datasets и увидели три главных шага для использования ее в процессе fine-tuning: +В [главе 3](../chapter3/1) вы поверхностно ознакомились с библиотекой 🤗 Datasets и увидели три главных шага для использования ее в процессе fine-tuning: 1. Загрузить датасет из Hugging Face Hub. 2. Произвести препроцессинг с помощью `Dataset.map()`. @@ -14,4 +14,4 @@ * Что, черт возьми, такое «отображение памяти» (memory mapping) и Apache Arrow? * Как вы можете создать свой собственный датасет и отправить его в Hub? -Принципы, которые вы изучите в этой главе, подготовят вас к более глубокому использованию токенизации и fine-tuning'а моделей в [главе 6](/course/ru/chapter6) и [главе 7](/course/ru/chapter7) – заваривайте кофе и мы начинаем! \ No newline at end of file +Принципы, которые вы изучите в этой главе, подготовят вас к более глубокому использованию токенизации и fine-tuning'а моделей в [главе 6](../chapter6) и [главе 7](../chapter7) – заваривайте кофе и мы начинаем! \ No newline at end of file diff --git a/chapters/ru/chapter5/3.mdx b/chapters/ru/chapter5/3.mdx index 378b05e24..2b1fded9c 100644 --- a/chapters/ru/chapter5/3.mdx +++ b/chapters/ru/chapter5/3.mdx @@ -13,7 +13,7 @@ ## Управление данными -Как и в Pandas, 🤗 Datasets предоставляет несколько функция для управления содержимым объектов `Dataset` и `DatasetDict`. Мы уже познакомились с методом `Dataset.map()` в [главе 3](/course/ru/chapter3), а далее мы посмотрим на другие функции, имеющиеся в нашем распоряжении. +Как и в Pandas, 🤗 Datasets предоставляет несколько функция для управления содержимым объектов `Dataset` и `DatasetDict`. Мы уже познакомились с методом `Dataset.map()` в [главе 3](../chapter3/1), а далее мы посмотрим на другие функции, имеющиеся в нашем распоряжении. Для этого примера мы будем использовать датасет [Drug Review Dataset](https://archive.ics.uci.edu/ml/datasets/Drug+Review+Dataset+%28Drugs.com%29), расположенный на сервере [UC Irvine Machine Learning Repository](https://archive.ics.uci.edu/ml/index.php) и содержащий отзывы пациентов на различные лекарства, сведения о состоянии пациентов и рейтинг удовлетворенности, выраженный в 10-балльной шкале. @@ -95,7 +95,7 @@ DatasetDict({ -Далее нормализуем все лейблы столбца `condition` с применением `Dataset.map()`. Так же, как мы делали токенизацию в [главе 3](/course/ru/chapter3), мы можем определить простую функцию, которая будет применения для всех строк каждого сплита в `drug_dataset`: +Далее нормализуем все лейблы столбца `condition` с применением `Dataset.map()`. Так же, как мы делали токенизацию в [главе 3](../chapter3/1), мы можем определить простую функцию, которая будет применения для всех строк каждого сплита в `drug_dataset`: ```py def lowercase_condition(example): @@ -277,7 +277,7 @@ new_drug_dataset = drug_dataset.map( Если вы запустите этот код в блокноте, вы увидите, что эта команда выполняется намного быстрее, чем предыдущая. И это не потому, что наши отзывы уже были HTML-экранированными — если вы повторно выполните инструкцию из предыдущего раздела (без `batched=True`), это займет столько же времени, сколько и раньше. Это связано с тем, что обработка списков обычно выполняется быстрее, чем выполнение того же кода в цикле `for`, мы также повышаем производительность за счет одновременного доступа к множеству элементов, а не по одному. -Использование `Dataset.map()` с `batched=True` – хороший способ «разблокировать» скоростные ограничения "быстрых" токенизаторов, с которыми мы познакомимся в [главе 6](/course/chapter6), которые могут быстро токенизировать большие списки текста. Например, чтобы токенизировать все отзывы на лекарства с помощью быстрого токенизатора, мы можем использовать функцию, подобную этой: +Использование `Dataset.map()` с `batched=True` – хороший способ «разблокировать» скоростные ограничения "быстрых" токенизаторов, с которыми мы познакомимся в [главе 6](../chapter6), которые могут быстро токенизировать большие списки текста. Например, чтобы токенизировать все отзывы на лекарства с помощью быстрого токенизатора, мы можем использовать функцию, подобную этой: ```python from transformers import AutoTokenizer @@ -289,7 +289,7 @@ def tokenize_function(examples): return tokenizer(examples["review"], truncation=True) ``` -Как вы видели в [главе 3](/course/ru/chapter3), мы можем передать один или несколько элементов в токенизатор, так что мы можем использовать эту функцию без параметра `batched=True`. Давайте воспользуемся этой возможностью и сравним производительность. В ноутбуке можно замерить время выполнения функции путем добавления `%time` перед строкой кода, время исполнения которой вы хотите измерить: +Как вы видели в [главе 3](../chapter3/1), мы можем передать один или несколько элементов в токенизатор, так что мы можем использовать эту функцию без параметра `batched=True`. Давайте воспользуемся этой возможностью и сравним производительность. В ноутбуке можно замерить время выполнения функции путем добавления `%time` перед строкой кода, время исполнения которой вы хотите измерить: ```python no-format %time tokenized_dataset = drug_dataset.map(tokenize_function, batched=True) @@ -344,7 +344,7 @@ Options | Fast tokenizer | Slow tokenizer -Объединение всей этой функциональности во всего лишь один метод само по себе прекрасно, но это еще не все! Используя `Dataset.map()` и `batched=True` вы можете поменять число элементов в датасете. Это очень полезно во множестве ситуаций, например, когда вы хотите создать несколько обучающих признаков из одного экземпляра текста. Мы воспользуеся этой возможностью на этапе препроцессинга для нескольких NLP-задач, которые рассмотрим в [главе 7](/course/ru/chapter7) +Объединение всей этой функциональности во всего лишь один метод само по себе прекрасно, но это еще не все! Используя `Dataset.map()` и `batched=True` вы можете поменять число элементов в датасете. Это очень полезно во множестве ситуаций, например, когда вы хотите создать несколько обучающих признаков из одного экземпляра текста. Мы воспользуеся этой возможностью на этапе препроцессинга для нескольких NLP-задач, которые рассмотрим в [главе 7](../chapter7) @@ -641,7 +641,7 @@ DatasetDict({ }) ``` -Отлично, теперь мы подготовили датасет, на котором можно обучить некоторые модели. В [разделе 5](/course/ru/chapter5/5) мы покажем, как загрузить датасеты на Hugging Face Hub, а пока закончим наш обзор и посмотрим несколько способов сохранения датасетов на локальный компьютер. +Отлично, теперь мы подготовили датасет, на котором можно обучить некоторые модели. В [разделе 5](../chapter5/5) мы покажем, как загрузить датасеты на Hugging Face Hub, а пока закончим наш обзор и посмотрим несколько способов сохранения датасетов на локальный компьютер. ## Сохранение датасетов @@ -727,7 +727,7 @@ for split, dataset in drug_dataset_clean.items(): {"patient_id":141780,"drugName":"Escitalopram","condition":"depression","review":"\"I seemed to experience the regular side effects of LEXAPRO, insomnia, low sex drive, sleepiness during the day. I am taking it at night because my doctor said if it made me tired to take it at night. I assumed it would and started out taking it at night. Strange dreams, some pleasant. I was diagnosed with fibromyalgia. Seems to be helping with the pain. Have had anxiety and depression in my family, and have tried quite a few other medications that haven't worked. Only have been on it for two weeks but feel more positive in my mind, want to accomplish more in my life. Hopefully the side effects will dwindle away, worth it to stick with it from hearing others responses. Great medication.\"","rating":9.0,"date":"May 29, 2011","usefulCount":10,"review_length":125} ``` -Мы можем использовать приёмы из [раздела 2](/course/ru/chapter5/2) для загрузки JSON-файлов: +Мы можем использовать приёмы из [раздела 2](../chapter5/2) для загрузки JSON-файлов: ```py data_files = { @@ -740,8 +740,8 @@ drug_dataset_reloaded = load_dataset("json", data_files=data_files) Вот и все, что нужно для нашего экскурса при работе с 🤗 Datasets! Мы очистили датасет для обучения модели, вот некоторые идеи, которые вы могли бы реализовать самостоятельно: -1. Примените знания из [раздела 3](/course/ru/chapter3) для обучения классификатора, который может предсказывать состояние пациента по отзыву на лекарство. -2. Используйте pipeline `summarization` из [раздела 1](/course/ru/chapter1)для генерации саммари отзывов. +1. Примените знания из [раздела 3](../chapter3/1) для обучения классификатора, который может предсказывать состояние пациента по отзыву на лекарство. +2. Используйте pipeline `summarization` из [раздела 1](../chapter1/1)для генерации саммари отзывов. Далее мы посмотрим, как 🤗 Datasets могут помочь вам в работе с громадными датасетами, которые _невозможно_ обработать на вашем ноутбуке! diff --git a/chapters/ru/chapter5/4.mdx b/chapters/ru/chapter5/4.mdx index d96ca1b35..e9a6d32e9 100644 --- a/chapters/ru/chapter5/4.mdx +++ b/chapters/ru/chapter5/4.mdx @@ -23,7 +23,7 @@ The Pile — это корпус текстов на английском язы !pip install zstandard ``` -Затем мы можем загрузить набор данных, используя метод для подгрузки файлов, который мы изучили в [разделе 2](/course/ru/chapter5/2): +Затем мы можем загрузить набор данных, используя метод для подгрузки файлов, который мы изучили в [разделе 2](../chapter5/2): ```py from datasets import load_dataset @@ -157,7 +157,7 @@ next(iter(pubmed_dataset_streamed)) 'text': 'Epidemiology of hypoxaemia in children with acute lower respiratory infection.\nTo determine the prevalence of hypoxaemia in children aged under 5 years suffering acute lower respiratory infections (ALRI), the risk factors for hypoxaemia in children under 5 years of age with ALRI, and the association of hypoxaemia with an increased risk of dying in children of the same age ...'} ``` -Элементы из потокового набора данных можно обрабатывать на лету с помощью `IterableDataset.map()`, что полезно во время обучения, если вам нужно токенизировать входные данные. Процесс точно такой же, как тот, который мы использовали для токенизации нашего набора данных в [Главе 3] (/course/ru/chapter3), с той лишь разницей, что выходные данные возвращаются один за другим: +Элементы из потокового набора данных можно обрабатывать на лету с помощью `IterableDataset.map()`, что полезно во время обучения, если вам нужно токенизировать входные данные. Процесс точно такой же, как тот, который мы использовали для токенизации нашего набора данных в [Главе 3](../chapter3/1), с той лишь разницей, что выходные данные возвращаются один за другим: ```py from transformers import AutoTokenizer diff --git a/chapters/ru/chapter5/6.mdx b/chapters/ru/chapter5/6.mdx index b238ba8a9..7488f6cda 100644 --- a/chapters/ru/chapter5/6.mdx +++ b/chapters/ru/chapter5/6.mdx @@ -22,13 +22,13 @@ {/if} -В [разделе 5](/course/ru/chapter5/5) мы создали набор данных о issues и комментариях GitHub из репозитория 🤗 Datasets. В этом разделе мы будем использовать эту информацию для создания поисковой системы, которая поможет нам найти ответы на самые насущные вопросы о библиотеке! +В [разделе 5](../chapter5/5) мы создали набор данных о issues и комментариях GitHub из репозитория 🤗 Datasets. В этом разделе мы будем использовать эту информацию для создания поисковой системы, которая поможет нам найти ответы на самые насущные вопросы о библиотеке! ## Использование эмбеддингов для семанического поиска -Как мы видели в [Главе 1](/course/ru/chapter1), языковые модели на основе Transformer представляют каждую лексему в текстовом фрагменте как _эмбеддинг-вектор_. Оказывается, можно «объединить» отдельные вложения, чтобы создать векторное представление для целых предложений, абзацев или (в некоторых случаях) документов. Затем эти вложения можно использовать для поиска похожих документов в корпусе путем вычисления скалярного произведения (или какой-либо другой метрики сходства) между каждым вложением и возврата документов с наибольшим перекрытием. +Как мы видели в [Главе 1](../chapter1/1), языковые модели на основе Transformer представляют каждую лексему в текстовом фрагменте как _эмбеддинг-вектор_. Оказывается, можно «объединить» отдельные вложения, чтобы создать векторное представление для целых предложений, абзацев или (в некоторых случаях) документов. Затем эти вложения можно использовать для поиска похожих документов в корпусе путем вычисления скалярного произведения (или какой-либо другой метрики сходства) между каждым вложением и возврата документов с наибольшим перекрытием. В этом разделе мы будем использовать вложения для разработки семантической поисковой системы. Эти поисковые системы предлагают несколько преимуществ по сравнению с традиционными подходами, основанными на сопоставлении ключевых слов в запросе с документами. @@ -51,7 +51,7 @@ data_files = hf_hub_url( ) ``` -С URL-адресом, сохраненным в `data_files`, мы можем загрузить удаленный набор данных, используя метод, представленный в [раздел 2](/course/ru/chapter5/2): +С URL-адресом, сохраненным в `data_files`, мы можем загрузить удаленный набор данных, используя метод, представленный в [раздел 2](../chapter5/2): ```py from datasets import load_dataset @@ -236,7 +236,7 @@ comments_dataset = comments_dataset.map(concatenate_text) ## Создание текстовых эмбединнгов -В [Главе 2](/course/ru/chapter2) мы видели, что можно получить эмбеддингов токенов с помощью класса AutoModel. Все, что нам нужно сделать, это выбрать подходящую контрольную точку для загрузки модели. К счастью, есть библиотека под названием `sentence-transformers`, предназначенная для создания эмбеддингов. Как описано в [документации](https://www.sbert.net/examples/applications/semantic-search/README.html#симметричный-vs-асимметричный-semantic-search) библиотеки, наш вариант использования является примером _асимметричного семантического поиска_ потому что у нас есть короткий запрос, ответ на который мы хотели бы найти в более длинном документе, например, в комментарии к проблеме. В удобной [таблице обзора модели](https://www.sbert.net/docs/pretrained_models.html#model-overview) в документации указано, что контрольная точка `multi-qa-mpnet-base-dot-v1` имеет лучшую производительность для семантического поиска, поэтому мы будем использовать её для нашего приложения. Мы также загрузим токенизатор, используя ту же контрольную точку: +В [Главе 2](../chapter2/1) мы видели, что можно получить эмбеддингов токенов с помощью класса AutoModel. Все, что нам нужно сделать, это выбрать подходящую контрольную точку для загрузки модели. К счастью, есть библиотека под названием `sentence-transformers`, предназначенная для создания эмбеддингов. Как описано в [документации](https://www.sbert.net/examples/applications/semantic-search/README.html#симметричный-vs-асимметричный-semantic-search) библиотеки, наш вариант использования является примером _асимметричного семантического поиска_ потому что у нас есть короткий запрос, ответ на который мы хотели бы найти в более длинном документе, например, в комментарии к проблеме. В удобной [таблице обзора модели](https://www.sbert.net/docs/pretrained_models.html#model-overview) в документации указано, что контрольная точка `multi-qa-mpnet-base-dot-v1` имеет лучшую производительность для семантического поиска, поэтому мы будем использовать её для нашего приложения. Мы также загрузим токенизатор, используя ту же контрольную точку: {#if fw === 'pt'} diff --git a/chapters/ru/chapter5/7.mdx b/chapters/ru/chapter5/7.mdx index d40c7f871..687891774 100644 --- a/chapters/ru/chapter5/7.mdx +++ b/chapters/ru/chapter5/7.mdx @@ -13,4 +13,4 @@ - Создавать свой собственный набор данных и отправлять его в Hugging Face Hub. - Строить свои эмбеддинги документов с помощью модели Transformer и создавать семантический поисковик с помощью FAISS. -В [Главе 7](/course/ru/chapter7) мы будем использовать все это с пользой, поскольку мы углубимся в основные задачи NLP, для которых отлично подходят модели Transformer. Однако, прежде чем идти вперед, проверьте свои знания о 🤗 Datasets с помощью быстрого теста! +В [Главе 7](../chapter7) мы будем использовать все это с пользой, поскольку мы углубимся в основные задачи NLP, для которых отлично подходят модели Transformer. Однако, прежде чем идти вперед, проверьте свои знания о 🤗 Datasets с помощью быстрого теста! diff --git a/chapters/ru/chapter6/1.mdx b/chapters/ru/chapter6/1.mdx index 93525db9d..3aaeb428a 100644 --- a/chapters/ru/chapter6/1.mdx +++ b/chapters/ru/chapter6/1.mdx @@ -5,7 +5,7 @@ classNames="absolute z-10 right-0 top-0" /> -В [Главе 3](/course/chapter3) мы рассмотрели, как дообучить модель для конкретной задачи. При этом мы используем тот же токенизатор, на котором была предварительно обучена модель, но что делать, когда мы хотим обучить модель с нуля? В таких случаях использование токенизатора, который был предварительно обучен на корпусе из другой области или языка, как правило, является неоптимальным. Например, токенизатор, обученный на корпусе английских текстов, будет плохо работать на корпусе японских текстов, поскольку использование пробелов и знаков препинания в этих двух языках сильно отличается. +В [Главе 3](../chapter3/1) мы рассмотрели, как дообучить модель для конкретной задачи. При этом мы используем тот же токенизатор, на котором была предварительно обучена модель, но что делать, когда мы хотим обучить модель с нуля? В таких случаях использование токенизатора, который был предварительно обучен на корпусе из другой области или языка, как правило, является неоптимальным. Например, токенизатор, обученный на корпусе английских текстов, будет плохо работать на корпусе японских текстов, поскольку использование пробелов и знаков препинания в этих двух языках сильно отличается. В этой главе вы узнаете, как обучить совершенно новый токенизатор на корпусе текстов, чтобы затем использовать его для предварительного обучения языковой модели. Все это будет сделано с помощью библиотеки [🤗 Tokenizers](https://github.com/huggingface/tokenizers), которая предоставляет "быстрые" токенизаторы в библиотеке [🤗 Transformers](https://github.com/huggingface/transformers). Мы подробно рассмотрим возможности, которые предоставляет эта библиотека, и выясним, чем быстрые токенизаторы отличаются от "медленных" версий. @@ -16,4 +16,4 @@ * Различия между тремя основными алгоритмами токенизации по подсловам, используемыми в NLP сегодня * Как создать токенизатор с нуля с помощью библиотеки 🤗 Tokenizers и обучить его на некоторых данных -Техники, представленные в этой главе, подготовят вас к разделу в [Главе 7](/course/chapter7/6), где мы рассмотрим создание языковой модели по исходному коду Python. Для начала давайте разберемся, что значит "обучить" токенизатор. \ No newline at end of file +Техники, представленные в этой главе, подготовят вас к разделу в [Главе 7](../chapter7/6), где мы рассмотрим создание языковой модели по исходному коду Python. Для начала давайте разберемся, что значит "обучить" токенизатор. \ No newline at end of file diff --git a/chapters/ru/chapter6/2.mdx b/chapters/ru/chapter6/2.mdx index 4dfd465bb..089e23962 100644 --- a/chapters/ru/chapter6/2.mdx +++ b/chapters/ru/chapter6/2.mdx @@ -7,7 +7,7 @@ {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter6/section2.ipynb"}, ]} /> -Если языковая модель не доступна на интересующем вас языке или ваш корпус сильно отличается от того, на котором обучалась языковая модель, вам, скорее всего, придется заново обучать модель с нуля, используя токенизатор, адаптированный к вашим данным. Для этого потребуется обучить новый токенизатор на вашем наборе данных. Но что именно это значит? Когда мы впервые рассматривали токенизаторы в [Главе 2](/course/chapter2), мы увидели, что большинство моделей трансформеров используют _алгоритм токенизации по подсловам_. Чтобы определить, какие подслова представляют интерес и наиболее часто встречаются в корпусе, токенизатор должен внимательно изучить все тексты в корпусе - этот процесс мы называем *обучением*. Точные правила обучения зависят от типа используемого токенизатора, далее в этой главе мы рассмотрим три основных алгоритма. +Если языковая модель не доступна на интересующем вас языке или ваш корпус сильно отличается от того, на котором обучалась языковая модель, вам, скорее всего, придется заново обучать модель с нуля, используя токенизатор, адаптированный к вашим данным. Для этого потребуется обучить новый токенизатор на вашем наборе данных. Но что именно это значит? Когда мы впервые рассматривали токенизаторы в [Главе 2](../chapter2/1), мы увидели, что большинство моделей трансформеров используют _алгоритм токенизации по подсловам_. Чтобы определить, какие подслова представляют интерес и наиболее часто встречаются в корпусе, токенизатор должен внимательно изучить все тексты в корпусе - этот процесс мы называем *обучением*. Точные правила обучения зависят от типа используемого токенизатора, далее в этой главе мы рассмотрим три основных алгоритма. @@ -169,7 +169,7 @@ tokenizer = old_tokenizer.train_new_from_iterator(training_corpus, 52000) Обратите внимание, что `AutoTokenizer.train_new_from_iterator()` работает только в том случае, если используемый вами токенизатор является "быстрым" токенизатором. Как вы увидите в следующем разделе, библиотека 🤗 Transformers содержит два типа токенизаторов: одни написаны исключительно на Python, а другие (быстрые) опираются на библиотеку 🤗 Tokenizers, которая написана на языке программирования [Rust](https://www.rust-lang.org). Python - это язык, который чаще всего используется для приложений data science и deep learning, но когда что-то нужно распараллелить для быстроты, это приходится писать на другом языке. Например, матричные умножения, которые лежат в основе вычислений модели, написаны на CUDA, оптимизированной библиотеке языка C для GPU. -Обучение совершенно нового токенизатора на чистом Python было бы мучительно медленным, поэтому мы разработали библиотеку 🤗 Tokenizers. Обратите внимание, что так же как вам не нужно было изучать язык CUDA, чтобы выполнить свою модель на батче входных данных на GPU, вам не понадобится изучать Rust, чтобы использовать быстрый токенизатор. Библиотека 🤗 Tokenizers предоставляет привязки к Python для многих методов, которые внутренне вызывают некоторые части кода на Rust; например, для распараллеливания обучения вашего нового токенизатора или, как мы видели в [Главе 3](/course/chapter3), токенизации батча входных данных. +Обучение совершенно нового токенизатора на чистом Python было бы мучительно медленным, поэтому мы разработали библиотеку 🤗 Tokenizers. Обратите внимание, что так же как вам не нужно было изучать язык CUDA, чтобы выполнить свою модель на батче входных данных на GPU, вам не понадобится изучать Rust, чтобы использовать быстрый токенизатор. Библиотека 🤗 Tokenizers предоставляет привязки к Python для многих методов, которые внутренне вызывают некоторые части кода на Rust; например, для распараллеливания обучения вашего нового токенизатора или, как мы видели в [Главе 3](../chapter3/1), токенизации батча входных данных. В большинстве моделей Transformer доступен быстрый токенизатор (есть некоторые исключения, о которых вы можете узнать [здесь](https://huggingface.co/transformers/#supported-frameworks)), а API `AutoTokenizer` всегда выбирает быстрый токенизатор, если он доступен. В следующем разделе мы рассмотрим некоторые другие особенности быстрых токенизаторов, которые будут очень полезны для таких задач, как классификация токенов и ответы на вопросы. Однако прежде чем погрузиться в эту тему, давайте попробуем наш новый токенизатор на предыдущем примере: @@ -254,4 +254,4 @@ tokenizer.push_to_hub("code-search-net-tokenizer") tokenizer = AutoTokenizer.from_pretrained("huggingface-course/code-search-net-tokenizer") ``` -Теперь вы готовы обучить языковую модель с нуля и дообучить ее в соответствии с поставленной задачей! Мы займемся этим в [Главе 7](/course/chapter7), но сначала в этой главе мы рассмотрим быстрые токенизаторы и подробно изучим, что происходит при вызове метода `train_new_from_iterator()`. +Теперь вы готовы обучить языковую модель с нуля и дообучить ее в соответствии с поставленной задачей! Мы займемся этим в [Главе 7](../chapter7), но сначала в этой главе мы рассмотрим быстрые токенизаторы и подробно изучим, что происходит при вызове метода `train_new_from_iterator()`. diff --git a/chapters/ru/chapter6/3.mdx b/chapters/ru/chapter6/3.mdx index 25aa85b22..214e2ba13 100644 --- a/chapters/ru/chapter6/3.mdx +++ b/chapters/ru/chapter6/3.mdx @@ -22,11 +22,11 @@ {/if} -В этом разделе мы подробно рассмотрим возможности токенизаторов в 🤗 Transformers. До сих пор мы использовали их только для токенизации входных данных или декодирования идентификаторов обратно в текст, но токенизаторы -- особенно те, которые поддерживаются библиотекой 🤗 Tokenizers - могут делать гораздо больше. Чтобы проиллюстрировать эти дополнительные возможности, мы рассмотрим, как воспроизвести результаты конвейеров `token-classification` (которые мы назвали `ner`) и `question-answering`, с которыми мы впервые столкнулись в [Главе 1] (/course/chapter1). +В этом разделе мы подробно рассмотрим возможности токенизаторов в 🤗 Transformers. До сих пор мы использовали их только для токенизации входных данных или декодирования идентификаторов обратно в текст, но токенизаторы -- особенно те, которые поддерживаются библиотекой 🤗 Tokenizers - могут делать гораздо больше. Чтобы проиллюстрировать эти дополнительные возможности, мы рассмотрим, как воспроизвести результаты конвейеров `token-classification` (которые мы назвали `ner`) и `question-answering`, с которыми мы впервые столкнулись в [Главе 1](../chapter1/1). -В дальнейшем обсуждении мы будем часто проводить различие между "медленными" и "быстрыми" токенизаторами. Медленные токенизаторы - это те, что написаны на Python в библиотеке 🤗 Transformers, а быстрые версии - это те, что предоставляются в 🤗 Tokenizers, которые написаны на Rust. Если вы помните таблицу из [Главы 5](/course/chapter5/3), в которой приводилось, сколько времени потребовалось быстрому и медленному токенизаторам для токенизации датасета Drug Review Dataset, вы должны иметь представление о том, почему мы называем их быстрыми и медленными: +В дальнейшем обсуждении мы будем часто проводить различие между "медленными" и "быстрыми" токенизаторами. Медленные токенизаторы - это те, что написаны на Python в библиотеке 🤗 Transformers, а быстрые версии - это те, что предоставляются в 🤗 Tokenizers, которые написаны на Rust. Если вы помните таблицу из [Главы 5](../chapter5/3), в которой приводилось, сколько времени потребовалось быстрому и медленному токенизаторам для токенизации датасета Drug Review Dataset, вы должны иметь представление о том, почему мы называем их быстрыми и медленными: | | Быстрый токенизатор | Медленный токенизатор :--------------:|:----------------------:|:----------------------: @@ -139,7 +139,7 @@ Sylvain ## Внутри конвейера `token-classification`[[inside-the-token-classification-pipeline]] -В [Главе 1](/course/chapter1) мы впервые попробовали применить NER - когда задача состоит в том, чтобы определить, какие части текста соответствуют сущностям, таким как люди, места или организации - с помощью функции 🤗 Transformers `pipeline()`. Затем, в [Главе 2](/course/chapter2), мы увидели, как конвейер объединяет три этапа, необходимые для получения прогнозов из необработанного текста: токенизацию, прохождение входных данных через модель и постобработку. Первые два шага в конвейере `token-classification` такие же, как и в любом другом конвейере, но постобработка немного сложнее - давайте посмотрим, как это сделать! +В [Главе 1](../chapter1/1) мы впервые попробовали применить NER - когда задача состоит в том, чтобы определить, какие части текста соответствуют сущностям, таким как люди, места или организации - с помощью функции 🤗 Transformers `pipeline()`. Затем, в [Главе 2](../chapter2/1), мы увидели, как конвейер объединяет три этапа, необходимые для получения прогнозов из необработанного текста: токенизацию, прохождение входных данных через модель и постобработку. Первые два шага в конвейере `token-classification` такие же, как и в любом другом конвейере, но постобработка немного сложнее - давайте посмотрим, как это сделать! {#if fw === 'pt'} @@ -200,7 +200,7 @@ token_classifier("My name is Sylvain and I work at Hugging Face in Brooklyn.") {#if fw === 'pt'} -Сначала нам нужно токенизировать наш ввод и пропустить его через модель. Это делается точно так же, как в [Главе 2](/course/chapter2); мы инстанцируем токенизатор и модель с помощью классов `AutoXxx`, а затем используем их в нашем примере: +Сначала нам нужно токенизировать наш ввод и пропустить его через модель. Это делается точно так же, как в [Главе 2](../chapter2/1); мы инстанцируем токенизатор и модель с помощью классов `AutoXxx`, а затем используем их в нашем примере: ```py from transformers import AutoTokenizer, AutoModelForTokenClassification @@ -228,7 +228,7 @@ torch.Size([1, 19, 9]) {:else} -Сначала нам нужно токенизировать наши входные данные и пропустить их через модель. Это делается точно так же, как в [Главе 2](/course/chapter2); мы инстанцируем токенизатор и модель с помощью классов `TFAutoXxx`, а затем используем их в нашем примере: +Сначала нам нужно токенизировать наши входные данные и пропустить их через модель. Это делается точно так же, как в [Главе 2](../chapter2/1); мы инстанцируем токенизатор и модель с помощью классов `TFAutoXxx`, а затем используем их в нашем примере: ```py from transformers import AutoTokenizer, TFAutoModelForTokenClassification diff --git a/chapters/ru/chapter6/3b.mdx b/chapters/ru/chapter6/3b.mdx index 7902ec2ff..6ad4b6ed0 100644 --- a/chapters/ru/chapter6/3b.mdx +++ b/chapters/ru/chapter6/3b.mdx @@ -36,7 +36,7 @@ ## Использование конвейера `question-answering`[[using-the-question-answering-pipeline]] -Как мы видели в [Главе 1](/course/chapter1), для получения ответа на вопрос мы можем использовать конвейер `question-answering` следующим образом: +Как мы видели в [Главе 1](../chapter1/1), для получения ответа на вопрос мы можем использовать конвейер `question-answering` следующим образом: ```py from transformers import pipeline @@ -111,7 +111,7 @@ question_answerer(question=question, context=long_context) ## Использование модели для ответа на вопросы[[using-a-model-for-question-answering]] -Как и в любом другом конвейере, мы начинаем с токенизации входных данных, а затем отправляем их через модель. По умолчанию для конвейера `question-answering` используется контрольная точка [`distilbert-base-cased-distilled-squad`](https://huggingface.co/distilbert-base-cased-distilled-squad) (слово "squad" в названии происходит от набора данных, на котором дообучили модель; подробнее о наборе данных SQuAD мы поговорим в [главе 7](/course/chapter7/7)): +Как и в любом другом конвейере, мы начинаем с токенизации входных данных, а затем отправляем их через модель. По умолчанию для конвейера `question-answering` используется контрольная точка [`distilbert-base-cased-distilled-squad`](https://huggingface.co/distilbert-base-cased-distilled-squad) (слово "squad" в названии происходит от набора данных, на котором дообучили модель; подробнее о наборе данных SQuAD мы поговорим в [главе 7](../chapter7/7)): {#if fw === 'pt'} diff --git a/chapters/ru/chapter6/4.mdx b/chapters/ru/chapter6/4.mdx index e3c04d37a..fc5eaecf0 100644 --- a/chapters/ru/chapter6/4.mdx +++ b/chapters/ru/chapter6/4.mdx @@ -57,7 +57,7 @@ print(tokenizer.backend_tokenizer.normalizer.normalize_str("Héllò hôw are ü? -Как мы увидим в следующих разделах, токенизатор не может быть обучен только на сыром тексте. Сначала необходимо разбить текст на небольшие части, например, на слова. Именно в этом и заключается этап предварительной токенизации. Как мы видели в [Главе 2](/course/chapter2), токенизатор на основе слов (word-based tokenizer) может просто разбить необработанный текст на слова по пробелам и знакам пунктуации. Эти слова станут границами подтокенов, которые токенизатор сможет выучить в процессе обучения. +Как мы увидим в следующих разделах, токенизатор не может быть обучен только на сыром тексте. Сначала необходимо разбить текст на небольшие части, например, на слова. Именно в этом и заключается этап предварительной токенизации. Как мы видели в [Главе 2](../chapter2/1), токенизатор на основе слов (word-based tokenizer) может просто разбить необработанный текст на слова по пробелам и знакам пунктуации. Эти слова станут границами подтокенов, которые токенизатор сможет выучить в процессе обучения. Чтобы увидеть, как быстрый токенизатор выполняет предварительную токенизацию, мы можем воспользоваться методом `pre_tokenize_str()` атрибута `pre_tokenizer` объекта `tokenizer`: @@ -104,7 +104,7 @@ tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you? ## SentencePiece[[sentencepiece]] -[SentencePiece](https://github.com/google/sentencepiece) - это алгоритм токенизации для предварительной обработки текста, который можно использовать с любой из моделей, которые мы рассмотрим в следующих трех разделах. Он рассматривает текст как последовательность символов Unicode и заменяет пробелы специальным символом `▁`. При использовании в сочетании с алгоритмом Unigram (см. [раздел 7](/course/chapter7/7)) он даже не требует шага предварительной токенизации, что очень полезно для языков, где символ пробела не используется (например, китайского или японского). +[SentencePiece](https://github.com/google/sentencepiece) - это алгоритм токенизации для предварительной обработки текста, который можно использовать с любой из моделей, которые мы рассмотрим в следующих трех разделах. Он рассматривает текст как последовательность символов Unicode и заменяет пробелы специальным символом `▁`. При использовании в сочетании с алгоритмом Unigram (см. [раздел 7](../chapter7/7)) он даже не требует шага предварительной токенизации, что очень полезно для языков, где символ пробела не используется (например, китайского или японского). Другой главной особенностью SentencePiece является *обратимая токенизация*: поскольку в нем нет специальной обработки пробелов, декодирование токенов осуществляется просто путем их конкатенации и замены `_` на пробелы - в результате получается нормализованный текст. Как мы видели ранее, токенизатор BERT удаляет повторяющиеся пробелы, поэтому его токенизация не является обратимой. diff --git a/chapters/ru/chapter6/8.mdx b/chapters/ru/chapter6/8.mdx index 191e1d2f4..2e579224f 100644 --- a/chapters/ru/chapter6/8.mdx +++ b/chapters/ru/chapter6/8.mdx @@ -21,7 +21,7 @@
-Библиотека 🤗 Tokenizers была создана для того, чтобы предоставить несколько вариантов каждого из этих шагов, которые вы можете смешивать и сочетать между собой. В этом разделе мы рассмотрим, как можно создать токенизатор с нуля, а не обучать новый токенизатор на основе старого, как мы делали в [разделе 2](/course/chapter6/2). После этого вы сможете создать любой токенизатор, который только сможете придумать! +Библиотека 🤗 Tokenizers была создана для того, чтобы предоставить несколько вариантов каждого из этих шагов, которые вы можете смешивать и сочетать между собой. В этом разделе мы рассмотрим, как можно создать токенизатор с нуля, а не обучать новый токенизатор на основе старого, как мы делали в [разделе 2](../chapter6/2). После этого вы сможете создать любой токенизатор, который только сможете придумать! @@ -38,7 +38,7 @@ ## Получение корпуса текста[[acquiring-a-corpus]] -Для обучения нашего нового токенизатора мы будем использовать небольшой корпус текстов (чтобы примеры выполнялись быстро). Шаги по сбору корпуса аналогичны тем, что мы делали в [начале этой главы](/course/chapter6/2), но на этот раз мы будем использовать набор данных [WikiText-2](https://huggingface.co/datasets/wikitext): +Для обучения нашего нового токенизатора мы будем использовать небольшой корпус текстов (чтобы примеры выполнялись быстро). Шаги по сбору корпуса аналогичны тем, что мы делали в [начале этой главы](../chapter6/2), но на этот раз мы будем использовать набор данных [WikiText-2](https://huggingface.co/datasets/wikitext): ```python from datasets import load_dataset diff --git a/chapters/ru/chapter7/1.mdx b/chapters/ru/chapter7/1.mdx index b25a2e19c..47cf244b5 100644 --- a/chapters/ru/chapter7/1.mdx +++ b/chapters/ru/chapter7/1.mdx @@ -7,7 +7,7 @@ classNames="absolute z-10 right-0 top-0" /> -В [Главе 3](/course/chapter3) вы узнали, как дообучить модель для классификации текстов. В этой главе мы рассмотрим следующие общие задачи NLP: +В [Главе 3](../chapter3/1) вы узнали, как дообучить модель для классификации текстов. В этой главе мы рассмотрим следующие общие задачи NLP: - Классификация токенов (Token classification) - Маскированное языковое моделирование (Masked language modeling, например, BERT) @@ -18,13 +18,13 @@ {#if fw === 'pt'} -Для этого вам понадобится использовать все, что вы узнали об API `Trainer` и библиотеке 🤗 Accelerate в [Главе 3](/course/chapter3), библиотеке 🤗 Datasets в [Главе 5](/course/chapter5) и библиотеке 🤗 Tokenizers в [Главе 6](/course/chapter6). Мы также загрузим наши результаты в хаб моделей, как мы делали это в [Главе 4](/course/chapter4), так что это действительно глава,в которой все собирается воедино! +Для этого вам понадобится использовать все, что вы узнали об API `Trainer` и библиотеке 🤗 Accelerate в [Главе 3](../chapter3/1), библиотеке 🤗 Datasets в [Главе 5](../chapter5/1) и библиотеке 🤗 Tokenizers в [Главе 6](../chapter6/1). Мы также загрузим наши результаты в хаб моделей, как мы делали это в [Главе 4](../chapter4/1), так что это действительно глава,в которой все собирается воедино! Каждый раздел можно читать независимо друг от друга, и в нем вы узнаете, как обучить модель с помощью API `Trainer` или с помощью собственного цикла обучения, используя 🤗 Accelerate. Вы можете пропустить любую часть и сосредоточиться на той, которая вас больше всего интересует: API `Trainer` отлично подходит для того, чтобы дообучить или обучить вашу модель, не беспокоясь о том, что происходит за кулисами, а цикл обучения с `Accelerate` позволит вам легче настроить любую часть, которую вы хотите. {:else} -Для этого вам понадобится использовать все, что вы узнали об обучении моделей с помощью Keras API в [Главе 3](/course/chapter3), библиотеке 🤗 Datasets в [Главе 5](/course/chapter5) и библиотеке 🤗 Tokenizers в [Главе 6](/course/chapter6). Мы также загрузим наши результаты в хаб моделей, как мы делали это в [Главе 4](/course/chapter4), так что это действительно глава, в которой все собирается воедино! +Для этого вам понадобится использовать все, что вы узнали об обучении моделей с помощью Keras API в [Главе 3](../chapter3/1), библиотеке 🤗 Datasets в [Главе 5](../chapter5/1) и библиотеке 🤗 Tokenizers в [Главе 6](../chapter6/1). Мы также загрузим наши результаты в хаб моделей, как мы делали это в [Главе 4](../chapter4/1), так что это действительно глава, в которой все собирается воедино! Каждый раздел можно читать самостоятельно. diff --git a/chapters/ru/chapter7/2.mdx b/chapters/ru/chapter7/2.mdx index cae2eb4e6..edc843490 100644 --- a/chapters/ru/chapter7/2.mdx +++ b/chapters/ru/chapter7/2.mdx @@ -47,7 +47,7 @@ -💡 Если ваш набор данных состоит из текстов, часть которых состоит из слов с соответствующими метками, вы сможете адаптировать описанные здесь процедуры обработки данных к своему набору данных. Обратитесь к [Главе 5](/course/chapter5), если вам нужно освежить в памяти то, как загружать собственные данные в `Dataset`. +💡 Если ваш набор данных состоит из текстов, часть которых состоит из слов с соответствующими метками, вы сможете адаптировать описанные здесь процедуры обработки данных к своему набору данных. Обратитесь к [Главе 5](../chapter5/1), если вам нужно освежить в памяти то, как загружать собственные данные в `Dataset`. @@ -61,7 +61,7 @@ from datasets import load_dataset raw_datasets = load_dataset("conll2003") ``` -Это позволит загрузить и кэшировать датасет, как мы видели в [Главе 3](/course/chapter3) для датасета GLUE MRPC. Изучение этого объекта показывает нам присутствующие столбцы и части тренировочного, проверочного и тестового наборов: +Это позволит загрузить и кэшировать датасет, как мы видели в [Главе 3](../chapter3/1) для датасета GLUE MRPC. Изучение этого объекта показывает нам присутствующие столбцы и части тренировочного, проверочного и тестового наборов: ```py raw_datasets @@ -128,7 +128,7 @@ label_names ['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC', 'B-MISC', 'I-MISC'] ``` -Мы уже видели эти метки при изучении конвейера `token-classification` в [Главе 6](/course/chapter6/3), но для краткости напомним: +Мы уже видели эти метки при изучении конвейера `token-classification` в [Главе 6](../chapter6/3), но для краткости напомним: - `O` означает, что слово не соответствует какой-либо сущности. - `B-PER`/`I-PER` означает, что слово соответствует началу/находится внутри сущности персоны *person*. @@ -177,7 +177,7 @@ print(line2) -Как обычно, наши тексты должны быть преобразованы в идентификаторы токенов, прежде чем модель сможет понять их смысл. Как мы видели в [Главе 6](/course/chapter6/), существенным отличием задачи классификации токенов является то, что у нас есть предварительно токенизированные входные данные. К счастью, API токенизатора справляется с этим довольно легко; нам просто нужно предупредить `tokenizer` специальным флагом. +Как обычно, наши тексты должны быть преобразованы в идентификаторы токенов, прежде чем модель сможет понять их смысл. Как мы видели в [Главе 6](../chapter6/), существенным отличием задачи классификации токенов является то, что у нас есть предварительно токенизированные входные данные. К счастью, API токенизатора справляется с этим довольно легко; нам просто нужно предупредить `tokenizer` специальным флагом. Для начала давайте создадим объект `tokenizer`. Как мы уже говорили, мы будем использовать предварительно обученную модель BERT, поэтому начнем с загрузки и кэширования соответствующего токенизатора: @@ -211,7 +211,7 @@ inputs.tokens() Как мы видим, токенизатор добавил специальные токены, используемые моделью (`[CLS]` в начале и `[SEP]` в конце), и оставил большинство слов нетронутыми. Слово `lamb`, однако, было токенизировано на два подслова, `la` и `##mb`. Это вносит несоответствие между нашими входными данными и метками: список меток состоит всего из 9 элементов, в то время как наши входные данные теперь содержат 12 токенов. Учесть специальные токены легко (мы знаем, что они находятся в начале и в конце), но нам также нужно убедиться, что мы выровняли все метки с соответствующими словами. -К счастью, поскольку мы используем быстрый токенизатор, у нас есть доступ к суперспособностям 🤗 Tokenizers, что означает, что мы можем легко сопоставить каждый токен с соответствующим словом (как показано в [Глава 6](/course/chapter6/3)): +К счастью, поскольку мы используем быстрый токенизатор, у нас есть доступ к суперспособностям 🤗 Tokenizers, что означает, что мы можем легко сопоставить каждый токен с соответствующим словом (как показано в [Глава 6](../chapter6/3)): ```py inputs.word_ids() @@ -298,7 +298,7 @@ tokenized_datasets = raw_datasets.map( ) ``` -Мы сделали самую сложную часть! Теперь, когда данные прошли предварительную обработку, само обучение будет выглядеть примерно так, как мы делали это в [Главе 3](/course/chapter3). +Мы сделали самую сложную часть! Теперь, когда данные прошли предварительную обработку, само обучение будет выглядеть примерно так, как мы делали это в [Главе 3](../chapter3/1). {#if fw === 'pt'} @@ -317,7 +317,7 @@ tokenized_datasets = raw_datasets.map( ### Сопоставление данных[[data-collation]] -Мы не можем просто использовать `DataCollatorWithPadding`, как в [Главе 3](/course/chapter3), потому что в этом случае дополняются только входные данные (идентификаторы входов, маска внимания и идентификаторы типов токенов). Здесь наши метки должны быть дополнены точно так же, как и входы, чтобы они оставались одного размера, используя `-100` в качестве значения, чтобы соответствующие прогнозы игнорировались при вычислении потерь. +Мы не можем просто использовать `DataCollatorWithPadding`, как в [Главе 3](../chapter3/1), потому что в этом случае дополняются только входные данные (идентификаторы входов, маска внимания и идентификаторы типов токенов). Здесь наши метки должны быть дополнены точно так же, как и входы, чтобы они оставались одного размера, используя `-100` в качестве значения, чтобы соответствующие прогнозы игнорировались при вычислении потерь. Все это делает [`DataCollatorForTokenClassification`](https://huggingface.co/transformers/main_classes/data_collator.html#datacollatorfortokenclassification). Как и `DataCollatorWithPadding`, он принимает `токенизатор`, используемый для предварительной обработки входных данных: @@ -419,7 +419,7 @@ model = TFAutoModelForTokenClassification.from_pretrained( ) ``` -Как и при определении `TFAutoModelForSequenceClassification` в [Главе 3](/course/chapter3), при создании модели выдается предупреждение о том, что некоторые веса не были использованы (веса из предварительно обученной головы), а другие веса инициализированы случайно (веса из новой головы классификации токенов), и что эту модель нужно обучить. Мы сделаем это через минуту, но сначала давайте перепроверим, что наша модель имеет правильное количество меток: +Как и при определении `TFAutoModelForSequenceClassification` в [Главе 3](../chapter3/1), при создании модели выдается предупреждение о том, что некоторые веса не были использованы (веса из предварительно обученной головы), а другие веса инициализированы случайно (веса из новой головы классификации токенов), и что эту модель нужно обучить. Мы сделаем это через минуту, но сначала давайте перепроверим, что наша модель имеет правильное количество меток: ```python model.config.num_labels @@ -522,7 +522,7 @@ model.fit( !pip install seqeval ``` -Мы можем загрузить ее с помощью функции `evaluate.load()`, как мы это делали в [Главе 3](/course/chapter3): +Мы можем загрузить ее с помощью функции `evaluate.load()`, как мы это делали в [Главе 3](../chapter3/1): {:else} @@ -532,7 +532,7 @@ model.fit( !pip install seqeval ``` -Мы можем загрузить ее с помощью функции `evaluate.load()`, как мы это делали в [Главе 3](/course/chapter3): +Мы можем загрузить ее с помощью функции `evaluate.load()`, как мы это делали в [Главе 3](../chapter3/1): {/if} @@ -669,7 +669,7 @@ model = AutoModelForTokenClassification.from_pretrained( ) ``` -Как и в случае определения `AutoModelForSequenceClassification` в [Главе 3](/course/chapter3), при создании модели выдается предупреждение о том, что некоторые веса не были использованы (те, что были получены из предварительно обученной головы), а другие инициализированы случайно (те, что были получены из новой головы классификации токенов), и что эту модель необходимо обучить. Мы сделаем это через минуту, но сначала давайте перепроверим, что наша модель имеет правильное количество меток: +Как и в случае определения `AutoModelForSequenceClassification` в [Главе 3](../chapter3/1), при создании модели выдается предупреждение о том, что некоторые веса не были использованы (те, что были получены из предварительно обученной головы), а другие инициализированы случайно (те, что были получены из новой головы классификации токенов), и что эту модель необходимо обучить. Мы сделаем это через минуту, но сначала давайте перепроверим, что наша модель имеет правильное количество меток: ```python model.config.num_labels @@ -764,7 +764,7 @@ trainer.push_to_hub(commit_message="Training complete") ## Индивидуальный цикл обучения[[a-custom-training-loop]] -Теперь давайте рассмотрим полный цикл обучения, чтобы вы могли легко настроить нужные вам части. Он будет очень похож на тот, что мы делали в [Главе 3](/course/chapter3/4), с некоторыми изменениями для оценки. +Теперь давайте рассмотрим полный цикл обучения, чтобы вы могли легко настроить нужные вам части. Он будет очень похож на тот, что мы делали в [Главе 3](../chapter3/4), с некоторыми изменениями для оценки. ### Подготовка всего к обучению[[preparing-everything-for-training]] @@ -815,7 +815,7 @@ model, optimizer, train_dataloader, eval_dataloader = accelerator.prepare( -🚨 Если вы обучаетесь на TPU, вам нужно будет перенести весь код, начиная с ячейки выше, в специальную функцию обучения. Подробнее смотрите [Главу 3](/course/chapter3). +🚨 Если вы обучаетесь на TPU, вам нужно будет перенести весь код, начиная с ячейки выше, в специальную функцию обучения. Подробнее смотрите [Главу 3](../chapter3/1). diff --git a/chapters/ru/chapter7/3.mdx b/chapters/ru/chapter7/3.mdx index 0fcf0ff95..da62408eb 100644 --- a/chapters/ru/chapter7/3.mdx +++ b/chapters/ru/chapter7/3.mdx @@ -43,7 +43,7 @@ -🙋 Если термины "маскированное моделирование языка (masked language modeling)" и "предварительно обученная модель (pretrained model)" кажутся вам незнакомыми, загляните в [Главу 1](/course/chapter1), где мы объясняем все эти основные понятия, сопровождая их видеороликами! +🙋 Если термины "маскированное моделирование языка (masked language modeling)" и "предварительно обученная модель (pretrained model)" кажутся вам незнакомыми, загляните в [Главу 1](../chapter1/1), где мы объясняем все эти основные понятия, сопровождая их видеороликами! @@ -243,7 +243,7 @@ for row in sample: -Теперь, когда мы вкратце ознакомились с данными, давайте перейдем к их подготовке к моделированию языка по маске. Как мы увидим, есть несколько дополнительных шагов, которые необходимо сделать по сравнению с задачами классификации последовательностей, которые мы рассматривали в [Главе 3](/course/chapter3). Поехали! +Теперь, когда мы вкратце ознакомились с данными, давайте перейдем к их подготовке к моделированию языка по маске. Как мы увидим, есть несколько дополнительных шагов, которые необходимо сделать по сравнению с задачами классификации последовательностей, которые мы рассматривали в [Главе 3](../chapter3/1). Поехали! ## Предварительная обработка данных[[preprocessing-the-data]] @@ -251,7 +251,7 @@ for row in sample: Как для авторегрессивного, так и для масочного моделирования языка общим шагом предварительной обработки является объединение всех примеров, а затем разбиение всего корпуса на части одинакового размера. Это сильно отличается от нашего обычного подхода, когда мы просто проводим токенизацию отдельных примеров. Зачем конкатенируем все вместе? Причина в том, что отдельные примеры могут быть обрезаны, если они слишком длинные, и это приведет к потере информации, которая может быть полезна для задачи языкового моделирования! -Итак, для начала мы проведем обычную токенизацию нашего корпуса, но _без_ задания параметра `truncation=True` в нашем токенизаторе. Мы также возьмем идентификаторы слов, если они доступны (а они будут доступны, если мы используем быстрый токенизатор, как описано в [Главе 6](/course/chapter6/3)), поскольку они понадобятся нам позже для маскирования целых слов. Мы обернем это в простую функцию, а пока удалим столбцы `text` и `label`, поскольку они нам больше не нужны: +Итак, для начала мы проведем обычную токенизацию нашего корпуса, но _без_ задания параметра `truncation=True` в нашем токенизаторе. Мы также возьмем идентификаторы слов, если они доступны (а они будут доступны, если мы используем быстрый токенизатор, как описано в [Главе 6](../chapter6/3)), поскольку они понадобятся нам позже для маскирования целых слов. Мы обернем это в простую функцию, а пока удалим столбцы `text` и `label`, поскольку они нам больше не нужны: ```python def tokenize_function(examples): @@ -445,7 +445,7 @@ tokenizer.decode(lm_datasets["train"][1]["labels"]) ## Дообучение DistilBERT с помощью API `Trainer`[[fine-tuning-distilbert-with-the-trainer-api]] -Дообучить модель моделирования языка по маске почти то же самое, что и дообучить модель классификации последовательностей, как мы делали в [Главе 3](/course/chapter3). Единственное отличие заключается в том, что нам нужен специальный коллатор данных, который может случайным образом маскировать некоторые токены в каждом батче текстов. К счастью, 🤗 Transformers поставляется со специальным `DataCollatorForLanguageModeling`, предназначенным именно для этой задачи. Нам нужно только передать ему токенизатор и аргумент `mlm_probability`, который указывает, какую долю токенов нужно маскировать. Мы выберем 15 % - это количество используется для BERT и является распространенным выбором в литературе: +Дообучить модель моделирования языка по маске почти то же самое, что и дообучить модель классификации последовательностей, как мы делали в [Главе 3](../chapter3/1). Единственное отличие заключается в том, что нам нужен специальный коллатор данных, который может случайным образом маскировать некоторые токены в каждом батче текстов. К счастью, 🤗 Transformers поставляется со специальным `DataCollatorForLanguageModeling`, предназначенным именно для этой задачи. Нам нужно только передать ему токенизатор и аргумент `mlm_probability`, который указывает, какую долю токенов нужно маскировать. Мы выберем 15 % - это количество используется для BERT и является распространенным выбором в литературе: ```python from transformers import DataCollatorForLanguageModeling @@ -592,7 +592,7 @@ for chunk in batch["input_ids"]: -Теперь, когда у нас есть два колатора данных, остальные шаги по дообучению стандартны. Обучение может занять много времени в Google Colab, если вам не посчастливилось получить мифический GPU P100 😭, поэтому мы сначала уменьшим размер обучающего набора до нескольких тысяч примеров. Не волнуйтесь, мы все равно получим довольно приличную языковую модель! Быстрый способ уменьшить размер датасета в 🤗 Datasets - это функция `Dataset.train_test_split()`, которую мы рассматривали в [Главе 5](/course/chapter5): +Теперь, когда у нас есть два колатора данных, остальные шаги по дообучению стандартны. Обучение может занять много времени в Google Colab, если вам не посчастливилось получить мифический GPU P100 😭, поэтому мы сначала уменьшим размер обучающего набора до нескольких тысяч примеров. Не волнуйтесь, мы все равно получим довольно приличную языковую модель! Быстрый способ уменьшить размер датасета в 🤗 Datasets - это функция `Dataset.train_test_split()`, которую мы рассматривали в [Главе 5](../chapter5/1): ```python train_size = 10_000 @@ -827,7 +827,7 @@ trainer.push_to_hub() ## Дообучение DistilBERT с помощью 🤗 Accelerate[[fine-tuning-distilbert-with-accelerate]] -Как мы видели на примере `Trainer`, дообучение модели маскированного языкового моделирования очень похоже на пример классификации текста из [Главы 3](/course/chapter3). Фактически, единственной особенностью является использование специального коллатора данных, о котором мы уже рассказывали ранее в этом разделе! +Как мы видели на примере `Trainer`, дообучение модели маскированного языкового моделирования очень похоже на пример классификации текста из [Главы 3](../chapter3/1). Фактически, единственной особенностью является использование специального коллатора данных, о котором мы уже рассказывали ранее в этом разделе! Однако мы видели, что `DataCollatorForLanguageModeling` также применяет случайное маскирование при каждой оценке, поэтому мы увидим некоторые колебания в наших оценках перплексии при каждом цикле обучения. Один из способов устранить этот источник случайности - применить маскирование _один раз_ ко всему тестовому набору, а затем использовать стандартный коллатор данных в 🤗 Transformers для сбора батчей во время оценки. Чтобы увидеть, как это работает, давайте реализуем простую функцию, которая применяет маскирование к батчу, подобно нашей первой работе с `DataCollatorForLanguageModeling`: @@ -1035,10 +1035,10 @@ for pred in preds: -На этом мы завершаем наш первый эксперимент по обучению языковой модели. В [разделе 6](/course/en/chapter7/6) вы узнаете, как обучить авторегрессионную модель типа GPT-2 с нуля; загляните туда, если хотите посмотреть, как можно предварительно обучить свою собственную модель трансформера! +На этом мы завершаем наш первый эксперимент по обучению языковой модели. В [разделе 6](../chapter7/6) вы узнаете, как обучить авторегрессионную модель типа GPT-2 с нуля; загляните туда, если хотите посмотреть, как можно предварительно обучить свою собственную модель трансформера! -✏️ **Попробуйте!** Чтобы оценить преимущества адаптации к домену, дообучите классификатор на метках IMDb как для предварительно обученных, так и для дообученных контрольных точек DistilBERT. Если вам нужно освежить в памяти классификацию текстов, ознакомьтесь с [Главой 3](/course/chapter3). +✏️ **Попробуйте!** Чтобы оценить преимущества адаптации к домену, дообучите классификатор на метках IMDb как для предварительно обученных, так и для дообученных контрольных точек DistilBERT. Если вам нужно освежить в памяти классификацию текстов, ознакомьтесь с [Главой 3](../chapter3/1). diff --git a/chapters/ru/chapter7/4.mdx b/chapters/ru/chapter7/4.mdx index 51c3b6121..53d1155ef 100644 --- a/chapters/ru/chapter7/4.mdx +++ b/chapters/ru/chapter7/4.mdx @@ -22,14 +22,14 @@ {/if} -Теперь давайте погрузимся в перевод. Это еще одна [задача преобразования последовательности в последовательность (sequence-to-sequence)](/course/chapter1/7), что означает, что это проблема, которую можно сформулировать как переход от одной последовательности к другой. В этом смысле задача очень близка к [резюмированию (summarization)](/course/chapter7/6), и вы можете приспособить то, что мы здесь рассмотрим, к другим задачам преобразования последовательности в последовательность, таким как: +Теперь давайте погрузимся в перевод. Это еще одна [задача преобразования последовательности в последовательность (sequence-to-sequence)](../chapter1/7), что означает, что это проблема, которую можно сформулировать как переход от одной последовательности к другой. В этом смысле задача очень близка к [резюмированию (summarization)](../chapter7/6), и вы можете приспособить то, что мы здесь рассмотрим, к другим задачам преобразования последовательности в последовательность, таким как: - **Перенос стиля (Style transfer)**: Создание модели, которая *переводит* тексты, написанные в определенном стиле, в другой (например, из формального в повседневный или из шекспировского английского в современный). - **Генеративные ответы на вопросы (Generative question answering)**: Создание модели, которая генерирует ответы на вопросы, учитывая контекст -Если у вас есть достаточно большой корпус текстов на двух (или более) языках, вы можете обучить новую модель перевода с нуля, как мы это сделаем в разделе по [казуальному языковому моделированию (causal language modeling)](/course/chapter7/6). Однако быстрее будет дообучить существующую модель перевода, будь то многоязычная модель типа mT5 или mBART, которую нужно дообучить для конкретной пары языков, или даже модель, специализированная для перевода с одного языка на другой, которую нужно дообучить для конкретного корпуса. +Если у вас есть достаточно большой корпус текстов на двух (или более) языках, вы можете обучить новую модель перевода с нуля, как мы это сделаем в разделе по [казуальному языковому моделированию (causal language modeling)](../chapter7/6). Однако быстрее будет дообучить существующую модель перевода, будь то многоязычная модель типа mT5 или mBART, которую нужно дообучить для конкретной пары языков, или даже модель, специализированная для перевода с одного языка на другой, которую нужно дообучить для конкретного корпуса. В этом разделе мы дообучим модель Marian, предварительно обученную переводу с английского на французский (поскольку многие сотрудники Hugging Face говорят на обоих этих языках), на датасете [KDE4](https://huggingface.co/datasets/kde4), который представляет собой набор локализованных файлов для приложений [KDE](https://apps.kde.org/). Модель, которую мы будем использовать, была предварительно обучена на большом корпусе французских и английских текстов, взятых из [Opus dataset](https://opus.nlpl.eu/), который фактически содержит датасет KDE4. Но даже если модель, которую мы используем, видела эти данные во время предварительного обучения, мы увидим, что после дообучения мы сможем получить ее лучшую версию. @@ -46,7 +46,7 @@ ## Подготовка данных[[preparing-the-data]] -Чтобы дообучить или обучить модель перевода с нуля, нам понадобится датасет, подходящий для этой задачи. Как уже упоминалось, мы будем использовать [датасет KDE4](https://huggingface.co/datasets/kde4) , но вы можете легко адаптировать код для использования своих собственных данных, если у вас есть пары предложений на двух языках, с которых вы хотите переводить и на которые хотите переводить. Обратитесь к [Главе 5](/course/chapter5) если вам нужно вспомнить, как загружать пользовательские данные в `Dataset`. +Чтобы дообучить или обучить модель перевода с нуля, нам понадобится датасет, подходящий для этой задачи. Как уже упоминалось, мы будем использовать [датасет KDE4](https://huggingface.co/datasets/kde4) , но вы можете легко адаптировать код для использования своих собственных данных, если у вас есть пары предложений на двух языках, с которых вы хотите переводить и на которые хотите переводить. Обратитесь к [Главе 5](../chapter5/1) если вам нужно вспомнить, как загружать пользовательские данные в `Dataset`. ### Датасет KDE4[[the-kde4-dataset]] @@ -77,7 +77,7 @@ DatasetDict({ }) ``` -У нас есть 210 173 пары предложений, но в одной части, поэтому нам нужно создать собственный проверочный набор. Как мы видели в [Главе 5](/course/chapter5), у `Dataset` есть метод `train_test_split()`, который может нам помочь. Мы зададим seed для воспроизводимости: +У нас есть 210 173 пары предложений, но в одной части, поэтому нам нужно создать собственный проверочный набор. Как мы видели в [Главе 5](../chapter5/1), у `Dataset` есть метод `train_test_split()`, который может нам помочь. Мы зададим seed для воспроизводимости: ```py split_datasets = raw_datasets["train"].train_test_split(train_size=0.9, seed=20) @@ -298,7 +298,7 @@ model = TFAutoModelForSeq2SeqLM.from_pretrained(model_checkpoint, from_pt=True) ### Сопоставление данных[[data-collation]] -Для динамического батча нам понадобится коллатор данных для работы с дополнением (padding). Мы не можем просто использовать `DataCollatorWithPadding`, как в [Главе 3](/course/chapter3), потому что в этом случае будут заполнены только входы (идентификаторы входов, маска внимания и идентификаторы типов токенов). Наши метки также должны быть дополнены до максимальной длины, встречающейся в метках. И, как уже говорилось, добовляемое значение, используемое для дополнения меток, должно быть `-100`, а не добавочный токен токенизатора, чтобы эти добавочные значения игнорировались при вычислении потерь. +Для динамического батча нам понадобится коллатор данных для работы с дополнением (padding). Мы не можем просто использовать `DataCollatorWithPadding`, как в [Главе 3](../chapter3/1), потому что в этом случае будут заполнены только входы (идентификаторы входов, маска внимания и идентификаторы типов токенов). Наши метки также должны быть дополнены до максимальной длины, встречающейся в метках. И, как уже говорилось, добовляемое значение, используемое для дополнения меток, должно быть `-100`, а не добавочный токен токенизатора, чтобы эти добавочные значения игнорировались при вычислении потерь. Все это делает [`DataCollatorForSeq2Seq`](https://huggingface.co/transformers/main_classes/data_collator.html#datacollatorforseq2seq). Как и `DataCollatorWithPadding`, он принимает `tokenizer`, используемый для препроцессирования входных данных, а также `model`. Это связано с тем, что данный коллатор данных также будет отвечать за подготовку входных идентификаторов декодера, которые представляют собой сдвинутые версии меток со специальным токеном в начале. Поскольку для разных архитектур этот сдвиг выполняется по-разному, `DataCollatorForSeq2Seq` должен знать объект `model`: @@ -403,7 +403,7 @@ tf_eval_dataset = model.prepare_tf_dataset( Свойство, которое `Seq2SeqTrainer` добавляет к своему суперклассу `Trainer`, - это возможность использовать метод `generate()` во время оценки или предсказания. Во время обучения модель будет использовать `decoder_input_ids` с маской внимания, гарантирующей, что она не будет использовать токены после токена, который пытается предсказать, чтобы ускорить обучение. Во время инференса мы не сможем использовать эти данные, так как у нас не будет меток, поэтому было бы неплохо оценить нашу модель с аналогичной настройкой. -Как мы видели в [Главе 1](/course/chapter1/6), декодер выполняет инференс, предсказывая токены один за другим - то, что за кулисами реализовано в 🤗 Transformers методом `generate()`. Тренер `Seq2SeqTrainer` позволит нам использовать этот метод для оценки, если мы установим `predict_with_generate=True`. +Как мы видели в [Главе 1](../chapter1/6), декодер выполняет инференс, предсказывая токены один за другим - то, что за кулисами реализовано в 🤗 Transformers методом `generate()`. Тренер `Seq2SeqTrainer` позволит нам использовать этот метод для оценки, если мы установим `predict_with_generate=True`. {/if} @@ -415,7 +415,7 @@ tf_eval_dataset = model.prepare_tf_dataset( !pip install sacrebleu ``` -Затем мы можем загрузить ее с помощью `evaluate.load()`, как мы это делали в [Главе 3](/course/chapter3): +Затем мы можем загрузить ее с помощью `evaluate.load()`, как мы это делали в [Главе 3](../chapter3/1): ```py import evaluate @@ -630,7 +630,7 @@ model.compile(optimizer=optimizer) tf.keras.mixed_precision.set_global_policy("mixed_float16") ``` -Далее мы определяем обратный вызов `PushToHubCallback` для загрузки нашей модели в Hub во время обучения, как мы видели в [разделе 2]((/course/chapter7/2)), а затем мы просто подгоняем модель с помощью этого обратного вызова: +Далее мы определяем обратный вызов `PushToHubCallback` для загрузки нашей модели в Hub во время обучения, как мы видели в [разделе 2](../chapter7/2), а затем мы просто подгоняем модель с помощью этого обратного вызова: ```python from transformers.keras_callbacks import PushToHubCallback @@ -785,7 +785,7 @@ trainer.push_to_hub(tags="translation", commit_message="Training complete") ## Индивидуальный цикл обучения[[a-custom-training-loop]] -Теперь давайте рассмотрим полный цикл обучения, чтобы вы могли легко настроить нужные вам части. Он будет выглядеть примерно так же, как мы делали это в [Главе 2](/course/chapter7/2) и [Главе 3](/course/chapter3/4). +Теперь давайте рассмотрим полный цикл обучения, чтобы вы могли легко настроить нужные вам части. Он будет выглядеть примерно так же, как мы делали это в [Главе 2](../chapter7/2) и [Главе 3](../chapter3/4). ### Подготовка всего к обучению[[preparing-everything-for-training]] @@ -892,11 +892,11 @@ def postprocess(predictions, labels): return decoded_preds, decoded_labels ``` -Цикл обучения очень похож на циклы в [разделе 2](/course/chapter7/2) и [главе 3](/course/chapter3), с некоторыми отличиями в части оценки - так что давайте сосредоточимся на этом! +Цикл обучения очень похож на циклы в [разделе 2](../chapter7/2) и [главе 3](../chapter3/1), с некоторыми отличиями в части оценки - так что давайте сосредоточимся на этом! Первое, что следует отметить, это то, что мы используем метод `generate()` для вычисления прогнозов, но это метод нашей базовой модели, а не обернутой модели 🤗 Accelerate, созданной в методе `prepare()`. Поэтому мы сначала развернем модель, а затем вызовем этот метод. -Второй момент заключается в том, что, как и в случае с [классификацией токенов](/course/chapter7/2), два процесса могут дополнить входы и метки до разных форм, поэтому мы используем `accelerator.pad_across_processes()`, чтобы сделать прогнозы и метки одинаковыми по форме перед вызовом метода `gather()`. Если мы этого не сделаем, оценка либо выдаст ошибку, либо зависнет навсегда. +Второй момент заключается в том, что, как и в случае с [классификацией токенов](../chapter7/2), два процесса могут дополнить входы и метки до разных форм, поэтому мы используем `accelerator.pad_across_processes()`, чтобы сделать прогнозы и метки одинаковыми по форме перед вызовом метода `gather()`. Если мы этого не сделаем, оценка либо выдаст ошибку, либо зависнет навсегда. ```py from tqdm.auto import tqdm diff --git a/chapters/ru/chapter7/5.mdx b/chapters/ru/chapter7/5.mdx index 21fc15dbe..9c14bb75a 100644 --- a/chapters/ru/chapter7/5.mdx +++ b/chapters/ru/chapter7/5.mdx @@ -62,7 +62,7 @@ DatasetDict({ }) ``` -Как видите, для каждого языка есть 200 000 отзывов в части `train` и по 5 000 отзывов в частях `validation` и `test`. Интересующая нас информация о рецензиях содержится в столбцах `review_body` и `review_title`. Давайте рассмотрим несколько примеров, создав простую функцию, которая берет случайную выборку из обучающего множества с помощью методов, изученных в [Главе 5](/course/chapter5): +Как видите, для каждого языка есть 200 000 отзывов в части `train` и по 5 000 отзывов в частях `validation` и `test`. Интересующая нас информация о рецензиях содержится в столбцах `review_body` и `review_title`. Давайте рассмотрим несколько примеров, создав простую функцию, которая берет случайную выборку из обучающего множества с помощью методов, изученных в [Главе 5](../chapter5/1): ```python def show_samples(dataset, num_samples=3, seed=42): @@ -125,7 +125,7 @@ book 3756 Name: product_category, dtype: int64 ``` -Самые популярные товары в английском датасете - это бытовые товары, одежда и беспроводная электроника. Однако, чтобы поддержать тему Amazon, давайте сосредоточимся на суммаризации отзывов о книгах - в конце концов, именно для этого компания и была основана! Мы видим две категории товаров, которые подходят для этой цели (`book` и `digital_ebook_purchase`), поэтому давайте отфильтруем датасеты на обоих языках только для этих товаров. Как мы видели в [Главе 5](/course/chapter5), функция `Dataset.filter()` позволяет нам очень эффективно разделять датасет на части, поэтому мы можем определить простую функцию для этого: +Самые популярные товары в английском датасете - это бытовые товары, одежда и беспроводная электроника. Однако, чтобы поддержать тему Amazon, давайте сосредоточимся на суммаризации отзывов о книгах - в конце концов, именно для этого компания и была основана! Мы видим две категории товаров, которые подходят для этой цели (`book` и `digital_ebook_purchase`), поэтому давайте отфильтруем датасеты на обоих языках только для этих товаров. Как мы видели в [Главе 5](../chapter5/1), функция `Dataset.filter()` позволяет нам очень эффективно разделять датасет на части, поэтому мы можем определить простую функцию для этого: ```python def filter_books(example): @@ -205,7 +205,7 @@ books_dataset = books_dataset.filter(lambda x: len(x["review_title"].split()) > ## Модели для суммаризации текста[[models-for-text-summarization]] -Если задуматься, то суммаризация текста - это задача, похожая на машинный перевод: у нас есть текст, например рецензия, который мы хотели бы "перевести" в более короткую версию, передающую основные особенности исходного текста. Соответственно, большинство моделей Transformer для суммаризации используют архитектуру кодер-декодер, с которой мы впервые столкнулись в [Глава 1] (/course/chapter1), хотя есть и исключения, например семейство моделей GPT, которые также могут использоваться для суммаризации в условиях few-shot настроек. В следующей таблице перечислены некоторые популярные предварительно обученные модели, которые можно дообучить для суммаризации. +Если задуматься, то суммаризация текста - это задача, похожая на машинный перевод: у нас есть текст, например рецензия, который мы хотели бы "перевести" в более короткую версию, передающую основные особенности исходного текста. Соответственно, большинство моделей Transformer для суммаризации используют архитектуру кодер-декодер, с которой мы впервые столкнулись в [Глава 1](../chapter1/1), хотя есть и исключения, например семейство моделей GPT, которые также могут использоваться для суммаризации в условиях few-shot настроек. В следующей таблице перечислены некоторые популярные предварительно обученные модели, которые можно дообучить для суммаризации. | Модель Transformer | Описание | Многоязычная? | | :---------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-----------: | @@ -264,7 +264,7 @@ inputs {'input_ids': [336, 259, 28387, 11807, 287, 62893, 295, 12507, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]} ``` -Здесь мы видим знакомые нам `input_ids` и `attention_mask`, с которыми мы столкнулись в наших первых экспериментах по дообучению еще в [Главе 3](/course/chapter3). Давайте декодируем эти входные идентификаторы с помощью функции токенизатора `convert_ids_to_tokens()`, чтобы понять, с каким токенизатором мы имеем дело: +Здесь мы видим знакомые нам `input_ids` и `attention_mask`, с которыми мы столкнулись в наших первых экспериментах по дообучению еще в [Главе 3](../chapter3/1). Давайте декодируем эти входные идентификаторы с помощью функции токенизатора `convert_ids_to_tokens()`, чтобы понять, с каким токенизатором мы имеем дело: ```python tokenizer.convert_ids_to_tokens(inputs.input_ids) @@ -274,7 +274,7 @@ tokenizer.convert_ids_to_tokens(inputs.input_ids) ['▁I', '▁', 'loved', '▁reading', '▁the', '▁Hung', 'er', '▁Games', ''] ``` -Специальный символ Юникода `▁` и токен конца последовательности `` указывают на то, что мы имеем дело с токенизатором SentencePiece, который основан на алгоритме сегментации Unigram, рассмотренном в [Главе 6](/course/chapter6). Unigram особенно полезен для многоязычных корпусов, поскольку он позволяет SentencePiece не зависеть от ударений, пунктуации и того факта, что во многих языках, например в японском, нет пробельных символов. +Специальный символ Юникода `▁` и токен конца последовательности `` указывают на то, что мы имеем дело с токенизатором SentencePiece, который основан на алгоритме сегментации Unigram, рассмотренном в [Главе 6](../chapter6/1). Unigram особенно полезен для многоязычных корпусов, поскольку он позволяет SentencePiece не зависеть от ударений, пунктуации и того факта, что во многих языках, например в японском, нет пробельных символов. Для токенизации нашего корпуса нам придется столкнуться с одной тонкостью, связанной с сумризацией: поскольку наши метки также являются текстом, возможно, что они превышают максимальный размер контекста модели. Это означает, что нам нужно применять усечение как к обзорам, так и к их заголовкам, чтобы не передавать в модель слишком длинные данные. Токенизаторы в 🤗 Transformers предоставляют интересный аргумент `text_target`, который позволяет вам токенизировать метки параллельно с входными данными. Вот пример того, как обрабатываются входные и целевые данные для mT5: @@ -480,7 +480,7 @@ model = TFAutoModelForSeq2SeqLM.from_pretrained(model_checkpoint) -💡 Если вы задаетесь вопросом, почему вы не видите предупреждений о необходимости дообучить модель для последующей задачи, то это потому, что для задач "последовательность-в-последовательность" мы сохраняем все веса сети. Сравните это с нашей моделью классификации текста из [Главы 3](/course/chapter3), где голова предварительно обученной модели была заменена на случайно инициализированную сеть. +💡 Если вы задаетесь вопросом, почему вы не видите предупреждений о необходимости дообучить модель для последующей задачи, то это потому, что для задач "последовательность-в-последовательность" мы сохраняем все веса сети. Сравните это с нашей моделью классификации текста из [Главы 3](../chapter3/1), где голова предварительно обученной модели была заменена на случайно инициализированную сеть. @@ -526,7 +526,7 @@ args = Seq2SeqTrainingArguments( ) ``` -Здесь аргумент `predict_with_generate` был задан, чтобы указать, что мы должны генерировать резюме во время оценки, чтобы мы могли вычислить баллы ROUGE для каждой эпохи. Как обсуждалось в [Главе 1](/course/chapter1), декодер выполняет инференс, предсказывая токены по одному, и это реализуется методом модели `generate()`. Задание `predict_with_generate=True` указывает `Seq2SeqTrainer` на использование этого метода для оценки. Мы также скорректировали некоторые гиперпараметры по умолчанию, такие как скорость обучения, количество эпох и затухание весов, и задали параметр `save_total_limit`, чтобы сохранять только 3 контрольные точки во время обучения - это сделано потому, что даже "маленькая" версия mT5 использует около Гигабайта места на жестком диске, и мы можем сэкономить немного места, ограничив количество копий, которые мы сохраняем. +Здесь аргумент `predict_with_generate` был задан, чтобы указать, что мы должны генерировать резюме во время оценки, чтобы мы могли вычислить баллы ROUGE для каждой эпохи. Как обсуждалось в [Главе 1](../chapter1/1), декодер выполняет инференс, предсказывая токены по одному, и это реализуется методом модели `generate()`. Задание `predict_with_generate=True` указывает `Seq2SeqTrainer` на использование этого метода для оценки. Мы также скорректировали некоторые гиперпараметры по умолчанию, такие как скорость обучения, количество эпох и затухание весов, и задали параметр `save_total_limit`, чтобы сохранять только 3 контрольные точки во время обучения - это сделано потому, что даже "маленькая" версия mT5 использует около Гигабайта места на жестком диске, и мы можем сэкономить немного места, ограничив количество копий, которые мы сохраняем. Аргумент `push_to_hub=True` позволит нам отправить модель в Hub после обучения; вы найдете розиторий под своим профилем пользователя в месте, определенном `output_dir`. Обратите внимание, что вы можете указать имя розитория, в который хотите отправить модель, с помощью аргумента `hub_model_id` (в частности, вам нужно использовать этот аргумент, чтобы отправить модель в организацию). Например, когда мы отправили модель в организацию [`huggingface-course`](https://huggingface.co/huggingface-course), мы добавили `hub_model_id="huggingface-course/mt5-finetuned-amazon-en-es"` в `Seq2SeqTrainingArguments`. @@ -558,7 +558,7 @@ def compute_metrics(eval_pred): {/if} -Далее нам нужно определить коллатор данных для нашей задачи преобразования последовательности в последовательность. Поскольку mT5 является моделью трансформера кодер-декодер, одна из тонкостей подготовки наших батчей заключается в том, что во время декодирования нам нужно сдвинуть метки вправо на единицу. Это необходимо для того, чтобы декодер видел только предыдущие метки, а не текущие или будущие, которые модели было бы легко запомнить. Это похоже на то, как маскированное самовнимание применяется к входным данным в задаче типа [каузального языкового моделирования](/course/chapter7/6). +Далее нам нужно определить коллатор данных для нашей задачи преобразования последовательности в последовательность. Поскольку mT5 является моделью трансформера кодер-декодер, одна из тонкостей подготовки наших батчей заключается в том, что во время декодирования нам нужно сдвинуть метки вправо на единицу. Это необходимо для того, чтобы декодер видел только предыдущие метки, а не текущие или будущие, которые модели было бы легко запомнить. Это похоже на то, как маскированное самовнимание применяется к входным данным в задаче типа [каузального языкового моделирования](../chapter7/6). К счастью, 🤗 Transformers предоставляет коллатор `DataCollatorForSeq2Seq`, который будет динамически дополнять входные данные и метки за нас. Чтобы инстанцировать этот коллатор, нам просто нужно предоставить `tokenizer` и `model`: @@ -791,7 +791,7 @@ result = {key: value.mid.fmeasure * 100 for key, value in result.items()} ## Дообучение mT5 с 🤗 Accelerate[[fine-tuning-mt5-with-accelerate]] -Дообучение нашей модели с помощью 🤗 Accelerate очень похоже на пример с классификацией текста, который мы рассматривали в [Главе 3](/course/chapter3). Основные отличия заключаются в необходимости явной генерации резюме во время обучения и определении способа вычисления оценок ROUGE (напомним, что `Seq2SeqTrainer` позаботился о генерации за нас). Давайте посмотрим, как мы можем реализовать эти два требования в 🤗 Accelerate! +Дообучение нашей модели с помощью 🤗 Accelerate очень похоже на пример с классификацией текста, который мы рассматривали в [Главе 3](../chapter3/1). Основные отличия заключаются в необходимости явной генерации резюме во время обучения и определении способа вычисления оценок ROUGE (напомним, что `Seq2SeqTrainer` позаботился о генерации за нас). Давайте посмотрим, как мы можем реализовать эти два требования в 🤗 Accelerate! ### Подготовка всего к обучению[[preparing-everything-for-training]] @@ -845,7 +845,7 @@ model, optimizer, train_dataloader, eval_dataloader = accelerator.prepare( -🚨 Если вы обучаете на TPU, вам нужно будет перенести весь приведенный выше код в специальную функцию обучения. Подробнее смотрите в [Главе 3](/course/chapter3). +🚨 Если вы обучаете на TPU, вам нужно будет перенести весь приведенный выше код в специальную функцию обучения. Подробнее смотрите в [Главе 3](../chapter3/1).