| Author |
Message |
< Erlang ~ Erlang and Neural Networks - Badmatch? |
| cosmixy |
Posted: Tue Aug 05, 2008 5:50 pm |
|
|
|
Joined: 05 Aug 2008
Posts: 3
|
I was going through this tut http://www.trapexit.org/Erlang_and_Neural_Networks.
Everything is going fine until I add the code for learning. Now I get a badmatch when a node tries to connect its output to more than one node.
When the second line here runs(in ann:run() )
Code: ann:connect(X1_pid, H1_pid),
ann:connect(X1_pid, H2_pid),
I've used debugger and it happens on {Key, _} = Tup, with a badmatch only when a node connects its output more than once. Connecting output from different nodes to the input of one node works fine.
Code: convert_to_keys(Tuple_list) ->
lists:map(fun(Tup) ->
{Key, _} = Tup,
Key
end,
Tuple_list).
The prompt.
Code: 1> ann:run().
<0.47.0> output connected to <0.49.0>: [<0.49.0>]
<0.48.0> output connected to <0.49.0>: [<0.49.0>]
<0.49.0> inputs connected to <0.47.0>: [{<0.47.0>,0.5}]
<0.50.0> inputs connected to <0.47.0>: [{<0.47.0>,0.5}]
<0.51.0> inputs connected to <0.49.0>: [{<0.49.0>,0.5}]
<0.49.0> inputs connected to <0.48.0>: [{<0.48.0>,0.5},{<0.47.0>,0.5}]
<0.50.0> inputs connected to <0.48.0>: [{<0.48.0>,0.5},{<0.47.0>,0.5}]
<0.51.0> inputs connected to <0.50.0>: [{<0.50.0>,0.5},{<0.49.0>,0.5}]
<0.49.0> output connected to <0.51.0>: [<0.51.0>]
<0.50.0> output connected to <0.51.0>: [<0.51.0>]
{pass,1.3}
=ERROR REPORT==== 5-Aug-2008::10:51:08 ===
Error in process <0.47.0> with exit value: {{badmatch,<0.49.0>},[{ann,'-convert_to_keys/1-fun-0-',1},{ann,perceptron,3}]}
=ERROR REPORT==== 5-Aug-2008::10:51:08 ===
Error in process <0.48.0> with exit value: {{badmatch,<0.49.0>},[{ann,'-convert_to_keys/1-fun-0-',1},{ann,perceptron,3}]}
Here is the full code.
Code:
-module(ann).
-export([run/0, perceptron/3, connect/2]).
feed_forward(Func, Weights, Inputs) ->
Func(dot_prod(Weights, Inputs)).
% like map, but with two lists instead.
vector_map(Func, [], []) ->
[];
vector_map(Func, [Xh | Xt], [Yh | Yt]) ->
[Func(Xh, Yh) | vector_map(Func, Xt, Yt)].
% Calculates the dot product of two lists
dot_prod(X, Y) ->
lists:foldl(fun(E, Sum) -> E + Sum end, 0,
vector_map(fun(Ex, Ey) -> Ex * Ey end, X, Y)).
perceptron(Weights, Inputs, Sensitivities) ->
Sigmoid = fun(X) ->
1 / (1 + math:exp(-X))
end,
Sigmoid_deriv = fun(X) ->
math:exp(-X) / (1 + math:exp(-2 * X))
end,
receive
{learn, Backprop} ->
Learning_rate = 0.5,
% Calculate the correct sensitivities
New_sensitivities = add_sensitivity(Sensitivities, Backprop),
Output_value = feed_forward(Sigmoid, Weights, convert_to_values(Inputs)),
Derv_value = feed_forward(Sigmoid_deriv, Weights, convert_to_values(Inputs)),
Sensitivity = calculate_sensitivity(Backprop, Inputs, New_sensitivities,
Output_value, Derv_value),
io:format("(~w) New Sensitivities: ~w~n", [self(), New_sensitivities]),
io:format("(~w) Calculated Sensitivity: ~w~n", [self(), Sensitivity]),
% Adjust all the weights
Weight_adjustments = lists:map(fun(Input) ->
Learning_rate * Sensitivity * Input
end,
convert_to_values(Inputs)),
New_weights = vector_map(fun(W, D) -> W + D end, Weights, Weight_adjustments),
io:format("(~w) Adjusted Weights: ~w~n", [self(), Weights]),
% propagate sensitivities and associated weights back to the previous layer
vector_map(fun(Weight, Input_PID) ->
Input_PID ! {learn, {self(), Sensitivity * Weight}}
end,
New_weights,
convert_to_keys(Inputs)),
perceptron(New_weights, Inputs, New_sensitivities);
{stimulate, Input} ->
New_inputs = replace_input(Inputs, Input),
Output_value = feed_forward(Sigmoid, Weights, convert_to_values(New_inputs)),
if Sensitivities =/= [] ->
% My output's connected to at least one perceptron:
lists:foreach(fun(Output_PID) ->
Output_PID ! {stimulate, {self(), Output_value}}
end,
convert_to_keys(Sensitivities));
Sensitivities =:= [] ->
% My output's connected to no one:
io:format("~w outputs: ~w~n", [self(), Output_value]),
% Call a trainer here instead and
self() ! {learn, {self(), 1}}
end,
perceptron(Weights, New_inputs, Sensitivities);
{connect_to_output, Receiver_PID} ->
Combined_output = [Receiver_PID | convert_to_keys(Sensitivities)],
io:format("~w output connected to ~w: ~w~n", [self(), Receiver_PID, Combined_output]),
perceptron(Weights, Inputs, Combined_output);
{connect_to_input, Sender_PID} ->
Combined_input = [{Sender_PID, 0.5} | Inputs],
io:format("~w inputs connected to ~w: ~w~n", [self(), Sender_PID, Combined_input]),
perceptron([0.5 | Weights], Combined_input, convert_to_keys(Sensitivities));
{pass, Input_value} ->
lists:foreach(fun(Output_PID) ->
io:format("Stimulating ~w with ~w~n", [Output_PID, Input_value]),
Output_PID ! {stimulate, {self(), Input_value}}
end,
convert_to_keys(Sensitivities))
end.
connect(Sender_PID, Receiver_PID) ->
Sender_PID ! {connect_to_output, Receiver_PID},
Receiver_PID ! {connect_to_input, Sender_PID}.
replace_input(Inputs, Input) ->
{Input_PID, _} = Input,
lists:keyreplace(Input_PID, 1, Inputs, Input).
convert_to_values(Tuple_list) ->
lists:map(fun(Tup) ->
{_, Val} = Tup,
Val
end,
Tuple_list).
convert_to_keys(Tuple_list) ->
lists:map(fun(Tup) ->
{Key, _} = Tup,
Key
end,
Tuple_list).
% adds the propagating sensitivity to the Sensitivities Hash
add_sensitivity(Sensitivities, Backprop) when Sensitivities =/= [] ->
replace_input(Sensitivities, Backprop);
add_sensitivity(Sensitivities, Backprop) when Sensitivities =:= [] ->
[].
% Calculates the sensitivity of this particular node
calculate_sensitivity(Backprop, Inputs, Sensitivities, Output_value, Derv_value)
when Sensitivities =/= [], Inputs =:= [] -> % When the node is an input node:
null;
calculate_sensitivity(Backprop, Inputs, Sensitivities, Output_value, Derv_value)
when Sensitivities =:= [], Inputs =/= [] -> % When the node is an output node:
{_, Training_value} = Backprop,
(Training_value - Output_value) * Derv_value;
calculate_sensitivity(Backprop, Inputs, Sensitivities, Output_value, Derv_value)
when Sensitivities =/= [], Inputs =/= [] -> % When the node is a hidden node:
Derv_value * lists:foldl(fun(E, T) -> E + T end, 0, convert_to_values(Sensitivities)).
run() ->
X1_pid = spawn(ann, perceptron, [[],[],[]]),
X2_pid = spawn(ann, perceptron, [[],[],[]]),
H1_pid = spawn(ann, perceptron, [[],[],[]]),
H2_pid = spawn(ann, perceptron, [[],[],[]]),
O_pid = spawn(ann, perceptron, [[],[],[]]),
% Connect input node X1 to hidden nodes H1 and H2
ann:connect(X1_pid, H1_pid),
ann:connect(X1_pid, H2_pid),
% Connect input node X2 to hidden nodes H1 and H2
ann:connect(X2_pid, H1_pid),
ann:connect(X2_pid, H2_pid),
% Connect input node H1 and H2 to output node O
ann:connect(H1_pid, O_pid),
ann:connect(H2_pid, O_pid),
X1_pid ! {status},
X2_pid ! {status},
H1_pid ! {status},
H2_pid ! {status},
O_pid ! {status},
X1_pid ! {pass, 1.8},
X2_pid ! {pass, 1.3}. |
|
|
| Back to top |
|
| cosmixy |
Posted: Wed Aug 06, 2008 8:12 pm |
|
|
|
Joined: 05 Aug 2008
Posts: 3
|
I have partially fixed the problem. A few instances of convert_to_values(Sensitivities) have been changed to just Sensitivities. That was causing Tup ({Key, _} = Tup) to be a single item rather than a 2 item tuple. Though I am still getting the error during the second layer of neurons which confuses me even more.
Code: 1> ann:run().
<0.47.0> output connected to <0.49.0>: [<0.49.0>]
<0.48.0> output connected to <0.49.0>: [<0.49.0>]
<0.49.0> inputs connected to <0.47.0>: [{<0.47.0>,0.5}]
<0.50.0> inputs connected to <0.47.0>: [{<0.47.0>,0.5}]
<0.51.0> inputs connected to <0.49.0>: [{<0.49.0>,0.5}]
<0.47.0> output connected to <0.50.0>: [<0.50.0>,<0.49.0>]
<0.48.0> output connected to <0.50.0>: [<0.50.0>,<0.49.0>]
<0.49.0> inputs connected to <0.48.0>: [{<0.48.0>,0.5},{<0.47.0>,0.5}]
<0.50.0> inputs connected to <0.48.0>: [{<0.48.0>,0.5},{<0.47.0>,0.5}]
<0.51.0> inputs connected to <0.50.0>: [{<0.50.0>,0.5},{<0.49.0>,0.5}]
Stimulating <0.50.0> with 1.8
Stimulating <0.50.0> with 1.3
<0.49.0> output connected to <0.51.0>: [<0.51.0>]
<0.50.0> output connected to <0.51.0>: [<0.51.0>]
Stimulating <0.49.0> with 1.8
Stimulating <0.49.0> with 1.3
{pass,1.3}
=ERROR REPORT==== 6-Aug-2008::12:57:38 ===
Error in process <0.50.0> with exit value: {{badmatch,<0.51.0>},[{ann,'-convert_to_keys/1-fun-0-',1},{ann,perceptron,3}]}
=ERROR REPORT==== 6-Aug-2008::12:57:38 ===
Error in process <0.49.0> with exit value: {{badmatch,<0.51.0>},[{ann,'-convert_to_keys/1-fun-0-',1},{ann,perceptron,3}]} |
|
|
| Back to top |
|
| cosmixy |
Posted: Sat Aug 09, 2008 8:07 pm |
|
|
|
Joined: 05 Aug 2008
Posts: 3
|
Fixed. Convert_to_keys() wanted a list of two item tuples, before the second items were added to Sensitivities it was just a list. Added an atom as a placeholder to make a two it item tuple from the get go. Was an awfully simple fix =O
From:
Code: {connect_to_output, Receiver_PID} ->
Combined_output = [Receiver_PID | Sensitivities],
To:
Code: {connect_to_output, Receiver_PID} ->
Combined_output = [{Receiver_PID, n} | Sensitivities], |
|
|
| Back to top |
|
|
|
All times are GMT
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|
|