Всем привет.
Сделал нейронку на LUA. Может кому пригодится:
Пример:
Сделал нейронку на LUA. Может кому пригодится:
| Код |
|---|
NeuralNetwork = {}
NeuralNetwork.__index = NeuralNetwork
function NeuralNetwork.new(inputs, layers, neyrons) -- Инициализация
local self = setmetatable({}, NeuralNetwork)
self.layers=layers -- слоев
self.inputs=inputs -- входов
self.neyrons=neyrons --нейронов в слое
self.k=0.5
self.e=0.01 -- Скорость обучения
self.im=0.01 -- импульс
self.traininig_count=0 --Будем считать обучения
self.w={}
self.nout={}
self.dw={}
self.delta={}
self.w[1]={}
self.nout[1]={}
self.dw[1]={}
self.delta[1]={}
local i
local l
for i = 1, self.neyrons, 1 do
self.w[1][i]={}
self.dw[1][i]={}
self.delta[1][i]={}
self.nout[1][i]={}
for ii = 1, self.inputs+1, 1 do
self.w[1][i][ii]=math.random()
self.dw[1][i][ii]=0
end
end
for l = 2, self.layers, 1 do --перебор остальных слоев
self.w[l]={}
self.dw[l]={}
self.delta[l]={}
self.nout[l]={}
for i = 1, self.neyrons, 1 do
self.w[l][i]={}
self.dw[l][i]={}
self.delta[l][i]={}
self.nout[l][i]={}
for ii = 1, self.neyrons+1, 1 do
self.w[l][i][ii]=1*math.random()
self.dw[l][i][ii]=0
end
end
end
--Выходной нейрон
self.w[self.layers+1]={}
self.dw[self.layers+1]={}
self.w[self.layers+1][1]={}
self.dw[self.layers+1][1]={}
self.delta[self.layers+1]={}
self.delta[self.layers+1][1]={}
for ii = 1, self.neyrons+1, 1 do -- +w0
self.w[self.layers+1][1][ii]=1*math.random()
self.dw[self.layers+1][1][ii]=0
end
return self
end
function NeuralNetwork.Save(self, filename)
local f,err = io.open(filename,"w")
if not f then
return false
end
f:write(table.tostring(self))
f:close()
return true
end
function NeuralNetwork.Load(self, filename)
local f,err = io.open(filename,"r")
if not f then
return false
end
local tbl = assert(load("return " .. f:read("*a")))
f:close()
for k,v in pairs(tbl()) do
if (type(v)=="table") then
self[k]=table_copy(v)
else
self[k] = v
end
end
return true
end
function NeuralNetwork.Training(self, data, res) --Одно обучение
self.traininig_count=self.traininig_count+1 -- счетчик обучений
local nres=self:Play(data) --Свой результат
self.delta[self.layers+1][1]=(res-nres) --Начинаем с выходного слоя
for tmpi = 1, self.neyrons, 1 do -- последний перед выходом слой
self.delta[self.layers][tmpi] = self.w[self.layers + 1][1][tmpi] * self.delta[self.layers + 1][1]*dsigmoda(self.nout[self.layers][tmpi], self.k)
end
for tmpl =self.layers-1, 1, -1 do -- слои
for tmpn = 1, self.neyrons, 1 do-- нейроны в слое
self.delta[tmpl][tmpn] = 0
for tmpi = 1, self.neyrons, 1 do
self.delta[tmpl][tmpn] = self.delta[tmpl][tmpn] + (self.w[tmpl + 1][tmpi][tmpn] * self.delta[tmpl + 1][tmpi])
end
self.delta[tmpl][tmpn] = self.delta[tmpl][tmpn] * dsigmoda(self.nout[tmpl][tmpn],self.k)
end
end
--Теперь правим веса
--Правим в первом/входном слое *************************** первый(0) *************************************
for tmpn = 1, self.neyrons, 1 do -- нейроны в слое
self.dw[1][tmpn][self.inputs + 1] = (self.e * self.delta[1][tmpn] * (1 - self.im)) + (self.im * self.dw[1][tmpn][self.inputs + 1])
self.w[1][tmpn][self.inputs + 1] = self.w[1][tmpn][self.inputs + 1] + self.dw[1][tmpn][self.inputs + 1]
for tmpi = 1, self.inputs, 1 do -- нейроны в слое
self.dw[1][tmpn][tmpi] = (data[tmpi] * self.e * self.delta[1][tmpn] * (1 - self.im)) + (self.im * self.dw[1][tmpn][tmpi])
self.w[1][tmpn][tmpi] = self.w[1][tmpn][tmpi] + self.dw[1][tmpn][tmpi]
end
end
--Остальные слои
for tmpl = 2, self.layers, 1 do
for tmpn = 1, self.neyrons, 1 do
self.dw[tmpl][tmpn][self.neyrons + 1] = (self.e * self.delta[tmpl][tmpn] * (1 - self.im)) + (self.im * self.dw[tmpl][tmpn][self.neyrons + 1])
self.w[tmpl][tmpn][self.neyrons + 1] = self.w[tmpl][tmpn][self.neyrons + 1] + self.dw[tmpl][tmpn][self.neyrons + 1]
for tmpi = 1, self.neyrons, 1 do --нейроны в слое
self.dw[tmpl][tmpn][tmpi] = (self.nout[tmpl-1][tmpi] * self.e * self.delta[tmpl][tmpn] * (1 - self.im)) + (self.im * self.dw[tmpl][tmpn][tmpi])
self.w[tmpl][tmpn][tmpi] = self.w[tmpl][tmpn][tmpi] + self.dw[tmpl][tmpn][tmpi]
end
end
end
-- Выходной слой из одного нейрона
self.dw[self.layers+1][1][self.neyrons + 1] = (self.e * self.delta[self.layers + 1][1] * (1 - self.im)) + (self.im * self.dw[self.layers + 1][1][self.neyrons + 1])
self.w[self.layers+1][1][self.neyrons + 1] = self.w[self.layers + 1][1][self.neyrons + 1] + self.dw[self.layers + 1][1][self.neyrons + 1]
for tmpi = 1, self.neyrons, 1 do -- нейроны в слое
self.dw[self.layers + 1][ 1][tmpi] = (self.nout[self.layers][tmpi] * self.e * self.delta[self.layers + 1][1] * (1 - self.im)) + (self.im * self.dw[self.layers + 1][1][tmpi])
self.w[self.layers + 1][1][tmpi] = self.w[self.layers + 1][1][tmpi] + self.dw[self.layers + 1][1][tmpi]
end
end
function NeuralNetwork.Play(self, tick_data) -- Принятие решения
local l
local n
local i
for l = 1, self.layers, 1 do -- проход по всем слоям, 1 - входной слой
for n = 1, self.neyrons, 1 do
local mmax
if (l==1) then --входной слой
self.nout[l][n]=1*self.w[l][n][self.inputs+1] --W0 последний
mmax=self.inputs
else
self.nout[l][n]=1*self.w[l][n][self.neyrons+1] --W0 последний
mmax=self.neyrons
end
for i = 1, mmax, 1 do
if (l==1) then --входной слой
self.nout[l][n]=self.nout[l][n]+(tick_data[i]*self.w[l][n][i]) --W0 последний
else
self.nout[l][n]=self.nout[l][n]+(self.nout[l-1][i]*self.w[l][n][i]) --W0 последний
end
end
self.nout[l][n]=sigmoda(self.nout[l][n], self.k)
end
end
--Выходной нейрон
self.nout[self.layers+1]=self.w[self.layers+1][1][self.neyrons+1] --W0
for i = 1, self.neyrons, 1 do
self.nout[self.layers+1]=self.nout[self.layers+1]+(self.nout[self.layers][i]*self.w[self.layers+1][1][i])
end
return sigmoda(self.nout[self.layers+1], self.k)
end
function dsigmoda(x, k)
local r
r = k * x * (1 - x)
return r
end
function sigmoda(x, k)
local r
r = 1 / (1 + math.exp(-x * k))
return r
end
function table_copy(originalTable)
local copyTable = {}
for k,v in pairs(originalTable) do
if (type(v)=="table") then
copyTable[k]=table_copy(v)
else
copyTable[k] = v
end
end
return copyTable
end
|
Пример:
| Код |
|---|
--Обучающие данные
local TrainingData={}
for i=1, 100, 1 do
local d1=math.random() -- Обучающие данные
local d2=math.random() -- Обучающие данные
local result=0 -- Правильный ответ
if (d1>d2) then
result=1
end
local td={d1, d2, result}
TrainingData[#TrainingData+1]=td
end
--Обучение
local nn=NeuralNetwork.new(2, 3, 3)
for age=1, 100, 1 do -- Эпохи
for i=1, #TrainingData, 1 do
local td=TrainingData[i]
nn:Training(td, td[#td])
end
end
--Проверка
local d1=math.random()
local d2=math.random()
td={d1, d2}
local result=nn:Play(td)
PrintDbgStr(d1.." "..d2.." "..result)
--Сохраним обученную нейронку
fn=getScriptPath().."\\test.nn"
nn:Save(fn)
|