Same, i dont know what causes it
i would just use tostring the table i guess
For whatever reason, the network provided isn’t a string or a StringValue. My guess is that somewhere the entry is replaced with a table version of a network. Its a bit difficult to check the code with the format its in so could you post the entire script in a code bubble?
With all the problems caused by my odd design choices and poor coding practices when I made this abomination of a library, I am really glad that I am working on a new one that will deprecate this one. If you would like to keep your sanity, please, don’t look into the code behind this thing.
I tried using tostring but its not working
sry for the bad scripting format
here’s the script
local module=require(workspace.KNNLibrary) --Activating and getting the library
local nets = module.createGenNet(workspace.Networks,20,9,2,6,5,"LeakyReLU") --Creating a generation of 20 networks with 2 inputs, 2 hidden layers, 2 nodes per hidden layer,
--1 output node, and with ReLU as the activation function
local vis = module.getVisual(nets[1])
vis.Parent = game.StarterGui
local function visualizeRay(ray, name, E)
--Visualize Ray
if game.Workspace:FindFirstChild(name) then
game.Workspace[name]:Destroy()
end
local hitpart, hitposition = workspace:FindPartOnRay(ray)
local p = Instance.new("Part", workspace) -- creating a part to visualize the ray)
p.Name = name
p.Position = hitposition
p.Anchored = true
p.CanCollide = false
p.Size = Vector3.new(1,1,1)
p.Shape = "Ball"
p.BrickColor = BrickColor.new("Really red")
return (p.Position - E.Position).Magnitude -- magnitude from Origin part and the part that visualizes the ray(i could use a better system)
end
function getray(part, food)
--Raycasting for inputs
local forwardray = Ray.new(part.Position, part.CFrame.LookVector * 500)
local backwardray =Ray.new(part.Position, part.CFrame.LookVector * 500*(-1))
local rightray = Ray.new(part.Position, part.CFrame.RightVector * 500)
local leftray = Ray.new(part.Position, (part.CFrame.RightVector * 500)*-1)
local forwardleftray = Ray.new(part.Position, ((part.CFrame.LookVector * 500) -(part.CFrame.RightVector * 500)*-1))
local forwardrightray = Ray.new(part.Position, ((part.CFrame.LookVector * 500) -(part.CFrame.RightVector * 500)*1))
local backwardleftray = Ray.new(part.Position, ((part.CFrame.LookVector * 500*(-1)) -(part.CFrame.RightVector*500)*-1))
local backwardrightray = Ray.new(part.Position, ((part.CFrame.LookVector * 500*(-1)) -(part.CFrame.RightVector*500)*1))
local foodray = Ray.new(part.Position, (food.Position - part.Position).unit)
local f = visualizeRay(forwardray, "forwardray", part)
local r = visualizeRay(rightray, "rightray", part)
local l = visualizeRay(leftray, "leftray", part)
local fl = visualizeRay(forwardleftray, "forwardleftray", part)
local fr = visualizeRay(forwardrightray, "forwardrightray", part)
local bl = visualizeRay(backwardleftray, "backwardleftray", part)
local br = visualizeRay(backwardrightray, "backwardrightray",part)
local b = visualizeRay(backwardray, "backwardray", part)
local fd = visualizeRay(foodray, "foodray", part)
return {f, r, l, fl, fr, bl, br, b, fd} -- table for input
end
for g=1, 1000 do --We will run for 1 million generations, which is basically forever
local i = 0
--print("Generation: "..g) --Print the generation number
local scores = {} --Array storing the scores for every network
local step = 8 --step value used for lowering the resolution of the scoring. Lower step means higher resolution but far slower
local neg = 1
local tim=tick()
for z=1,#nets do --Looping through every network in the generation
local network = module.loadNet(nets[z]) --We load up the StringValue of the network in question
local wins=0
local part = game.ReplicatedStorage.Jaco:Clone()
local food = game.ReplicatedStorage.Food:Clone()
local previousWin = game.ServerScriptService.PreviousGen
part.Parent = workspace
food.Parent = workspace
game.ServerScriptService.StopGeneration.Value = false
game.ServerScriptService.Touching.Value = false
game.ServerScriptService.Food.Value = false
while game.ServerScriptService.StopGeneration.Value ~= true do
local answer=module.forwardNet(network,getray(part, food))
local ra = unpack(answer)
print(g, nets[z])
i = i + 1
if ra >= 0.9 then
part.CFrame = CFrame.new(part.CFrame.X+1, part.CFrame.Y, part.CFrame.Z)
elseif ra > 0.6 and ra < 0.9 then
part.CFrame = CFrame.new(part.CFrame.X, part.CFrame.Y, part.CFrame.Z-1)
elseif ra < 0.6 and ra > 0.4 then
part.CFrame = CFrame.new(part.CFrame.X-1, part.CFrame.Y, part.CFrame.Z)
elseif ra < 0.4 then
part.CFrame = CFrame.new(part.CFrame.X, part.CFrame.Y, part.CFrame.Z+1)
end
if game.ServerScriptService.Food.Value == true then
wins = wins + 1
game.ServerScriptService.Food.Value = false
i=i-50
end
if tick()-tim>=0.1 then --To avoid timeouts, we add a wait() every tenth of a second the script runs. This is to make sure even potato processors will work
tim=tick() --If you want a little more speed over the pretty effects, switch the 0.1 into a 0.5
end
if game.ServerScriptService.StopGeneration.Value == true then
i = 0
break
end
if game.ServerScriptService.Touching.Value == true then
previousWin.Value = g
wins = wins - 1
wait()
i = 0
break
end
if i == 100 then
wait()
wins = wins - 1
i = 0
break
end
game.StarterGui.bruhmoment.Wins.Text = "Wins: "..wins
game.StarterGui.bruhmoment.Moves.Text = "Move Left: ".. 100-i
game.StarterGui.bruhmoment.Answer.Text = ra
game.StarterGui.bruhmoment.TextLabel.Text = "Generation: "..g.." Part: "..z
wait()
table.insert(scores,wins) --With the score calculated, we insert it into the scores array
end
local best = module.runGenNet(nets, scores)
module.updateVisualActive(network,vis, getray(part, food))
part:Destroy()
food:Destroy()
end
--With all of the networks scored, we run the next generation
--For every new generation, we show how the best network looks
--for a split second
table.sort(scores) --Purely for demo purposes, I sort the scores to find the best one
--We calculate the best possible score using our step value and print out the success rate %
print("Best network success rate: "..scores[#scores]/(800/step)^2*(100).."%")
end
btw my things are named VERY badly. i could reformat and make it easier to understand
so the network not being a tostring i went into the module, and the line in the module the error was is 495, and then i did
print(tostring(nets[best[1]]))
and it printed nil, so somewhere i mustve messed it up where it would return nil
SOLVED
Here is a script I had a problem with, but not anymore. its supposed to make a part, “Goobee,” play tag with you; this is basically the finished product for those who want to see it or use it. (If you see something wrong, feel free to tell me!)
-- CONFIGURATIONS --------------------------------------------------------------------------------
local totalGenerations, step, netsPerGen = 10000, 16, 60 --Generation Amount, Generation length, Generation Size
local inputs, layers, nodes, outputs = 3,2,6,3 --Nerual network configurations
local yourName = "qwert347" --Player name for tagging
-- VARIABLES --------------------------------------------------------------------------------
local module=require(workspace.KNNLibrary) --Activating and getting the library
local nets = module.createGenNet(workspace.Networks,netsPerGen, inputs, layers, nodes, outputs,"LeakyReLU")
local vis = module.getVisual(nets[1]); vis.Parent = game.StarterGui
local player = game.Players.PlayerAdded:Wait()
local character = player.CharacterAdded:Wait()
local rootPart = character.HumanoidRootPart
--- CODE -------------------------------------------------------------------------------------
--Generations
for g=1, totalGenerations do
--Setup Gen
print("Generation: "..g)
local scores = {}
local updater = Instance.new("NumberValue",script)
local botFolder = Instance.new("Folder",workspace)
botFolder.Name = "BotFolder"
updater.Name = "Updater"
--Networks
for z=1,#nets do
print("Network: "..z)
--Setup Net
local network = module.loadNet(nets[z])
local bot = game:GetService("ReplicatedStorage").Goobee:Clone()
bot.Parent = botFolder
--Scoring player hits
local wins = 10000
bot.Touched:Connect(function(hit)
if hit.Parent.Name == yourName then wins=wins+100 end
end)
--Updater setup
script.Updater.Changed:Connect(function()
if script.Updater.Value ~= 0 then
--Normal update
local cac = math.tanh(rootPart.CFrame:ToObjectSpace(bot.CFrame).X/50)
local cac2 = math.tanh(rootPart.CFrame:ToObjectSpace(bot.CFrame).Z/50)
local cac3 = bot.Velocity.Magnitude/50
local answer=module.forwardNet(network,{cac,cac2,cac3})
bot.Speed.Force = Vector3.new(0,0,(answer[1]-.5)*10000)
bot.Steering.AngularVelocity = Vector3.new(0,answer[2]-answer[3],0)
else --Final update
wins= wins - math.floor((rootPart.Position-bot.Position).Magnitude + .5) --scoring distance from player
table.insert(scores,wins) -- logging score
end
end)
end
--Updater Running
for d=0,399,step do updater.Value=d; wait(.2) end
--Ending Gen
botFolder:Destroy()
updater.Value = 0
updater:Destroy()
local best = module.runGenNet(nets,scores)
module.updateVisualState(nets[best],vis)
print("Best network success: " ,module.hardCode(nets[best]))
end
My tiny brain cannot comprehend yet .
Could it be because the reward being below 0? I have experienced this couple of times too but due to how KNN calculates stuff based of scores, it always have to be above 0. try clamping the wins, or perhaps lower the rate of giving punishments
i fixed the that not popping up, but now it just has nil for this
local min,max = scores[best[#best]],scores[best[1]]
local range = max-min
I know why the nets[best[1]] is nil
because nets is the GenNet Folder and it has 1 array only
if the value is higher than 1 then it will return to nil
i tried print(nets[1])
and it returns “GenNet_1”
…this is exactly why I am retiring this module. I made it before I discovered dictionaries and my use of arrays here is absolutely disgusting. The user shouldn’t have to guess what they are getting when they put a bunch of numbers into a 4 dimensional array.
Quick update on the new library! I’ve finally gotten past the main roadblock of the development (LSTM backpropagation) and am speeding through the remaining portions of the library’s features.
Currently, this is what the package structure looks like:
Yes, genetic learning is next on the list.
I’ll soon post a thread where I want any NN enthusiasts to post any features they would like to see in the module as I do not want anyone to be left out. I will link the thread here when I make it.
EDIT: I posted the thread here.
Stay safe out there.
I’m hype for the new library so I can continue my project
I’m also hyped as I’m excited about this module.
Ik You’re Working on a new module, But I have found out how to make a successful NN without it error’ing. I’ll send the place file. It works like Jabrils NN where the Ai controls a character that’s moving forward based on its direction. (I was gonna use coroutine but I don’t know a way to kill them) I also could’ve used better code. nn.rbxl (45.9 KB)
Wow this is amazing! definitely will be useful, thank you for this resource!
Forgot to write here that the second library was released a few days ago. Doesn’t seem like people are nearly as interested anymore but if you want to check it out, go ahead.