// SPDX-License-Identifier: Apache-2.0 ; specs/widgets/nn-huber.t27 -- the Huber loss: square inside delta, linear outside ; Source of truth for public/widgets/nn-huber/ (gHashTag/trinity): scripts/widget-pages-from-spec.mjs ; compiles this file, checks its constants, evaluates the tests below and writes the page; the page ; hands every constant to tool.js as window.T27_WIDGET. tool.js holds no English and NO FORMULA of ; its own: every value it draws comes from public/widgets/nn-huber/logic.js -- the fn bodies of ; gHashTag/t27 specs/ml/loss/huber_loss.t27 compiled to wasm, beside its copy logic.t27. ; Lesson 15 of the course neural-networks. ASCII only (L3), English only (LANG-EN). ; Numbers are integers (the schema reads no float): a K_ name ending in _C is in hundredths. ; WHAT IT DOES: the reader drags the error from -4 to 4 and sets delta from 0.25 to 3. The green ; curve is huber_one(e, delta), the dashed curve huber_one(e, 1000), which never leaves its ; quadratic part on this window, and the tiles huber_two on the spec's pair. ; WHAT IT DOES NOT CLAIM: the 30-error figure in the hook is the same two fns at e = 30, read off ; the compiled logic, not a measurement of a model. ; phi^2 + 1/phi^2 = 3 | TRINITY module widget_nn_huber; pub const KIND : str = "widget-tool"; pub const ID : str = "nn-huber"; pub const TITLE : str = "Huber loss: a loss that does not panic at an outlier"; pub const DESCRIPTION : str = "Drag the error along: Huber is half its square inside delta and only grows linearly outside, so one wild miss pulls on the model with a bounded force. The dashed curve is the pure square."; pub const IMAGE_ALT : str = "Huber card at delta 1, error 3: the green Huber curve is a small parabola between the cyan dashed lines at -1 and 1 and then two straight arms; the dashed gold square climbs much faster. Tiles read Huber 2.5000, square 4.5000 and, for the spec's pair of errors (0.5, 3), 1.3125 against 2.3125."; pub const HOOK : str = "An error of 3 costs 2.5 under Huber with delta 1 and 4.5 squared. At 30 the gap is 29.5 against 450: why robust regression uses it."; pub const CATEGORY : str = "compiler"; pub const DATA_SOURCES : [2]str = ["gHashTag/t27 specs/ml/loss/huber_loss.t27 (t27 master 239b4b059): every value on the page is its fn bodies, compiled to wasm (logic.js)", "Course 10 of t27.ai, neural-networks (gHashTag/trinity#1695): lesson 15 opens this widget"]; pub const READS_LOCAL_FILES : bool = false; pub const SENDS_NOTHING : bool = true; pub const K_CARD_WIDTH : u16 = 1200; pub const K_CARD_HEIGHT : u16 = 630; ; --- Numbers: ranges, presets, and fixtures the spec holds (held equal by the tests below) pub const K_E_LO_C : i16 = -400; pub const K_E_HI_C : u16 = 400; pub const K_Y_HI_C : u16 = 800; pub const K_X_TICKS : [5]i8 = [-4, -2, 0, 2, 4]; pub const K_Y_TICKS : [5]u8 = [0, 2, 4, 6, 8]; pub const K_DELTA_LO_C : u8 = 25; pub const K_DELTA_HI_C : u16 = 300; pub const K_WIDE : u16 = 1000; pub const K_PAIR_C : [2]u16 = [50, 300]; pub const K_PRESET_E_C : [4]i16 = [300, 50, -300, 200]; pub const K_PRESET_DELTA_C : [4]u16 = [100, 100, 50, 300]; pub const K_START_PRESET : u8 = 0; ; --- Words on screen ------------------------------------------------------------------------ pub const SAY_PRESETS_LABEL : str = "Start from"; pub const SAY_PRESET_NAMES : [4]str = ["Error 3, delta 1", "Error 0.5, delta 1", "Error -3, delta 0.5", "Error 2, delta 3"]; pub const SAY_ASK : str = "Can a loss stay calm when one data point is far off?"; pub const SAY_E : str = "error e"; pub const SAY_DELTA : str = "delta"; pub const SAY_HUBER : str = "Huber"; pub const SAY_SQUARE : str = "half the square"; pub const SAY_PLOT_LABEL : str = "Huber loss and half the squared error as the error goes from -4 to 4"; pub const SAY_PAIR : str = "Huber of ({0}, {1})"; pub const SAY_PAIR_SQ : str = "square of ({0}, {1})"; pub const SAY_NOTE : str = "Inside delta Huber is the square; outside it is delta |e| - delta^2 / 2, joined so that value and slope agree. Its gradient never grows past delta."; pub const SAY_SOURCE : str = "Logic: t27 spec ml/loss/huber_loss.t27, compiled"; test the_card_is_the_share_size { assert K_CARD_WIDTH == 1200; assert K_CARD_HEIGHT == 630; assert K_CARD_WIDTH * 21 == K_CARD_HEIGHT * 40; } test the_wide_delta_never_clips_the_window { assert K_WIDE * 100 > K_E_HI_C; assert K_DELTA_HI_C < K_WIDE * 100; } test the_pair_is_the_spec_example { assert K_PAIR_C[0] == 50; assert K_PAIR_C[1] == 300; assert K_PRESET_DELTA_C[3] == K_DELTA_HI_C; }