Непоследовательное поведение с Haskell - PullRequest
1 голос
/ 23 июля 2010

Я читал на персептронах и пытался внедрить их в haskell.Кажется, алгоритм работает, насколько я могу проверить.Я собираюсь полностью переписать код в какой-то момент, но перед этим я подумал задать несколько вопросов, которые возникли при кодировании этого.

Нейрон можно обучить при возврате полного нейрона.let neuron = train set [1,1] работает, но если я изменю функцию поезда, чтобы она возвращала неполный нейрон без входов, или попытаюсь сопоставить с образцом и создать только неполный нейрон, код попадет в бесконечный цикл.

tl; dr при возврате полного нейрона все работает, но при возврате каррируемого нейрона код попадает в цикл.

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 on@(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 ()

Редактировать: Согласно комментариям, указав немного больше.

Работая с кодом выше, я получаю: perceptron: <<loop>>

Но, отредактировав основной метод так:

main = do
  w <- randomWeights 2
  let neuron = train w set
  print $ neuron
  return ()

(обратите внимание на let neuron и напечатайте строки) все работает и вывод:

Neuron 1.0 [0.71345896,0.33792675] [1.0,0.0]

Ответы [ 2 ]

4 голосов
/ 23 июля 2010

Возможно, я что-то упустил, но я свел ваш тестовый пример к этой программе:

module Main where
data Foo a = Foo a

main = do
  x ← getLine
  let (Foo x) = Foo x
  putStrLn x

Это еще больше упрощает:

main = do
  x ← getLine
  let x = x
  putStrLn x

Проблема в том, что привязка (Foo x) к чему-то, что зависит от х циклическая зависимость Чтобы оценить х, нам нужно знать значение Икс. Итак, нам просто нужно вычислить х. Чтобы вычислить х, нам нужно знать значение х. Это хорошо, мы просто посчитаем х. И так далее.

Это не C, помните: это привязка, а не присваивание и привязка оценивается лениво.

Используйте лучшие имена переменных, и все это работает:

module Main where
data Foo a = Foo a

main = do
  line ← getLine
  let (Foo x) = Foo line
  putStrLn x

(В данном случае рассматриваемая переменная w.)

3 голосов
/ 23 июля 2010

Это распространенная ошибка в Haskell. Вы не можете говорить такие вещи, как:

let x = 0
let x = x + 1

И пусть это будет означать то, что было бы в языке с присваиванием или даже нерекурсивным связыванием. Первая строка неактуальна, она затеняется второй строкой, которая определяет x как x+1, то есть рекурсивно определяет x = ((((...)+1)+1)+1)+1, который зацикливается при оценке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...