FlowingSystems/Cake-examples

Switch branches/tags
Nothing to show
Fetching contributors…
Cannot retrieve contributors at this time
113 lines (89 sloc) 3.4 KB
 package systems.flowing.example import systems.flowing.cake._ import store._ import io._ trait Error { this: State => var error: Double = 0.0 } trait Target extends Error { this: Output => var target: Double = 0.0 } trait Bias extends Input { state = 1 } object Backprop extends App { val learningRate = 0.005 val bp = new Nodes[State with Order] with Hierarchy with Directed with AdjacencyList with Signal with Feedback with Flow with IO { val nodes = Hierarchy(2, 2, 1).nodes( () => new {val order = 0} with Input with Order, () => new {val order = 1} with State with Order with Error, () => new {val order = 2} with Output with Order with Target ) ++ Nodes.nodes( ((() => new {val order = 0} with Bias with Order), 1), ((() => new {val order = 1} with Bias with Order), 1) ) def sig(x: Double) = 1 / (1 + Math.pow(Math.E, -x)) def dsig(x: Double) = x * (1 - x) def propagate(i: Int) = nodes(i).state = sig(this(i) map { case (i: Int, weight: Double) => nodes(i).state * weight } sum) def backpropagate(i: Int) = nodes(i).asInstanceOf[Error].error = nodes(i) match { case o: Output with Target => (o.state - o.target) case s: State with Error => { val weights = from(i) (weights map { edge => weights(edge._1) * nodes(edge._1).asInstanceOf[Error].error * dsig(nodes(edge._1).state) } sum) } } def updateWeight(i: Int) = this(i) = this(i) map { case (from: Int, weight: Double) => from -> (weight - learningRate * nodes(i).asInstanceOf[Error].error * dsig(nodes(i).state) * nodes(from).state) } def input(channels: Map[String, Seq[Double]]) = { (channels("inputValues") zip of[Input].values). foreach { case (x: Double, i: Input) => i.state = x } (channels("targetValues") zip of[Target].values). foreach { case (x: Double, t: Target) => t.target = x } signal(propagate) feedback(backpropagate) flow(updateWeight) } def output = Map( "inputs" -> of[Input].values.toSeq.map(_.state), "outputs" -> of[Output].values.toSeq.map(_.state), "errors" -> of[Error].values.toSeq.map(_.error) ) } // initialize weights bp <= Hierarchy(2, 2, 1).random(-1, 1) // initialize weights from bias nodes bp.of[Bias with Order]. map(in => (in._1 -> in._2.order)). foreach { case (i: Int, inRow: Int) => bp.order(inRow+1). filter(!bp.nodes(_).isInstanceOf[Bias]). foreach { j => bp(i, j) = Some(Util.random(-1, 1)) } } val inputs = List(List(0.0, 0.0), List(0.0, 1.0), List(1.0, 0.0), List(1.0, 1.0)) val or = List(0.0, 1.0, 1.0, 1.0) map (x=>List(x)) val xor = List(0.0, 1.0, 1.0, 0.0) map (x=>List(x)) def pickRandom(i: Int) = scala.util.Random.nextInt(inputs.length) val training = Revolve("inputValues" -> inputs, "targetValues" -> xor)(pickRandom) >> bp >> Print(10000) for(i <- 1 to 1000000) training.output }