diff --git a/src/Creature.ts b/src/Creature.ts index b5b9a74d..0895ce56 100644 --- a/src/Creature.ts +++ b/src/Creature.ts @@ -630,12 +630,6 @@ export class Creature implements CreatureInternal { * Back propagate the creature */ propagate(expected: number[], config: BackPropagationConfig) { - if (expected === undefined || expected.length !== this.output) { - throw new Error( - `Expected length should match creature's output length: ${this.output} was: ${expected?.length}`, - ); - } - this.state.cacheAdjustedActivation.clear(); const indices = Int32Array.from({ length: this.output }, (_, i) => i); // Create an array of indices @@ -644,18 +638,16 @@ export class Creature implements CreatureInternal { } const lastOutputIndx = this.neurons.length - this.output; - for (let attempts = this.output; attempts--;) { - for (let i = this.output; i--;) { - const expectedIndex = indices[i]; - const nodeIndex = lastOutputIndx + expectedIndex; + for (let i = this.output; i--;) { + const expectedIndex = indices[i]; + const nodeIndex = lastOutputIndx + expectedIndex; - const n = this.neurons[nodeIndex]; + const n = this.neurons[nodeIndex]; - n.propagate( - expected[expectedIndex], - config, - ); - } + n.propagate( + expected[expectedIndex], + config, + ); } } diff --git a/src/architecture/BackPropagation.ts b/src/architecture/BackPropagation.ts index 711b1f29..6428e656 100644 --- a/src/architecture/BackPropagation.ts +++ b/src/architecture/BackPropagation.ts @@ -1,7 +1,8 @@ import { ActivationInterface } from "../methods/activations/ActivationInterface.ts"; import { NeuronActivationInterface } from "../methods/activations/NeuronActivationInterface.ts"; import { UnSquashInterface } from "../methods/activations/UnSquashInterface.ts"; -import { CreatureState, SynapseState } from "./CreatureState.ts"; +import { SynapseState } from "../propagate/SynapseState.ts"; +import { CreatureState } from "./CreatureState.ts"; import { Neuron } from "./Neuron.ts"; import { Synapse } from "./Synapse.ts"; @@ -43,7 +44,7 @@ export interface BackPropagationOptions { /** When limiting the weight/bias use exponential scaling, Default enabled */ disableExponentialScaling?: boolean; - /** the minimum unit of weights/baises */ + /** the minimum unit of weights/biases */ plankConstant?: number; } diff --git a/src/architecture/CreatureState.ts b/src/architecture/CreatureState.ts index 1b51d57b..6de4f959 100644 --- a/src/architecture/CreatureState.ts +++ b/src/architecture/CreatureState.ts @@ -1,4 +1,5 @@ import { Creature } from "../Creature.ts"; +import { SynapseState } from "../propagate/SynapseState.ts"; import { BackPropagationConfig } from "./BackPropagation.ts"; export interface NeuronStateInterface { @@ -63,13 +64,6 @@ export class NeuronState implements NeuronStateInterface { } } -export class SynapseState { - count = 0; - - averageWeight = 0; - public used?: boolean; -} - export class CreatureState { private nodeMap; private connectionMap; diff --git a/src/architecture/SynapseInterfaces.ts b/src/architecture/SynapseInterfaces.ts index 54b9187a..99403572 100644 --- a/src/architecture/SynapseInterfaces.ts +++ b/src/architecture/SynapseInterfaces.ts @@ -1,5 +1,5 @@ import { TagInterface } from "https://deno.land/x/tags@v1.0.2/mod.ts"; -import { SynapseState } from "./CreatureState.ts"; +import { SynapseState } from "../propagate/SynapseState.ts"; interface SynapseCommon { weight: number; diff --git a/src/propagate/SynapseState.ts b/src/propagate/SynapseState.ts new file mode 100644 index 00000000..800f9196 --- /dev/null +++ b/src/propagate/SynapseState.ts @@ -0,0 +1,6 @@ +export class SynapseState { + count = 0; + + averageWeight = 0; + public used?: boolean; +} diff --git a/test/Propagate/AccumulateWeight.ts b/test/Propagate/AccumulateWeight.ts index 523ab92c..c32109cd 100644 --- a/test/Propagate/AccumulateWeight.ts +++ b/test/Propagate/AccumulateWeight.ts @@ -1,9 +1,9 @@ import { assertAlmostEquals } from "https://deno.land/std@0.220.1/assert/mod.ts"; import { accumulateWeight } from "../../src/architecture/BackPropagation.ts"; -import { SynapseState } from "../../src/architecture/CreatureState.ts"; import { BackPropagationConfig } from "../../src/architecture/BackPropagation.ts"; import { Creature, CreatureExport } from "../../mod.ts"; import { adjustedWeight } from "../../src/architecture/BackPropagation.ts"; +import { SynapseState } from "../../src/propagate/SynapseState.ts"; Deno.test("AccumulateWeight-Standard", () => { const cs = new SynapseState(); diff --git a/test/Propagate/SingleNeuron.ts b/test/Propagate/SingleNeuron.ts index a5bcc649..e209ca49 100644 --- a/test/Propagate/SingleNeuron.ts +++ b/test/Propagate/SingleNeuron.ts @@ -85,10 +85,13 @@ Deno.test("OneAndDone", () => { ); const input = [-1, 0, 1]; - creature.activate(input); const expected = makeOutput(input); - creature.propagate(expected, config); + for (let i = 0; i < 100; i++) { + creature.activateAndTrace(input); + + creature.propagate(expected, config); + } Deno.writeTextFileSync( `${traceDir}/1-trace.json`, diff --git a/test/Propagate/SkipCount.ts b/test/Propagate/SkipCount.ts new file mode 100644 index 00000000..b0f4743b --- /dev/null +++ b/test/Propagate/SkipCount.ts @@ -0,0 +1,61 @@ +import { assertEquals } from "https://deno.land/std@0.220.1/assert/mod.ts"; +import { Creature, CreatureExport } from "../../mod.ts"; +import { BackPropagationConfig } from "../../src/architecture/BackPropagation.ts"; + +Deno.test("SkipCount", () => { + const config = new BackPropagationConfig({ generations: 0, learningRate: 1 }); + + const creature = makeCreature(); + + const expected = creature.activateAndTrace([1, 2, 3]); + + creature.propagate(expected, config); + const cs = creature.state.connection(0, 3); + + assertEquals(cs.count, 2); +}); + +function makeCreature() { + /* + * i0 i1 i2 + * h3=(i0 * -0.1) + (i1 * 0.2) - 0.3 + * o4=(h3 * 0.4) - 0.5 + * o5=(h3 * -0.6) + (i2 * 0.7 ) + 0.8 + */ + const json: CreatureExport = { + neurons: [ + { type: "hidden", uuid: "hidden-3", squash: "IDENTITY", bias: 0 }, + + { + type: "output", + squash: "IDENTITY", + uuid: "output-0", + bias: 1, + }, + { + type: "output", + squash: "IDENTITY", + uuid: "output-1", + bias: 0, + }, + ], + synapses: [ + /* h3=(i0 * -0.1) + (i1 * 0.2) - 0.3 */ + { fromUUID: "input-0", toUUID: "hidden-3", weight: -1 }, + { fromUUID: "input-1", toUUID: "hidden-3", weight: 0 }, + + /* o4=(h3 * 0.4) - 0.5*/ + { fromUUID: "hidden-3", toUUID: "output-0", weight: 1 }, + + /* o5=(h3 * -0.6) + (i2 * 0.7 ) + 0.8*/ + { fromUUID: "hidden-3", toUUID: "output-1", weight: 1 }, + { fromUUID: "input-2", toUUID: "output-1", weight: 1 }, + ], + input: 3, + output: 2, + }; + const creature = Creature.fromJSON(json); + creature.validate(); + + return creature; +}