sclass Perceptron implements IPred { srecord Example(double[] inputs, bool answer) { double getInput(int i) { ret i < inputs.length ? inputs[i] : 1; } } new L examples; double c = 1; bool randomizeC = true, startWithRandomWeights = false; long trainingRound; double error = -1; // -1 = not trained yet double[] weights; *() {} *(L examples) {} ItIt trainingIterator() { if (empty(examples)) fail("No examples"); int n = l(first(examples).inputs)+1; if (weights == null) { weights = new double[n]; if (startWithRandomWeights) for i over weights: weights[i] = random(-1.0, 1.0); } ret iff(() -> { if (error == 0) ret endMarker(); ++trainingRound; double lastError = error; trainARound(); ret error != lastError ? error : null; }); } double trainARound() { double error = 0; for (Example e : examples) error += abs(trainAnExample(e)); ret this.error = error/l(examples); } int feedForward(double[] inputs) { double sum = last(weights); for i over inputs: sum += inputs[i] * weights[i]; ret activate(sum); } public Bool get(double[] inputs) { ret feedForward(inputs) > 0; } int activate(double s) { return s > 0 ? 1 : -1; } double recalcError() { double error = 0; for (Example e : examples) error += abs(errorForExample(e)); ret this.error = error/l(examples); } double errorForExample(Example e) { int guess = feedForward(e.inputs); ret (e.answer ? 1 : -1) - guess; } double trainAnExample(Example e) { double error = errorForExample(e); if (error != 0) { double cc = c/l(examples); for i over weights: weights[i] += (randomizeC ? rand(cc) : cc) * error * e.getInput(i); } ret error; } void printWithWeights { print("Error: " + error + ", round " + trainingRound + ", weights: " + sfu(weights)); } // scaling the weights doesn't make a difference double scaleWeights(double factor) { for i over weights: weights[i] *= factor; ret recalcError(); } }