नहीं सीख सकता है, मैं तंत्रिका नेटवर्क के बारे में जानने की कोशिश कर रहा हूं और एक सरल, बैक-प्रोपेगेशन, तंत्रिका नेटवर्क को कोडित करता हूं जो सिग्मोइड सक्रियण कार्यों, यादृच्छिक वजन प्रारंभिकरण, और सीखने/ढाल गति का उपयोग करता है।सरल तंत्रिका नेटवर्क XOR
जब 2 इनपुट, 2 छुपे हुए नोड्स के साथ कॉन्फ़िगर किया गया, और 1 यह XOR और AND सीखने में विफल रहता है। हालांकि, यह सही ढंग से सीख जाएगा या।
मैं यह देखने में असफल रहा कि मैंने क्या किया है और इसलिए किसी भी मदद की सराहना की जाएगी।
धन्यवाद
संपादित करें: के रूप में कहा गया है, मैं 2 छिपा नोड्स के साथ परीक्षण किया, लेकिन नीचे कोड 3. के विन्यास मैं बस 3 छिपा नोड्स का उपयोग कर चल रहे परीक्षणों के बाद 2 को यह वापस बदलने के लिए भूल गया पता चलता है।
network.rb:
module Neural
class Network
attr_accessor :num_inputs, :num_hidden_nodes, :num_output_nodes, :input_weights, :hidden_weights, :hidden_nodes,
:output_nodes, :inputs, :output_error_gradients, :hidden_error_gradients,
:previous_input_weight_deltas, :previous_hidden_weight_deltas
def initialize(config)
initialize_input(config)
initialize_nodes(config)
initialize_weights
end
def initialize_input(config)
self.num_inputs = config[:inputs]
self.inputs = Array.new(num_inputs+1)
self.inputs[-1] = -1
end
def initialize_nodes(config)
self.num_hidden_nodes = config[:hidden_nodes]
self.num_output_nodes = config[:output_nodes]
# treat threshold as an additional input/hidden node with no incoming inputs and a value of -1
self.output_nodes = Array.new(num_output_nodes)
self.hidden_nodes = Array.new(num_hidden_nodes+1)
self.hidden_nodes[-1] = -1
end
def initialize_weights
# treat threshold as an additional input/hidden node with no incoming inputs and a value of -1
self.input_weights = Array.new(hidden_nodes.size){Array.new(num_inputs+1)}
self.hidden_weights = Array.new(output_nodes.size){Array.new(num_hidden_nodes+1)}
set_random_weights(input_weights)
set_random_weights(hidden_weights)
self.previous_input_weight_deltas = Array.new(hidden_nodes.size){Array.new(num_inputs+1){0}}
self.previous_hidden_weight_deltas = Array.new(output_nodes.size){Array.new(num_hidden_nodes+1){0}}
end
def set_random_weights(weights)
(0...weights.size).each do |i|
(0...weights[i].size).each do |j|
weights[i][j] = (rand(100) - 49).to_f/100
end
end
end
def calculate_node_values(inputs)
inputs.each_index do |i|
self.inputs[i] = inputs[i]
end
set_node_values(self.inputs, input_weights, hidden_nodes)
set_node_values(hidden_nodes, hidden_weights, output_nodes)
end
def set_node_values(values, weights, nodes)
(0...weights.size).each do |i|
nodes[i] = Network::sigmoid(values.zip(weights[i]).map{|v,w| v*w}.inject(:+))
end
end
def predict(inputs)
calculate_node_values(inputs)
output_nodes.size == 1 ? output_nodes[0] : output_nodes
end
def train(inputs, desired_results, learning_rate, momentum_rate)
calculate_node_values(inputs)
backpropogate_weights(desired_results, learning_rate, momentum_rate)
end
def backpropogate_weights(desired_results, learning_rate, momentum_rate)
output_error_gradients = calculate_output_error_gradients(desired_results)
hidden_error_gradients = calculate_hidden_error_gradients(output_error_gradients)
update_all_weights(inputs, desired_results, hidden_error_gradients, output_error_gradients, learning_rate, momentum_rate)
end
def self.sigmoid(x)
1.0/(1 + Math::E**-x)
end
def self.dsigmoid(x)
sigmoid(x) * (1 - sigmoid(x))
end
def calculate_output_error_gradients(desired_results)
desired_results.zip(output_nodes).map{|desired, result| (desired - result) * Network::dsigmoid(result)}
end
def reversed_hidden_weights
# array[hidden node][weights to output nodes]
reversed = Array.new(hidden_nodes.size){Array.new(output_nodes.size)}
hidden_weights.each_index do |i|
hidden_weights[i].each_index do |j|
reversed[j][i] = hidden_weights[i][j];
end
end
reversed
end
def calculate_hidden_error_gradients(output_error_gradients)
reversed = reversed_hidden_weights
hidden_nodes.each_with_index.map do |node, i|
Network::dsigmoid(hidden_nodes[i]) * output_error_gradients.zip(reversed[i]).map{|error, weight| error*weight}.inject(:+)
end
end
def update_all_weights(inputs, desired_results, hidden_error_gradients, output_error_gradients, learning_rate, momentum_rate)
update_weights(hidden_nodes, inputs, input_weights, hidden_error_gradients, learning_rate, previous_input_weight_deltas, momentum_rate)
update_weights(output_nodes, hidden_nodes, hidden_weights, output_error_gradients, learning_rate, previous_hidden_weight_deltas, momentum_rate)
end
def update_weights(nodes, values, weights, gradients, learning_rate, previous_deltas, momentum_rate)
weights.each_index do |i|
weights[i].each_index do |j|
delta = learning_rate * gradients[i] * values[j]
weights[i][j] += delta + momentum_rate * previous_deltas[i][j]
previous_deltas[i][j] = delta
end
end
end
end
end
test.rb:
#!/usr/bin/ruby
load "network.rb"
learning_rate = 0.3
momentum_rate = 0.2
nn = Neural::Network.new(:inputs => 2, :hidden_nodes => 3, :output_nodes => 1)
10000.times do |i|
# XOR - doesn't work
nn.train([0, 0], [0], learning_rate, momentum_rate)
nn.train([1, 0], [1], learning_rate, momentum_rate)
nn.train([0, 1], [1], learning_rate, momentum_rate)
nn.train([1, 1], [0], learning_rate, momentum_rate)
# AND - very rarely works
# nn.train([0, 0], [0], learning_rate, momentum_rate)
# nn.train([1, 0], [0], learning_rate, momentum_rate)
# nn.train([0, 1], [0], learning_rate, momentum_rate)
# nn.train([1, 1], [1], learning_rate, momentum_rate)
# OR - works
# nn.train([0, 0], [0], learning_rate, momentum_rate)
# nn.train([1, 0], [1], learning_rate, momentum_rate)
# nn.train([0, 1], [1], learning_rate, momentum_rate)
# nn.train([1, 1], [1], learning_rate, momentum_rate)
end
puts "--- TESTING ---"
puts "[0, 0]"
puts "result "+nn.predict([0, 0]).to_s
puts
puts "[1, 0]"
puts "result "+nn.predict([1, 0]).to_s
puts
puts "[0, 1]"
puts "result "+nn.predict([0, 1]).to_s
puts
puts "[1, 1]"
puts "result "+nn.predict([1, 1]).to_s
puts
मैं एक पूर्ण परीक्षण केस स्थापित करके डिबगिंग शुरू करूंगा जिसमें प्रारंभिक वजन और डेरिवेटिव/त्रुटियों को दो उदाहरणों के लिए शामिल किया गया है, फिर कोड में कदम उठाएं। – Motasim
आपको उस समस्या को समझाते हुए * न्यूनतम * बिट कोड को वास्तव में कम करना चाहिए। आपके पास जो कुछ है वह काफी संपूर्ण एप्लिकेशन है। – tadman
आपका प्रोग्राम ऐसा लगता है कि यह कुछ दिलचस्प कर रहा है। लेकिन प्रत्येक भाषा का अपना सम्मेलन होता है, और रूबी की शक्ति का हिस्सा इसकी समानता है। आप इस सवाल को codereview.stackexchange.com पर ला सकते हैं। –