Что такое Марк?
Сейчас Марк от медиа Маркер — это генеративная языковая модель, которая умеет придумывать новостные статьи без помощи человека. Марк может писать свободно, опираясь на свой опыт и выбирая каждое слово самостоятельно. Либо же мы можем помочь ему с темой новости и дать начало заголовка или заголовок, тогда Марк продолжит нашу мысль.
Что такое языковые модели?
Говоря просто, языковые модели — это когда мы пытаемся найти закономерности и правильные речевые последовательности в человеческом языке, а потом на основе этого пробуем создать “язык” независимо от самого человека.
Как это можно сделать?
Можно оценить вероятность появления какого-то словосочетания в языке. Иными словами, каждый раз мы отвечаем себе на вопрос: корректно ли использовать такую последовательность слов (формулировку) в русском языке? Если это допустимо, то вероятность употребления такого словосочетания достаточно велика, а значит мы используем языковую конструкцию, которую могут понять остальные, знающие русский.
В противном случае появляются конструкции вроде “лето наступила”, по правилам нашего языка составленные некорректно, а значит, вероятность появления такой конструкции в речи довольно мала.
Главная идея: правильные языковые конструкции могут быть созданы не только человеком, но и искусственным интеллектом (или роботом). Соответственно между хорошей языковой моделью (которая хорошо понимает правила нашего языка) и человеком можно наладить продуктивную взаимную коммуникацию. И вот это уже идея на миллион!
Ты сам можешь генерировать новости!
Начнём с простого: сейчас мы покажем тебе, как генерировать новости. Целиком код для генерации лежит на COLAB — можно запустить всё и посмотреть, какую новость Марк сгенерирует для тебя!
Нашу обученную модель мы выложили на Hugging Face — технологический стартап с активным open source сообществом, который способствовал внедрению моделей на основе трансформеров (к примеру, предшественников и самой ChatGPT) во всем мире.
Благодаря стартапу к большому количеству тяжелых (и умных) моделей можно подключиться просто по API и самому творить магию, не имея огромных вычислительных машин.
Например, вот так мы получим доступ к нашей модели:
from transformers import GPT2LMHeadModel, GPT2Tokenizer
path = 'AnyaSchen/news_gpt-3'
tokenizer = GPT2Tokenizer.from_pretrained(path)
model = GPT2LMHeadModel.from_pretrained(path).to(DEVICE)
Возможно, нужно будет установить библиотеку transformers. Например, вот так:
!pip install transformers
Ну, а новости ты можешь сгенерировать вот этим кодом:
inp = input('Введи начало заголовка или просто нажми Enter:')
inp = inp if len(inp) > 0 else tokenizer.bos_token #токен начала предложения
input_ids = tokenizer.encode(inp, return_tensors="pt").to(DEVICE)
out = model.generate(input_ids,
do_sample = True,
num_beams = 3,
temperature = 2.0,
top_p = 0.9,
max_length = 200,
stopping_criteria = StoppingCriteriaList([stop_criteria]),
eos_token_id = tokenizer.eos_token_id,
bos_token_id = tokenizer.bos_token_id).to(DEVICE)
print(tokenizer.batch_decode(out, skip_special_tokens=False)[0])
Что тут происходит? Сейчас расскажем.
Шаг 1: Мы задаём начало заголовка нашей новости в переменную input
. Если вдруг нам нечего дать в начало, и мы нажимаем Enter, то подставляется специальный символ, обозначающий для нашей модели начало предложения (мол, генерируй давай с самого начала).
inp = input('Введи начало заголовка или просто нажми Enter:')
inp = inp if inp else tokenizer.bos_token #токен начала предложения
Шаг 2: Дальше мы берём наш входной текст и говорим (дословно): токенайзер, тебе нужно заэнкодить наше начало.
input_ids = tokenizer.encode(inp, return_tensors="pt").to(DEVICE)
По факту мы берем наш кусочек заголовка, пилим его на слова (это делает токенайзер) и преобразуем каждое слово в большие наборы чисел (это и делает энкодер), к которым можно получить доступ по уникальным, назначенным им номерам.
Зачем так?
Цель: Мы пытаемся научить компьютер “понимать” наш язык.
Компьютер хранит наши буковки числами, например, в виде ASCII-кода, где каждому символу присваивается уникальный номер (1, 2, 3…), а потом оно конвертируется в нолики и единички. Так вот слова в такой системе просто набор чисел, например:
котик → 1000011101010000111110100010000101000011100010000111010 (попробуй сам)
Но в нашем языке у каждого слова есть смысловой окрас и значение: для нас грусть и радость имеют противоположные смыслы, а в целом — это чувства. Компьютер должен ощущать эту разницу между семантикой слов, чтобы хорошо “говорить” на нашем языке, но для него это всё равно набор ноликов и единичек, не имеющих смысла. Например, вот тебе послание:
10000011010100010000001000011000010001000001100001100001000011001010001000111100001110001000011101010110010000010001000010100010010111000001000100000110001000011100001111111000011010110001000000100001
Понятно, что тут ничего не понятно: ни сколько тут слов, ни что они собой значат. Ты можешь прочитать эти 1 и 0, но в чем смысл, это просто цифры, да?) Ещё одно послание (как у тебя дела с китайским?) — 你會成功的! Но ты не поймешь, пока кто-то не переведёт это на понятный тебе язык.
Энкодер делает именно это: переводит с человеческого на понятный компьютеру.
Проблема: как объяснить компьютеру, что это за слова и что они значат?
Умные ученые нашли решение:
разбиваем предложения на кусочки, из которых могут быть составлены родственные слова (именно это и делает токенайзер в нашей модели)
-
превращаем каждый кусочек в вектор из чисел, который будет отвечать за семантику.
Почему кусочки, а не слова? Потому что кот и котик — это про одно и тоже, но настроение меняется)
Можно сравнить с настройкой робота из фильма Интерстеллар: 70% честности, 80% позитивности и т.д. Мы задаем какие-то параметры, по которым можно “почувствовать” каждое слово, но не нам, а компьютеру.
В реальности, конечно, все сильно сложнее…???? Но идея понятна, да?
-
Каждому кусочку присваивается уникальный номер, и энкодер нам возвращает именно его. Почему так? Чтобы общаться, мы используем слова в определенной последовательности и не сообщаем собеседнику все трактовки каждого сказанного нами слова, надеясь, что наше понимание слов идентично. Так и с компьютером: наборы уникальных номеров — это его слова.
Например, слово “нейросеть”, переведенное на язык нашей модели, выглядит так:
[[ 845, 648, 1380 ]]
Шаг 3: Генерация на понятном компьютеру языке
out = model.generate(input_ids,
do_sample = True,
num_beams = 3,
temperature = 2.0,
top_p = 0.9,
max_length = 200,
stopping_criteria = StoppingCriteriaList([stop_criteria]),
eos_token_id = tokenizer.eos_token_id,
bos_token_id = tokenizer.bos_token_id).to(DEVICE)
Мы научили языковую модель генерировать новости (как? Потом расскажем), но создаёт она их, подбирая семантически каждый кусочек по своим выученным закономерностям и правилам. Чтобы новости получались разнообразнее и умнее, чем тексты у T9, мы использовали самые разные параметры генерации: температура, количество звеньев и т.д. Если будет интересно — расскажем, как они влияют на процесс (можешь поменять значения у себя в коде — увидишь, как всё ломается).
Из интересного тут — критерий остановки (код ниже тоже тебе нужен).
class KeywordsStoppingCriteria(StoppingCriteria):
def __init__(self, keywords_ids:list):
self.keywords = keywords_ids
def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
if input_ids[0][-1] in self.keywords:
print(input_ids)
return True
return False
stop_criteria = KeywordsStoppingCriteria(tokenizer.encode(tokenizer.eos_token, return_tensors="pt").to(DEVICE))
Что на выходе генерации? Чтобы модель не выдавала бесконечные потоки слов, мы ограничили длину предложения в 200 слов (смотри параметры генерации). Но это не всё, ей нужно помочь с окончанием процесса в момент, когда она сгенерировала свою логическую мысль и напечатала специальный токен конца предложения <eos>
. Для этого нужен код выше: остановить генерацию, когда увидели ключевое слово (токен) для остановки.
После выполнения этого шага генерации в переменной out
будут лежать числа — уникальные значения кусочков, которые наша языковая модель нагенерировал (aka новости, только на языке, понятном компьютеру).
Шаг 4: Перевести это обратно на человеческий
print(tokenizer.batch_decode(out, skip_special_tokens=False)[0])
Мы перевели человеческий в машинный, машина нагененерировала нам новости на своем языке, а теперь что? Правильно, машинный на человеческий, пожалуйста, чтобы нам понять. → Это и делает декодер.
И вот нам выводится новость, которая поделена на специальные токены: начала, отделения заголовка от описания и конца предложения. Чтобы эти токены нормально сработали, нужно вначале их показать токенайзеру (смотри, у нас и такие специальные “слова” есть).
SPECIAL_TOKENS = {'bos_token':'<bos>','eos_token' :'<eos>', 'pad_token':'<pad>', 'sep_token': '<sep>'}
tokenizer.add_special_tokens(SPECIAL_TOKENS)
Напоминаем, что целиком код для генерации можно найти тут: COLAB
Что же ты сегодня узнал:
Что такое языковая модель
Как происходит генерация кода в языковых моделях
Энкодер переводит с человеческого на машинный, а декодер — наоборот
Токенайзер пилит слова на кусочки, а модель — обрабатывает семантику этих кусочков
Автор статьи: @anyaschenikova
Комментарии (7)
cry_san
00.00.0000 00:00Выдает ошибку на последнем шаге
marker_media Автор
00.00.0000 00:00Починили:)
Вероятно, случились сложности с подключением к видеокарте, поскольку часть кода удалили (случайно, остались права на редактирование у всех пользователей по ссылке). Теперь все должно быть в порядке!
vladimircape
00.00.0000 00:00Итак в мире было много белого шума(перепечатка новостей ,сеошные статьи, пропаганда и ....) так теперь и мл модели увеличат его на порядок
venanen
00.00.0000 00:00Интересно было бы посмотреть на процесс fine-tuning модели, хотелось бы такую статью
anonymous
НЛО прилетело и опубликовало эту надпись здесь
dimars08
Вы серьезно решили задать этот главный вопрос?;