应用神经网络识别数字

Vya*_*nov 4 ruby neural-network

我试着去理解神经网络

我将输入数组合为

..# ### ### #.#
.## ..# ..# #.#
..# ### ### ###
..# #.. ..# ..#
..# ### ### ..#, etc
Run Code Online (Sandbox Code Playgroud)

期望的ouptut我设置为数字/ 10,即数字= 5输出= 0.5

代码

require 'ruby-fann'

train = RubyFann::TrainData.new(
  inputs: [
    [0,0,1,0,1,1,0,0,1,0,0,1,0,0,1],
    [1,1,1,0,0,1,1,1,1,1,0,0,1,1,1],
    [1,1,1,0,0,1,1,1,1,0,0,1,1,1,1],
    [1,0,1,1,0,1,1,1,1,0,0,1,0,0,1],
    [1,1,1,1,0,0,1,1,1,0,0,1,1,1,1],
    [1,1,1,1,0,0,1,1,1,1,0,1,1,1,1],
    [1,1,1,0,0,1,0,1,0,1,0,0,1,0,0],
    [1,1,1,1,0,1,1,1,1,1,0,1,1,1,1],
    [1,1,1,1,0,1,1,1,1,0,0,1,1,1,1]
  ],
  desired_outputs: [[0.1],[0.2],[0.3], [0.4], [0.5], [0.6], [0.7], [0.8], [0.9]]
)
fann = RubyFann::Standard.new(
  num_inputs: 15,
  hidden_neurons: [8,4,3,4,1],
  num_outputs: 1
)
fann.train_on_data(train, 100000, 10, 0.1) # 100000 max_epochs, 100 errors between reports and 0.1 desired MSE (mean-squared-error)
outputs = fann.run([0,0,1,0,1,1,0,0,1,0,0,1,0,0,1])
result = outputs.first
abort result.inspect
Run Code Online (Sandbox Code Playgroud)

每个运行脚本的输出

0.5367386954219215
0.5141728468011051
0.5249739971144654
0.5373135467504666
0.5182686028674102
0.46710004502372293
0.4723526462690119
0.5306690734137796
0.5151398228322749
0.5359153267266001
0.469100790593523
0.4749347798092478
0.5094355973839471
0.5205985468860461
0.5277528652471375
0.4825827561254995
Run Code Online (Sandbox Code Playgroud)

我不明白为什么输出不等于0.1,这与第一次输入完全相同.

什么意味着价值在0.46 - 0.53 diapason?

UPDATE

我用0.1替换0,用0.9替换1

产量

0.4794515462681635
0.5332274595769928
0.4601992972516728
0.427064909364266
0.43466252163025687
0.46931411920827737
0.4455544021835517
0.48051179013023565
0.4798245565677274
0.4479353078492235
0.4646710791032779
0.4887400910135108
Run Code Online (Sandbox Code Playgroud)

此外,我为零位添加+1输入,没有发生任何重大事件

Nei*_*ter 5

训练神经网络是一种黑暗的艺术.在这里,您最大的问题是将RMS误差目标设置为0.1 - 这意味着您将接受大于您感兴趣的差异的平均绝对误差.将其设置得更低应该会有很大帮助.

另外(但不太重要):

  • 你不需要那么多隐藏层.足够的神经元.从反复试验中我认为你的[8,4,3,4,1]问题有点低(最后一个没有用).价值[30]似乎有效 - 我基本上通过尝试一些猜测得到了这个.

  • 分类通常最好使用每个类别一个0/1输出,然后选择最大值.你不需要那个,我测试你的0.1,0.2等目标,它就像那样工作得很好.解释为什么单独的输出更好:如果你的输入有一些噪音,理想情况下网络应该在3和8之间选择,那么使用单个输出的中间值可能是0.55 - 即使你绕它也不是很有用价值基本上是不正确的.但是,有9个输出用于分类,"3"和"8"的输出都会很高,你可以选择略高的输出,或者有信心地显示正确的值是"3" "或"8".

  • 您选择作为测试用例的问题可能会陷入局部最小值,您需要调整动量和学习率以获得更好的成功机会.

  • 改组训练数据也可能有所帮助.

您的代码/参数的以下更改应该更接近您期望的结果:

require 'ruby-fann'

train = RubyFann::TrainData.new(
  inputs: [
    [0,0,1,0,1,1,0,0,1,0,0,1,0,0,1], [1,1,1,0,0,1,1,1,1,1,0,0,1,1,1],
    [1,1,1,0,0,1,1,1,1,0,0,1,1,1,1], [1,0,1,1,0,1,1,1,1,0,0,1,0,0,1],
    [1,1,1,1,0,0,1,1,1,0,0,1,1,1,1], [1,1,1,1,0,0,1,1,1,1,0,1,1,1,1],
    [1,1,1,0,0,1,0,1,0,1,0,0,1,0,0], [1,1,1,1,0,1,1,1,1,1,0,1,1,1,1],
    [1,1,1,1,0,1,1,1,1,0,0,1,1,1,1]
  ],
  desired_outputs: [ [1,0,0,0,0,0,0,0,0], [0,1,0,0,0,0,0,0,0],
                     [0,0,1,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0],
                     [0,0,0,0,1,0,0,0,0], [0,0,0,0,0,1,0,0,0],
                     [0,0,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,1,0],
                     [0,0,0,0,0,0,0,0,1] ]
)

fann = RubyFann::Standard.new(
  num_inputs: 15,
  hidden_neurons: [30],
  num_outputs: 9
)

fann.learning_rate = 0.5
fann.momentum = 0.5

fann.train_on_data(train, 10000, 1000, 0.001)

outputs = fann.run([0,0,1,0,1,1,0,0,1,0,0,1,0,0,1])
m = outputs.max
puts "Result: #{( outputs.find_index { |x| x == m } ) + 1}"
Run Code Online (Sandbox Code Playgroud)