method train input example (alpha :float) =
         let loop rep activation =
         
            (* this loop handles layers 2 to n *)
            let rec loop2 rep activation =
               match rep with
                  layer :: rest_rep ->
                     begin
                        if Array.length layer.(0) != Array.length activation +1 then
                           failwith "Input Size Error"
                        else ();
                        (* add the bias *)
                        let activation = Array.append [|1.0|] activation in
                        (* calculate the weighted sums *)
                        let sums = layer |*| activation in
                        (* apply transfer functions *)
                        let output = Array.map sigmoid sums in
                        (* descend to next layer and get weighted sums of deltas from there*)
                        let delta_sums = loop2 rest_rep output in
                        (* calculate deltas from those sums *)
                        let deltas = Array.mapi (fun i x -> output.(i) *. (1.0-.output.(i))*.x) delta_sums in
                        (* create array to hold new deltas*)
                        let new_deltas = Array.make (Array.length activation) 0.0 in
                        
                        (* calculate the differences*)
                        let n = Array.length layer in
                        let m = Array.length (Array.unsafe_get layer 0) in
                        for i = 0 to n - 1 do
                           let weightsi = Array.unsafe_get layer i in
                           let deltai = Array.unsafe_get deltas i in
                           for j = 0 to m - 1 do
                              let weightij = Array.unsafe_get weightsi j in
                              let change = alpha *. deltai *. Array.unsafe_get activation j in
                              (* get this part of the corresponding new_delta *)
                              Array.unsafe_set new_deltas j (Array.unsafe_get new_deltas j +. deltai *. weightij);
                              Array.unsafe_set weightsi j  (weightij +. change);
                           done
                        done;
                        
                        (* pass the deltas to caller, but throw away the one for the bias *)
                        Array.sub new_deltas 1 (Array.length activation - 1) 
                     end
               |   [] -> Array.mapi (fun i x -> example.(i) -. x) activation
            in
            (* Special faster case for the first (and most often largest) layer *)
            match rep with 
               layer :: rest_rep ->
                  begin
                     if Array.length layer.(0) != Array.length activation +1 then
                        failwith "Input Size Error"
                     else ();
                     (* add the bias *)
                     let activation = Array.append [|1.0|] activation in
                     (* calculate the weighted sums *)
                     let sums = layer |*| activation in
                     (* apply transfer functions *)
                     let output = Array.map sigmoid sums in
                     (* descend to next layer and get weighted sums of deltas from there*)
                     let delta_sums = loop2 rest_rep output in
                     (* calculate deltas from those sums *)
                     let deltas = Array.mapi (fun i x -> output.(i) *. (1.0-.output.(i))*.x) delta_sums in
                      
                     (* calculate the differences*)
                     let n = Array.length layer in
                     let m = Array.length (Array.unsafe_get layer 0) in
                     for i = 0 to n - 1 do
                        let weightsi = Array.unsafe_get layer i in
                        let deltai = Array.unsafe_get deltas i in
                        for j = 0 to m - 1 do
                           let weightij = Array.unsafe_get weightsi j in
                           let change = alpha *. deltai *. Array.unsafe_get activation j in
                           (* get this part of the corresponding new_delta *)
                           Array.unsafe_set weightsi j  (weightij +. change);
                        done
                     done
                     (* from the first layer nothing has to be returned *)
                  end
            | [] ->
               ()
         in loop rep input