JavaScript: a forward pass through two dense layers
A dense (fully connected) layer computes output = activation(W·x + b). Each output unit has one weight for every input, plus a bias. Stacking layers with non-linear activations lets the network represent far more than a single linear map.
JavaScript
const relu = (z) => Math.max(0, z);
function dense(input, weights, biases, activation) {
return weights.map((row, j) => activation(row.reduce((sum, w, i) => sum + w * input[i], biases[j])));
}
function softmax(scores) {
const largest = Math.max(...scores);
const exps = scores.map((s) => Math.exp(s - largest));
const total = exps.reduce((a, b) => a + b, 0);
return exps.map((e) => e / total);
}
const input = [1, 2];
const w1 = [[0.5, -0.2], [0.3, 0.8], [-0.6, 0.1]];
const b1 = [0.1, 0.0, 0.2];
const w2 = [[1.0, -1.0, 0.5], [0.2, 0.4, -0.3], [-0.5, 0.9, 0.1]];
const b2 = [0.0, 0.1, -0.1];
const hidden = dense(input, w1, b1, relu);
const scores = dense(hidden, w2, b2, (z) => z);
const probabilities = softmax(scores);
console.log("hidden: " + hidden.map((h) => h.toFixed(2)).join(" "));
console.log("scores: " + scores.map((s) => s.toFixed(3)).join(" "));
console.log("probabilities: " + probabilities.map((p) => p.toFixed(3)).join(" "));
console.log("sum: " + probabilities.reduce((a, b) => a + b, 0).toFixed(3));