// ChucK Brain // Copyright 2008 Les Hall // This software is protected by the GNU General Public License // parameters 10 => int num_delays; // number of delay UGens 4 => int num_layers; // number of layers (input + hidden + output) 100::ms => dur total_delay; // the total delay duration 0.99 => float tau; // time constant for convergence 0.001 => float T_limit; // lower limit on T // variables num_delays => int num_width; // width of neural net total_delay / num_delays => dur dly; // the delay amount 1 => float T; // temperature float delta; // used in updating weights // define the patch // define and hook up the delays Delay delay[num_delays]; // instantiate the delays adc => delay[0]; // hook the adc to the input for (1 => int i; i < num_delays; i++) { delay[i-1] => delay[i]; // chain them together in series } for (0 => int i; i < num_delays; i++) { delay[i].max (dly); // set the max delays delay[i].delay (dly); // set the delays } delay[num_delays-1] => blackhole; // suck out samples // define and hook up the neurons Gain nn_weights[num_layers][num_width][num_width]; // define the neural net weights Dyno nn_outputs[num_layers][num_width]; // define the neural net outputs for (0 => int neuron; neuron < num_width; neuron++ ) { delay[neuron] => nn_outputs[0][neuron]; // connect inputs to delay lines } for (1 => int layer; layer < num_layers; layer++) { for (0 => int neuron; neuron < num_width; neuron++ ) { for (0 => int weight; weight < num_width; weight++) { nn_outputs[layer-1][neuron] => nn_weights[layer][neuron][weight]; // connect weight input nn_weights[layer][neuron][weight] => nn_outputs[layer][neuron]; // connect weight output } } } for (0 => int layer; layer < num_layers; layer++) { for (0 => int neuron; neuron < num_width; neuron++ ) { nn_outputs[layer][neuron].limit (); // the activation function } } // define the output node and hook it up Dyno out => dac; for (0 => int neuron; neuron < num_width; neuron++ ) { nn_outputs[num_layers-1][neuron] => out; // connect all neural net outputs to out } out.limit (); // set output as limiter // // define the figure of merit // the fom patch and its parameters out => LPF lpf_music => FullRect lpf_fwr => LPF lpf_averaging => Gain fom => blackhole; out => HPF hpf_music => FullRect hpf_fwr => LPF hpf_averaging => fom; Step offset => fom; lpf_music.freq (1000); hpf_music.freq (1000); lpf_averaging.freq (10); hpf_averaging.freq (10); hpf_averaging.gain (-1); offset.next (-1); // // backpropagate the error // define the backpropagation network Gain nn_errors[num_layers][num_width]; // define the neural net errors Gain nn_back_weights[num_layers][num_width][num_width]; // backward weights for backpropagation of error // hook up the backpropagation network for (0 => int neuron; neuron < num_width; neuron++) { fom => nn_errors[num_layers-1][neuron]; // send the fom back as the error } for (num_layers - 1 => int layer; layer > 0; layer--) { for (0 => int neuron; neuron < num_width; neuron++) { for (0 => int weight; weight < num_width; weight++) { // backpropagate the errors along the weights nn_errors[layer][neuron] => nn_back_weights[layer][neuron][weight] => nn_errors[layer-1][weight]; } } } // seed the neural net weights for (1 => int layer; layer < num_layers; layer++) { for (0 => int neuron; neuron < num_width; neuron++) { for (0 => int weight; weight < num_width; weight++) { Std.randf () => nn_weights[layer][neuron][weight].gain; nn_weights[layer][neuron][weight].gain () => nn_back_weights[layer][neuron][weight].gain; } } } // time loop while (true) { // update the weights for (1 => int layer; layer < num_layers; layer++) { for (0 => int neuron; neuron < num_width; neuron++) { for (0 => int weight; weight < num_width; weight++) { if ( (nn_errors[layer][neuron].last () <= 0.5) | (nn_errors[layer][neuron].last () >= 0.5) ) { T * nn_errors[layer][neuron].last () * 1 * nn_outputs[layer-1][neuron].last () => delta; } else { T * nn_errors[layer][neuron].last () * 0.1 * nn_outputs[layer-1][neuron].last () => delta; } delta + nn_weights[layer][neuron][weight].gain () => nn_weights[layer][neuron][weight].gain; nn_weights[layer][neuron][weight].gain () => nn_back_weights[layer][neuron][weight].gain; } } } // update the temperature tau *=> T; if (T < T_limit) { 1 => T; } // time delay 1000::ms => now; }