Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Matrix = {}
- function random(min, max)
- min = min or 0
- max = max or 1
- return min + math.random() * (max - min)
- end
- local matrixmeta = {
- __add = function(self, M2)
- local NewMatrix = Matrix.new(self.rows, self.cols, self.comment..M2.comment)
- for x = 1, NewMatrix.rows do
- for y = 1, NewMatrix.cols do
- NewMatrix.Matrix[x][y] = self.Matrix[x][y] + M2.Matrix[x][y]
- end
- end
- return NewMatrix
- end;
- __sub = function(self, M2)
- local NewMatrix = Matrix.new(self.rows, self.cols, self.comment..M2.comment)
- for x = 1, NewMatrix.rows do
- for y = 1, NewMatrix.cols do
- NewMatrix.Matrix[x][y] = self.Matrix[x][y] - M2.Matrix[x][y]
- end
- end
- return NewMatrix
- end;
- __div = function(self, M2)
- local NewMatrix = Matrix.new(self.rows, self.cols, self.comment..M2.comment)
- for x = 1, NewMatrix.rows do
- for y = 1, NewMatrix.cols do
- NewMatrix.Matrix[x][y] = self.Matrix[x][y] / M2.Matrix[x][y]
- end
- end
- return NewMatrix
- end;
- __mul = function(self, M2)
- if type(M2) == "number" and type(self) == "table" then
- local newMatrix = Matrix.new(self.rows, self.cols, self.comment)
- for x = 1, newMatrix.rows do
- for y = 1, newMatrix.cols do
- newMatrix.Matrix[x][y] = self.Matrix[x][y] * M2
- end
- end
- return newMatrix
- elseif type(self) == "number" and type(M2) == "table" then
- local newMatrix = Matrix.new(M2.rows, M2.cols, M2.comment)
- for x = 1, newMatrix.rows do
- for y = 1, newMatrix.cols do
- newMatrix.Matrix[x][y] = M2.Matrix[x][y] * self
- end
- end
- return newMatrix
- end
- if type(self) == "table" and type(M2) == "table" then
- local newMatrix = Matrix.new(self.rows, M2.cols, self.comment..M2.comment)
- for x = 1, newMatrix.rows do
- for y = 1, newMatrix.cols do
- local sum = 0
- for z = 1, self.cols do
- sum = sum + self.Matrix[x][z] * M2.Matrix[z][y]
- end
- newMatrix.Matrix[x][y] = sum
- end
- end
- return newMatrix
- end
- end;
- }
- function Matrix.new(rows, cols, comment)
- -- Creates a new Matrix with x rows and y coloums
- local Table = {}
- Table.rows = rows
- Table.cols = cols
- Table.comment = comment or ""
- Table.Matrix = {}
- for x = 1, rows do
- Table.Matrix[x] = {}
- for y = 1, cols do
- Table.Matrix[x][y] = 0
- end
- end
- Table.set = function(p)
- if p["Matrix"] ~= nil then
- Table.Matrix = p.Matrix
- else
- Table.Matrix = p
- end
- end
- setmetatable(Table, matrixmeta)
- return Table
- end
- function Matrix:randomizeMatrix(M, min, max)
- for x = 1, M.rows do
- for y = 1, M.cols do
- M.Matrix[x][y] = random(min, max)
- end
- end
- end
- function Matrix:toMatrix(array, i, comment)
- local isMATRIX
- for i, v in pairs(array) do
- if i == "Matrix" then
- isMATRIX = true
- end
- end
- if isMATRIX then return array end
- if i then
- arrayToMatrix = Matrix.new(1, #array, comment)
- for y = 1, #array do
- arrayToMatrix.Matrix[1][y] = array[y]
- end
- else
- arrayToMatrix = Matrix.new(#array, 1, comment)
- for x = 1, #array do
- arrayToMatrix.Matrix[x][1] = array[x]
- end
- end
- return arrayToMatrix
- end
- function Matrix:toArray(M)
- local array = {}
- for x = 1, M.rows do
- for y = 1, M.cols do
- array[#array + 1] = M.Matrix[x][y]
- end
- end
- return array
- end
- function Matrix:transposeMatrix(M)
- local newMatrix = Matrix.new(M.cols, M.rows, M.comment)
- for x = 1, M.rows do
- for y = 1, M.cols do
- newMatrix.Matrix[y][x] = M.Matrix[x][y]
- end
- end
- return newMatrix
- end
- function Matrix:multMatrices(M1, M2)
- local newMatrix = Matrix.new(M1.rows, M1.cols, M1.comment)
- for x = 1, newMatrix.rows do
- for y = 1, newMatrix.cols do
- newMatrix.Matrix[x][y] = M1.Matrix[x][y] * M2.Matrix[x][y]
- end
- end
- return newMatrix
- end
- function Matrix:mapMatrix(M, functio, s)
- local newMatrix = Matrix.new(M.rows, M.cols, M.comment)
- for x = 1, newMatrix.rows do
- for y = 1, newMatrix.cols do
- newMatrix.Matrix[x][y] = functio(M.Matrix[x][y], s)
- end
- end
- return newMatrix
- end
- local module = {}
- function he(_,h)
- return random(h[1], h[2])*math.sqrt(2/h[3])
- end
- local ActivationFuncs = {}
- ActivationFuncs.Sigmoid = function(x, d)
- if d then
- return x*(1-x)
- end
- return 1/(1+math.exp(-x))
- end
- ActivationFuncs.Tanh = function(x, d)
- if d then
- return 1/math.cosh(x)^2
- end
- return math.tanh(x)
- end
- ActivationFuncs.Identity = function(x, d)
- if d then
- return 1
- end
- return x
- end
- ActivationFuncs.ArcTanh = function(x, d)
- if d then
- return 1/(x^2+1)
- end
- return math.atan(x)
- end
- ActivationFuncs.Sign = function(x, d)
- if d then
- return 0
- end
- return math.sign(x)
- end
- ActivationFuncs.LeakyReLU = function(x, d)
- if d then
- if x >= 0 then
- return 1
- end
- return 0.1
- end
- return math.max(0.1*x, x)
- end
- ActivationFuncs.Sin = function(x, d)
- if d then
- return math.cos(x)
- end
- return math.sin(x)
- end
- ActivationFuncs.V = function(x, d)
- if d then
- return math.abs(x)/x
- end
- return math.abs(x)
- end
- function module:MAp(tabl, functio, d)
- for i, v in pairs(tabl) do
- if type(v) == "table" then
- module:MAp(tabl[i], functio)
- elseif type(v) == "number" then
- tabl[i] = functio(tabl[i], d)
- end
- end
- end
- function module:CopyTable(s)
- local f = {}
- for i, v in pairs(s) do
- if type(v) == "table" then
- f[i] = module:CopyTable(v)
- else
- f[i] = v
- end
- end
- return f
- end
- function module:LayerM(net, input, layer, f, d, s)
- local minput = Matrix:toMatrix(input)
- if f then
- local n = net.__Weights[layer] * minput
- local nplusb = n + net.__Bias[layer]
- local nplusb_a = Matrix:mapMatrix(nplusb, ActivationFuncs[net.__AF[layer]], d)
- return nplusb_a
- else
- if s then
- return Matrix:transposeMatrix(net.__Weights[layer-1]) * minput
- end
- local n = Matrix:transposeMatrix(net.__Weights[layer-1]) * minput
- local nplusb = n + net.__Bias[layer-1]
- local nplusb_a = Matrix:mapMatrix(nplusb, ActivationFuncs[(net.__AF[layer-2] or "Identity")], d)
- return nplusb_a
- end
- end
- function module:CreateNN(NumberInputs, NumberHidden, NumberHLayers, NumberOutputs, LearningRate, ActivationFunction)
- local NewNN = {}
- NewNN.__NumberInputs = NumberInputs
- NewNN.__NumberHidden = NumberHidden
- NewNN.__NumberHLayers = NumberHLayers
- NewNN.__NumberOut = NumberOutputs
- NewNN.__LR = LearningRate
- NewNN.__AF = {}
- NewNN.__Weights = {}
- NewNN.__Layers = {}
- NewNN.__Bias = {}
- NewNN.__Hidden = {}
- if type(ActivationFunction) == "string" then
- for i = 1, NumberHLayers+1, 1 do
- NewNN.__AF[i] = ActivationFunction
- end
- elseif type(ActivationFunction) == "table" then
- for i = 1, NumberHLayers+1, 1 do
- NewNN.__AF[i] = ActivationFunction[i]
- end
- end
- NewNN.__Layers[1] = NumberInputs
- for layer = 1,NumberHLayers,1 do
- NewNN.__Bias[layer] = Matrix.new(NumberHidden, 1)
- NewNN.__Layers[#NewNN.__Layers+1] = NumberHidden
- end
- NewNN.__Bias[NumberHLayers+1] = Matrix.new(NumberOutputs, 1)
- NewNN.__Layers[#NewNN.__Layers+1] = NumberOutputs
- local iw = Matrix.new(NumberHidden, NumberInputs)
- iw = Matrix:mapMatrix(iw, he, {-1, 1, NumberHidden})
- NewNN.__Weights[1] = iw
- for i=1,NumberHLayers-1 do
- local hw = Matrix.new(NumberHidden, NumberHidden)
- hw = Matrix:mapMatrix(hw, he, {-1, 1, NumberHidden})
- NewNN.__Weights[#NewNN.__Weights+1] = hw
- end
- local ow = Matrix.new(NumberOutputs, NumberHidden)
- ow = Matrix:mapMatrix(ow, he, {-1, 1, NumberOutputs})
- NewNN.__Weights[#NewNN.__Weights+1] = ow
- function NewNN:Forward(Inputs, giveotherstuff, d)
- local output = {}
- local otherstuff = {}
- otherstuff[1] = Inputs
- local oh = module:LayerM(self, Inputs, 1, true)
- if giveotherstuff then
- otherstuff[#otherstuff+1] = Matrix:toArray(oh)
- end
- local inpu = oh
- for l = 1,self.__NumberHLayers,1 do
- inpu = module:LayerM(self, inpu, l+1, true)
- if giveotherstuff then
- otherstuff[#otherstuff+1] = Matrix:toArray(inpu)
- end
- end
- output = inpu
- if giveotherstuff then
- return Matrix:toArray(output), otherstuff
- end
- return Matrix:toArray(output)
- end
- function NewNN:BackProp(Inputs, Targets)
- local mTargets = Matrix:toMatrix(Targets)
- local Output, stuff = self:Forward(Inputs, true)
- local mOutput = Matrix:toMatrix(Output)
- local l_error = mTargets - mOutput
- for layer = self.__NumberHLayers+2, 2, -1 do
- local vinlayer = Matrix:toMatrix(stuff[layer])
- local lvinlayer = Matrix:toMatrix(stuff[layer-1])
- local t_lvinlayer = Matrix:transposeMatrix(lvinlayer)
- local g = Matrix:mapMatrix(vinlayer, ActivationFuncs[self.__AF[layer-1]], true)
- g = Matrix:multMatrices(g, l_error)
- g = g * self.__LR
- self.__Weights[layer-1] = self.__Weights[layer-1] + g * t_lvinlayer
- self.__Bias[layer-1] = self.__Bias[layer-1] + g
- l_error = module:LayerM(self, l_error, layer, false, false, true)
- end
- end
- function NewNN:CopyNet()
- return module:CreateNN(self.__NumberInputs, self.__NumberHidden, self.__NumberHLayers, self.__NumberOut, self.__LR, self.__AF)
- end
- function NewNN:CopyNet2()
- local copied = module:CopyTable(self)
- --local copied = module:CreateNN(self.__NumberInputs, self.__NumberHidden, self.__NumberHLayers, self.__NumberOut, self.__LR, self.__AF)
- --copied.__Weights = module:CopyTable(self.__Weights)
- --copied.__Bias = module:CopyTable(self.__Bias)
- --copied.__Layers = module:CopyTable(self.__Layers)
- --copied.__Hidden = module:CopyTable(self.__Hidden)
- return copied
- end
- function NewNN:Randomize()
- for i = 1,#self.__Weights do
- for ii = 1,#self.__Weights[i].Matrix do
- for iii = 1,#self.__Weights[i].Matrix[ii] do
- self.__Weights[i].Matrix[ii][iii] = random(-1, 1)
- end
- end
- end
- for i = 1,#self.__Bias do
- for ii = 1,#self.__Bias[i].Matrix do
- for iii = 1,#self.__Bias[i].Matrix[ii] do
- local c_biasr = self.__Bias[i].Matrix[ii]
- local rando = random(-1,1)
- c_biasr[iii] = rando
- end
- end
- end
- end
- function NewNN:Mutate(c, chance, rate)
- chance = chance or 50
- for i = 1,#self.__Weights do
- for ii = 1,#self.__Weights[i].Matrix do
- for iii = 1,#self.__Weights[i].Matrix[ii] do
- local c_weightr = self.__Weights[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_weightr[iii] += rando
- end
- else
- c_weightr[iii] += rando
- end
- end
- end
- end
- for i = 1,#self.__Bias do
- for ii = 1,#self.__Bias[i].Matrix do
- for iii = 1,#self.__Bias[i].Matrix[ii] do
- local c_biasr = self.__Bias[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_biasr[iii] += rando
- end
- else
- c_biasr[iii] += rando
- end
- end
- end
- end
- end
- return NewNN
- end
- function module:CopyNet(net)
- local cnet = {}
- for i, v in pairs(net) do
- cnet[i] = v
- end
- return cnet
- end
- function module:CreateGA(t, b)
- local ga = {}
- for i = 1, b, 1 do
- ga[i] = module:CopyNet(t):RandomizeWeights()
- end
- return ga
- end
- local GA = {}
- function GA:CopyTable(t)
- local f = {}
- for i, v in pairs(t) do
- f[i]=v
- end
- return f
- end
- function random(min, max)
- min = min or 0
- max = max or 1
- return (max - min)*math.random() + min
- end
- function GA:MutateNet(net, c, chance, rate)
- chance = chance or 50
- for i = 1,#net.__Weights do
- for ii = 1,#net.__Weights[i].Matrix do
- for iii = 1,#net.__Weights[i].Matrix[ii] do
- local c_weightr = net.__Weights[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_weightr[iii] += rando
- end
- else
- c_weightr[iii] += rando
- end
- end
- end
- end
- for i = 1,#net.__Bias do
- for ii = 1,#net.__Bias[i].Matrix do
- for iii = 1,#net.__Bias[i].Matrix[ii] do
- local c_biasr = net.__Bias[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_biasr[iii] += rando
- end
- else
- c_biasr[iii] += rando
- end
- end
- end
- end
- end
- function GA:MutateNet2(snet, c, chance, rate)
- chance = chance or 50
- local net = snet:CopyNet2()
- for i = 1,#net.__Weights do
- for ii = 1,#net.__Weights[i].Matrix do
- for iii = 1,#net.__Weights[i].Matrix[ii] do
- local c_weightr = net.__Weights[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_weightr[iii] += rando
- end
- else
- c_weightr[iii] += rando
- end
- end
- end
- end
- for i = 1,#net.__Bias do
- for ii = 1,#net.__Bias[i].Matrix do
- for iii = 1,#net.__Bias[i].Matrix[ii] do
- local c_biasr = net.__Bias[i].Matrix[ii]
- local rando = random(-rate,rate)
- if c then
- if rando > (chance/100-.5) then
- c_biasr[iii] += rando
- end
- else
- c_biasr[iii] += rando
- end
- end
- end
- end
- return net
- end
- function GA:CrossNets(net1, net2, m, rate)
- local child = net1:CopyNet()
- for i, v in pairs(net1.__Weights) do
- for ii, vv in pairs(v) do
- local p1w = net1.__Weights[i][ii]
- local p2w = net2.__Weights[i][ii]
- if m then
- local rando = random(-1, 1)*(rate or 1)
- child.__Weights[i][ii] = ((p1w + p2w)/2) + rando
- else
- child.__Weights[i][ii] = (p1w + p2w)/2
- end
- end
- end
- for i, v in pairs(net1.__Bias) do
- for ii, vv in pairs(v) do
- local p1w = net1.__Bias[i][ii]
- local p2w = net2.__Bias[i][ii]
- if m then
- local rando = random(-1, 1)*(rate or 1)
- child.__Bias[i][ii] = ((p1w + p2w)/2) + rando
- else
- child.__Bias[i][ii] = (p1w + p2w)/2
- end
- end
- end
- return child
- end
- function GA:CreateGA(n, q)
- local ns = {}
- ns.ns = {}
- ns.q = q
- function ns:RunGA(scores, mt)
- local mut = {}
- local bnet = self.ns[table.find(scores,math.max(table.unpack(scores)))]
- for i = 1,self.q do
- ns.ns[i] = bnet:CopyNet2()
- ns.ns[i]:Mutate(false, 0, mt)
- end
- end
- for i = 1,q do
- table.insert(ns.ns, n:CopyNet())
- end
- return ns
- end
- function random(min, max)
- min = min or 0
- max = max or 1
- return min + math.random() * (max-min)
- end
- return module, Matrix, GA
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement