Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- export interface Descriptor {
- /** the activation type. */
- activation? : "linear" | "sigmoid" | "hypertan" | "relu" | "softmax"
- /** the number of neurons in this layer. */
- neurons : number
- }
- export interface Activation {
- (value: number) : number
- }
- export interface Layer {
- /** this layers index. */
- index : number,
- /** this layers activation function. */
- activation : number,
- /** the neuron indices for this layer. */
- neurons : Array<number>
- }
- export interface Synapse {
- /** the index for this synapse. */
- index : number,
- /** the input neuron for this synapse. */
- input : number,
- /** the output neuron for this synapse */
- output : number,
- /** the weight index for this synapse. */
- weight : number
- }
- export interface Neuron {
- /** this neurons index, maps to the networks values array. */
- index : number,
- /** the index layer for which this neuron exists. */
- layer : number,
- /** input synapses for this neuron. */
- inputs : Array<number>,
- /** output synapses for this neuron */
- outputs : Array<number>
- }
- export class Network {
- public layers : Array<Layer>
- public synapses : Array<Synapse>
- public neurons : Array<Neuron>
- public activations : Array<Activation>
- public values : Float32Array
- public weights : Float32Array
- /**
- * creates a new network with the given descriptor.
- * @param {Array<LayerDescriptor>} an array of layer descriptors defining the network topology.
- * @returns {Network}
- */
- constructor(descriptors: Array<Descriptor>) {
- //----------------------------------------
- // activation mapping function.
- //----------------------------------------
- const activation_map = (activation: string) : number => {
- switch(activation) {
- case undefined: return 0;
- case "linear": return 0;
- case "sigmoid": return 1;
- case "hypertan": return 2;
- case "relu": return 3;
- case "softmax": return 4;
- default: throw Error("unknown activation type " + activation)
- }
- }
- // create activation functions.
- this.activations = [
- /* 0: linear */ (x: number) => x,
- /* 1: sigmoid */ (x: number) => 1.0 / (1.0 + Math.exp(-x)),
- /* 2: hypertan */ (x: number) => x,
- /* 3: relu */ (x: number) => x,
- /* 4: softmax */ (x: number) => x,
- ]
- // create network layers.
- let neuron_index = 0;
- this.layers = descriptors.map((descriptor, index) => {
- let layer = {
- index : index,
- activation: activation_map(descriptor.activation),
- neurons : []
- }
- for(let i = 0; i < (descriptor.neurons + 1); i++) {
- layer.neurons.push(neuron_index)
- neuron_index += 1;
- } return layer
- })
- // create neurons.
- this.neurons = []
- neuron_index = 0;
- for(let i = 0; i < this.layers.length; i++) {
- for(let j = 0; j < this.layers[i].neurons.length; j++) {
- this.neurons.push({
- index : neuron_index,
- layer : i,
- inputs : [],
- outputs: []
- }); neuron_index += 1;
- }
- }
- // create synapses.
- let synapse_index = 0
- this.synapses = []
- for(let i = 0; i < (this.layers.length - 1); i++) {
- let input = this.layers[i+0]
- let output = this.layers[i+1]
- for(let output_idx = 1; output_idx < output.neurons.length; output_idx += 1 ) {
- for(let input_idx = 0; input_idx < input.neurons.length; input_idx += 1 ) {
- this.synapses.push({
- index : synapse_index,
- input : input.neurons[input_idx],
- output : output.neurons[output_idx],
- weight : synapse_index
- }); synapse_index += 1;
- }
- }
- }
- // neuron -> synapse -> neuron.
- for(let i = 0; i < this.synapses.length; i+=1) {
- let input = this.neurons[this.synapses[i].input]
- let output = this.neurons[this.synapses[i].output]
- input.outputs.push(this.synapses[i].index)
- output.inputs.push(this.synapses[i].index)
- }
- // setup buffers
- this.values = new Float32Array(this.neurons.length)
- this.weights = new Float32Array(this.synapses.length)
- // setup bias values + weights
- for(let i = 0; i < this.layers.length; i += 1) {
- let layer = this.layers[i]
- let neuron = this.neurons[layer.neurons[0]]
- this.values[neuron.index] = 1.0
- for(let j = 0; j < neuron.outputs.length; j += 1) {
- let synapse = this.synapses[neuron.outputs[j]]
- this.weights[synapse.index] = 1.0
- }
- }
- // setup weights.
- for(let i = 0; i < this.layers.length; i += 1) {
- let layer = this.layers[i]
- for(let j = 1; j < layer.neurons.length; j += 1) {
- let neuron = this.neurons[layer.neurons[j]]
- for(let k = 0; k < neuron.outputs.length; k++) {
- let synapse = this.synapses[neuron.outputs[k]]
- this.weights[synapse.weight] = 0.5 // should be random.
- }
- }
- }
- }
- /**
- * forward feeds the given value through the network and returns an result.
- * @param {Array<number>} the inputs to this network.
- * @returns {Array<number>} the network output.
- */
- public forward(input: Array<number>): Array<number> {
- // validate input.
- if(this.layers[0].neurons.length - 1 !== input.length) {
- throw Error("input length mismatch.")
- }
- // load input (layer + 0)
- for(let i = 0; i < input.length; i += 1) {
- let neuron = this.neurons[this.layers[0].neurons[i + 1]]
- this.values[neuron.index] = input[i]
- }
- // feed forward (layer + 1)
- for(let i = 1; i < this.layers.length; i += 1) {
- let layer = this.layers[i]
- for(let j = 1; j < layer.neurons.length; j += 1) {
- let output = this.neurons[layer.neurons[j]]
- let accumulator = 0
- for(let k = 0; k < output.inputs.length; k += 1) {
- let synapse = this.synapses[output.inputs[k]]
- let input = this.neurons[synapse.input]
- accumulator += (this.values [input.index] * this.weights[synapse.weight])
- }
- let activation = this.activations[layer.activation]
- this.values[output.index] = activation(accumulator)
- }
- }
- // read output.
- return this.layers[this.layers.length - 1].neurons
- .filter((_, i) => i > 0).map(index => {
- let neuron = this.neurons[index]
- return this.values[neuron.index]
- })
- }
- }
- let network = new Network([
- {neurons: 2},
- {neurons: 2000, activation: "sigmoid"},
- {neurons: 2000, activation: "sigmoid"},
- {neurons: 2000, activation: "sigmoid"},
- {neurons: 1, activation: "sigmoid"}
- ])
- console.log( network.forward([0, 1]))
- console.log( network.forward([0, 1]))
- console.log( network.forward([0, 1]))
- console.log( network.forward([0, 1]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement