内容简介:翻译自:https://stackoverflow.com/questions/42749541/sequence-prediction-lstm-neural-network-is-falling-behind
我正在尝试实现猜测游戏,其中用户猜测硬币翻转和神经网络试图预测他的猜测(当然没有后见之明的知识).游戏应该是实时的,它适应用户.我使用了突触js,因为它看起来很稳固.
然而,我似乎无法通过一个绊脚石:神经网络不断跟踪它的猜测.就像,如果用户按下
heads heads tail heads heads tail heads heads tail
它确实识别出这种模式,但它却落后于两个动作
tail heads heads tail heads heads tail heads heads
我尝试了无数的策略:
>随着用户与用户一起点击头部或尾部,训练网络
>记录用户条目并清除网络内存,并使用所有条目进行重新训练,直到猜测为止
>通过一系列方式混合搭配训练与激活
>尝试移动到感知器立即传递一堆动作(比LSTM更糟糕)
>一堆我忘记的其他事情
建筑:
> 2个输入,无论用户是否在前一回合中点击了头部或尾部
> 2个输出,预测用户下次点击的内容(这将在下一轮输入)
我已经在隐藏层和各种训练时期尝试了10-30个神经元,但我经常遇到同样的问题!
我将发布我正在执行此操作的bucklescript代码.
我究竟做错了什么?或者我的期望仅仅是无法预测用户猜测实时?有没有替代算法?
class type _nnet = object method activate : float array -> float array method propagate : float -> float array -> unit method clone : unit -> _nnet Js.t method clear : unit -> unit end [@bs] type nnet = _nnet Js.t external ltsm : int -> int -> int -> nnet = "synaptic.Architect.LSTM" [@@bs.new] external ltsm_2 : int -> int -> int -> int -> nnet = "synaptic.Architect.LSTM" [@@bs.new] external ltsm_3 : int -> int -> int -> int -> int -> nnet = "synaptic.Architect.LSTM" [@@bs.new] external perceptron : int -> int -> int -> nnet = "synaptic.Architect.Perceptron" [@@bs.new] type id type dom (** Abstract type for id object *) external dom : dom = "document" [@@bs.val] external get_by_id : dom -> string -> id = "getElementById" [@@bs.send] external set_text : id -> string -> unit = "innerHTML" [@@bs.set] (*THE CODE*) let current_net = ltsm 2 16 2 let training_momentum = 0.1 let training_epochs = 20 let training_memory = 16 let rec train_sequence_rec n the_array = if n > 0 then ( current_net##propagate training_momentum the_array; train_sequence_rec (n - 1) the_array ) let print_arr prefix the_arr = print_endline (prefix ^ " " ^ (Pervasives.string_of_float (Array.get the_arr 0)) ^ " " ^ (Pervasives.string_of_float (Array.get the_arr 1))) let blank_arr = fun () -> let res = Array.make_float 2 in Array.fill res 0 2 0.0; res let derive_guess_from_array the_arr = Array.get the_arr 0 < Array.get the_arr 1 let set_array_inp the_value the_arr = if the_value then Array.set the_arr 1 1.0 else Array.set the_arr 0 1.0 let output_array the_value = let farr = blank_arr () in set_array_inp the_value farr; farr let by_id the_id = get_by_id (dom) the_id let update_prediction_in_ui the_value = let elem = by_id "status-text" in if not the_value then set_text elem "Predicted Heads" else set_text elem "Predicted Tails" let inc_ref the_ref = the_ref := !the_ref + 1 let total_guesses_count = ref 0 let steve_won_count = ref 0 let sequence = Array.make training_memory false let seq_ptr = ref 0 let seq_count = ref 0 let push_seq the_value = Array.set sequence (!seq_ptr mod training_memory) the_value; inc_ref seq_ptr; if !seq_count < training_memory then inc_ref seq_count let seq_start_offset () = (!seq_ptr - !seq_count) mod training_memory let traverse_seq the_fun = let incr = ref 0 in let begin_at = seq_start_offset () in let next_i () = (begin_at + !incr) mod training_memory in let rec loop () = if !incr < !seq_count then ( let cval = Array.get sequence (next_i ()) in the_fun cval; inc_ref incr; loop () ) in loop () let first_in_sequence () = Array.get sequence (seq_start_offset ()) let last_in_sequence_n n = let curr = ((!seq_ptr - n) mod training_memory) - 1 in if curr >= 0 then Array.get sequence curr else false let last_in_sequence () = last_in_sequence_n 0 let perceptron_input last_n_fields = let tot_fields = (3 * last_n_fields) in let out_arr = Array.make_float tot_fields in Array.fill out_arr 0 tot_fields 0.0; let rec loop count = if count < last_n_fields then ( if count >= !seq_count then ( Array.set out_arr (3 * count) 1.0; ) else ( let curr = last_in_sequence_n count in let the_slot = if curr then 1 else 0 in Array.set out_arr (3 * count + 1 + the_slot) 1.0 ); loop (count + 1) ) in loop 0; out_arr let steve_won () = inc_ref steve_won_count let propogate_n_times the_output = let rec loop cnt = if cnt < training_epochs then ( current_net##propagate training_momentum the_output; loop (cnt + 1) ) in loop 0 let print_prediction prev exp pred = print_endline ("Current training, previous: " ^ (Pervasives.string_of_bool prev) ^ ", expected: " ^ (Pervasives.string_of_bool exp) ^ ", predicted: " ^ (Pervasives.string_of_bool pred)) let train_from_sequence () = current_net##clear (); let previous = ref (first_in_sequence ()) in let count = ref 0 in print_endline "NEW TRAINING BATCH"; traverse_seq (fun i -> let inp_arr = output_array !previous in let out_arr = output_array i in let act_res = current_net##activate inp_arr in print_prediction !previous i (derive_guess_from_array act_res); propogate_n_times out_arr; previous := i; inc_ref count ) let update_counts_in_ui () = let tot = by_id "total-count" in let won = by_id "steve-won-count" in set_text tot (Pervasives.string_of_int !total_guesses_count); set_text won (Pervasives.string_of_int !steve_won_count) let train_sequence (the_value : bool) = train_from_sequence (); let last_guess = (last_in_sequence ()) in let before_train = current_net##activate (output_array last_guess) in let act_result = derive_guess_from_array before_train in (*side effects*) push_seq the_value; inc_ref total_guesses_count; if the_value = act_result then steve_won (); print_endline "CURRENT"; print_prediction last_guess the_value act_result; update_prediction_in_ui act_result; update_counts_in_ui () let guess (user_guess : bool) = train_sequence user_guess let () = ()
在每次训练迭代之前清除网络上下文是修复
您的代码中的问题是您的网络已经过循环培训.而不是训练1> 2> 3 RESET 1> 2> 3你正在训练网络1> 2> 3> 1> 2> 3.这使您的网络认为3之后的值应为1.
其次,没有理由使用2个输出神经元.有一个就足够了,输出1等于头,输出0等于尾.我们只是围绕输出.
我没有使用Synaptic,而是在此代码中使用了 Neataptic – 它是Synaptic的改进版本,增加了功能和遗传算法.
代码
代码很简单.稍微贬低它,它看起来像这样:
var network = new neataptic.Architect.LSTM(1,12,1);; var previous = null; var trainingData = []; // side is 1 for heads and 0 for tails function onSideClick(side){ if(previous != null){ trainingData.push({ input: [previous], output: [side] }); // Train the data network.train(trainingData, { log: 500, iterations: 5000, error: 0.03, clear: true, rate: 0.05, }); // Iterate over previous sets to get into the 'flow' for(var i in trainingData){ var input = trainingData[i].input; var output = Math.round(network.activate([input])); } // Activate network with previous output, aka make a prediction var input = output; var output = Math.round(network.activate([input])) } previous = side; }
这段代码的关键是明确的:是的.这基本上确保网络知道它从第一个训练样本开始,而不是从最后一个训练样本继续. LSTM的大小,迭代次数和学习率是完全可定制的.
成功!
请注意,它需要大约2倍的网络模式才能学习它.
但它确实存在非重复模式的问题:
翻译自:https://stackoverflow.com/questions/42749541/sequence-prediction-lstm-neural-network-is-falling-behind
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 聊聊从脑神经到神经网络
- 神经网络历史以及浅析神经网络与感知机
- 【神经网络】11行Python代码实现的神经网络
- 常见的五种神经网络(三):循环神经网络(上篇)
- 常见的五种神经网络(三):循环神经网络(中篇)
- 人工智能、机器学习、神经网络和深度神经网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
黑客简史:棱镜中的帝国
刘创 / 电子工业出版社 / 2015-1 / 39.80元
“黑客”,伴随着计算机和互联网而诞生,他们掌握着前沿的计算机和网络技术,能够发现并利用计算机系统和网络的弱点,他们的行为动机多样,因此我们必须对这一群体进行分解,认识他们及其技术的两面性——“黑客”中那些不断拓展技术边界、富于创造力的,和那些掌握技术、却利欲熏心的,就像硬币的两面,谁都无法清晰地辨别是非。相对于主流文化,黑客的行为方式和理念等形成了一种“亚文化”,与主流文化相互作用。一起来看看 《黑客简史:棱镜中的帝国》 这本书的介绍吧!