burnchart/-old-/test/neural.coffee

59 lines
2.0 KiB
CoffeeScript

{ assert } = require 'chai'
Chance = require 'chance'
brain = require 'brain'
_ = require 'lodash'
d3 = require 'd3'
chance = new Chance()
module.exports =
'neural net - detect sine chart type': (done) ->
fns =
# A "rough" sine wave.
sine: (x) -> Math.sin chance.floating 'min': Math.max(x - 1, 0), 'max': x + 1
# A linear function.
linear: (x) -> ( chance.floating 'min': Math.max(x - 1, 0), 'max': x + 1 ) + 2
# Generate sample data points.
samples = 10
data = _.map [ 0 ... 10 ], (i) ->
fn = fns[ [ 'linear', 'sine' ][ sine = +(i < (samples / 2)) ] ]
points = ( fn(j) for j in [ 0 ... 100 ] )
{ points, sine }
# Scale the data to just 6 points.
for chart in data then do (chart) ->
step = Math.round (len = chart.points.length) / 5
chart.points = ( chart.points[ Math.min(i, len - 1) ] for i in _.range(0, len + step, step) )
# Scale the values for each chart.
for chart in data then do (chart) ->
scale = d3.scale.linear().range([ 0, 1 ]).domain([ d3.min(chart.points), d3.max(chart.points) ])
chart.points = _.map chart.points, scale
# Split the dataset.
training = data[ 1...9 ]
testing = [ data[0] ].concat data[9]
net = new brain.NeuralNetwork()
keys = [ 0, 0.2, 0.4, 0.6, 0.8, 1 ]
input = for chart in training then do (chart) ->
'input': _.zipObject keys, chart.points
'output':
'sine': chart.sine
net.train input,
'errorThresh': 0.005 # error threshold to reach
'iterations': 5e4 # maximum training iterations
'log': no # console.log() progress periodically
'logPeriod': 1e3 # number of iterations between logging
'learningRate': 0.2 # learning rate
# Now test it.
for sample in testing
out = net.run _.zipObject keys, sample.points
assert sample.sine is Math.round(out.sine), "Network says #{out.sine} but sample says #{sample.sine}"
do done