scalar-autograd
Version:
Scalar-based reverse-mode automatic differentiation in TypeScript.
55 lines (54 loc) • 2.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const Value_1 = require("./Value");
const Losses_1 = require("./Losses");
describe("Losses", () => {
it("mse computes value and gradients correctly", () => {
const x = new Value_1.Value(2, "x", true);
const y = new Value_1.Value(3, "y", true);
const tx = new Value_1.Value(5, "tx");
const ty = new Value_1.Value(1, "ty");
const loss = Losses_1.Losses.mse([x, y], [tx, ty]); // (1/2)*((2-5)^2 + (3-1)^2) = (1/2)*(9+4) = 6.5
expect(loss.data).toBeCloseTo(6.5);
loss.backward();
expect(x.grad).toBeCloseTo(-3);
expect(y.grad).toBeCloseTo(2);
});
it("mae computes value and gradients correctly", () => {
const x = new Value_1.Value(2, "x", true);
const y = new Value_1.Value(-3, "y", true);
const tx = new Value_1.Value(5, "tx");
const ty = new Value_1.Value(2, "ty");
const loss = Losses_1.Losses.mae([x, y], [tx, ty]); // (1/2)*(abs(2-5)+abs(-3-2)) = (1/2)*(3+5)=4
expect(loss.data).toBeCloseTo(4);
loss.backward();
expect(x.grad).toBeCloseTo(-0.5);
expect(y.grad).toBeCloseTo(-0.5);
});
it("binaryCrossEntropy computes value and gradients correctly for easy case", () => {
const out = new Value_1.Value(0.9, "out", true);
const target = new Value_1.Value(1, "target");
const loss = Losses_1.Losses.binaryCrossEntropy([out], [target]);
expect(loss.data).toBeCloseTo(-Math.log(0.9));
loss.backward();
expect(out.grad).toBeCloseTo(-1 / 0.9, 4);
});
it("categoricalCrossEntropy computes value and gradients (softmax+NLL)", () => {
// logits: [2, 1, 0], true = 0
const a = new Value_1.Value(2, "a", true);
const b = new Value_1.Value(1, "b", true);
const c = new Value_1.Value(0, "c", true);
const targets = [0];
const loss = Losses_1.Losses.categoricalCrossEntropy([a, b, c], targets);
const softmax = [
Math.exp(2) / (Math.exp(2) + Math.exp(1) + Math.exp(0)),
Math.exp(1) / (Math.exp(2) + Math.exp(1) + Math.exp(0)),
Math.exp(0) / (Math.exp(2) + Math.exp(1) + Math.exp(0))
];
expect(loss.data).toBeCloseTo(-Math.log(softmax[0]), 4);
loss.backward();
expect(a.grad).toBeCloseTo(softmax[0] - 1, 4);
expect(b.grad).toBeCloseTo(softmax[1], 4);
expect(c.grad).toBeCloseTo(softmax[2], 4);
});
});