Je lisais sur les perceptrons et essayais d'en implémenter un en haskell. L'algorithme semble fonctionner aussi loin que je peux tester. Je vais réécrire entièrement le code à un moment donné, mais avant de le faire, j'ai pensé à poser quelques questions qui ont été soulevées lors du codage.Comportement incohérent avec Haskell
Le neurone peut être entraîné lors du retour du neurone complet. let neuron = train set [1,1]
fonctionne, mais si je change la fonction de train pour renvoyer un neurone incomplet sans les entrées, ou essayer de modéliser correspondre et créer seulement un neurone incomplet, le code tombe en boucle sans fin. Lors du retour du neurone complet, tout fonctionne, mais lors du retour du neurone curryable, le code tombe dans une boucle.
module Main where
import System.Random
type Inputs = [Float]
type Weights = [Float]
type Threshold = Float
type Output = Float
type Trainingset = [(Inputs, Output)]
data Neuron = Neuron Threshold Weights Inputs deriving Show
output :: Neuron -> Output
output (Neuron threshold weights inputs) =
if total >= threshold then 1 else 0
where total = sum $ zipWith (*) weights inputs
rate :: Float -> Float -> Float
rate t o = 0.1 * (t - o)
newweight :: Float -> Float -> Weights -> Inputs -> Weights
newweight t o weight input = zipWith nw weight input
where nw w x = w + (rate t o) * x
learn :: Neuron -> Float -> Neuron
learn [email protected](Neuron tr w i) t =
let o = output on
in Neuron tr (newweight t o w i) i
converged :: (Inputs -> Neuron) -> Trainingset -> Bool
converged n set = not $ any (\(i,o) -> output (n i) /= o) set
train :: Weights -> Trainingset -> Neuron
train w s = train' s (Neuron 1 w)
train' :: Trainingset -> (Inputs -> Neuron) -> Neuron
train' s n | not $ converged n set
= let (Neuron t w i) = train'' s n
in train' s (Neuron t w)
| otherwise = n $ fst $ head s
train'' :: Trainingset -> (Inputs -> Neuron) -> Neuron
train'' ((a,b):[]) n = learn (n a) b
train'' ((a,b):xs) n = let
(Neuron t w i) = learn (n a) b
in
train'' xs (Neuron t w)
set :: Trainingset
set = [
([1,0], 0),
([1,1], 1),
([0,1], 0),
([0,0], 0)
]
randomWeights :: Int -> IO [Float]
randomWeights n =
do
g <- newStdGen
return $ take n $ randomRs (-1, 1) g
main = do
w <- randomWeights 2
let (Neuron t w i) = train w set
print $ output $ (Neuron t w [1,1])
return()
Modifier: Comme pour les commentaires, en précisant un peu plus.
Courir avec le code ci-dessus, je reçois: perceptron: <<loop>>
Mais en éditant la principale méthode pour:
main = do
w <- randomWeights 2
let neuron = train w set
print $ neuron
return()
(Notez les let neuron
et les lignes d'impression), tout fonctionne et la sortie est :
Neuron 1.0 [0.71345896,0.33792675] [1.0,0.0]
1) De quelle manière la "boucle infinie lorsque je fais un changement" est-elle un "comportement incohérent"? 2) Pourriez-vous réduire (ou au moins commenter) votre exemple pour isoler une petite partie qui vous rend confus, si vous le faites, les gens sont plus susceptibles de répondre et de corriger correctement votre confusion dans la réponse. –
Il serait utile de montrer le code qui fait ce que vous attendez, ainsi que le changement qui fait ce à quoi vous ne vous attendez pas. – intoverflow
Le problème n'est-il pas lié à w? "let a = a; print a" va toujours être une boucle infinie. – jrockway