Skip to content

Instantly share code, notes, and snippets.

@Lambdanaut
Last active December 11, 2015 14:18
Show Gist options
  • Select an option

  • Save Lambdanaut/4613240 to your computer and use it in GitHub Desktop.

Select an option

Save Lambdanaut/4613240 to your computer and use it in GitHub Desktop.
A binary labeling perceptron written in Haskell
module Percept where
-- The example training/testing data has single digit numbers set to True, and double digit numbers set to False
trainingData :: [([Double], Bool)]
testingData :: [([Double], Bool)]
trainingData = [
([1], True),
([5], True),
([6], True),
([9], True),
([15], False),
([12], False),
([25], False),
([19], False)]
testingData = [
([4], True),
([2], True),
([3], True),
([8], True),
([13], False),
([11], False),
([29], False),
([18], False)]
learningIterations = 100
startingWeights = take (length $ fst $ testingData !! 0 ) $ repeat 0.0
startingTheta = 0.0
dotProduct x y = sum $ zipWith (*) x y
decision x w theta = dotProduct x w > theta
-- Updates the weights and theta from a single training record.
-- (Training Data, Binary Value of Training Data) -> (Previous Weights, Old Theta) -> (New Weights, New Theta)
perceptron :: ([Double], Double) -> ([Double], Bool) -> ([Double], Double)
perceptron (weights, theta) (trainingData, val)
| d == False && val == True = (newWeights (+), theta - 1)
| d == True && val == False = (newWeights (-), theta + 1)
| otherwise = (weights, theta)
where
d = decision trainingData weights theta
newWeights combiningFunction = zipWith combiningFunction weights trainingData
-- Loops through a list of training records "learningIterations" times, and returns adjusted weights and theta.
learn :: ([Double], Double) -> [([Double], Bool)] -> ([Double], Double)
learn (weights, theta) trainingData = last $ take learningIterations $ iterate (\ currentWeightTheta -> foldl perceptron currentWeightTheta trainingData) (startingWeights, startingTheta)
-- Loops through a list of training records and prints "Correct" if the given weights/theta correctly classified the value, and "Incorrect" otherwise.
act :: ([Double], Double) -> [([Double], Bool)] -> IO ()
act (weights, theta) testingData = mapM_ (\ (dataSet, val) -> putStrLn $ boolToEnglish $ val == decision dataSet weights theta) testingData
where
boolToEnglish True = "Correct"
boolToEnglish False = "Incorrect"
main :: IO ()
main = (\ x -> act x testingData) $ learn (startingWeights, startingTheta) trainingData
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment