-module(gleam_synapses@model@net_elems@neuron). -compile(no_auto_import). -export([init/3, output/2, back_propagated/4, serialized/1, deserialized/1, json_encoded/1, json_decoder/0, generator/1]). -export_type([neuron/0, neuron_serialized/0]). -type neuron() :: {neuron, gleam_synapses@model@net_elems@activation:activation(), gleam_zlists@interop:z_list(float())}. -type neuron_serialized() :: {neuron_serialized, binary(), list(float())}. -spec init( integer(), gleam_synapses@model@net_elems@activation:activation(), fun(() -> float()) ) -> neuron(). init(Input_size, Activation_f, Weight_init_f) -> Weights = gleam_zlists:map( gleam_zlists:take(gleam_zlists:indices(), Input_size + 1), fun(_) -> Weight_init_f() end ), {neuron, Activation_f, Weights}. -spec output(neuron(), gleam_zlists@interop:z_list(float())) -> float(). output(Neuron, Input_val) -> Activation_input = gleam_synapses@model@mathematics:dot_product( gleam_zlists:cons(Input_val, 1.0), erlang:element(3, Neuron) ), (erlang:element(3, erlang:element(2, Neuron)))( gleam_synapses@model@net_elems@activation:restricted_input( erlang:element(2, Neuron), Activation_input ) ). -spec back_propagated( neuron(), float(), gleam_zlists@interop:z_list(float()), {float(), float()} ) -> {gleam_zlists@interop:z_list(float()), neuron()}. back_propagated(Neuron, Learning_rate, Input_val, Output_with_error) -> {Output_val, Error} = Output_with_error, Output_inverse = (erlang:element(5, erlang:element(2, Neuron)))(Output_val), Common = Error * (erlang:element(4, erlang:element(2, Neuron)))( Output_inverse ), In_errors = gleam_zlists:map(Input_val, fun(X) -> X * Common end), New_weights = gleam_zlists:map( gleam_zlists:zip( gleam_zlists:cons(Input_val, 1.0), erlang:element(3, Neuron) ), fun(X@1) -> {A, B} = X@1, B - ((Learning_rate * Common) * A) end ), New_neuron = {neuron, erlang:element(2, Neuron), New_weights}, {In_errors, New_neuron}. -spec serialized(neuron()) -> neuron_serialized(). serialized(Neuron) -> {neuron_serialized, gleam_synapses@model@net_elems@activation:serialized( erlang:element(2, Neuron) ), gleam_zlists:to_list(erlang:element(3, Neuron))}. -spec deserialized(neuron_serialized()) -> neuron(). deserialized(Neuron_serialized) -> {neuron, gleam_synapses@model@net_elems@activation:deserialized( erlang:element(2, Neuron_serialized) ), gleam_zlists:of_list(erlang:element(3, Neuron_serialized))}. -spec json_encoded(neuron_serialized()) -> gleam@jsone:json_value(). json_encoded(Neuron_serialized) -> gleam@jsone:object( [{<<"activationF"/utf8>>, gleam_synapses@model@net_elems@activation:json_encoded( erlang:element(2, Neuron_serialized) )}, {<<"weights"/utf8>>, gleam@jsone:array( erlang:element(3, Neuron_serialized), fun gleam@jsone:float/1 )}] ). -spec json_decoder() -> decode:decoder(neuron_serialized()). json_decoder() -> decode:map2( fun(A, B) -> {neuron_serialized, A, B} end, decode:field( <<"activationF"/utf8>>, gleam_synapses@model@net_elems@activation:json_decoder() ), decode:field(<<"weights"/utf8>>, decode:list(decode:float())) ). -spec generator(integer()) -> minigen:generator(neuron()). generator(Input_size) -> Weights_generator = minigen:map( minigen:list( minigen:map(minigen:float(), fun(X) -> 1.0 - (2.0 * X) end), Input_size + 1 ), fun gleam_zlists:of_list/1 ), minigen:map2( gleam_synapses@model@net_elems@activation:generator(), Weights_generator, fun(A, B) -> {neuron, A, B} end ).