惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
O
OpenAI News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Google Online Security Blog
Google Online Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News and Events Feed by Topic
S
Security Affairs
SecWiki News
SecWiki News
Project Zero
Project Zero
L
Lohrmann on Cybersecurity
P
Proofpoint News Feed
P
Palo Alto Networks Blog
L
LINUX DO - 最新话题
H
Hacker News: Front Page
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
Intezer
Simon Willison's Weblog
Simon Willison's Weblog
W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
I
InfoQ
云风的 BLOG
云风的 BLOG
雷峰网
雷峰网
B
Blog
IT之家
IT之家
AWS News Blog
AWS News Blog
Jina AI
Jina AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Spread Privacy
Spread Privacy
N
News and Events Feed by Topic
Security Latest
Security Latest
美团技术团队
C
Check Point Blog
WordPress大学
WordPress大学
T
Tenable Blog
S
Security @ Cisco Blogs
Last Week in AI
Last Week in AI
博客园 - 聂微东
月光博客
月光博客
博客园 - 【当耐特】
S
Schneier on Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Secure Thoughts
Schneier on Security
Schneier on Security
C
Cisco Blogs
Cyberwarzone
Cyberwarzone

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Кто решает судьбу вашего проекта? Разбираем заинтересованные стороны. BABOK #1 Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Сжать четыре токена в один вектор: запускаем автоэнкодер CALM на доменных данных (и на одном CPU)
Vjacheslav Borisov · 2026-06-13 · via Все публикации подряд на Хабре

Взяли автоэнкодер из свежей работы CALM (Continuous Autoregressive Language Models), который учится упаковывать чанк из K=4 токенов в один непрерывный вектор и разворачивать обратно, и обучили его не на 15 миллиардах токенов Pile на 8 GPU, как в оригинале, а на 18 тысячах коротких строк с требованиями из IT-вакансий - на обычной машине без видеокарты. По дороге выгребли три классических грабли (flash-attn без CUDA, deepspeed, который не импортируется под NumPy 2.x, и тихий OOM на 33 ГБ логитов). Ниже - подробный разбор архитектуры, конфигов и честные результаты round-trip-реконструкции.

💡 Зачем вообще что-то менять в языковых моделях

Современные LLM упираются в фундаментальное ограничение: они генерируют текст по одному токену за шаг. Сгенерировал токен → подал обратно на вход → сгенерировал следующий. Чем длиннее ответ, тем больше последовательных шагов авторегрессии, и это плохо параллелится по своей природе.

Авторы CALM (GitHubблог) предлагают сместить парадигму: вместо предсказания одного дискретного токена модель предсказывает один непрерывный вектор, который кодирует сразу чанк из K токенов. Если K=4, то число шагов авторегрессии падает в 4 раза.

Появляется новая ось масштабирования - авторы называют её semantic bandwidth (K): можно наращивать не только параметры и данные, но и объём информации, обрабатываемой за один шаг.

Чтобы это заработало, нужно две модели:

  1. Автоэнкодер высокой точности - учится сжимать K токенов в один вектор и реконструировать их почти без потерь. Это «словарь» между дискретным миром токенов и непрерывным латентным пространством.

  2. Continuous-domain LM - авторегрессионная модель, которая предсказывает следующий вектор в этом непрерывном пространстве (а не следующий токен).

Так как мы уходим из дискретного softmax-мира, обычный maximum likelihood больше не применим напрямую - поэтому в CALM есть целый likelihood-free тулкит: Energy-based training, метрика BrierLM и temperature sampling поверх чёрного ящика-сэмплера.

Эта статья - про первую стадию, автоэнкодер. Именно он определяет, насколько хорошо вообще возможна вся затея: если чанк токенов нельзя восстановить из вектора, то и моделировать в этом пространстве бессмысленно.

📚 Зоопарк моделей в репозитории

Чтобы было понятно, куда вписывается наш эксперимент, вот что лежит в репозитории CALM:

Модель

Что делает

Параметры

Autoencoder

сжатие K токенов ↔ вектор (стадия 1)

75M

CALM-M / L / XL

непрерывная авторегрессия (стадия 2)

371M / 735M / 1.82B

AR baseline

обычный токенный трансформер для сравнения

-

Для стадии 2 предусмотрены три варианта генеративной «головы», которая моделирует распределение следующего вектора:

  • Energy-based (train_energy.py) - основной, лучший по качеству;

  • Diffusion (train_diffusion.py);

  • Flow Matching (train_flow.py).

Качество в статье меряют метрикой BrierLM: CALM-M даёт 5.72, CALM-XL - 8.53, токенный baseline сопоставимого размера - 6.05. Энергетическая голова в их экспериментах обошла diffusion и flow.

Мы во всё это богатство не лезли - наш фокус строго на автоэнкодере.

🏗️ Архитектура автоэнкодера: разбираем по слоям

Это самое интересное. Автоэнкодер CALM - не «трансформер-энкодер», как можно подумать. Это вариационный автоэнкодер (VAE), работающий внутри патча, целиком на MLP-слоях, без self-attention. Разберём почему так и как именно.

Базовый блок: AELayer (MLP, без внимания)

class AELayer(nn.Module):
    def __init__(self, config):
        self.mlp = LlamaMLP(config)                 # SwiGLU как в LLaMA
        self.layernorm = LlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)

    def forward(self, hidden_states):
        residual = hidden_states
        hidden_states = self.layernorm(hidden_states)
        hidden_states = self.mlp(hidden_states)
        return residual + hidden_states             # pre-norm + residual

Никакого attention. Это принципиально: автоэнкодер обрабатывает каждый патч из K токенов независимо от соседних. Его задача - локальное сжатие/распаковка чанка, а не моделирование длинных зависимостей. Контекст и последовательность - это уже работа авторегрессионной модели на стадии 2. Поэтому AE можно сделать дешёвым и быстрым.

Энкодер: 4 токена → один вектор

Поток данных (для K=patch_size=4, hidden_size=512, latent_size=128):

  1. Вход input_ids решейпится в патчи: (B, L) → (B·L/4, 4).

  2. Эмбеддинги: (N, 4) → (N, 4, 512).

  3. Стадия 0: один AELayer поверх 4 токенов.

  4. Squeeze: конкатенируем 4 токена и сжимаем - Linear(4·512 → 512). Вот тут и происходит компрессия патча: (N, 4, 512) → (N, 1, 512).

  5. Стадия 1: ещё один AELayer.

  6. hidden_to_latentLinear(512 → 256) → (N, 1, 256).

Почему 256, а не 128? Потому что это VAE: 256 = latent_size·2 - половина на mean, половина на log_std.

mean, log_std = torch.chunk(latent_states, 2, dim=-1)   # по 128
std = torch.exp(log_std)
eps = torch.randn_like(mean)
latent_states = mean + eps * std                        # репараметризация
kl_loss = 0.5 * (mean**2 + std**2 - 1 - 2*log_std)
kl_loss = torch.clamp(kl_loss, min=config.kl_clamp).sum(-1).mean()

То есть латент - не просто вектор, а параметры гауссианы, из которой сэмплируется. KL-член с kl_clamp=0.5 и весом kl_weight=1e-3 регуляризует пространство, чтобы оно было гладким (важно для стадии 2, где по нему надо «ходить» авторегрессией).

Декодер: вектор → 4 токена

Симметрично энкодеру:

  1. latent_to_hiddenLinear(128 → 512).

  2. Стадия 0: один AELayer.

  3. Expand: Linear(512 → 4·512) и решейп обратно в 4 позиции - «разжимаем» патч.

  4. Стадия 1: ещё один AELayer.

  5. lm_head: проекция на словарь. Веса lm_head связаны (tied) с матрицей эмбеддингов энкодера - экономит параметры и стабилизирует обучение.

Лосс реконструкции - обычная кросс-энтропия по токенам, в режиме обучения домноженная на patch_size и сложенная с KL:

loss = CrossEntropy(logits, labels)
if self.training:
    loss = loss * patch_size + kl_loss * kl_weight

Гиперпараметры (дефолтный конфиг)

Параметр

Значение

patch_size (K)

4

hidden_size

512

intermediate_size (MLP)

1280

latent_size

128

num_encoder_layers

2

num_decoder_layers

2

ae_dropout

0.15

kl_weight / kl_clamp

1e-3 / 0.5

токенайзер

Llama-3 (~128k словарь)

всего параметров

~75.8M

Любопытный факт: из 75.8M параметров подавляющая часть - это таблица эмбеддингов (~128k x 512 ≈ 65M). Сама «логика» энкодера-декодера весит единицы миллионов. Так что это очень лёгкая модель - что и делает её реалистичной для запуска без GPU.

🔬 Наш эксперимент: доменная адаптация на вакансиях

В оригинале автоэнкодер учат на ~15 млрд токенов датасета pile-uncopyrighted, на 8 GPU, в bf16, 30 000 шагов. Нам было интересно другое: как поведёт себя эта архитектура на узком домене и на скромном железе?

Данные

jobs_requirements.jsonl - 18 065 коротких строк с требованиями из IT-вакансий, смесь русского и английского:

{"text": "React JS 18+"}
{"text": "Понимание REST API"}
{"text": "Уверенное знание JavaScript: замыкания, асинхронное программирование (async/await | Promises), ES6+"}

Всего после токенизации и склейки получилось ~340k токенов. Это, конечно, на пять-шесть порядков меньше оригинала - так что это proof-of-concept доменной адаптации, а не воспроизведение результатов статьи. Договоримся об этом сразу, чтобы потом честно смотреть на цифры.

Железо

Машина без видеокарты: 62 ГБ RAM, 28 ядер CPU, ни nvidia-smi, ни nvcctorch.cuda.is_available() == False. То есть условия максимально «бытовые».

Конфигурация запуска

Параметр

Оригинал (статья)

Наш запуск

данные

~15B токенов Pile

18k строк вакансий (~340k токенов)

устройство

8x GPU, bf16

1x CPU, fp32

block_size

2048

256 (см. грабли ниже)

per_device_train_batch_size

8

32

learning_rate

3e-4

2e-4

эпохи / шаги

1 эпоха / 30 000 шагов

5 эпох / 220 шагов

latent_sizepatch_size

128, 4

128, 4

🚧 Три грабли по дороге

1. flash-attn не собирается без CUDA

requirements.txt тянет flash-attn==2.1.1, который требует nvcc на сборку и GPU на запуск. На CPU-машине он не ставится в принципе. Лечение - поставить всё остальное, исключив его:

grep -v '^flash-attn' requirements.txt | uv pip install -r /dev/stdin

К счастью, сам автоэнкодер flash-attn не использует (его импортируют только головы energy/flow/diffusion/calm, и то - под if is_flash_attn_2_available()).

2. deepspeed не импортируется под NumPy 2.x

Обучение падало уже внутри Trainer.train() с такой трассой:

File ".../accelerate/utils/other.py", line 80, in extract_model_from_parallel from deepspeed import DeepSpeedEngine ... File ".../deepspeed/autotuning/scheduler.py", line 8 from numpy import BUFSIZE ImportError: cannot import name 'BUFSIZE' from 'numpy'

numpy.BUFSIZE убрали в NumPy 2.0, а deepspeed==0.10.0 на него завязан. При этом HF-accelerate импортирует deepspeed только если он установлен (is_deepspeed_available() = «пакет присутствует»). deepspeed нужен для распределённого обучения на GPU - у нас его нет и быть не может. Поэтому самое чистое решение - просто снести его:

uv pip uninstall deepspeed

(Откатывать NumPy вниз - рискованно: колёса pandas/pyarrow в окружении собраны под NumPy 2.x, можно поймать ABI-несовместимость.)

3. Тихий OOM на 33 ГБ логитов

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

Причина - в форме тензора логитов. Декодер выдаёт логиты на весь словарь для каждой позиции:

logits: (batch x block_size x vocab) = 32 x 2048 x 128256 x 4 байта ≈ 33.6 ГБ

Плюс столько же на градиент в backward → ~67 ГБ на один шаг при 56 ГБ свободных. Отсюда мгновенный kill. В оригинале спасало то, что batch был 8 и обучение шло на GPU с большой памятью.

Лечение: логиты линейны по batch x block_size. Данные у нас короткие, поэтому длинный block_size не нужен. Снизили его до 256 (batch оставили 32):

32 x 256 x 128256 x 4 ≈ 4.2 ГБ ← помещается с огромным запасом

RSS процесса после фикса держался на ~6.6 ГБ - стабильно.

🚀 Итоговый скрипт запуска

Все правки свели в воспроизводимый лаунчер (важно: запуск модулем -m train.train_autoencoder из корня репозитория, иначе не разрешается import models):

.venv/bin/python -m train.train_autoencoder \
    --train_file ./data/jobs_requirements.json \
    --validation_file ./data/jobs_requirements.json \
    --tokenizer_name ./llama3_tokenizer \
    --config_overrides "latent_size=128" \
    --block_size 256 \
    --output_dir ./checkpoints/autoencoder_requirements \
    --overwrite_output_dir \
    --per_device_train_batch_size 32 \
    --per_device_eval_batch_size 32 \
    --learning_rate 2e-4 \
    --num_train_epochs 5 \
    --do_train --do_eval \
    --save_safetensors False \
    --logging_steps 10 --report_to none

Мелочи, на которых тоже можно споткнуться:

  • аргумент --validation_file не принимает расширение .jsonl (только csv/json/txt) - сделали симлинк .json;

  • --save_safetensors False обязателен: у модели tied-веса (lm_head ≡ эмбеддинги), и safetensors отказывается сериализовать общие тензоры.

📊 Результаты

Обучение: 220 шагов, 5 эпох, 22 минуты на CPU. Лосс падал монотонно (с ~47 на случайной инициализации до ~10.6 к пятой эпохе на тренировочной цели).

Метрика

Значение

eval_loss

2.20

eval perplexity

9.04

train_runtime

22 мин 20 с

примеров/с

5.2 (train) / 14.3 (eval)

Почему train-loss (~10.6) выше eval-loss (2.20)? В режиме обучения модель домножает реконструкционный лосс на patch_size, добавляет KL, кастует эмбеддинги в bf16 и применяет ae_dropout=0.15; на eval всё это выключено и считается чистый fp32. Так что разрыв ожидаем, это не баг.

Проверка «себя»: round-trip через энкодер и декодер

Главный тест для автоэнкодера - прогнать фразу текст → encoder → латент → decoder → текст и сравнить. Делаем это детерминированно: в eval(), беря mean латента напрямую (минуя VAE-сэмплирование), и готовим вход как при обучении (добавить EOS, дополнить pad до кратности K):

ids = tok(text)["input_ids"] + [tok.eos_token_id]
while len(ids) % P: ids.append(pad_id)
x = torch.tensor(ids).view(1, -1).reshape(-1, P)   # патчи (L/4, 4)
latent = model.encoder(input_ids=x)
mean, _ = torch.chunk(latent, 2, dim=-1)           # берём mean
logits = model.decoder(latent_states=mean)
pred = logits.argmax(-1).reshape(-1)               # реконструированные токены

Что получилось:

Вход

Выход

Точность по токенам

React JS 18+

React от 3+

75%

Understanding of REST API

егра и REST API

75%

`Уверенное знание JavaScript: замыкания, асинхронное программирование (async/await Promises), ES6+

Уверенное знание JavaScript:овыкания, асинхронное программирование ( CI/CD,тами), егра+

75%

Честный разбор

Реконструкция узнаваемая, но шумная: каркас и значимые куски сохраняются («React ... +», «REST API», «Уверенное знание JavaScript: ... асинхронное программирование ...»), но примерно каждый четвертый токен искажается. И это не случайность: ровно 75% на фразах совершенно разной длины - сильный сигнал, что модель систематически теряет ~1 токен из каждого патча в 4. Учитывая, что латент в 128 чисел сжимает 4x512 = 2048-мерное представление патча, а обучение длилось всего 5 эпох на крошечном датасете - это похоже на недообучение, а не на потолок архитектуры. В статье «near-perfect reconstruction» достигается на 15 млрд токенов; мы дали модели в ~44 000 раз меньше данных.

⏭️ Что дальше

Очевидные рычаги, чтобы поднять точность реконструкции на этом же домене:

  • больше эпох (20-50 вместо 5) - данных мало, переобучение здесь скорее в плюс для AE-реконструкции;

  • больше данных того же домена;

  • если появится GPU - вернуть block_size/batch оригинала и bf16, обучение ускорится на порядки;

  • поэкспериментировать с latent_size (шире латент → точнее реконструкция, но «тяжелее» пространство для стадии 2) и с kl_weight.

Выводы

  1. Автоэнкодер CALM - это MLP-VAE на патчах без attention, и это осмысленно: задача локального сжатия чанка не требует моделирования контекста.

  2. Архитектура достаточно лёгкая, чтобы крутиться на CPU - 75M параметров, из которых 87% это эмбеддинги.

  3. Главные практические препятствия оказались не в ML, а в инфраструктуре: несовместимость deepspeed/NumPy и OOM из-за полноразмерных логитов на словарь в 128k. Оба лечатся за минуту, если понять причину.

  4. На микроскопическом доменном датасете за 22 минуты на CPU получаем рабочий, но лоссовый автоэнкодер (perplexity 9.04, ~75% точность реконструкции) - отличная отправная точка, чтобы дальше крутить гиперпараметры.

Код эксперимента: лаунчер train/run_autoencoder_requirements.sh и скрипт проверки roundtrip_autoencoder.py. Форк iconicompany/calm, оригинал - shaochenze/calm, статья - arXiv:2510.27688.