{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Transformation(identity,one)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type Transformation\n", " self :: Function\n", " deriv :: Function\n", "end\n", "\n", "import Core.eval\n", "\n", "function eval(transformation :: Transformation)\n", " transformation.self\n", "end\n", "\n", "function deriv(transformation :: Transformation)\n", " transformation.deriv\n", "end\n", "\n", "function sigmoid(x)\n", " 1. / (1. + exp(-x)) - 0.5\n", "end\n", "\n", "function dsigmoid(x)\n", " exp(-x) / (1. + exp(-x))^2\n", "end\n", "\n", "Sigmoid = Transformation(sigmoid, dsigmoid)\n", "\n", "Identity = Transformation(identity, one) " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "apply! (generic function with 1 method)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function calc_norm(array :: Matrix{Float64})\n", " sqrt(sumabs2(array)/size(array, 1))\n", "end\n", "\n", "function calc_norm(vector :: Array{Float64, 1})\n", " sqrt(sumabs2(vector))\n", "end\n", "\n", "function restriction(vector)\n", " vector / (calc_norm(vector)+0.001)\n", "end\n", "\n", "function init(a...)\n", " restriction(randn(a...))\n", "end\n", "\n", "const DefaultRate = 0.01\n", "\n", "type Class\n", " type_len :: Int64\n", " feature_len :: Int64\n", " feature_matrix :: Matrix{Float64}\n", " feature_transformation :: Transformation\n", " learning_rate :: Float64\n", "end\n", "\n", "LClass(type_len, feature_len, learning_rate = DefaultRate) = \n", " Class(type_len, feature_len, init(feature_len, type_len), Identity, learning_rate)\n", "\n", "SClass(type_len, feature_len, learning_rate = DefaultRate) =\n", " Class(type_len, feature_len, init(feature_len, type_len), Sigmoid, learning_rate)\n", "\n", "Class(type_len, feature_len, feature_transformation = Sigmoid, learning_rate = DefaultRate) =\n", " Class(type_len, feature_len, init(feature_len, type_len), feature_transformation, learning_rate)\n", "\n", "type Object\n", " class :: Class\n", " value :: Array{Float64, 1}\n", "end\n", "\n", "Object(class :: Class) = Object(class, init(class.type_len))\n", "\n", "function feature(obj :: Object)\n", " class = obj.class\n", " eval(class.feature_transformation).(class.feature_matrix * obj.value)\n", "end\n", "\n", "type DFunction\n", " in_classes :: Array{Class, 1}\n", " out_class :: Class\n", " f_matrix :: Matrix{Float64}\n", " f_transformation :: Transformation\n", " learning_rate :: Float64\n", "end\n", "\n", "function LFunction(in_classes :: Array{Class, 1}, out_class :: Class, learning_rate = DefaultRate)\n", " in_len = sum([class.feature_len for class in in_classes])\n", " out_len = out_class.type_len\n", " DFunction(in_classes, out_class, init(out_len, in_len), Identity, learning_rate)\n", "end\n", "\n", "function SFunction(in_classes :: Array{Class, 1}, out_class :: Class, learning_rate = DefaultRate)\n", " in_len = sum([class.feature_len for class in in_classes])\n", " out_len = out_class.type_len\n", " DFunction(in_classes, out_class, init(out_len, in_len), Sigmoid, learning_rate)\n", "end\n", "\n", "function DFunction(in_classes :: Array{Class, 1}, out_class :: Class, f_transformation = Sigmoid, learning_rate = DefaultRate)\n", " in_len = sum([class.feature_len for class in in_classes])\n", " out_len = out_class.type_len\n", " DFunction(in_classes, out_class, init(out_len, in_len), f_transformation, learning_rate)\n", "end\n", "\n", "function apply(func :: DFunction, objs :: Array{Object, 1})\n", " inputs = vcat(feature.(objs)...)\n", " outputs = eval(func.f_transformation).(func.f_matrix * inputs)\n", " Object(func.out_class, outputs)\n", "end\n", "\n", "function apply!(func :: DFunction, in_objs :: Array{Object, 1}, out_obj :: Object)\n", " inputs = vcat(feature.(in_objs)...)\n", " out_obj.value .= eval(func.f_transformation).(func.f_matrix * inputs)\n", "end" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Object(Class(6,12,[-0.0952685 0.123531 … 0.0617522 -0.432929; -0.391715 0.464444 … 0.121159 -0.2601; … ; -0.350052 -0.275652 … -0.0239876 0.488634; 0.367416 0.503514 … 0.0262668 0.457226],Transformation(sigmoid,dsigmoid),0.01),[-0.0138375,0.047348,-0.0206478,0.0537356,-0.000992343,0.0128627])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Sensor = Class(5, 10)\n", "sensor = Object(Sensor)\n", "Action = Class(6, 12)\n", "action = Object(Action)\n", "act = DFunction([Sensor, Sensor, Action], Action)\n", "apply(act, [sensor, sensor, action])" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "bottom_up (generic function with 1 method)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type Tree\n", " op\n", " value\n", " subtrees :: Array{Tree, 1}\n", "end\n", "\n", "function _bottom_up(func :: Function, tree :: Tree, dict :: Dict)\n", " function f()\n", " func(tree, [_bottom_up(func, t, dict) for t in tree.subtrees])\n", " end\n", " get!(f, dict, tree)\n", "end\n", "\n", "## bottom_up(func :: Function, tree :: Tree) = _bottom_up(func, tree, Dict())\n", "\n", "function bottom_up(func :: Function, tree :: Tree)\n", " func(tree, [bottom_up(func, t) for t in tree.subtrees])\n", "end" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "eval_tree! (generic function with 1 method)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function init_node!(op :: Object, value :: Dict)\n", " ## value[:value] = Array{Float64, 1}(op.class.type_len)\n", " value[:pre_feature] = Array{Float64, 1}(op.class.feature_len)\n", " value[:post_feature] = Array{Float64, 1}(op.class.feature_len)\n", "end\n", "\n", "function lens_split(x :: Array, lens :: Array{Int64, 1})\n", " ind = cumsum(lens)\n", " n = length(ind)\n", " ind = [0; ind]\n", " [view(x, (ind[i]+1):ind[i+1]) for i in 1:n]\n", "end\n", "\n", "function init_node!(op :: DFunction, value :: Dict)\n", " value[:pre_matrix] = Array{Float64, 1}(size(op.f_matrix, 2))\n", " value[:pre_transform] = Array{Float64, 1}(op.out_class.type_len)\n", " value[:value] = Array{Float64, 1}(op.out_class.type_len)\n", " value[:pre_feature] = Array{Float64, 1}(op.out_class.feature_len)\n", " value[:post_feature] = Array{Float64, 1}(op.out_class.feature_len)\n", " value[:inputs] = lens_split(value[:pre_matrix], [c.feature_len for c in op.in_classes])\n", " value[:d] = Array{Float64, 1}(size(op.f_matrix, 2))\n", " value[:ds] = lens_split(value[:d], [c.feature_len for c in op.in_classes])\n", "end\n", "\n", "function _init_tree!(tree :: Tree, _)\n", " init_node!(tree.op, tree.value)\n", " tree\n", "end\n", " \n", "function init_tree!(tree :: Tree)\n", " bottom_up(_init_tree!, tree)\n", "end\n", "\n", "function eval_node!(op :: Object, value :: Dict, value_list)\n", " value[:value] = op.value\n", " A_mul_B!(value[:pre_feature], op.class.feature_matrix, op.value)\n", " value[:post_feature] .= eval(op.class.feature_transformation).(value[:pre_feature])\n", "end\n", "\n", "function eval_node!(op :: DFunction, value :: Dict, value_list)\n", " i = 1\n", " for v in value_list\n", " value[:inputs][i] .= v[:post_feature]\n", " i += 1\n", " end\n", " ## value[:pre_matrix] .= vcat([v[:post_feature] for v in value_list]...)\n", " A_mul_B!(value[:pre_transform], op.f_matrix, value[:pre_matrix])\n", " value[:value] .= eval(op.f_transformation).(value[:pre_transform])\n", " A_mul_B!(value[:pre_feature], op.out_class.feature_matrix, value[:value])\n", " value[:post_feature] .= eval(op.out_class.feature_transformation).(value[:pre_feature])\n", "end\n", "\n", "function _eval_tree!(tree :: Tree, _)\n", " eval_node!(tree.op, tree.value, (t.value for t in tree.subtrees))\n", " tree\n", "end\n", " \n", "function eval_tree!(tree :: Tree)\n", " bottom_up(_eval_tree!, tree)\n", "end" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "6-element Array{Float64,1}:\n", " 0.0\n", " 0.0\n", " 0.0\n", " 0.0\n", " 0.0\n", " 0.0" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Sensor = Class(5, 10)\n", "sensor = Object(Sensor)\n", "Action = Class(6, 12)\n", "action = Object(Action)\n", "act = DFunction([Sensor, Action], Action)\n", "tree = Tree(act, Dict(), [Tree(sensor, Dict(), []), Tree(action, Dict(), [])])\n", "init_tree!(tree)\n", "eval_tree!(tree).value[:value] - apply(act, [sensor, action]).value" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "bp_tree! (generic function with 1 method)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function bp_transformation!(transformation :: Transformation, inputs :: Array{Float64, 1}, d)\n", " for i in 1:length(inputs)\n", " d[i] = deriv(transformation)(inputs[i]) * d[i]\n", " end\n", " ## d .= deriv(transformation).(inputs) .* d\n", "end\n", "\n", "function bp_matrix!(inputs :: Array{Float64, 1}, matrix :: Matrix{Float64}, d, step)\n", " ## step = 0.01\n", " ## dmatrix = reshape(d, (length(d), 1)) * reshape(inputs, (1, length(inputs)))\n", " ## matrix[:, :] += step * reshape(d, (length(d), 1)) * reshape(inputs, (1, length(inputs)))\n", " for i in 1:size(matrix, 1)\n", " for j in 1:size(matrix, 2)\n", " matrix[i, j] = matrix[i, j] + step * d[i] * inputs[j]\n", " end\n", " end\n", " matrix' * d\n", "end\n", "\n", "function bp_class!(class :: Class, value :: Dict, d)\n", " bp_transformation!(class.feature_transformation, value[:pre_feature], d)\n", " bp_matrix!(value[:value], class.feature_matrix, d, class.learning_rate)\n", "end\n", "\n", "function bp_function!(op :: DFunction, value :: Dict, d :: Array{Float64, 1})\n", " bp_transformation!(op.f_transformation, value[:pre_transform], d)\n", " bp_matrix!(value[:pre_matrix], op.f_matrix, d, op.learning_rate)\n", "end\n", "\n", "function bp_tree!(tree :: Tree, d :: Array{Float64, 1})\n", " if typeof(tree.op) == DFunction\n", " tree.value[:d] .= bp_function!(tree.op, tree.value, d)\n", " ## ds = lens_split(d, [c.feature_len for c in tree.op.in_classes])\n", " for i in 1:length(tree.subtrees)\n", " bp_tree!(tree.subtrees[i], bp_class!(tree.op.in_classes[i], tree.subtrees[i].value, tree.value[:ds][i]))\n", " end\n", " ## dds = map(bp_class!, tree.op.in_classes, [t.value for t in tree.subtrees], tree.value[:ds])\n", " ## foreach(bp_tree!, tree.subtrees, dds)\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "6-element Array{Float64,1}:\n", " 0.520171\n", " 0.519918\n", " 0.519255\n", " 0.519372\n", " 0.520931\n", " 0.522424" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Sensor = Class(5, 10)\n", "sensor = Object(Sensor)\n", "Action = Class(6, 12)\n", "action = Object(Action)\n", "act = DFunction([Sensor, Action], Action)\n", "tree = Tree(act, Dict(), [Tree(sensor, Dict(), []), Tree(action, Dict(), [])])\n", "init_tree!(tree)\n", "d = ones(6) - eval_tree!(tree).value[:value]\n", "for i in 1:5000\n", " d = ones(6) - eval_tree!(tree).value[:value]\n", " bp_tree!(tree, d)\n", "end\n", "ones(6) - eval_tree!(tree).value[:value]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "train! (generic function with 2 methods)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function toTree(op)\n", " Tree(op, Dict(), [])\n", "end\n", "\n", "function toTree(skeleton :: Array)\n", " op = skeleton[1]\n", " subs = skeleton[2:end]\n", " Tree(op, Dict(), [toTree(s) for s in subs])\n", "end\n", "\n", "function add!(dict :: Dict, dict1 :: Dict)\n", " for key in keys(dict1)\n", " dict[key] = vcat(get!(dict, key, []), dict1[key])\n", " end\n", " dict\n", "end\n", "\n", "function _index(tree :: Tree, inds :: Array)\n", " ind = Dict(tree.op => [tree])\n", " for ind1 in inds\n", " add!(ind, ind1)\n", " end\n", " ind\n", "end\n", "\n", "index(tree :: Tree) = bottom_up(_index, tree)\n", "\n", "type Axiom\n", " tree1 :: Tree\n", " tree2 :: Tree\n", " index :: Dict\n", "end\n", "\n", "Axiom(tree1 :: Tree, tree2 :: Tree) = Axiom(tree1, tree2, add!(index(tree1), index(tree2)))\n", "\n", "Axiom(skeleton1, skeleton2) = Axiom(toTree(skeleton1), toTree(skeleton2))\n", "\n", "function push!(index :: Dict, ops :: Array)\n", " n = length(ops)\n", " for i in 1:n\n", " for t in index[i]\n", " t.op = ops[i]\n", " end\n", " end\n", "end\n", "\n", "function push!(index :: Dict, ops :: Dict)\n", " for key in keys(ops)\n", " if haskey(index, key)\n", " ts = index[key]\n", " for t in ts\n", " t.op = ops[key]\n", " end\n", " end\n", " end\n", "end\n", "\n", "function push!(axiom :: Axiom, ops)\n", " push!(axiom.index, variables)\n", "end\n", "\n", "function train!(axiom :: Axiom, variables)\n", " push!(axiom.index, variables)\n", " init_tree!(axiom.tree1)\n", " init_tree!(axiom.tree2)\n", " d = eval_tree!(axiom.tree2).value[:value] - eval_tree!(axiom.tree1).value[:value]\n", " bp_tree!(axiom.tree1, d)\n", " bp_tree!(axiom.tree2, -d)\n", "end\n", "\n", "function train!(axiom :: Axiom, variables :: Array, n :: Int64)\n", " push!(axiom.index, variables)\n", " init_tree!(axiom.tree1)\n", " init_tree!(axiom.tree2)\n", " for i in 1:n\n", " d = eval_tree!(axiom.tree2).value[:value] - eval_tree!(axiom.tree1).value[:value]\n", " bp_tree!(axiom.tree1, d)\n", " bp_tree!(axiom.tree2, -d)\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Axiom(Tree(1,Dict{Any,Any}(),Tree[Tree(2,Dict{Any,Any}(),Tree[Tree(3,Dict{Any,Any}(),Tree[])])]),Tree(3,Dict{Any,Any}(),Tree[]),Dict(2=>Tree[Tree(2,Dict{Any,Any}(),Tree[Tree(3,Dict{Any,Any}(),Tree[])])],3=>Tree[Tree(3,Dict{Any,Any}(),Tree[]),Tree(3,Dict{Any,Any}(),Tree[])],1=>Tree[Tree(1,Dict{Any,Any}(),Tree[Tree(2,Dict{Any,Any}(),Tree[Tree(3,Dict{Any,Any}(),Tree[])])])]))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Sensor = Class(5, 10)\n", "sensor = Object(Sensor)\n", "Action = Class(6, 12)\n", "action = Object(Action)\n", "act = DFunction([Sensor], Action)\n", "invact = DFunction([Action], Sensor)\n", "axiom = Axiom([1, [2, 3]], 3)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 0.222576 seconds (2.14 M allocations: 42.585 MB, 2.45% gc time)\n" ] }, { "data": { "text/plain": [ "5-element Array{Float64,1}:\n", " -0.00211209\n", " 0.0980249 \n", " 0.0193965 \n", " 0.00262933\n", " -0.183088 " ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@time train!(axiom, [invact, act, sensor], 10000)\n", "eval_tree!(axiom.tree2).value[:value] - eval_tree!(axiom.tree1).value[:value]" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Count File Line Function \n", " 23 ./ -1 anonymous \n", " 1 ./In[1] 21 dsigmoid(::Float64) \n", " 26 ./In[4] 17 bottom_up(::#_eval_tree!, ::Tree) \n", " 11 ./In[5] 54 _eval_tree!(::Tree, ::Array{Tree,1}) \n", " 1 ./In[5] 36 eval_node!(::Object, ::Dict{Any,Any... \n", " 4 ./In[5] 37 eval_node!(::Object, ::Dict{Any,Any... \n", " 2 ./In[5] 47 eval_node!(::DFunction, ::Dict{Any,... \n", " 1 ./In[5] 48 eval_node!(::DFunction, ::Dict{Any,... \n", " 2 ./In[5] 50 eval_node!(::DFunction, ::Dict{Any,... \n", " 3 ./In[7] 21 bp_class!(::Class, ::Dict{Any,Any},... \n", " 1 ./In[7] 22 bp_class!(::Class, ::Dict{Any,Any},... \n", " 2 ./In[7] 26 bp_function!(::DFunction, ::Dict{An... \n", " 3 ./In[7] 27 bp_function!(::DFunction, ::Dict{An... \n", " 1 ./In[7] 14 bp_matrix!(::Array{Float64,1}, ::Ar... \n", " 3 ./In[7] 17 bp_matrix!(::Array{Float64,1}, ::Ar... \n", " 5 ./In[7] 3 bp_transformation!(::Transformation... \n", " 6 ./In[7] 32 bp_tree!(::Tree, ::Array{Float64,1}) \n", " 10 ./In[7] 35 bp_tree!(::Tree, ::Array{Float64,1}) \n", " 13 ./In[9] 76 train!(::Axiom, ::Array{Any,1}, ::I... \n", " 10 ./In[9] 77 train!(::Axiom, ::Array{Any,1}, ::I... \n", " 1 ./abstractarray.jl 159 stride(::Array{Float64,2}, ::Int64) \n", " 13 ./array.jl 307 collect(::Base.Generator{Array{Tree... \n", " 2 ./array.jl 308 collect(::Base.Generator{Array{Tree... \n", " 3 ./linalg/blas.jl 454 gemv!(::Char, ::Float64, ::Array{Fl... \n", " 3 ./linalg/matmul.jl 88 A_mul_B!(::Array{Float64,1}, ::Arra... \n", " 2 ./linalg/matmul.jl 114 Ac_mul_B \n", " 4 ./linalg/matmul.jl 230 gemv!(::Array{Float64,1}, ::Char, :... \n", " 24 ./loading.jl 441 include_string(::String, ::String) \n", " 23 ./profile.jl 16 macro expansion; \n", " 2 ./subarray.jl 169 setindex! \n", " 24 ./task.jl 360 (::IJulia.##9#15)() \n", " 24 ...IJulia/src/eventloop.jl 8 eventloop(::ZMQ.Socket) \n", " 24 .../src/execute_request.jl 169 execute_request(::ZMQ.Socket, ::IJu... \n" ] } ], "source": [ "Profile.clear()\n", "@profile train!(axiom, [invact, act, sensor], 1000)\n", "## Profile.print()\n", "Profile.print(format = :flat)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3×3 Array{Float64,2}:\n", " 1.0 0.0 0.0\n", " 0.0 1.0 0.0\n", " 0.0 0.0 1.0" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "diagm(ones(3))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 0.5.0", "language": "julia", "name": "julia-0.5" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "0.5.0" } }, "nbformat": 4, "nbformat_minor": 1 }