Слушаю книгу Питера Тиля ,"от нуля к единице" и там задаётся вопрос: что очевидное сейчас всем на самом деле не является правдой. Пришел в голову такой ответ: IT будет расти, у него ещё не выбран весь потенциал и профессия программиста перспективная. ИМХО все эти утверждения неверны. И хреново то, что я сам по уши а этой индустрии. 😀
Смею предположить, что дальше выстрелит что-то вроде киборгов. Или совмещение человека и технологий. Тот тюнинг, коим сейчас увлечены женщины, перекинется на мужчин, как только он сможет дать им физическую силу. Например, на деньги военных.
Смею предположить, что дальше выстрелит что-то вроде киборгов. Или совмещение человека и технологий. Тот тюнинг, коим сейчас увлечены женщины, перекинется на мужчин, как только он сможет дать им физическую силу. Например, на деньги военных.
- где этот ваш интеллект? Ну скажите мне, где? Это такая же несуществующая вещь, как душа. Сколько не препарировали человека, не нашли ни ту, ни другую. Есть только очень сложные рефлексы. А разобраться мы в них не можем потому, что их сложность выше нашей собственной, что вполне логично. Всё, точка.
🤣
🤣
Недавно на HF зарелизили веса MobileLLM https://arxiv.org/pdf/2402.14905 , у которой для уменьшения размеров модели одни и те же веса используются повторно в разных блоках трансформера. Как я не пробовал повторить их успешный успех в CV-нейронках, у меня ничего не вышло. И по-разному делал повторения, и повторял только часть блоков. Loss и accuracy на проверочной выборке всегда были значительно хуже, чем без повторений. Только начал проявляться стабильно один эффект, который я прежде никогда не наблюдал: скатывание нейронки к не обучаемому состоянию, когда в задачи классификации на CIFAR 10 accuracy равно 10.00%. Я не разбирался, но подозреваю, что там просто всегда нули на выходе. А причина, я предполагаю, в увеличении глубины сети. Сеть из свёрток и активации ReLU.
За три недели удалось сгенерить примерно 320 тыс. небольших историй https://github.com/MichaelMonashev/TinyStories-ru . Думаю, пока достаточно, а то все другие эксперименты простаивают...
GitHub
GitHub - MichaelMonashev/TinyStories-ru
Contribute to MichaelMonashev/TinyStories-ru development by creating an account on GitHub.
Пришла мысль, что галлюцинации LLM - это признак отсутствия интеллекта.
Продолжая тему повторений блоков в сети... Похоже я нащупал место применения повторяющихся блоков в нейросетях...
Если взять одну свёртку, то такая сеть будет обучена заметно хуже, чем если б та же свёртка была повторена 10 раз. Но если взять 10 сверток с разными весами, то сеть обучится ещё лучше. Если же начать повторять эти 10 свёрток на разный манер, то получающиеся сети будут обучаться хуже, чем просто 10 свёрток. Всё это естественно на одном и том же датасете.
Из чего можно сделать вывод, что повторение блоков сети улучшит качество сети, если сложность датасета сильно выше сложности сети. Т.е. вполне можно пробовать делать сети с очень малым числом весов, сносно работающие на сложных датасетах.
Если взять одну свёртку, то такая сеть будет обучена заметно хуже, чем если б та же свёртка была повторена 10 раз. Но если взять 10 сверток с разными весами, то сеть обучится ещё лучше. Если же начать повторять эти 10 свёрток на разный манер, то получающиеся сети будут обучаться хуже, чем просто 10 свёрток. Всё это естественно на одном и том же датасете.
Из чего можно сделать вывод, что повторение блоков сети улучшит качество сети, если сложность датасета сильно выше сложности сети. Т.е. вполне можно пробовать делать сети с очень малым числом весов, сносно работающие на сложных датасетах.
Немного накосячил с экспериментами и в прошлом посте всё неверно.
Короче, сколько блоки не повторяй, лучше не становится. Сеть остаётся или так же обученной, или чуть хуже.
Короче, сколько блоки не повторяй, лучше не становится. Сеть остаётся или так же обученной, или чуть хуже.
Китайцы оформили вполне очевидную идею в виде статьи с формулами, графиками и всем прочим. Назвали метод SWITCH EMA (SEMA) вместо Exponential Moving Average (EMA) . Идея в том, чтобы периодически присваивать исходной модели веса EMA-модели. https://arxiv.org/pdf/2402.09240 .
Жду статью с подбором оптимального decay для EMA. От себя предложу такой алгоритм: берём основную EMA-модель и две параллельных с чуть большим и чуть меньшим decay. И периодически смотрим, какая из трёх EMA моделей даёт лучшее значение loss-а на валидации. Её далее используем как основную и из неё порождаем две параллельных. И так по кругу. Интересно было бы посмотреть, как decay будет меняться по мере обучения модели и изменения LR.
Жду статью с подбором оптимального decay для EMA. От себя предложу такой алгоритм: берём основную EMA-модель и две параллельных с чуть большим и чуть меньшим decay. И периодически смотрим, какая из трёх EMA моделей даёт лучшее значение loss-а на валидации. Её далее используем как основную и из неё порождаем две параллельных. И так по кругу. Интересно было бы посмотреть, как decay будет меняться по мере обучения модели и изменения LR.
В продолжение прошлого поста про EMA. Не совсем ясный момент, как быть с буферами модели, где, например, хранятся статистики по BarchNorm-ам.
В Stochastic Weight Averaging (SWA), который был предшественником EMA, предлагается пересчитывать батчнормы https://pytorch.org/blog/stochastic-weight-averaging-in-pytorch/ одну эпоху после усреднения весов https://pytorch.org/blog/stochastic-weight-averaging-in-pytorch/ . Вот функция для этого https://github.com/pytorch/contrib/blob/master/torchcontrib/optim/swa.py#L274 .
В
Ещё бывает, что статистики у BatchNorm-а обновляются во время тренировки, когда через EMA-модель пропускают данные.
Есть улучшенный вариант BatchNorm-а, в котором предлагается через EMA усреднять статистики у BN и тем самым сеть якобы улучшается: https://arxiv.org/pdf/2101.08482 .
Вопрос на засыпку: а как правильно?
В Stochastic Weight Averaging (SWA), который был предшественником EMA, предлагается пересчитывать батчнормы https://pytorch.org/blog/stochastic-weight-averaging-in-pytorch/ одну эпоху после усреднения весов https://pytorch.org/blog/stochastic-weight-averaging-in-pytorch/ . Вот функция для этого https://github.com/pytorch/contrib/blob/master/torchcontrib/optim/swa.py#L274 .
В
timm статистики у BatchNorm-а усредняют по дефолту, но есть возможность просто копировать их https://github.com/huggingface/pytorch-image-models/blob/main/timm/utils/model_ema.py#L133 .Ещё бывает, что статистики у BatchNorm-а обновляются во время тренировки, когда через EMA-модель пропускают данные.
Есть улучшенный вариант BatchNorm-а, в котором предлагается через EMA усреднять статистики у BN и тем самым сеть якобы улучшается: https://arxiv.org/pdf/2101.08482 .
Вопрос на засыпку: а как правильно?
👍1
Профайлир вчера свой скрипт, обучающий нейронку и обнаружил, что 30% времени тратися вот этой строчке https://github.com/pytorch/pytorch/blob/main/torch/amp/grad_scaler.py#L351 . Там с GPU на CPU в цикле тащутся данные, что естественно жутко медленно. В обычной жизни эта строчка никогда не работает, потому что все используют оптимизаторы из торча. А же взял AdamP из timm.
Как я понял, если обучать модельку в режиме Automatic Mixed Precision, который сильно ускоряет и уменьшает расход памяти, то обычно используется скалинг градиентов. И после того, как сделан обратный проход градиенты нужно сначала unscale обратно, а потом уже использовать оптимизатор. Т.е. сначала по всем градиентам проходится torch.GradScaler, а потом оптимизаитор. Чтобы всё ускорить, оптимизаторы из торча умеют сами unscale градиенты и проверять их на inf . А те опимизаторы, которые не из торча, конечно ничего подобного не умеют и потом за них эту работу делает torch.GradScaler, который, как оказалось, написан не очень эффективно. 😞
P.S.
Попробовал с AdamW из торча. Там картина точно такая же, к сожалению. Что-то мне даже кажется, что скорость обучения в режиме Automatic Mixed Precision из-за скалинга градиентов замедяется сильнее, чем если учить во float32.
Как я понял, если обучать модельку в режиме Automatic Mixed Precision, который сильно ускоряет и уменьшает расход памяти, то обычно используется скалинг градиентов. И после того, как сделан обратный проход градиенты нужно сначала unscale обратно, а потом уже использовать оптимизатор. Т.е. сначала по всем градиентам проходится torch.GradScaler, а потом оптимизаитор. Чтобы всё ускорить, оптимизаторы из торча умеют сами unscale градиенты и проверять их на inf . А те опимизаторы, которые не из торча, конечно ничего подобного не умеют и потом за них эту работу делает torch.GradScaler, который, как оказалось, написан не очень эффективно. 😞
P.S.
Попробовал с AdamW из торча. Там картина точно такая же, к сожалению. Что-то мне даже кажется, что скорость обучения в режиме Automatic Mixed Precision из-за скалинга градиентов замедяется сильнее, чем если учить во float32.
GitHub
pytorch/torch/amp/grad_scaler.py at main · pytorch/pytorch
Tensors and Dynamic neural networks in Python with strong GPU acceleration - pytorch/pytorch
gemma-2-27b-it_rus_vocab.txt
68.6 KB
Решил тут посмотреть, какие русскоязычные токены есть в довольно не плохой в русском языке на данный момент модельке google/gemma-2-27b-it .
Написал примерно такой код:
Если посмотреть то, что получилось, то можно примерно представить, на чём обучали модель и что BPE-токенизация в данном случае не очень эффективна и на практике большинство слов разбиваются на токены по 2-3 буквы. И при этом всё работает!
Интересно почитать, какой буст даёт BPE-токенизация по сравнению с посимвольной, например...
Написал примерно такой код:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, Gemma2ForCausalLM
import re
huggingface_assecc_token = 'hf_xxxxxxxxxxxxxx'
model_id = "google/gemma-2-27b-it"
tokenizer = AutoTokenizer.from_pretrained(model_id, token=huggingface_assecc_token)
tokens = tokenizer.vocab.keys()
rus_tokens = list(filter(lambda t: bool(re.search('^[\n0123456789абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ —–!",.:;?-]+$', t)), tokens))
rus_tokens.sort()
print(rus_tokens)
Если посмотреть то, что получилось, то можно примерно представить, на чём обучали модель и что BPE-токенизация в данном случае не очень эффективна и на практике большинство слов разбиваются на токены по 2-3 буквы. И при этом всё работает!
Интересно почитать, какой буст даёт BPE-токенизация по сравнению с посимвольной, например...
В выходные попытался вкатиться в NLP на своём датасете https://github.com/MichaelMonashev/TinyStories-ru/ . 😊
Сама первая проблема, с которой сталкиваешься: большие размерности входных данных: батч*длина последовательности*размер эмбединга. Пока сократил до: 64*1500*8 и с этим как-то можно уже работать.
Вторая проблема - очень зашумлённые входные данные. Нейронке сложно найти там хоть какой-то сигнал и она не может ничему научиться. Пока решил начинать учить всего на одном батче, а по достижении определённого значения лоса на валидации, добавлять в обучающую выборку данных. При этом сама валидационная выборка - это те данные, которые были недавно добавлены в обучающую выборку. Если брать за валидацию какие-то ранее не виденные нейронкой данные, то там вообще не видно никакого обобщения и просто муть какая идёт на выходе из нейронки.
Фактически сейчас я учу сеть запоминать обучающую выборку в надежде, что постепенно она научится обобщать. Пока сеть сопротивляется запоминанию через схлопывание эмбедингов примерно к одному вектору, но это я вроде победил и не даю ей этого делать.
Задача: предсказать продолжение текста, т.е. 80 эмбедингов 80-ти буковок. Токенизатор посимвольный, а не BPE.
Сетка самая примитивная:
Есть идеи, почему не обобщает? Я понимаю, что обычно предсказывают всего один следующий токен, а не сразу 80. Но хоть как-то оно ведь должно заводиться...
Сама первая проблема, с которой сталкиваешься: большие размерности входных данных: батч*длина последовательности*размер эмбединга. Пока сократил до: 64*1500*8 и с этим как-то можно уже работать.
Вторая проблема - очень зашумлённые входные данные. Нейронке сложно найти там хоть какой-то сигнал и она не может ничему научиться. Пока решил начинать учить всего на одном батче, а по достижении определённого значения лоса на валидации, добавлять в обучающую выборку данных. При этом сама валидационная выборка - это те данные, которые были недавно добавлены в обучающую выборку. Если брать за валидацию какие-то ранее не виденные нейронкой данные, то там вообще не видно никакого обобщения и просто муть какая идёт на выходе из нейронки.
Фактически сейчас я учу сеть запоминать обучающую выборку в надежде, что постепенно она научится обобщать. Пока сеть сопротивляется запоминанию через схлопывание эмбедингов примерно к одному вектору, но это я вроде победил и не даю ей этого делать.
Задача: предсказать продолжение текста, т.е. 80 эмбедингов 80-ти буковок. Токенизатор посимвольный, а не BPE.
Сетка самая примитивная:
class Net(nn.Module):
def __init__(self, vocab_size=83, embedding_size = 8, seq_len = 1500, num_of_predicted_tokens=80):
super().__init__()
self.embedding_size = embedding_size
self.embedding = nn.Embedding(vocab_size, embedding_size)
self.fc1 = nn.Linear(seq_len*embedding_size, 1024)
self.linears = nn.ModuleList([nn.Linear(1024, 1024) for i in range(10)])
self.fc2 = nn.Linear(1024, num_of_predicted_tokens*embedding_size)
def forward(self, x):
x = self.embedding(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = F.leaky_relu(x, negative_slope=0.5)
for linear in self.linears:
x = x+ linear(x)
x = F.leaky_relu(x, negative_slope=0.5)
x = self.fc2(x)
return x
Есть идеи, почему не обобщает? Я понимаю, что обычно предсказывают всего один следующий токен, а не сразу 80. Но хоть как-то оно ведь должно заводиться...
GitHub
GitHub - MichaelMonashev/TinyStories-ru
Contribute to MichaelMonashev/TinyStories-ru development by creating an account on GitHub.
Начинаю понимать смысл трансформеров для больших моделей. На входе у них всего один токен - это вектор из 4 тысяч значений. И таких векторов тысячи, а то и сотни тысяч. И ещё размерность батча, где тоже что-то должно быть больше 1 . И выходит, что нормально работать можно только с отдельными токенами и перевзвешивать их относительно друг друга. Правда кроме трансформера, подробное модно делать и другими способами.
Grok от Маска стал бесплатным для юзеров экс-твиттера с небольшими ограничениями в использовании. Плюс Маск строит датацентры с миллионами GPU.
Если сложить вместе эти два события, то можно предположить, что сделана ставка на массовый доступный ИИ для каждого. И сейчас Маск растит клиентскую базу в условиях ещё не самой высокой конкуренции, заодно подрывая доходы самих конкурентов.
При этом сами конкуренты в очевидном ступоре и не знаю, что им делать дальше, кидаясь в разное, вместо фокусирования на чём-то одном самом важном. Например, в лучших традициях инфоциганства выпускают адвент-календари. Или берут инвестиции в виде GPU-часов...
Если сложить вместе эти два события, то можно предположить, что сделана ставка на массовый доступный ИИ для каждого. И сейчас Маск растит клиентскую базу в условиях ещё не самой высокой конкуренции, заодно подрывая доходы самих конкурентов.
При этом сами конкуренты в очевидном ступоре и не знаю, что им делать дальше, кидаясь в разное, вместо фокусирования на чём-то одном самом важном. Например, в лучших традициях инфоциганства выпускают адвент-календари. Или берут инвестиции в виде GPU-часов...
Родилась мысль, что путь мыслящего существа, вроде человека, весьма примитивен: он сначала жадно напитывается жизненным опытом, потом постепенно начинает всё сильнее и сильнее его обобщать, чтобы родить нечто новое, и потом попытаться сохранить его в какой-то форме: книге, мелодии, рисунке и т.п. И так и поколения в поколение, одно и то же, снова и снова.
Сделал слой перекодировщик: он ищет по входному вектору наиближайший к нему из списка имеющихся векторов и ставит в соответствие ему соответвующее значение эмединга:
С одной стороны мне вообще странно, что через такой слой проходят градиенты и сеть с этим слоем учится. С другой стороны он работает очень хреново, что бы я не делал...
class Lookup(nn.Module):
def __init__(self, num_embeddings, input_embedding_size, output_embedding_size):
super().__init__()
self.input_embedding = torch.nn.Embedding(num_embeddings, input_embedding_size)
self.output_embedding = torch.nn.Embedding(num_embeddings, output_embedding_size)
def forward(self, x):
distances = torch.cdist(x, self.input_embedding.weight)
pos = distances.argmin(-1)
return self.output_embedding(pos)
С одной стороны мне вообще странно, что через такой слой проходят градиенты и сеть с этим слоем учится. С другой стороны он работает очень хреново, что бы я не делал...
Должен признать, что проще узнать ответ у Gemini 2.0 Flash Thinking Experimental и потом верифицировать его, чем в специализированной телеграмм-группе спрашивать , ждать ответа и потом обнаружить, что группе нет никого, кто мог бы ответить на твой вопрос. 😞
Это весьма интересная тема, ведь человек не малую часть своего общения перекладывает на машину. Это сильно переформатирует общение между людьми. И возможно сейчас мы переживаем его расцвет и на пути к его закату.
Это весьма интересная тема, ведь человек не малую часть своего общения перекладывает на машину. Это сильно переформатирует общение между людьми. И возможно сейчас мы переживаем его расцвет и на пути к его закату.
👌2
Пришло ещё одно откровение про Трансформеры.
На входе у нас имеется довольно большой тензор (batch size, sequence length, embedding size). На практике он может быть таким (64, 8192, 4096), т.е. 2 147 483 648 значений. 2 млд. !!! Вся фишка трансформера в том, что он умудряется в каждом своём блоке учесть взаимосвязь каждого значения с каждым!
Когда GPU научатся быстро умножать матрицы размером в млд. значений, трансформер станет не нужен.
На входе у нас имеется довольно большой тензор (batch size, sequence length, embedding size). На практике он может быть таким (64, 8192, 4096), т.е. 2 147 483 648 значений. 2 млд. !!! Вся фишка трансформера в том, что он умудряется в каждом своём блоке учесть взаимосвязь каждого значения с каждым!
Когда GPU научатся быстро умножать матрицы размером в млд. значений, трансформер станет не нужен.
По Трансформерам у меня пока есть один непонятный вопрос: как его придумали. Т.е. какая была цепочка размышлений, почему он вышел именно таким, а не другим, какие ещё варианты получались, но были отметены и почему?
Чивиня (Multi-layer Parkinson)
Когда GPU научатся быстро умножать матрицы размером в млд. значений, трансформер станет не нужен.
На самом деле это возможно уже сейчас. Только такие огромные матрицы должны быть разряженными. Но даже если научиться вставлять веса в нужные места такой разряженной матрицы, то всё равно это не будет учётом ВСЕХ значений входной матрицы, что скорее всего приведёт к проигрышу относительно трансформеров.
Наконец-то получилось нормально предсказывать текст. Без трансформеров, на свёртках и полносвязанных слоях. Написал всё с нуля без использования сторонних либ.
К сожалению, заработало только тогда, когда стал предсказывать по одному токену. Думал, сразу много предсказывать, но по много не работает почему-то. 4-5 токенов ещё какие-то предсказываются, а дальше идёт паравозик из одного повторяющегося токена. Очень похоже на то, что все токены там равновероятны и сеть не может вычленить полезный сигнал при обучении почему-то.
Вот, что генерится через 15 минут обучения:
На входе сети всегда 80 токенов. На выходе тоже. Но берётся только первый. Никаких top_p, top_k и пенальти за повторения нет.
Токенизатор посимвольный.
Parameters: 230,048 Buffers: 0
Что-то похожее на слова выдаётся уже после 1000 шагов оптимизатора:
А вот, что после 12 часов обучения:
К сожалению, заработало только тогда, когда стал предсказывать по одному токену. Думал, сразу много предсказывать, но по много не работает почему-то. 4-5 токенов ещё какие-то предсказываются, а дальше идёт паравозик из одного повторяющегося токена. Очень похоже на то, что все токены там равновероятны и сеть не может вычленить полезный сигнал при обучении почему-то.
Вот, что генерится через 15 минут обучения:
Input : "Ой!"
Миша испугался и начал щипать маму за руки. Мама рассердилась. "Миша, хв
Predict: остик". Маша поняла, что смотрела на схватила посмотрела на схватила посмотрела
На входе сети всегда 80 токенов. На выходе тоже. Но берётся только первый. Никаких top_p, top_k и пенальти за повторения нет.
Токенизатор посимвольный.
Parameters: 230,048 Buffers: 0
Что-то похожее на слова выдаётся уже после 1000 шагов оптимизатора:
Input : "Ой!"
Миша испугался и начал щипать маму за руки. Мама рассердилась. "Миша, хв
Predict: оРехстила пока– Маша спа съала постел маща сала сла слся и ска 0остала и спа4ала
А вот, что после 12 часов обучения:
Input : "Ой!"
Миша испугался и начал щипать маму за руки. Мама рассердилась. "Миша, хв
Predict: ошла сова. . Маша поняла, что нужно быть осторожным. Он посмотрел на Машу и сказ