lib/nn.rb in nn-1.5 vs lib/nn.rb in nn-1.6

- old
+ new

@@ -1,10 +1,10 @@ require "numo/narray" require "json" class NN - VERSION = "1.5" + VERSION = "1.6" include Numo attr_accessor :weights attr_accessor :biases @@ -20,11 +20,11 @@ def initialize(num_nodes, learning_rate: 0.01, batch_size: 1, activation: %i(relu identity), - momentum: 0, + momentum: 0.9, weight_decay: 0, use_dropout: false, dropout_ratio: 0.5, use_batch_norm: false) SFloat.srand(rand(2 ** 64)) @@ -62,33 +62,41 @@ nn.betas = json["betas"].map{|beta| SFloat.cast(beta)} end nn end - def train(x_train, y_train, epoch, - save_dir: nil, save_interval: 1, test: nil, border: nil, tolerance: 0.5, &block) + def train(x_train, y_train, epochs, + learning_rate_decay: 0, + save_dir: nil, + save_interval: 1, + test: nil, + border: nil, + tolerance: 0.5, + &block) num_train_data = x_train.is_a?(SFloat) ? x_train.shape[0] : x_train.length - (epoch * num_train_data / @batch_size).times do |count| - loss = learn(x_train, y_train, &block) - if loss.nan? - puts "loss is nan" - break - end - if (count + 1) % (num_train_data / @batch_size) == 0 - now_epoch = (count + 1) / (num_train_data / @batch_size) - if save_dir && now_epoch % save_interval == 0 - save("#{save_dir}/epoch#{now_epoch}.json") + (1..epochs).each do |epoch| + loss = nil + (num_train_data.to_f / @batch_size).ceil.times do + loss = learn(x_train, y_train, &block) + if loss.nan? + puts "loss is nan" + break end - msg = "epoch #{now_epoch}/#{epoch} loss: #{loss}" - if test - acc = accurate(*test, tolerance, &block) - puts "#{msg} accurate: #{acc}" - break if border && acc >= border - else - puts msg - end end + if save_dir && epoch % save_interval == 0 + save("#{save_dir}/epoch#{epoch}.json") + end + msg = "epoch #{epoch}/#{epochs} loss: #{loss}" + if test + acc = accurate(*test, tolerance, &block) + puts "#{msg} accurate: #{acc}" + break if border && acc >= border + else + puts msg + end + @learning_rate -= learning_rate_decay + @learning_rate = 1e-7 if @learning_rate < 1e-7 end end def test(x_test, y_test, tolerance = 0.5, &block) acc = accurate(x_test, y_test, tolerance, &block) @@ -97,10 +105,10 @@ end def accurate(x_test, y_test, tolerance = 0.5, &block) correct = 0 num_test_data = x_test.is_a?(SFloat) ? x_test.shape[0] : x_test.length - (num_test_data / @batch_size).times do |i| + (num_test_data.to_f / @batch_size).ceil.times do |i| x = SFloat.zeros(@batch_size, @num_nodes.first) y = SFloat.zeros(@batch_size, @num_nodes.last) @batch_size.times do |j| k = i * @batch_size + j if x_test.is_a?(SFloat)