Как правильно реализовать и проверить персептрон и градиентный спуск для изучения базовых булевых функций в Haskell? - PullRequest
3 голосов
/ 25 апреля 2019

Я пытаюсь сконструировать блок персептрона в Хаскеле, чтобы выучить булевы функции И и Или, как в книге Митчелла.

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

(i) Правильна ли моя реализация градиентного спуска?

(ii) Если да, то учитывает ли он «лучшие» веса?

(iii) Как проверить, правильно ли изучены веса? oor и aand - это значения, когда вы подключаете логические пары к весам, приведенным в книге, но я думал, что порог sgn будет применяться к этим значениям? Если это была правильная гипотеза оценки, то решение Митчелла угадывает ту же функцию и / или. Являются ли мои обученные функции и и или (вычисленные в ans1, ans2) неверными?

import System.Random

-- for generating random initial weights
randomList :: Int -> [Double]
randomList seed = randoms (mkStdGen seed) :: [Double]

dotProd x y = foldr (+) 0 $ zipWith (*) x y

gdHelper [] _ del_w _ _ = del_w
gdHelper (x:xs) (t:ts) y@(weight:weights) w nu = gdHelper xs ts del_w w nu
  where del_w = zipWith (+) y (map (*asdf) x)
        asdf = nu * (t - o) 
        o = dotProd w x

gd _  _  _  w _  0 = w
gd xs ts ws w nu n = gd xs ts [0,0,0] w2 nu (n-1)
  where w2 = zipWith (+) w delW
        delW = gdHelper xs ts ws w nu

-- initial weights
w = map (/20) $ take 3 $ randomList 30

trainingData = [([1,1],1),([1,-1],-1),([-1,1],-1),([-1,-1],-1)]
andData = map (1:) (map fst trainingData) 
andOuts = map snd trainingData
orOuts = [1,1,1,-1]

gdand = gd andData andOuts [0,0,0] w 0.02 10000
gdor = gd andData orOuts [0,0,0] w 0.01 10000

ans1 = map (dotProd gdand) andData 
ans2 = map (dotProd gdor) andData 

-- trying to verify this from the book
aand = map (dotProd [-0.8,0.5,0.5]) andData 
oor = map (dotProd [-0.3,0.5,0.5]) andData 

От Митчелла:

[1]: https://i.stack.imgur.com/XVRAn.png

Edit: В заключение предположим, что я хочу реплицировать новые логические значения и и или для данных о логических значениях. Замените следующий код, и геометрическая картина останется прежней. (w1 = w2 = 1/2, а точка пересечения равна 1/2 от первоначального значения). Однако, поскольку данные были масштабированы (на 1/2) и переведены (на (1 / 2,1 / 2)), и мой алгоритм теперь узнает неправильную функцию. `andData = map (1 :) [[x, y] | x <- [0,1], y <- [0,1]] </p>

andData = map (1:) [[x,y] | x <- [0,1], y <- [0,1]]
andOuts = [0,0,0,1]
orOuts = [0,1,1,1]
oor = map (dotProd [-0.5,1,1]) andData
aand = map (dotProd [-1.5,1,1]) andData

1 Ответ

1 голос
/ 25 апреля 2019

Я подозреваю, что в книге есть опечатка: порог для ИЛИ должен быть 0,3, а не -0,3.После внесения этого изменения я проверяю правильность перцептронов следующим образом:

> map signum aand == andOuts
True
> map signum oor == orOuts
True
> map signum ans1 == andOuts
True
> map signum ans2 == orOuts
True

Первые два подтверждают, что фиксированная версия весов книги подходит;последние два подтверждают, что веса, которые вы узнали при градиентном спуске, являются подходящими.

...