Излом в нуле
Вы узнаете
Почему ReLU нужен тест с отрицательным входом, прежде чем можно сказать, что у неё есть излом.
Запись ещё не готова: она ждёт команд tri test и tri mutate plant из gHashTag/t27#7400, которые запись запускает, а до тех пор виджет ниже -- заглушка без запуска. Нейрон пропускает свою сумму через функцию активации, и в gft_relu.t27 это relu(x) = max(0, x). on_comb возвращает 0 для нуля и для любого входа с битом знака, а иначе сам x. Заголовок говорит, что у ReLU точный градиент 0/1 и что 2-слойная сеть с ReLU решает XOR, а линейная модель GF-T этого не может. Браузер пропускает все 4 теста, потому что его исполнитель пока не знает assert_eq; нативный t27c запускает все 4, все проходят, ни один не пустой. Запись пропускает отрицательные входы, и relu становится тождеством, прямой линией. Падает ровно один тест, negz; больше ни у одного теста нет отрицательного входа. Каждый байт в записи напечатала команда; инсценирован только набор текста.
Попробуйте
Найдите в записи изменённую строку и значение, которого ждёт negz; затем найдите в спеке комментарий на этой строке и проверьте, описывает ли он код после замены.

Recording pending: waits on tri test and tri mutate plant from gHashTag/t27#7400. Until then this page is a placeholder and shows no run.
specs/ternary/gft_relu.t27
module GftRelu;
// #1764 + GF-T: a GF-T ReLU activation -- relu(x) = max(0, x). For a signed GF-T16
// input, returns x if x > 0 else 0 (raw 0). Unlike the sign/trit quantizer, ReLU
// has an EXACT 0/1 gradient (no straight-through estimate needed), so it enables
// clean multi-layer backprop on GF-T (see tools/gft_deep_demo.py: a 2-layer ReLU
// net solves XOR, which a linear GF-T model cannot).
//
// Input: x signed GF-T16 (u32). Output: max(0,x) as GF-T16 (u32).
fn on_comb(x: u32) -> u32 {
if (x == 0) { return 0; }
if ((x >> 16) == 1) { return 0; } // negative -> 0
return x; // positive -> identity
}
// relu(+1.0) = +1.0 (0x5000).
test pos { assert_eq(on_comb(20480), 20480); }
// relu(-1.0) = 0.
test negz { assert_eq(on_comb(86016), 0); }
// relu(0) = 0.
test zero { assert_eq(on_comb(0), 0); }
// relu(+2.0) = +2.0 (0x5200).
test pos2 { assert_eq(on_comb(20992), 20992); }
endmodule
Все уроки
Модуль 1 · Лаборатория: наши исследования
Свой формат чисел, честная таблица результатов и таблицы модели, перемноженные на плате.
Модуль 2 · ИИ-числа: блок MX
Как ИИ-чипы хранят веса в нескольких битах: один общий масштаб на блок, сам байт масштаба и что один выброс делает с соседями.
Модуль 3 · Тернарные веса
Веса, которые бывают только минус масштаб, ноль или плюс масштаб, пять правил, которые должен пройти тернарный алфавит, и прогон тестов, который ничего не проверил.
Модуль 4 · Тернарный формат Ternary Network Float
Правило, которое компилятор проверяет до запуска любого теста, и 17-битное число с плавающей точкой, порядок которого — четыре сбалансированных трита.
Модуль 5 · Арифметика чисел со знаком
Умножить два числа со знаком, сложить их, когда знаки разные, и сделать то и другое сразу в умножении с накоплением.
Модуль 6 · Части нейрона
ReLU с изломом в нуле, степень двойки для softmax и argmax, который называет ответ.
Модуль 7 · Обучение на ошибке
Потеря, которая оценивает неверную догадку в битах, один шаг, который сдвигает вес против градиента, и скрытый слой, который нужен XOR.
Модуль 8 · BitNet: тернарные сети
Порог, который сжимает сумму обратно до трёх значений, один нейрон, который становится другой функцией при смене весов, и нейрон, который читает входы по 27 тритов за раз.
Модуль 9 · Тернарный MAC как чип
Скалярное произведение 27 тритов как провода без регистра, та же сумма, которую регистр копит на каждом такте, и небольшая целая сеть в конце курса.