Permalink
Browse files

Add option for learning rate

  • Loading branch information...
1 parent b409743 commit 327a0438c192a0085037a2e3c22f13f25fa9c4f8 @larrytheliquid committed Jan 21, 2010
Showing with 38 additions and 34 deletions.
  1. +29 −26 Perceptron.hs
  2. +4 −4 PerceptronTest.hs
  3. +1 −1 README.markdown
  4. +1 −1 neurosis.rb
  5. +3 −2 neurosis_spec.rb
View
@@ -3,55 +3,58 @@ import qualified Data.Map as M
import qualified Data.ByteString.Char8 as B
import Data.List (transpose, foldl')
-learningRate = 1.0
bias = 1.0
epochsLimit = 4000
hubris_learn :: M.Map B.ByteString [[Double]] -> Maybe [[Int]]
hubris_learn m = result
+ (M.lookup (B.pack "learning_rate") m)
(M.lookup (B.pack "input_patterns") m)
(M.lookup (B.pack "output_patterns") m)
(M.lookup (B.pack "hidden_weights_group") m)
(M.lookup (B.pack "output_weights_group") m)
where
- result (Just a) (Just b) (Just c) (Just d) =
- Just (learn a b c d)
- result _ _ _ _ = Nothing
+ result (Just [[a]]) (Just b) (Just c) (Just d) (Just e)=
+ Just (learn a b c d e)
+ result _ _ _ _ _ = Nothing
-learn :: [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
+learn :: Double -> [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
[[Int]]
-learn inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup =
+learn learningRate inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup =
map finalOutput inputPatterns
where
(hiddenWeightsGroup', outputWeightsGroup') =
- learnWeights 0 inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup
+ learnWeights 0 learningRate
+ inputPatterns outputPatterns
+ hiddenWeightsGroup outputWeightsGroup
finalOutput inputNodes = map (round . fromRational . toRational) outputNodes
where inputNodes' = calculateInputNodes inputNodes
hiddenNodes = calculateHiddenNodes inputNodes' hiddenWeightsGroup'
outputNodes = calculateOutputNodes hiddenNodes outputWeightsGroup'
-learnWeights :: Integer -> [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
+learnWeights :: Integer -> Double -> [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
( [[Double]], [[Double]] )
-learnWeights i inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup
+learnWeights i learningRate inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup
| i < epochsLimit =
let (hiddenWeightsGroup', outputWeightsGroup') =
- epoch inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup
+ epoch learningRate inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup
in
- learnWeights (succ i) inputPatterns outputPatterns
+ learnWeights (succ i) learningRate
+ inputPatterns outputPatterns
hiddenWeightsGroup' outputWeightsGroup'
| otherwise = (hiddenWeightsGroup, outputWeightsGroup)
-epoch :: [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
+epoch :: Double -> [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] ->
( [[Double]], [[Double]] )
-epoch inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup =
+epoch learningRate inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup =
foldl' (\ (hiddenWeights, outputWeights) (inputPattern, outputPattern) ->
- pattern inputPattern outputPattern hiddenWeights outputWeights)
+ pattern learningRate inputPattern outputPattern hiddenWeights outputWeights)
(hiddenWeightsGroup, outputWeightsGroup)
(zip inputPatterns outputPatterns)
-pattern :: [Double] -> [Double] -> [[Double]] -> [[Double]] ->
+pattern :: Double -> [Double] -> [Double] -> [[Double]] -> [[Double]] ->
( [[Double]], [[Double]] )
-pattern inputNodes desiredOutputs hiddenWeightsGroup outputWeightsGroup =
+pattern learningRate inputNodes desiredOutputs hiddenWeightsGroup outputWeightsGroup =
(hiddenWeightsGroup', outputWeightsGroup')
where
-- forward propogation
@@ -63,14 +66,14 @@ pattern inputNodes desiredOutputs hiddenWeightsGroup outputWeightsGroup =
hiddenErrorTerms = zipWith (`hiddenErrorTerm` outputErrorTerms)
hiddenNodes (transpose outputWeightsGroup)
-- weight change
- hiddenWeightsGroup' = zipWith (\ hiddenWeights hiddenError ->
- zipWith (`changedWeight` hiddenError)
- hiddenWeights inputNodes')
- hiddenWeightsGroup (tail hiddenErrorTerms)
- outputWeightsGroup' = zipWith (\ outputWeights outputError ->
- zipWith (`changedWeight` outputError)
- outputWeights hiddenNodes)
- outputWeightsGroup outputErrorTerms
+ hiddenWeightsGroup' = zipWith (\ hiddenError hiddenWeights ->
+ zipWith (changedWeight learningRate hiddenError)
+ inputNodes' hiddenWeights)
+ (tail hiddenErrorTerms) hiddenWeightsGroup
+ outputWeightsGroup' = zipWith (\ outputError outputWeights ->
+ zipWith (changedWeight learningRate outputError)
+ hiddenNodes outputWeights)
+ outputErrorTerms outputWeightsGroup
averageError :: [[Double]] -> [[Double]] -> [[Double]] -> [[Double]] -> Double
averageError inputPatterns outputPatterns hiddenWeightsGroup outputWeightsGroup =
@@ -100,8 +103,8 @@ calculateHiddenNodes inputNodes hiddenWeightsGroup =
calculateInputNodes :: [Double] -> [Double]
calculateInputNodes = (bias:)
-changedWeight :: Double -> Double -> Double -> Double
-changedWeight weight errorTerm node =
+changedWeight :: Double -> Double -> Double -> Double -> Double
+changedWeight learningRate errorTerm node weight =
weight + product [learningRate, errorTerm, node]
hiddenErrorTerm :: Double -> [Double] -> [Double] -> Double
View
@@ -6,14 +6,14 @@ import HUnitExtensions
main = runTestTT (TestList [
"learn given the XOR problem returns its definition (caveat: with learningRate 1.0)" ~:
- [[0], [1], [1], [1]] @=? (learn
+ [[0], [1], [1], [0]] @=? (learn 0.5
[[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]
[[0.0], [1.0], [1.0], [0.0]]
[[0.0923, 0.1958, -0.4049], [0.2904, 0.1946, -0.1057]]
[[0.0276, 0.1621, 0.2559]]),
"epoch given input and output patterns, and hidden and output weights groups" ~:
- let (hiddenWeights, outputWeights) = epoch
+ let (hiddenWeights, outputWeights) = epoch 1.0
[[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]
[[0.0], [1.0], [1.0], [0.0]]
[[0.1, 0.2, -0.4], [0.3, 0.2, -0.1]]
@@ -27,7 +27,7 @@ main = runTestTT (TestList [
True @=? True,
"pattern given input and output nodes, and hidden and output weights groups" ~:
- let (hiddenWeights, outputWeights) = pattern
+ let (hiddenWeights, outputWeights) = pattern 1.0
[0.0, 0.0]
[0.0]
[[0.1, 0.2, -0.4], [0.3, 0.2, -0.1]]
@@ -57,7 +57,7 @@ main = runTestTT (TestList [
"changedWeight given weight, error term, and node " ++
"returns the sum of the weight and the product of the " ++
"learning rate, error term, and node" ~:
- (0.1249, 0.0001) @~? changedWeight 0.2 (-0.1431) 0.5250,
+ (0.1249, 0.0001) @~? changedWeight 1.0 (-0.1431) 0.5250 0.2,
"hiddenErrorTerm given the hidden node, output error terms, and " ++
"output weights of the hidden node multiplies the actual output derivative " ++
View
@@ -4,7 +4,7 @@
Neurosis is an example application to show off [Hubris](http://github.com/mwotton/Hubris) (a Haskell -> Ruby bridge) being used with non-trivial Haskell-code. See [this post](http://engineyard.com/blog/2010/a-hint-of-hubris/) for an intro to Hubris and for which Neurosis was written.
-Feel free to fork the code and send in pull requests if you would like to see this turn into a more sophisticated example webservice. I will be hacking on little improvements here and there as time goes on. Of course `learningRate` will need to be paramaterized as it is silly that it is a constant currently.
+Feel free to fork the code and send in pull requests if you would like to see this turn into a more sophisticated example webservice. I will be hacking on little improvements here and there as time goes on.
## Up next
View
@@ -16,7 +16,7 @@ def perceptron() Perceptron.new end
else
status 400
"Please specify all correct options for: " +
- "input_patterns, output_patterns, hidden_weights_group, output_weights_group"
+ "input_patterns, output_patterns, hidden_weights_group, output_weights_group, learning_rate"
end
end
end
View
@@ -21,12 +21,13 @@ def app
"hidden_weights_group" =>
[[0.0923, 0.1958, -0.4049], [0.2904, 0.1946, -0.1057]],
"output_weights_group" =>
- [[0.0276, 0.1621, 0.2559]]
+ [[0.0276, 0.1621, 0.2559]],
+ "learning_rate" => [[0.5]]
}.to_json
last_response.should be_successful
JSON.parse(last_response.body).should ==
- [[0], [1], [1], [1]]
+ [[0], [1], [1], [0]]
end
it "responds with error message when missing options" do

0 comments on commit 327a043

Please sign in to comment.