все-таки, J - забавная штука. ниже код обучения сети с обратным распространением ошибки. комментарии есть. вначале несколько вспомогательных глаголов. качество кода - плохое, сам знаю: несколько раз используется 'while.', а глагол 'bw' привести в нормальный вид, честно говоря, лень.
запускать так:
0.99 100 0.05 init_BP_ 256 64 8 NB. 0.99 - коэф. обучения, 100 - max число шагов, 0.05 - допустимая ошибка, последние три числа размерность сети по-слойно
(? 256 $ 2) run_BP_ 1 0 1 0 1 0 1 0 NB. x - какие-то случайные данные, y - целевой выход
у меня учится в среднем 0.01 секунды.
кстати, все параметры сети выставлены наружу и подбирать их можно тем же генетическим алгоритмом (он, например, говорит, что хорошое число узлов на втором слое ~100).
cocurrent 'BP'
NB. создание пустой коробочной структуры заданного размера
empty_box =: (<'') {.~ ]
NB. box partial - наречие - аналог "/\" применительно к коробочной структуре
NB. +ba ;/ i.5 NB. 0;1;3;6;10
ba =: 1 : 0
'i r l' =. 1 ; (>0 { y) ; (# y)
b =. (i { y
b =. (: i
end.
b
)
NB. произведение матриц
mp =: +/ . *
NB. покомпонентное произведение матриц
mpx =: (([: ,. [) mp ([: ,: ]))
NB. randsh 2 2 NB. вектор случайных чисел на промежутке (0.0;1.0) с shape, равным 2 2
NB. 10 randsh 2 2 NB. вектор случайных чисел на промежутке (0;10) с shape, равным 2 2
randsh =: ([: ? 0 $~ ]) :([: ? $~)
init =: 4 : 0
'eta max_steps err' =: x
net =: create_nnet y
)
NB. запуск обучения с ограничением на максимальное число шагов и допустимую ошибку
NB. возвращает пройденное число шагов и итоговую ошибку
run =: 4 : 0
data =: x [ target =: y
'e i' =. err ; 0
while. (e >: err) *. i < max_steps do.
e =. bw2 fw2 data;net
i =. >: i
end.
i , e
)
NB. create_nnet 6 3 2 1 NB. создание сети(весов) с тремя скрытыми слоями.
NB. каждый слой задается числом узлов
create_nnet =: [: (0.5 -~ randsh) each 2&(<\)
NB. mf NET NB. функция принадлежности
NB. membership_function = {1} over {1+func e^{-NET}}
mf =: [: % [: >: [: ^ -
NB. data =: (? 256 $ 2) [ net =: (create_nnet 256 64 8)
NB. fw2 data;net
fw2 =: ([: mf mp)ba
NB. delta =: OUT ge Target NB. get error
NB. подшагивание = OUT*(1-OUT)*(Target-OUT)
ge =: [*(1-[) * -~
NB. back propagation
bw =: 3 : 0
delta =. target ge~ >2 { y
fix =. eta * ((>1 { y) mpx delta)
net =: (1 { net) 1 } net
NB. hidden layer
a =. (>2 { y) mp (|: >1 { net)
det =: (>1 { y) mp (1-(>1 { y))
delta0 =: a mpx det
fix =. eta * ((>0 { y) mpx delta0)
net =: (0 { net) 0 } net
NB. return error sum
+/ *: target - >2{y
)
cocurrent 'base'