Выбрать наибольшее
Вы узнаете
Как argmax называет класс, сравнивая одни только биты, и какое правило решает ничью.
Запись ещё не готова: она ждёт команд tri test и tri mutate plant из gHashTag/t27#7400, которые запись запускает, а до тех пор виджет ниже -- заглушка без запуска. Классификатор в конце называет класс с наибольшей оценкой. gft_argmax4.t27 делает это без арифметики: gt ставит отрицательные ниже нуля, ноль ниже положительных, а затем сравнивает младшие 16 бит, растущие с величиной. По заголовку ничью выигрывает меньший индекс, сравнение строгое >. Браузер пропускает все 4 теста, потому что его исполнитель пока не знает assert_eq; нативный t27c запускает все 4, все проходят, ни один не пустой. Запись меняет > на >= для двух положительных оценок, и падает ровно один тест, tie_low: четыре оценки 1.0 теперь выбирают индекс 3, а не 0. Ни один тест не даёт решить ответ двум отрицательным оценкам: переворот их сравнения ничего не роняет. Каждый байт в записи напечатала команда; инсценирован только набор текста.
Попробуйте
Найдите в записи изменённую строку и упавший тест; затем найдите в спеке строку, которая сравнивает две отрицательные оценки, и тот один тест, который до неё доходит.

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_argmax4.t27
module GftArgmax4;
// #1764 + GF-T: a classification head over four signed GF-T16 logits. Returns the
// INDEX {0,1,2,3} of the maximum real value (lowest index wins ties, strict >).
// This is the final stage of a GF-T classifier: a GF-T MLP (gft_mlp3) emits a
// vector of logits, argmax picks the predicted class. Comparison is exact on the
// real values -- no arithmetic, just a total order on the GF-T encoding.
//
// A signed GF-T16 value in u32 is [sign(bit16)][offset(7)][mant(9)]; the low 16
// bits (offset<<9 | mant) are MONOTONIC in the real magnitude, and raw 0 is the
// only zero. So the real order is: negatives < zero < positives; within positives
// larger magnitude bits = larger; within negatives larger magnitude bits = smaller.
//
// Inputs: x0..x3 signed GF-T16 (u32). Output: index u8 in {0,1,2,3}.
// sign category: zero->1, positive->2, negative->0 (higher category = greater).
fn category(a: u32) -> u8 {
if (a == 0) { return 1; }
if ((a >> 16) == 0) { return 2; }
return 0;
}
// gt(a,b) = 1 iff real value(a) > value(b), else 0.
fn gt(a: u32, b: u32) -> u8 {
var ca : u8 = category(a);
var cb : u8 = category(b);
if (ca != cb) { if (ca > cb) { return 1; } return 0; }
var ma : u32 = a & 65535;
var mb : u32 = b & 65535;
if (ca == 2) { if (ma > mb) { return 1; } return 0; } // both positive
if (ca == 0) { if (ma < mb) { return 1; } return 0; } // both negative
return 0; // both zero -> equal
}
// argmax over four logits, lowest index on ties.
fn on_comb(x0: u32, x1: u32, x2: u32, x3: u32) -> u8 {
var idx : u8 = 0;
var best : u32 = x0;
if (gt(x1, best) == 1) { idx = 1; best = x1; }
if (gt(x2, best) == 1) { idx = 2; best = x2; }
if (gt(x3, best) == 1) { idx = 3; best = x3; }
return idx;
}
// +1.0, -1.0, +2.0, 0 -> max is +2.0 at index 2.
test pick_pos { assert_eq(on_comb(20480, 86016, 20992, 0), 2); }
// -1.0, -2.0, 0, +1.0 -> max is +1.0 at index 3.
test pick_last { assert_eq(on_comb(86016, 86528, 0, 20480), 3); }
// -1.0, 0, -4.0, -2.0 -> max is 0 at index 1 (zero beats all negatives).
test zero_wins { assert_eq(on_comb(86016, 0, 87040, 86528), 1); }
// all equal (+1.0) -> lowest index 0.
test tie_low { assert_eq(on_comb(20480, 20480, 20480, 20480), 0); }
endmodule
Все уроки
Модуль 1 · Лаборатория: наши исследования
Свой формат чисел, честная таблица результатов и таблицы модели, перемноженные на плате.
Модуль 2 · ИИ-числа: блок MX
Как ИИ-чипы хранят веса в нескольких битах: один общий масштаб на блок, сам байт масштаба и что один выброс делает с соседями.
Модуль 3 · Тернарные веса
Веса, которые бывают только минус масштаб, ноль или плюс масштаб, пять правил, которые должен пройти тернарный алфавит, и прогон тестов, который ничего не проверил.
Модуль 4 · Тернарный формат Ternary Network Float
Правило, которое компилятор проверяет до запуска любого теста, и 17-битное число с плавающей точкой, порядок которого — четыре сбалансированных трита.
Модуль 5 · Арифметика чисел со знаком
Умножить два числа со знаком, сложить их, когда знаки разные, и сделать то и другое сразу в умножении с накоплением.
Модуль 6 · Части нейрона
ReLU с изломом в нуле, степень двойки для softmax и argmax, который называет ответ.
Модуль 7 · Обучение на ошибке
Потеря, которая оценивает неверную догадку в битах, один шаг, который сдвигает вес против градиента, и скрытый слой, который нужен XOR.
Модуль 8 · BitNet: тернарные сети
Порог, который сжимает сумму обратно до трёх значений, один нейрон, который становится другой функцией при смене весов, и нейрон, который читает входы по 27 тритов за раз.
Модуль 9 · Тернарный MAC как чип
Скалярное произведение 27 тритов как провода без регистра, та же сумма, которую регистр копит на каждом такте, и небольшая целая сеть в конце курса.