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

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
P
Privacy International News Feed
U
Unit 42
B
Blog
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Forbes - Security
Forbes - Security
Engineering at Meta
Engineering at Meta
J
Java Code Geeks
Scott Helme
Scott Helme
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
美团技术团队
T
Threat Research - Cisco Blogs
MyScale Blog
MyScale Blog
爱范儿
爱范儿
Schneier on Security
Schneier on Security
Y
Y Combinator Blog
C
Cisco Blogs
P
Proofpoint News Feed
T
Tenable Blog
TaoSecurity Blog
TaoSecurity Blog
aimingoo的专栏
aimingoo的专栏
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
H
Heimdal Security Blog
N
News and Events Feed by Topic
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
W
WeLiveSecurity
SecWiki News
SecWiki News
小众软件
小众软件
I
InfoQ
Project Zero
Project Zero
Recent Announcements
Recent Announcements
Microsoft Azure Blog
Microsoft Azure Blog
Blog — PlanetScale
Blog — PlanetScale
Attack and Defense Labs
Attack and Defense Labs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
S
Secure Thoughts
Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Cloudbric
Cloudbric
G
Google Developers Blog
Hacker News: Ask HN
Hacker News: Ask HN
Help Net Security
Help Net Security
C
Cybersecurity and Infrastructure Security Agency CISA
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

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

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче 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 миллионов точек без потерь
Сказ о том, как нейросеть занялась reward hacking прямо у меня на кухне
inkedsymon · 2026-06-18 · via Все публикации подряд на Хабре

Средний

9 мин

63

С чего все началось

Я хотел просто пожарить кесадилью. В холодильнике лежали зеленые оливки (солено-кислые), сулугуни и фарш, а на полке — консервированная кукуруза. И вот стою я над сковородкой и думаю: а оливки с кукурузой вообще сочетаются? А сулугуни не пересолит блюдо вместе с оливками? Сколько чего вообще класть?

В любой другой ситуации я бы загуглил рецепт. Но не тут-то было, я же великий комбинатор оптимизатор, и у меня в голове сразу всплыло: «это же задача оптимизации». Тем же вечером у меня был ноутбук с обученной нейросетью вместо ужина. Рассказываю, как дошел до жизни такой, и как из этого внезапно получился реально вкусный рецепт.

Вкус — это вектор

Базовая идея простая. Любой вкус раскладывается на оси. 

Я взял семь: соль, кислота, сладость, горечь, умами, острота, жир.

Тогда каждый ингредиент — это точка в 7-мерном пространстве. Я закодировал свою кладовую руками (да, по ощущениям и кулинарному имхо, это самая субъективная часть):

Ингредиент

соль

кислота

сладкое

горечь

умами

острота

жир

фарш гов.-свин.

3

0

1

0

8

0

7

сулугуни

6

2

1

0

5

0

6

зел. оливки

8

5

0

2

4

0

3

кукуруза

0

0

7

1

2

0

1

карамел. лук

1

1

8

1

2

0

2

помидор

1

4

3

0

3

0

0

лайм

0

9

1

2

0

0

0

То есть вкус готового блюда — это просто взвешенная сумма векторов ингредиентов:

import numpy as np

# оси: соль, кислота, сладость, горечь, умами, острота, жир
ING = {
    "фарш": np.array([3, 0, 1, 0, 8, 0, 7.0]),
    "сулугуни": np.array([6, 2, 1, 0, 5, 0, 6.0]),
    "оливки": np.array([8, 5, 0, 2, 4, 0, 3.0]),
    "кукуруза": np.array([0, 0, 7, 1, 2, 0, 1.0]),
    "лук": np.array([1, 1, 8, 1, 2, 0, 2.0]),
    "помидор": np.array([1, 4, 3, 0, 3, 0, 0.0]),
    "лайм": np.array([0, 9, 1, 2, 0, 0, 0.0]),
}

V = np.stack(list(ING.values()))


def profile(amounts):  # amounts — сколько каждого кладем
    return amounts @ V

Облачная инфраструктура для ваших проектов

Виртуальные машины в Москве, Санкт-Петербурге и Новосибирске с оплатой по потреблению.

Подробнее →

Уравнение баланса (главный инсайт)

Проблема зеленых оливок: они бьют по двум осям — соль и горечь. Если бросить их в сыр и завернуть, получится соленое нечто, которое невозможно есть.

Как это лечится физиологически? Сладкое и кислое подавляют восприятие соли и горечи. Тот же принцип объясняет, почему в горький кофе кладут сахар, а в соленую карамель, соответственно, соль.

Отсюда метрика, вокруг которой крутится вся идея:

def rho(p):
    # (соль + горечь) / (кислота + сладость), цель ≈ 1.0
    return (p[0] + p[3]) / (p[1] + p[2] + 1e-9)

ρ ≫ 1 → солено-горький перекос, есть невозможно 

ρ ≈ 1 → соль и горечь «пойманы» сладким и кислым

ρ ≪ 1 → приторно/кисло, уехали в десерт

Голая версия «сыр + оливки» дает ρ = 2.0. Цель — притянуть к единице, добавив сладость (кукуруза, карамелизованный лук) и кислоту (лайм, помидор). Казалось бы, все, идея дошла до логического конца, иди жарь...

«А давай нейросеть»

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

Датасет собрал на коленке. Позитивы — это 14 классических блюд, закодированных как вкусовые профили: маргарита, болоньезе, путанеска, цезарь, том-ям, паэлья, шакшука, чили кон карне и компания. 

Негативы — это случайные миксы ингредиентов и «шипы», когда одна ось задрана в потолок, а остальные на нуле.

Сеть самая обычная, 7 → 16 → 1, на numpy:

def sigmoid(z):
    return 1 / (1 + np.exp(-z))


W1 = rng.normal(0, 0.5, (7, 16))
b1 = np.zeros(16)

W2 = rng.normal(0, 0.5, (16, 1))
b2 = np.zeros(1)


def forward(X):
    a1 = np.tanh(X @ W1 + b1)
    return sigmoid(a1 @ W2 + b2), a1

Тут на секунду остановимся, чтобы все понимали, что тут происходит. На входе семь чисел, мои оси вкуса. Дальше один скрытый слой из 16 нейронов с tanh, на выходе — одно число от 0 до 1 через сигмоиду. Читаем как «насколько это похоже на нормальную еду»: 1 — это гармония, 0 — это абсолютно несъедобно. И все, это самый базовый перцептрон, который влезает в десяток строк.

Учится через обычный backprop. То есть сеть смотрит на блюдо, выдает догадку. Сравнивает догадку с правильным ответом (1 для классики, 0 для мусора), считает ошибку. Backprop говорит, в какую сторону шевельнуть каждый вес, чтобы ошибка чуть уменьшилась. Сетка шевелит, и повторяет всего лишь 4 000 раз. И к концу сеть перестает путать борщ с белым шумом.

Датасет, негативы и обучение
import numpy as np

rng = np.random.default_rng(42)
AXES = ["соль","кислота","сладость","горечь","умами","острота","жир"]
N = len(AXES)

def normalize(p):                 # профиль -> сумма 1
    s = p.sum()
    return p / s if s > 0 else p

# Функция оценки гармонии
def harmony(p): 
    out, _ = forward(normalize(p).reshape(1, -1))
    return float(out.item())

# ПОЗИТИВЫ: 14 классических блюд как вкусовые профили
CLASSICS = {
    "маргарита": [3,3,2,0,5,0,5], "греч.салат": [5,4,1,2,3,0,4],
    "болоньезе": [3,2,2,0,7,1,6], "тако": [4,4,3,0,6,3,5],
    "путанеска": [6,4,1,2,6,2,4], "цезарь": [5,3,1,1,6,0,6],
    "карбонара": [5,1,1,0,7,1,7], "том-ям": [4,6,3,1,5,5,3],
    "хумус": [3,3,1,1,4,0,6],     "рагу": [3,3,4,1,5,1,4],
    "чили": [4,3,3,1,7,4,5],      "паэлья": [4,2,2,0,6,1,4],
    "шакшука": [4,4,3,0,5,2,4],   "том-кха": [4,4,4,0,5,3,5],
}
pos = np.array([normalize(np.array(v, float)) for v in CLASSICS.values()])

# НЕГАТИВЫ: «не еда», 200 штук, два типа поровну
def random_negative():
    if rng.random() < 0.5:
        # 1) абсурдный микс: случайные порции случайного подмножества
        a = rng.random(len(ING)) * (rng.random(len(ING)) < 0.5)
        p = profile(a)
        return None if p.sum() == 0 else normalize(p)
    else:
        # 2) «шип»: все оси низкие, одна задрана в потолок
        v = rng.random(N) * 0.3
        v[rng.integers(N)] = 1.0 + rng.random()
        return normalize(v)

neg = []
while len(neg) < 200:
    s = random_negative()
    if s is not None:
        neg.append(s)
neg = np.array(neg)

X = np.vstack([pos, neg])
y = np.array([1.0]*len(pos) + [0.0]*len(neg)).reshape(-1, 1)

# ОБУЧЕНИЕ: обычный backprop, 4000 эпох
lr = 0.5
for epoch in range(4000):
    out, a1 = forward(X)
    out = np.clip(out, 1e-7, 1 - 1e-7)
    loss = -np.mean(y*np.log(out) + (1 - y)*np.log(1 - out))
    d2 = (out - y) / len(X)
    dW2 = a1.T @ d2;  db2 = d2.sum(0)
    dz1 = (d2 @ W2.T) * (1 - a1**2)
    dW1 = X.T @ dz1;  db1 = dz1.sum(0)
    W2 -= lr*dW2;  b2 -= lr*db2
    W1 -= lr*dW1;  b1 -= lr*db1

Точные loss и точность немного плавают от состава кладовой и порядка генерации случайных чисел, так что может выйти 96–97%, а не ровно мои 97.20%. Но на мораль это не влияет, негативы тут все равно отделяются легко.

В итоге я увидел loss=0,0825, точность=97,20%

97% на отделении нормальной еды от треша. Сеть работает, и я уже мысленно набирал заголовок «ИИ изобрел идеальный рецепт».

А теперь, прежде чем праздновать, две оговорки. Напишу их сам, пока их не написали за меня.

Первая. Эти 97% почти ничего не стоят. Негативы у меня — это случайный шум и блюда с одной задранной осью. Отличить такое от настоящей еды может и линейка, не то что нейросеть. Так что 97% значит всего лишь «сеть сносно отделяет еду от шума». Запомните это число, дальше я покажу, насколько оно пустое.

Вторая, и она важнее. Позитивы, те самые 14 блюд, я закодировал руками, и, самое главное, по своему вкусу. Значит сеть выучила не вкус вообще, а мой вкус. То бишь я построил прокси собственного вкуса и сейчас отдам его оптимизатору. Дальше посмотрим, что оптимизатор делает с любым прокси, даже с честно сделанным.

Что выучила сеть

Прежде чем доверять модели ужин, я решил заглянуть внутрь и посмотреть, что сеть любит, а что ненавидит. Делается это в лоб: берем сбалансированный профиль, по очереди чуть-чуть добавляем каждую ось и смотрим, как меняется оценка. Растет — сеть награждает ось, падает — штрафует. Это численная производная гармонии по каждой оси:

base = normalize(np.array([4, 3, 3, 1, 5, 1, 4.0]))  # типичный баланс
eps = 1e-3

for i, ax in enumerate(AXES):
    d = base.copy()
    d[i] += eps  # чуть добавили одну ось
    g = (harmony(d) - harmony(base)) / eps  # как изменилась оценка

И вот что получилось:

соль     : +1.09  (награждает)

кислота  : +0.18  (награждает)

сладость : -3.54  (штрафует)

горечь   : -8.75  (штрафует сильно)

умами    : +1.39  (награждает)

острота  : +6.88  (награждает)

жир      : +0.17  (награждает)

То есть сеть лютой ненавистью ненавидит горечь (−8.75). Логично, в классике горечь почти всегда фоновая.

Любит умами, жир и соль, потому что любимые человечеством блюда жирные и насыщенные (кто бы сомневался).

Обожает остроту (+6.88) — в датасете полно острых хитов (том-ям, тако, чили). А я хотел неострую кесадилью. Первый звоночек, что у нас с моделью разные планы на вечер.

Подозрительно относится к сладости (−3.54) — сладкое в несладком блюде, по всей видимости, она читает как «что-то не так».

И вот последний пункт был бомбой замедленного действия.

Reward hacking за моей сковородкой

Теперь инверсная готовка. До этого я спрашивал сеть «оцени вот это блюдо». Далее переворачиваю вопрос: «придумай количества ингредиентов с максимальной оценкой». Стартовые количества задаю сам, где-то в середине допустимых диапазонов. 

Дальше дело алгоритма: на каждом шаге он смотрит, в какую сторону двигать ингредиенты, чтобы оценка подросла (больше сыра? меньше кукурузы?), делает шаг туда и сразу обрезает результат до разумных рамок (нельзя же класть минус два помидора или килограмм лайма). Вот это обрезание и называется проекция. Запускаю на 600 шагов. По сути это градиентный подъем: тот же градиентный спуск, только наоборот, лезем вверх к максимуму оценки.

lo = np.array([1.0, 1.0, 0.3, 0.2, 0.2, 0.0, 0.2])  # минимумы порций
hi = np.array([3.0, 2.5, 1.2, 1.2, 1.5, 1.0, 1.0])  # максимумы

a = (lo + hi) / 2  # старт посередине
step = 0.05

for _ in range(600):
    grad = np.zeros(len(a))
    f0 = objective(a)

    for i in range(len(a)):  # численный градиент по каждой порции
        da = a.copy()
        da[i] += 1e-3
        grad[i] = (objective(da) - f0) / 1e-3

    a = np.clip(a + step * grad, lo, hi)  # шаг вверх + проекция в рамки

# objective — это оценка сети с мягким штрафом за дисбаланс

И абра-кадабра, модель, придумай мне идеальную кесадилью:

фарш      : 1.19

сулугуни  : 2.50   ← уперлась в максимум

оливки    : 0.91

кукуруза  : 0.20   ← минимум

лук       : 0.20   ← минимум

помидор   : 0.25   ← минимум

лайм      : 0.20   ← минимум

Сеть выкрутила сыр на максимум и задавила в пол ровно те ингредиенты, которые балансируют оливки: кукурузу, лук, помидор, лайм. Она хотела приготовить мне солено-жирно-умами питту с сыром.

И вот контрольный выстрел. Я попросил сеть оценить напрямую две версии: питту из сыра с оливками и сбалансированную — ту самую, которую я в итоге и приготовил:

одна и та же сеть, две тарелки:

harmony(profile(naive))   # сыр + оливки, ρ=2.0          -> 0.5845

harmony(profile(final))   # мой ручной баланс, ρ≈1.0     -> 0.1320

простая (только сыр + оливки):          58.45%

сбалансированная (мой будущий фаворит):  13.20%

То есть блюдо, которое потом возьмет на дегустации твердые 9/10, нейросеть оценила в 13%. А соленую питту, от которой должно воротить, в 58%, почти вчетверо выше. Метрика не просто кривая, на моем блюде она отрицательно скоррелирована с тем, что реально вкусно.

Почему так? Возвращаемся в пункт Что выучила сеть: она штрафует сладость и обожает остроту. А мой баланс держится ровно на сладости (кукуруза, карамелизованный лук) и принципиально не содержит остроты. Для модели, выросшей на острой насыщенной классике, мой вариант выглядит как «пресная сладковатая ерунда». Она выучила «вкусное = жирное + соленое + умами + остренькое», и теперь бьет меня этим по голове. Зачем модели овощи, если можно больше сыра?

Это классический закон Гудхарта во всей красе: «когда метрика становится целью, она перестает быть хорошей метрикой». Я дал модели прокси («похоже на классическое блюдо»), она честно его оптимизировала, и проигнорировала настоящую цель («чтобы было не противно есть»). Та же история, что с агентами, которые вместо прохождения уровня игры учатся вечно собирать одну монетку в цикле. Только у меня вместо монетки сыр.

Как человек победил модель

Решение оказалось не «выкинуть нейросеть», а добавить ей интерпретируемый намордник — тот самый ρ из части 2, как регуляризатор:

def objective(a):
    p = profile(a)
    return harmony(p) - 0.15 * (rho(p) - 1.0) ** 2  # штраф за дисбаланс

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

Этот штраф уже стоял в оптимайзере — и все равно сеть дотащила баланс лишь до ρ = 1,43 (с наивных 2.0), попутно задавив овощи в пол. До честной 1.0 я дожал пропорции руками, фактически перестав слушать harmony-оценку. Зеленая фигура на картинке ниже — это финал, где жир ≈ умами ≈ соль держат базу, а сладость с кислотой подпирают, не давая оливкам солить в одни ворота. Красная пунктирная — наивная бомба. Желтая пунктирная — то, что хотела модель: чуть ровнее бомбы по балансу, но все еще перекос в жир и соль.

Дегустация

Я пожарил только ту, которую довел до ума по параметрам, и по итогу оливки дают соленый укол, кукуруза и карамелизованный лук ловят его сладостью, лайм в конце освежает, сулугуни отлично сочетается. «Это можно подавать». 9/10.

Победила, что характерно, связка «модель предлагает — человек правит метрику». И да, напомню: именно этот итоговый вариант нейросеть оценила в 13%, а сырную бомбу — в 58%. Вопросы к метрике?

Что я из этого всего понял для себя

Закон Гудхарта живет даже на кухне. Модель оптимизирует ровно то, что ты измеряешь, а не то, что ты имеешь в виду. Прокси «похоже на классику» ≠ «вкусно поесть».

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

Лучшая архитектура — человек в петле. Модель генерирует, человек правит функцию награды. Скучно, зато съедобно.

Я потратил время, чтобы пожарить кесадилью с помощью градиентного спуска.

P.S. Если дочитали до сюда, то возможно, вы тоже из тех, кто оптимизирует бутерброды, добро пожаловать в клуб.