Пришла мысль, что можно много спорить о том, есть ли уже интеллект у того, что делает OpenAI и прочие. Но правда в том, что реальный искусственный интеллект возможно и не так уж и нужен. Большинству вполне сойдёт хорошая его имитация.
👌2💯1
В продолжение прошлого поста...
В разгар Второй мировой Айзек Азимов формирует три закона робототехники https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B8_%D0%B7%D0%B0%D0%BA%D0%BE%D0%BD%D0%B0_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D0%BA%D0%B8 . Внимание, вопрос: как реализовать выполнение этих законов на практике? Например, на текущем уровне развития нейронок.
Наверное, одна нейронка что-то генерит (например, текст), а вторая проверяет, на сколько сгенерённое безопасно. И, кстати, все предыдущие генерации вместе с новой тоже. В голову сразу приходят состязательные сети, где одна пытается обмануть другую. И вспомним, что для их обучения требуется примерно одинаковая выразительная сила нейронок. В случае с контролем одной нейронкой другой, очевидно, что генерящая должна быть значительно слабее, чем проверяющая. Но даже это не гарантирует, что сильную нейронку не получится обмануть, ибо это не та задача, где на проверочной выборке у нас 100% accuracy.
Из чего, надеюсь пока, следует два грустных вывода:
- делать безопасные для человека нейронки экономически невыгодно;
- сделать абсолютно безопасную нейронку невозможно.
Описанное не совсем корректно, ибо я сам придумал схему с двумя нейронками и сам показал её ущербность. Возможно есть другие подходы. Например, при обучении нейронки пенализировать генерации, которые похожи на плохие. Или что-то подобное.
P.S.
Сейчас безопасность в текстовых моделях реализуется порой регэкспами, что конечно курам на смех, но позволяет снять политическую остроту, например.
В разгар Второй мировой Айзек Азимов формирует три закона робототехники https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B8_%D0%B7%D0%B0%D0%BA%D0%BE%D0%BD%D0%B0_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D0%BA%D0%B8 . Внимание, вопрос: как реализовать выполнение этих законов на практике? Например, на текущем уровне развития нейронок.
Наверное, одна нейронка что-то генерит (например, текст), а вторая проверяет, на сколько сгенерённое безопасно. И, кстати, все предыдущие генерации вместе с новой тоже. В голову сразу приходят состязательные сети, где одна пытается обмануть другую. И вспомним, что для их обучения требуется примерно одинаковая выразительная сила нейронок. В случае с контролем одной нейронкой другой, очевидно, что генерящая должна быть значительно слабее, чем проверяющая. Но даже это не гарантирует, что сильную нейронку не получится обмануть, ибо это не та задача, где на проверочной выборке у нас 100% accuracy.
Из чего, надеюсь пока, следует два грустных вывода:
- делать безопасные для человека нейронки экономически невыгодно;
- сделать абсолютно безопасную нейронку невозможно.
Описанное не совсем корректно, ибо я сам придумал схему с двумя нейронками и сам показал её ущербность. Возможно есть другие подходы. Например, при обучении нейронки пенализировать генерации, которые похожи на плохие. Или что-то подобное.
P.S.
Сейчас безопасность в текстовых моделях реализуется порой регэкспами, что конечно курам на смех, но позволяет снять политическую остроту, например.
Wikipedia
Три закона роботехники
в научной фантастике — обязательные правила поведения для роботов
Утром родилась мысль о том, что слои в сети можно переставлять случайным образом или выбирать нужное количество раз случайный слой из имеющихся. В случае со свёртками обоснование такое: свёртка фильтрует всё лишнее и если выполнить эту фильтрацию несколько раз, то не сильно важно, в какой последовательности. Оказалось, что этот подход работает. И даёт результаты чуть хуже, чем если бы свёртки шли всегда в одном и том же порядке. Вот три варианта сети: базовый и два со случайным выбором слоёв или их последовательности:
Училось на MNIST-е. Перед каждой эпохой подбирались оптимальные LR и WD для weight и bias трёх групп параметров: стема, свёрток и полносвязанного слоя. Хотелось так обезопасить эксперимент от влияния неверных гиперпараметров. Училось 14 эпох. В комментариях в коде сети я написал accuracy, которых достиг каждый вариант сети.
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.stem = nn.Conv2d(1, 32, 3)
self.conv1 = nn.Conv2d(32, 32, 3)
self.conv2 = nn.Conv2d(32, 32, 3)
self.conv3 = nn.Conv2d(32, 32, 3)
self.fc1 = nn.Linear(3200, 10)
def forward(self, x):
x = self.stem(x)
x = F.relu(x)
if self.training: # обучение
# # 0 вариант
# # Accuracy: 9916/10000
# x = self.conv1(x)
# x = F.relu(x)
# x = self.conv2(x)
# x = F.relu(x)
# x = self.conv3(x)
# x = F.relu(x)
# # 1 вариант
# # Accuracy: 9880/10000
# for _ in range(3):
# conv = random.choice([self.conv1,self.conv2,self.conv3])
# x = conv(x)
# x = F.relu(x)
# # 2 вариант
# # Accuracy: 9888/10000
# # так лучше, ибо тогда свёртка выполняется одинаковое число раз, а потому всегда будут градиенты и они будут схожей амплитуды.
# convs = [self.conv1,self.conv2,self.conv3]
# random.shuffle(convs)
# for conv in convs:
# x = conv(x)
# x = F.relu(x)
# 3 вариант
# все три раза один слой используем
# Accuracy: 9925/10000
x = self.conv1(x)
x = F.relu(x)
x = self.conv1(x)
x = F.relu(x)
x = self.conv1(x)
x = F.relu(x)
else: # валидация
# x = self.conv1(x)
# x = F.relu(x)
# x = self.conv2(x)
# x = F.relu(x)
# x = self.conv3(x)
# x = F.relu(x)
x = self.conv1(x)
x = F.relu(x)
x = self.conv1(x)
x = F.relu(x)
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x, kernel_size=2)
x = torch.flatten(x, start_dim=1)
x = self.fc1(x)
return x
Училось на MNIST-е. Перед каждой эпохой подбирались оптимальные LR и WD для weight и bias трёх групп параметров: стема, свёрток и полносвязанного слоя. Хотелось так обезопасить эксперимент от влияния неверных гиперпараметров. Училось 14 эпох. В комментариях в коде сети я написал accuracy, которых достиг каждый вариант сети.
Для задачи классификации при работе с нейронками есть три известных мне подхода. One hot encoding, генерацию векторного представления и потом поиск похожих среди уже классфицированных векторов и генерация класса в виде текста (хотя можно использовать и другие модальности, а не только текст). Первые удобны для машин, третий - для человека. Но я не знаю удобного и для машин и для человека одновременно.
👍1
Чивиня (Multi-layer Parkinson)
Утром родилась мысль о том, что слои в сети можно переставлять случайным образом или выбирать нужное количество раз случайный слой из имеющихся. В случае со свёртками обоснование такое: свёртка фильтрует всё лишнее и если выполнить эту фильтрацию несколько…
Переделал всё на Cifar10, добавил больше свёрток и уменьшил полносвязанный слой, чтобы хорошо видеть эффект именно от свёрток. Получилась вот такая сетка (в ней разные варианты с полученными при обучении значениями accuracy):
class Net(nn.Module):
def __init__(self):
super().__init__()
self.stem = nn.Conv2d(3, 32, 3)
self.conv1 = nn.Conv2d(32, 32, 3)
self.conv2 = nn.Conv2d(32, 32, 3)
self.conv3 = nn.Conv2d(32, 32, 3)
self.conv4 = nn.Conv2d(32, 32, 3)
self.conv5 = nn.Conv2d(32, 32, 3)
self.conv6 = nn.Conv2d(32, 32, 3)
self.conv7 = nn.Conv2d(32, 32, 3)
self.conv8 = nn.Conv2d(32, 32, 3)
self.conv9 = nn.Conv2d(32, 32, 3)
self.fc1 = nn.Linear(288, 10)
def forward(self, x):
x = self.stem(x)
x = F.relu(x)
# 0 вариант
# Accuracy: 6417/10000
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
x = self.conv4(x)
x = F.relu(x)
x = self.conv5(x)
x = F.relu(x)
x = self.conv6(x)
x = F.relu(x)
x = self.conv7(x)
x = F.relu(x)
x = self.conv8(x)
x = F.relu(x)
x = self.conv9(x)
x = F.relu(x)
# 1 вариант
# Accuracy: 5902/10000
for _ in range(3):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
# 2 вариант
# Accuracy: 5351/10000
for _ in range(9):
x = self.conv1(x)
x = F.relu(x)
# 3 вариант
# Accuracy: 4081/10000
if self.training: # обучение
for _ in range(9):
conv = random.choice([self.conv1,self.conv2,self.conv3])
x = conv(x)
x = F.relu(x)
else: # валидация
for _ in range(3):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
# 4 вариант
# Accuracy: 2652/10000
if self.training: # обучение
for _ in range(9):
conv = random.choice([self.conv1,self.conv2,self.conv3,self.conv4,self.conv5,self.conv6,self.conv7,self.conv8,self.conv9])
x = conv(x)
x = F.relu(x)
else: # валидация
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
x = self.conv4(x)
x = F.relu(x)
x = self.conv5(x)
x = F.relu(x)
x = self.conv6(x)
x = F.relu(x)
x = self.conv7(x)
x = F.relu(x)
x = self.conv8(x)
x = F.relu(x)
x = self.conv9(x)
x = F.relu(x)
# 5 вариант
# Accuracy: 3798/10000
if self.training: # обучение
for _ in range(3):
convs = [self.conv1,self.conv2,self.conv3]
random.shuffle(convs)
for conv in convs:
x = conv(x)
x = F.relu(x)
else: # валидация
for _ in range(3):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
Чивиня (Multi-layer Parkinson)
Утром родилась мысль о том, что слои в сети можно переставлять случайным образом или выбирать нужное количество раз случайный слой из имеющихся. В случае со свёртками обоснование такое: свёртка фильтрует всё лишнее и если выполнить эту фильтрацию несколько…
# 6 вариант
# Accuracy: 3131/10000
if self.training: # обучение
convs = [self.conv1,self.conv2,self.conv3,self.conv4,self.conv5,self.conv6,self.conv7,self.conv8,self.conv9]
random.shuffle(convs)
for conv in convs:
x = conv(x)
x = F.relu(x)
else: # валидация
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.conv3(x)
x = F.relu(x)
x = self.conv4(x)
x = F.relu(x)
x = self.conv5(x)
x = F.relu(x)
x = self.conv6(x)
x = F.relu(x)
x = self.conv7(x)
x = F.relu(x)
x = self.conv8(x)
x = F.relu(x)
x = self.conv9(x)
x = F.relu(x)
x = F.avg_pool2d(x, kernel_size=4)
x = torch.flatten(x, start_dim=1)
x = self.fc1(x)
return x
В целом вывод такой: свёрткам сложно адаптироваться под разное положение в сети.
Была гипотеза, что так можно уменьшать избыточную выразительную способность слоёв, но похоже случайно менять положения слоя в сети - это явный перебор.
🤔1
Я большой неспециалист в NLP и видимо поэтому у меня возник этот вопрос.
При общении люди обмениваются фразами. Т.е. единица общения - это не слово и тем более не токен, а много большая смысловая единица.
Почему современные диалоговые модели на самом нижнем уровне до сих пор предсказывают следующий токен? Неужели так важно обучать модель именно этой задаче из-за наличия большого количества неразменных текстов?
При общении люди обмениваются фразами. Т.е. единица общения - это не слово и тем более не токен, а много большая смысловая единица.
Почему современные диалоговые модели на самом нижнем уровне до сих пор предсказывают следующий токен? Неужели так важно обучать модель именно этой задаче из-за наличия большого количества неразменных текстов?
В timm появилась vission-модель, основанная на архитектуре Mamba https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/mambaout.py .
Самое мутное происходит в коде блоков, из которых строится вся сетка:
Самое мутное происходит в коде блоков, из которых строится вся сетка:
class GatedConvBlock(nn.Module):
r""" Our implementation of Gated CNN Block: https://arxiv.org/pdf/1612.08083
Args:
conv_ratio: control the number of channels to conduct depthwise convolution.
Conduct convolution on partial channels can improve paraitcal efficiency.
The idea of partial channels is from ShuffleNet V2 (https://arxiv.org/abs/1807.11164) and
also used by InceptionNeXt (https://arxiv.org/abs/2303.16900) and FasterNet (https://arxiv.org/abs/2303.03667)
"""
def __init__(
self,
dim,
expansion_ratio=8 / 3,
kernel_size=7,
conv_ratio=1.0,
ls_init_value=None,
norm_layer=LayerNorm,
act_layer=nn.GELU,
drop_path=0.,
**kwargs
):
super().__init__()
self.norm = norm_layer(dim)
hidden = int(expansion_ratio * dim)
self.fc1 = nn.Linear(dim, hidden * 2)
self.act = act_layer()
conv_channels = int(conv_ratio * dim)
self.split_indices = (hidden, hidden - conv_channels, conv_channels)
self.conv = nn.Conv2d(
conv_channels,
conv_channels,
kernel_size=kernel_size,
padding=kernel_size // 2,
groups=conv_channels
)
self.fc2 = nn.Linear(hidden, dim)
self.ls = LayerScale(dim) if ls_init_value is not None else nn.Identity()
self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
def forward(self, x):
shortcut = x # [B, H, W, C]
x = self.norm(x)
x = self.fc1(x)
g, i, c = torch.split(x, self.split_indices, dim=-1)
c = c.permute(0, 3, 1, 2) # [B, H, W, C] -> [B, C, H, W]
c = self.conv(c)
c = c.permute(0, 2, 3, 1) # [B, C, H, W] -> [B, H, W, C]
x = self.fc2(self.act(g) * torch.cat((i, c), dim=-1))
x = self.ls(x)
x = self.drop_path(x)
return x + shortcut
GitHub
pytorch-image-models/timm/models/mambaout.py at main · huggingface/pytorch-image-models
The largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Vision Transformer (V...
👍3
Для будущих NLP-экспериментов пробую спомощью модельки google/gemma-2-27b-it сгенерить русскоязычную версию датасета TinyStories. Получаются вот такие json-ы:
Как видите, тексты выходят более-менее, хотя иногда есть косяки с падежами, склонениями и прочим. Тут имя весьма странное. Есть конечно женское имя Филиппа, но согласитесь, больше похоже на путаницу с мужским и женским родом, чем на выбор редкого имени...
Датасет лежит здесь https://github.com/MichaelMonashev/TinyStories-ru .
{"adjective": "спокойный", "features": ["быть похожим на сказку", "быть поучительным", "иметь трёх персонажей", "иметь хороший конец"], "model": "google/gemma-2-27b-it bnb_4bit", "noun": "чешуя", "sha3_256": "0039668bf3ee8f46f512bff45c8b136b27a7888572f5e37ab02865f6937084fb", "story": "Жила-была маленькая рыбка по имени Филя. Филя была очень спокойной рыбой. Она любила плавать медленно и смотреть на красивые водоросли. Однажды Филя увидела, что по дну катится что-то блестящее. Это была чешуя от большой золотой рыбки!\n\nФиля решила найти хозяина чешуи. Она катилась по дну, спрашивая всех рыб: \"Чья это чешуя?\" Но никто не знал. Филя грустила, потому что хотела вернуть чешую ее хозяину.\n\nВдруг Филя увидела большую золотую рыбку. Рыбка плавала очень медленно, словно устала. Филя подоплыла к ней и спросила: \"Это твоя чешуя?\" Золотая рыбка улыбнулась и сказала: \"Да, спасибо тебе, маленькая Филя!\"\n\nФиля была очень рада, что нашла хозяина чешуи. Золотая рыбка поблагодарила Филю и сказала, что она очень добрая и спокойная рыбка. Филя вернулась домой, счастливая и гордая.\n\nС тех пор Филя всегда помогала другим рыбкам. Она поняла, что быть спокойным и добрым - это очень важно.", "verb": "катиться"}Как видите, тексты выходят более-менее, хотя иногда есть косяки с падежами, склонениями и прочим. Тут имя весьма странное. Есть конечно женское имя Филиппа, но согласитесь, больше похоже на путаницу с мужским и женским родом, чем на выбор редкого имени...
Датасет лежит здесь https://github.com/MichaelMonashev/TinyStories-ru .
GitHub
GitHub - MichaelMonashev/TinyStories-ru
Contribute to MichaelMonashev/TinyStories-ru development by creating an account on GitHub.
Читаю про АльфаЗеро и прихожу к выводу, что в подобных задачах очень важна способность сети быстро учиться. В начале простому, потом всё более и более сложному. И выходит, что такую умную сеть надо как-то выращивать из простой маленькой сети. Иначе куча ресурсов будет потрачено впустую, ведь для генерации данных для обучения делается куча симуляций.
Слушаю книгу Питера Тиля ,"от нуля к единице" и там задаётся вопрос: что очевидное сейчас всем на самом деле не является правдой. Пришел в голову такой ответ: 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