local matrix = require("matrixx")
local Class = require("class")
NeuralNetwork = Class{}
function NeuralNetwork:init(input_nodes, hidden_nodes, output_nodes)
self.input_nodes = input_nodes
self.hidden_nodes = hidden_nodes
self.output_nodes = output_nodes
self.weights_ih = matrix(self.hidden_nodes, self.input_nodes, math.random())
self.weights_ho = matrix(self.output_nodes, self.hidden_nodes, math.random())
self.bias_h = matrix(self.hidden_nodes, 1, math.random())
self.bias_o = matrix(self.output_nodes, 1, math.random())
self.learning_rate = 0.1
end
function NeuralNetwork:feedforward(input_array)
--Generating the Hidden Outputs
local inputs = matrix(input_array)
for i=1, #input_array do
inputs[i][1] = input_array[i]
end
local hidden = self.weights_ih * inputs
hidden = hidden + self.bias_h
--Activation Function
hidden = matrix.map(hidden, tanh)
--Generating the output's output
local output = self.weights_ho * hidden
output = output + self.bias_o
output = matrix.map(output, tanh)
return output
end
function NeuralNetwork:train(input_array, target_array)
--Generating the Hidden Outputs
local inputs = matrix(input_array)
for i=1, #input_array do
inputs[i][1] = input_array[i]
end
local hidden = self.weights_ih * inputs
hidden = hidden + self.bias_h
--Activation Function
hidden = matrix.map(hidden, tanh)
--Generating the output's output
local outputs = self.weights_ho * hidden
outputs = outputs + self.bias_o
outputs = matrix.map(outputs, tanh)
--Convert Targets Array to Matrix object
local targets = matrix(#target_array, 1)
for i=1, #target_array do
targets[i][1] = target_array[i]
end
--Calculate the error
local output_errors = targets - outputs
--Calculate gradient
local gradients = matrix.map(outputs, tanhd)
gradients = gradients * output_errors
gradients = gradients * self.learning_rate
-- Calculate deltas
local hidden_T = matrix.transpose(hidden)
local weight_ho_deltas = gradients * hidden_T
-- Adjust the weights by deltas
self.weights_ho = self.weights_ho + weight_ho_deltas
-- Adjust the bias by its deltas (which is just the gradients)
self.bias_o = self.bias_o + gradients
-- Calculate the hidden layer errors
local who_t = matrix.transpose(self.weights_ho)
local hidden_errors = who_t * output_errors
-- Calculate hidden gradient
local hidden_gradient = matrix.map(hidden, tanhd)
hidden_gradient = hidden_gradient * hidden_errors * self.learning_rate
-- Calcuate input->hidden deltas
local inputs_T = matrix.transpose(inputs)
local weight_ih_deltas = hidden_gradient * inputs_T
self.weights_ih = self.weights_ih + weight_ih_deltas
-- Adjust the bias by its deltas (which is just the gradients)
self.bias_h = self.bias_h + hidden_gradient
self.weights_ih:print()
print()
self.weights_ho:print()
print()
end
function sigmoid(x)
return 1 / (1 + math.exp(-x))
end
function dsigmoid(x)
return sigmoid(x) * (1 - sigmoid(x))
end
function tanh(x)
return (math.exp(x) - math.exp(-x)) / (math.exp(x) + math.exp(-x))
end
function tanhd(x)
return 1 / math.cosh(x)^2
end
--MAIN
local nn = NeuralNetwork(2, 2, 1)
local training_data = {
{
inputs = {0, 1},
target = {1}
},
{
inputs = {1, 1},
target = {0}
},
{
inputs = {1, 0},
target = {1}
},
{
inputs = {0, 0},
target = {0}
}
}
for i = 1, 30 do
local data = training_data[math.floor(math.random(#training_data))]
nn:train(data.inputs, data.target)
end
nn:feedforward({0, 1}):print()
nn:feedforward({1, 1}):print()
nn:feedforward({0, 0}):print()
nn:feedforward({1, 0}):print()
Я написал этот класс NeuralNetwork.Я использовал библиотеку классов и матричную библиотеку. Соответственно class matrix
Кажется, что все это правильно для меня (в идеале, по крайней мере), кстати, когда я создаю новый экземплярNN с 2 входами, 2 скрытыми нейронами и 1 выходом и попыткой решить XOR, это не работает.
Чего мне не хватает?Может быть, я неправильно понял матричную библиотеку, надеюсь, кто-нибудь может мне помочь
РЕДАКТИРОВАТЬ: я добавил функцию карты в библиотеку, чтобы применить математическую функцию к каждому числу в матрице.
function matrix.map( m1, func )
local mtx = {}
for i = 1,#m1 do
mtx[i] = {}
for j = 1,#m1[1] do
mtx[i][j] = func(m1[i][j])
end
end
return setmetatable( mtx, matrix_meta )
end