/**
 * A two dimensional example: x and y coordinates with the label.
 */ export type Example2D = { x : number ; y : number ; label : number ; } ; type Point = { x : number ; y : number ; } ; export type DataGenerator = ( numSamples : number , noise : number ) => Example2D [ ] ; interface HTMLInputEvent extends Event { target : HTMLInputElement & EventTarget ; } /********************************************************************************/ /********************************************************************************/ /********************************************************************************/ /********************************************************************************/ export function classifyBYOData ( numSamples , noise ) { let points = [ ] ; return points ; } /********************************************************************************/ /********************************************************************************/ export function classifyTwoGaussData ( numSamples , noise ) { let points = [ ] ; let variance = 0.5 ; let dNoise = dSNR ( noise ) ; function genGauss ( cx , cy , label ) { for ( let i = 0 ; i < numSamples / 2 ; i ++ ) { let noiseX = normalRandom ( 0 , variance * dNoise ) ; let noiseY = normalRandom ( 0 , variance * dNoise ) ; let signalX = normalRandom ( cx , variance ) ; let signalY = normalRandom ( cy , variance ) ; let x = signalX + noiseX ; let y = signalY + noiseY ; points . push ( { x , y , label } ) ; } } genGauss ( 2 , 2 , 1 ) ; genGauss ( - 2 , - 2 , - 1 ) ; return points ; } /********************************************************************************/ /********************************************************************************/ export function classifySpiralData ( numSamples , noise ) { let dNoise = dSNR ( noise ) ; let points = [ ] ; let n = numSamples / 2 ; function genSpiral ( deltaT , label ) { for ( let i = 0 ; i < n ; i ++ ) { let r = i / n * 5 ; let r2 = r * r ; let t = 1.75 * i / n * 2 * Math . PI + deltaT ; let noiseX = normalRandom ( 0 , r * dNoise ) ; let noiseY = normalRandom ( 0 , r * dNoise ) ; let x = r * Math . sin ( t ) + noiseX ; let y = r * Math . cos ( t ) + noiseY ; points . push ( { x , y , label } ) ; } } genSpiral ( 0 , 1 ) ; genSpiral ( Math . PI , - 1 ) ; return points ; } /********************************************************************************/ /********************************************************************************/ export function classifyCircleData ( numSamples , noise ) { let dNoise = dSNR ( noise ) ; let points = [ ] ; let radius = 5 ; for ( let i = 0 ; i < numSamples / 2 ; i ++ ) { let r = randUniform ( 0 , radius * 0.5 ) ; let r2 = r * r ; let angle = randUniform ( 0 , 2 * Math . PI ) ; let x = r * Math . sin ( angle ) ; let y = r * Math . cos ( angle ) ; let noiseX = normalRandom ( 0 , 1 / radius * dNoise ) ; let noiseY = normalRandom ( 0 , 1 / radius * dNoise ) ; x += noiseX ; y += noiseY ; let label = 1 ; points . push ( { x , y , label } ) ; } for ( let i = 0 ; i < numSamples / 2 ; i ++ ) { let r = randUniform ( radius * 0.7 , radius ) ; let rr2 = r * r ; let angle = randUniform ( 0 , 2 * Math . PI ) ; let x = r * Math . sin ( angle ) ; let y = r * Math . cos ( angle ) ; let noiseX = normalRandom ( 0 , 1 / radius * dNoise ) ; let noiseY = normalRandom ( 0 , 1 / radius * dNoise ) ; x += noiseX ; y += noiseY ; let label = - 1 ; points . push ( { x , y , label } ) ; } return points ; } /********************************************************************************/ /********************************************************************************/ export function classifyXORData ( numSamples , noise ) { let dNoise = dSNR ( noise ) ; let stdSignal = 5 ; function getXORLabel ( p ) { return p . x * p . y >= 0 ? 1 : - 1 ; } let points = [ ] ; for ( let i = 0 ; i < numSamples ; i ++ ) { let x = randUniform ( - stdSignal , stdSignal ) ; let padding = 0.3 ; x += x > 0 ? padding : - padding ; let y = randUniform ( - stdSignal , stdSignal ) ; y += y > 0 ? padding : - padding ; let varianceSignal = stdSignal * stdSignal ; let noiseX = normalRandom ( 0 , varianceSignal * dNoise ) ; let noiseY = normalRandom ( 0 , varianceSignal * dNoise ) ; let label = getXORLabel ( { x : x + noiseX , y : y + noiseY } ) ; points . push ( { x , y , label } ) ; } return points ; } /********************************************************************************/ /********************************************************************************/ export function regressPlane ( numSamples , noise ) { let dNoise = dSNR ( noise ) ; let radius = 6 ; let r2 = radius * radius ; let labelScale = d3 . scale . linear ( ) . domain ( [ - 10 , 10 ] ) . range ( [ - 1 , 1 ] ) ; let getLabel = ( x , y ) => labelScale ( x + y ) ; let points = [ ] ; for ( let i = 0 ; i < numSamples ; i ++ ) { let x = randUniform ( - radius , radius ) ; let y = randUniform ( - radius , radius ) ; let noiseX = normalRandom ( 0 , r2 * dNoise ) ; let noiseY = normalRandom ( 0 , r2 * dNoise ) ; let label = getLabel ( x + noiseX , y + noiseY ) ; points . push ( { x , y , label } ) ; } return points ; } export function regressGaussian ( numSamples , noise ) { let dNoise = dSNR ( noise ) ; let points = [ ] ; let labelScale = d3 . scale . linear ( ) . domain ( [ 0 , 2 ] ) . range ( [ 1 , 0 ] ) . clamp ( true ) ; let gaussians = [ [ - 4 , 2.5 , 1 ] , [ 0 , 2.5 , - 1 ] , [ 4 , 2.5 , 1 ] , [ - 4 , - 2.5 , - 1 ] , [ 0 , - 2.5 , 1 ] , [ 4 , - 2.5 , - 1 ] ] ; function getLabel ( x , y ) { let label = 0 ; gaussians . forEach ( ( [ cx , cy , sign ] ) => { let newLabel = sign * labelScale ( dist ( { x , y } , { x : cx , y : cy } ) ) ; if ( Math . abs ( newLabel ) > Math . abs ( label ) ) { label = newLabel ; } } ) ; return label ; } let radius = 6 ; let r2 = radius * radius ; for ( let i = 0 ; i < numSamples ; i ++ ) { let x = randUniform ( - radius , radius ) ; let y = randUniform ( - radius , radius ) ; let noiseX = normalRandom ( 0 , r2 * dNoise ) ; let noiseY = normalRandom ( 0 , r2 * dNoise ) ; let label = getLabel ( x + noiseX , y + noiseY ) ; points . push ( { x , y , label } ) ; } return points ; } /********************************************************************************/ /********************************************************************************/ /**
 * Shuffles the array using Fisher-Yates algorithm. Uses the seedrandom
 * library as the random generator.
 */ export function shuffle ( array ) { let counter = array . length ; let temp = 0 ; let index = 0 ; while ( counter > 0 ) { index = Math . floor ( Math . random ( ) * counter ) ; counter -- ; temp = array [ counter ] ; array [ counter ] = array [ index ] ; array [ index ] = temp ; } } function log2 ( x ) { return Math . log ( x ) / Math . log ( 2 ) ; } function log10 ( x ) { return Math . log ( x ) / Math . log ( 10 ) ; } function signalOf ( x ) { return log2 ( 1 + Math . abs ( x ) ) ; } function dSNR ( x ) { return 1 / Math . pow ( 10 , x / 10 ) ; } /**
 * Returns a sample from a uniform [a, b] distribution.
 * Uses the seedrandom library as the random generator.
 */ function randUniform ( a , b ) { return Math . random ( ) * ( b - a ) + a ; } param mean param variance function normalRandom ( mean = 0 , variance = 1 ) { let v1 , v2 , s ; do { v1 = 2 * Math . random ( ) - 1 ; v2 = 2 * Math . random ( ) - 1 ; s = v1 * v1 + v2 * v2 ; } while ( s > 1 ) ; let result = Math . sqrt ( - 2 * Math . log ( s ) / s ) * v1 ; return mean + Math . sqrt ( variance ) * result ; } /** Returns the euclidean distance between two points in space. */ function dist ( a , b ) { let dx = a . x - b . x ; let dy = a . y - b . y ; return Math . sqrt ( dx * dx + dy * dy ) ; }