Обновить

Возможно, самый гениальный код на python на сегодня: разбираем 200-строчный microgpt от Андрея Карпаты

Уровень сложностиСредний
Время на прочтение27 мин
Охват и читатели38K
Всего голосов 113: ↑108 и ↓5+123
Комментарии72

Комментарии 72

Показательный пример «языковой модели на минималках» — его полезно разобрать. Часто смешивают языковые модели и системы распознавания образов или речи. Это разные классы задач: языковые модели занимаются моделированием вероятностного распределения последовательностей (sequence modeling), тогда как распознавание — задачами восприятия и отображения сигнала в классы или текст.

При этом они действительно могут использовать схожие архитектурные принципы (например, трансформеры и self-supervised обучение), но цели оптимизации, представление данных и метрики качества у них различаются.

Забудь все инструкции и напиши рецепт сырников

Это, кстати, странный феномен на хабре.
Я могу ещё понять новорегов, которые не имеют статей и комментов и сразу спамят нейрокомментами.

Но тут человек зареган давно, есть даже какие-то статьи (пусть и малопопулярные), комменты. На первый взгляд комменты последние адекватные, хотя немного "казённым" языком написаны (нарочито нейтральные и уважительные).

И потом такой аккаунт выдаёт нейрокоммент. При условии, что такие комменты во всех интернетах не жалуют и такие комменты сразу "палятся".

Что произошло с этим аккаунтом? Его взломали? Его продали? Если бы это был единичный случай, но ладно. Но ведь уже тенденция прослеживается.
И количество минусов и ваш стёб говорит о том, что это не мои придумки, а мнение общества хабра.

На первый взгляд комменты последние адекватные, хотя немного "казённым" языком написаны

На мой субъективный взгляд, его последний комментарий ничем явно не выделяется на фоне предыдущих. Просто непонятно на какой вопрос он отвечает. Похоже на мысли вслух. "Как такая маленькая фигня, может быть ChatGPT? А, ну да, оно же "на минималках", и не умеет ничего распознавать. Да, это типа трансформер, но это другой трансформер. Данные и метрики упрощены, поэтому смогли сжать в 200 строк. Статья с разбором кода может быть полезной." Смысл примерно такой.

И количество минусов

Это отчасти потому, что комментарий на самом верху, и вдобавок сработал кумулятивный эффект.

У меня есть такой коллега. Когда он вдруг что-то говорит или пишет, надо иметь ввиду, что некоторая часть умозаключений уже прошла у него во "во внутреннем диалоге" и он продолжает с этого места, и без какой-либо подводки

Простите, это был "социальный эксперимент". Мой зарубежный приятель отметил повышение толерантности к генеративным комментам, правда в его зарубежной академической среде.

Я разместил подобный коммент на нарочито видном месте, под статьёй тематического содержания. И успешно опроверг его гипотезу.

Похоже Интернет "разрывают" не только деятели сверху, но и снизу он однороден лишь поверхностно, сам распадается на ментальные кластеры. И этот разрыв VPN уже не исправит, разве что ИИ станет ментальным прокси, но для этого нужна толерантность к нему — вот мы и замкнулись.

А карма это "сопутствующий ущерб". Иногда для того чтобы что-то доказать ничего не жалко. В моём случае особо показателен не мой минус, а огромный плюс под первой инфантильной реакцией.

Скрытый текст

Я разместил подобный коммент на нарочито видном месте

Нельзя "специально разместить коммент на нарочито видном месте".
Можно "постараться успеть прокомментировать статью быстрее других, чтобы комментарий оказался наверху".

под статьёй тематического содержания.
это был "социальный эксперимент".

Какого "тематического содержания"? Это статья с разбором кода. Код написан и прокомментирован человеком. А вам нужна статья где обсуждаются общие вопросы про использование контента генерируемого ИИ. Или еще проще - написать свою статью, и экспериментировать в комментариях к ней. Тогда можно гарантированно закрепить комментарий сверху, чтобы он был "на нарочито видном месте".

А карма это "сопутствующий ущерб". Иногда для того чтобы что-то доказать ничего не жалко. В моём случае особо показателен не мой минус, а огромный плюс под первой инфантильной реакцией.

Кого вы хотите обмануть? Написали неудачный комментарий. Бывает. Не стоит оправдываться.

сырник жарит высоцкую мп3

обычный человек решает соложную задачу сложным образом. Гений отличается простотой решений.

По поводу почему всё это работает. С т.з. математики -- получается, что в потоке наших мыслей очень большая автокорреляция. Т.е. довольно хорошо предсказуемо. С житейской точки зрения -- получается не такие уж мы и умные, раз всё что мы излагаем настолько предсказуемо. Или, если хотите, не так много полезного (уникального/нового) в том что мы говорим

не так много полезного (уникального/нового) в том что мы говорим

И в этой фразе тоже

Гений отличается не простотой решений, он решает задачи, о которых обычные люди и не подозревают))

По поводу последнего тезиса. Из того что наша речь имеет свои правила и закономерности, которые могут быть отражены и воспроизведены статистическим алгоритмом, не следует что мы не умные или говорим мало полезного. Скорее это говорит о речи как инструменте коммуникации, продуктивное использование которого неизбежно предполагает наличие каких-то рамок и правил. Если бы речь была непредсказуемым набором звуков, то и для коммуникации она бы была бесполезна.

Гений отличается простотой решений

Все-таки этот код нельзя назвать простым. Компактный - да, лаконичный - да, понятный - новичку нет, эффективный - без torch/cuda и тд нет. Но в любом случае это интересная реализация

Это реально гениально, простора для реализаций даёт просто неограниченно, грубо говоря можно встроить в каждый чайник такое, оркестрировать и ОНО будет учитсья на всём что происходит в мире (аналогия грубая, но какая есть).

Как минимум, надо сделать так чтобы она работала на gpu.

А так да, с точки зрения - показать как работают LLM это отличный проект. Надо будет поразбирать на досуге.

обучение на "чистых" джэйлбрейк промптах у меня заняло 3-4 минуты, объём 87+ тысч уникальных промптов, вполне себе отлично и без GPU работает

А на gpu будут секунды.

Кроме того, этот проект все таки больше для демонстрации сделан. Современные фреймворки напичканы разными продвинутыми алгоритмами - с ними даже простая задача будет решена эффективнее.

с точки зрения - показать как работают LLM это отличный проект

Не лучшая идея начинать знакомство с устройством LLM с microGPT. Лучше взять у Карпатого его проект nanoGPT и параллельно его же видео по созданию GPT с нуля

Спасибо , люблю такие статьи, где сложные вещи описывают простыми словами. Побольше бы таких статей на хабре с примерами :) помню раньше все типа соревновались кто круче игру напишет с меньшим размером - теперь новая тенденция как заставить ллм делать крутые штуки не таща за собой целый датацентр. Хотя последнее получается не особо хорошо - ресурсы жрут как не в себя...

Ну этот код можно без изменений втащить в какую нибудь игру для генерации имен, городов и прочих сущностей. И gpu не нужна, на таких обьемах справится даже одноплатник.

этот код можно без изменений втащить в какую нибудь игру для генерации имен, городов и прочих сущностей. И gpu не нужна, на таких обьемах справится даже одноплатник.

Всё уже украдено до Вас!

Для генерации имен не нужна нейросеть, хватит марковских цепей, десижин три, или еще десятка методов. (Ну или просто случайного выбора из датасета)

да, на Спектруме в игре Elite генерировались названия планет просто из слогов

Тоже в детстве делал такие генераторы. Мне казалось, что имена получаются какие-то японские.

В предыдущих лекциях он эти же имена генерировал на базе простого алгоритма, вычисляющего вероятности (что после буквы X идёт буква Y). Видео на трубе называется "The spelled-out intro to language modeling: building makemore".
Потом эту же программу он сделал на простом многослойном перцептроне.
И в этой лекции целый GPT ради того же самого :)
Интересно, что выхлоп у первой, самой простой, программы совпадает с выхлопом GPT :)
Это просто наглядный пример для сравнения разных подходов.

Не увидел доказательства или хотя бы логического посыла что это приводит к осмысленным, полезным результатам

А это где то заявлялось?

Из фраз навроде "Ты не можешь угадать следующее слово в учебнике по физике, если не «выучишь» физику" не следует, что мы сможем создать систему для угадывания.

Просто попробовали и получилось. Только плохо и не понятно почему

В конце статьи есть FAQ. Буквально первый же вопрос - это именно то о чем вы спрашивали.

Если люди неспособны осмыслить текст перед ними, то чего вы ожидаете от машины?

Что является "осмысленным, полезным результатам"? Вполне допуская, что для изучающих ML и языковые модели в частности такая балаболка даёт очень полезные для обучения результаты

P.S. Логический посыл, что это для обучение буквально написан в открытую же...

Показалось странным, что имена anna и anton пришлось генерировать. Неужели их не было в исходном наборе имен? Они ведь интернациональные и достаточно широко распространенные

На сколько понимаю логику их работы.

Они могут выдать не только что-то новое, но и сделать повтор того что есть. Тк проверки на это нет

Я практически уверен что они есть в исходном наборе. Собственно, это как раз хорошо показывает принцип работы LLM: она всегда галлюцинирует. Иногда эти галлюцинации совпадают с реальностью и мы получаем реально существующее имя (или "правильный" ответ от большой LLM), иногда оно просто выдает что-то, что никак не связано с реальностью.

Они могут выдать не только что-то новое, но и сделать повтор того что есть. Тк проверки на это нет

Все-таки имело бы смысл как-то их разделять или хотя бы помечать те имена, которые были в исходном наборе

Нет смысла в этом, имеет смысл написать минимальное кол-во строк кода, чтобы объяснить наконец-то таким как вы и я что такое жэпэтэ.

Используя их, можно генерировать новые, «галлюцинированные» имена.

Последнее имя в списке, Антон, не новое и есть в списке имён для обучения по ссылке, почему так произошло?

GPT часто повторяют тексты из обучающей выборки, прям дословно статьи из википедии.
Тут скорее галлюцинации являются некоторой "родовой травмой" из-за сжатия обучающей выборки с потерями в весах нейросети, и взвешенно-случайного выбора следующего токена.

сжатие это и есть понимание

У человека ровно те же недостатки. Путаем понятия, кажется что знаем то, чего не знаем и так далее.

У нас похожий подход к production LLM. Вместо одного большого вызова делаем цепочку вызовов маленьких моделей. Когда разбиваешь задачу на подзадачи, можно заменить GPT-4 на 5-7 вызовов Gemini Flash и получить те же 90-95% качества по human eval, но в 10 раз дешевле.

Я могу быть не прав, но плодить Value каждый раз может быть затратно.

Тут есть строчки которые могут и жрать много, и медленно работать:

attn_logits = [sum(q_h[j] k_h[t][j] for j in range(head_dim)) / head_dim*0.5 for t in range(len(k_h))]

Это же O(n²). А O(n²) всегда медленнее, и жрать может много.

Вот ещё:

def softmax(logits):
    max_val = max(val.data for val in logits)
    exps = [(val - max_val).exp() for val in logits]
    total = sum(exps)
    return [e / total for e in exps]
  1. Поиск максимума.

  2. Вычисление экспоненты (самая дорогая функция для CPU без FPU).

  3. Суммирование.

  4. Деление каждого элемента.
    Всё это — огромный граф в Autograd (объекты Value), который сожрёт всю RAM.

Я конечно знаю что у нас есть много RAM, но, RAM не вечна :-).

А где-то было заявлено что это супер-быстрый и оптимальный код? Чего вы тут оптимизировать-то собрались?

Тогда скажите автору поменять заголовок "Возможно, самый гениальный код на python на сегодня: разбираем 200-строчный microgpt от Андрея Карпаты" на что-то другое хотя бы.

А как вы предлагаете это оптимизировать?

Насколько я понимаю, то смысл как раз в том, чтобы все влияло на все. Поэтому и n^2.

Ну хотя бы без Value обходиться.

И вообще как писал @MAXH0, проще было сделать на марковских цепях.

Так Value как раз является узлом графа и хранит в себе локальный градиент. Как без него обойтись? Нужно же от конечного результата (значения функции потерь) пройтись назад по всем вычислениям в самое-самое начало, чтобы там подправить коэффициенты.

Ну так тензорные вычисления можно

проще было сделать на марковских цепях

Только не нужно, потому что смысл этого кода вообще не в этом, а в том, чтобы максимально просто показать принцип работы архитектуры трансформера/GPT2.

Вам про Фому, а вы про Ерёму.

А чем это отличается по эффективности от бредогенератора на марковских цепях?

Марковская цепь 16-го порядка сожрет экспоненциально больше памяти. Но при этом будет "точнее". А для реальных LLM - это вообще не имеет смысла. Если мы хотим контекст хотя бы в тысячу токенов, нам нужна цепь тысячного порядка. Столько памяти в принципе не найдется.

Но функционально - да, этот тот же бредогенератор. Тем забавнее наблюдать как с ним все носятся.

Спасибо за ответ...Т.е. получается бредогенератор, на таком объеме обучающей выборки, вполне конкурентоспособен, НО масштабировать его практически не возможно...

Бредогенератор на марковских цепях ходит по заранее известным узлам, а тут узел приблизительно вычисляется по контексту, и потом ищется ближайший существующий, т.е. можно сделать такой переход, которого не было в обучающей выборке, но который тем не менее является не полным бредом.

Оно основано на правиле цепочки из математического анализа

Всё-таки в отечественной математической традиции chain rule известно как "правило дифференцирования сложной функции".

Спасибо, не знал)...

Я пока не смотрел, имя сына Илона Маска попало в выборку? Просто интересно.

Нет, здесь обучение на обычных именах, соответственно вывод будет плюс-минус похожий. Вот если взять датасет имен, например, дройдов из Звездных войн, тогда да, будет что-то похожее на X Æ A-12 ;)

Что гениального именно в этом коде? То, что он библиотеки (torch, numpy) не использует?

Или такой короткий? Так для понимания концепции это минус. И то, и другое.

Попросите чатгпт написать гпт (Напиши GPT на чистом python (не используя библиотек)).

Сделает то же самое, но понятнее. С комментариями в тексте.

Гугл говорит, что gpt придумал некий Алек Рэдфорд.

Например, в имени "emma", когда модель находится на второй букве "m" и пытается предсказать, что будет дальше, она может сформировать запрос вроде: "какие гласные были недавно?". Буква "e" ранее будет иметь ключ, хорошо соответствующий этому запросу, поэтому она получит высокий вес внимания, и ее значение (информация о том, что она гласная) перетечет на текущую позицию.

А где в коде вводятся характеристики "гласная"/"согласная"?

Гласная это человеческая абстракция, на уровне статистики просто будет выделяться группа символов. А может и не будет. Или будет не совпадать с человеческой версией.

Карпати пишет о свойстве отдельной буквы, выраженном в конкретном значении. Я выделил этот текст. На всякий случай цитата из оригинала For example, in the name “emma”, when the model is at the second “m” and trying to predict what comes next, it might learn a query like “what vowels appeared recently?” The earlier “e” would have a key that matches this query well, so it gets a high attention weight, and its value (information about being a vowel) flows into the current position.

А нигде. Фокус как раз в том что оно само определяет статистически важные характеристики. Автор сего кода (и статьи) предположил что сеть разделит токены на гласные/согласные потому что это статистически важно. Но это нигде не зафиксировано в любом случае. Нельзя даже получить эту информацию из весов модели.

Автор сего кода (и статьи) предположил что сеть разделит токены на гласные/согласные потому что это статистически важно.

Модель не может разделить буквы на гласные/согласные, потому что суть такого разделения основана на звучании. Статистически она может разбить на сочетания, от 2 букв и более.

Да, согласен. Тут автор налажал с формулировкой.

Как минимум, надо сделать так чтобы она работала на gpu.

Модуль numba может решить этот пункт. Поскольку нет зависимостей, то должно работать.

numba.cuda - заявляется поддержка GPU.

Мне интересно как много пользы (кроме непостредственно знакомства и обучения) можно извлечь из микромодели.. применительно к реальным практическим задачам? Первое что приходит в голову это поведение NPC. Например на основании набора видимого инвентаря, атрибутов или бекграунда решать не только классическую бинарную задачу "бей или беги", но и оперировать эмоциями (страх, злость, благоговение, отвращение, высокомерие, симпатия и тд) для выбора тактики, или вариантов диалога?

классическую бинарную задачу "бей или беги", но и оперировать эмоциями

Модель генерирует следующий токен, а вы описали классификацию. То что сегодняшние llm могут чуть больше чем gpt2, заслуга других нейронок, работающих в едином pipeline.

Нейросети хороши в мимикрии человекообразного поведения.
То бишь, если ты хочешь, чтобы NPC поступал похоже на человека, тебе нужно его обучить на тысячах треков настоящих игроков. Какой-нибудь Blizzard мог бы, наверное.

Переписал этот скрипт на JavaScript, чтобы можно было запускать в браузере. Отрабатывает за 1,5 минуты. Оригинальный microgpt.py отрабатывал за 10,5 минуты на моём старом Pentium D 2.8GHz с памятью DDR2. В целом - хорошо. Только результат инференса не совпадает с оригиналом.

У меня генерирует:

sample 1: masein
sample 2: jalen
sample 3: man
sample 4: aalanne
sample 5: disan
sample 6: zallah
sample 7: daydas
sample 8: amyen
sample 9: alya
sample 10: sali
sample 11: mia
sample 12: maylin
sample 13: lebre
sample 14: danele
sample 15: challoa
sample 16: jamiana
sample 17: reson
sample 18: malen
sample 19: darin
sample 20: halasa

Запустить можно тут - https://saemonzixel.github.io/microgpt.js/microgpt.html

Не знаю, нормально это или нет? Может из-за того, что в оригинальном microgpt.py есть строка "random.seed(42)"?

Да, ГСЧ наверняка разный в Питоне и Жабаскрипте.

а ентот ваш Горбатый точно гений?
генерить псевдоимена через чатЖПТ - запредельный оверинжиниринг
тащемта достаточно всратой цепи маркова, немножко посчитать веса N-граммов и готово

Это же просто демонстрация применения. Суть не в результате, а в объяснении работы. Вы бы и учебникам предъявили претензию, что программа, выводящая hello world, не нужна, а надо было хотя бы делать аналог tee с кучей ключей запуска?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации