Neural Network Library (Obsolete)

Same, i dont know what causes it

1 Like

i would just use tostring the table i guess

1 Like

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
2 Likes

My tiny brain cannot comprehend yet :flushed:.

1 Like

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

1 Like

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.

5 Likes

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.

4 Likes

I’m hype for the new library so I can continue my project

4 Likes

I’m also hyped as I’m excited about this module.

2 Likes

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)

2 Likes

Wow this is amazing! definitely will be useful, thank you for this resource!

1 Like

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.

5 Likes