4
0

neural_network #25

Merged
s481834 merged 12 commits from neural_network into refactor 2024-06-04 13:23:20 +02:00
14 changed files with 212 additions and 10 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
__pycache__/ __pycache__/
.idea/ .idea/
tree.png tree.png
dataset/
dataset.zip

23
App.py
View File

@ -9,6 +9,7 @@ import Osprzet
import Ui import Ui
import BFS import BFS
import AStar import AStar
import neuralnetwork
bfs1_flag=False bfs1_flag=False
@ -18,7 +19,9 @@ Astar = False
Astar2 = False Astar2 = False
if bfs3_flag or Astar or Astar2: if bfs3_flag or Astar or Astar2:
Pole.stoneFlag = True Pole.stoneFlag = True
TreeFlag=True TreeFlag=False
nnFlag=True
newModel=False
pygame.init() pygame.init()
show_console=True show_console=True
@ -29,7 +32,7 @@ image_loader=Image.Image()
image_loader.load_images() image_loader.load_images()
goalTreasure = AStar.getRandomGoalTreasure() # nie wiem czy to najlepsze miejsce, obecnie pole zawiera pole gasStation, które służy do renderowania odpowiedniego zdjęcia goalTreasure = AStar.getRandomGoalTreasure() # nie wiem czy to najlepsze miejsce, obecnie pole zawiera pole gasStation, które służy do renderowania odpowiedniego zdjęcia
pole=Pole.Pole(screen,image_loader, goalTreasure) pole=Pole.Pole(screen,image_loader, goalTreasure)
pole.draw_grid() #musi byc tutaj wywołane ponieważ inicjalizuje sloty do slownika pole.draw_grid(nnFlag) #musi byc tutaj wywołane ponieważ inicjalizuje sloty do slownika
ui=Ui.Ui(screen) ui=Ui.Ui(screen)
#Tractor creation #Tractor creation
traktor_slot = pole.get_slot_from_cord((0, 0)) traktor_slot = pole.get_slot_from_cord((0, 0))
@ -40,7 +43,7 @@ def init_demo(): #Demo purpose
old_info="" old_info=""
traktor.draw_tractor() traktor.draw_tractor()
time.sleep(2) time.sleep(2)
pole.randomize_colors() pole.randomize_colors(nnFlag)
traktor.draw_tractor() traktor.draw_tractor()
start_flag=True start_flag=True
while True: while True:
@ -116,6 +119,20 @@ def init_demo(): #Demo purpose
if(TreeFlag): if(TreeFlag):
traktor.move_forward(pole) traktor.move_forward(pole)
traktor.tree_move(pole) traktor.tree_move(pole)
if(nnFlag):
global model
if (newModel):
print_to_console("uczenie sieci neuronowej")
model = neuralnetwork.trainNewModel()
neuralnetwork.saveModel(model, 'model.pth')
print_to_console("sieć nuronowa nauczona")
print('model został wygenerowany')
else:
model = neuralnetwork.loadModel('model.pth')
print_to_console("model został załądowny")
testset = neuralnetwork.getDataset(False)
print(neuralnetwork.accuracy(model, testset))
traktor.snake_move_predict_plant(pole, model)
start_flag=False start_flag=False
# demo_move() # demo_move()
old_info=get_info(old_info) old_info=get_info(old_info)

View File

@ -1,6 +1,8 @@
import pygame import pygame
import displayControler as dCon import displayControler as dCon
import random import random
import neuralnetwork
import os
class Image: class Image:
def __init__(self): def __init__(self):
@ -53,3 +55,28 @@ class Image:
def return_gasStation(self): def return_gasStation(self):
return self.gasStation_image return self.gasStation_image
# losowanie zdjęcia z testowego datasetu bez powtórzeń
imagePathList = []
def getRandomImageFromDataBase():
label = random.choice(neuralnetwork.labels)
folderPath = f"dataset/test/{label}"
files = os.listdir(folderPath)
random_image = random.choice(files)
imgPath = os.path.join(folderPath, random_image)
while imgPath in imagePathList:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
label = random.choice(neuralnetwork.labels)
folderPath = f"dataset/test/{label}"
files = os.listdir(folderPath)
random_image = random.choice(files)
imgPath = os.path.join(folderPath, random_image)
imagePathList.append(imgPath)
image = pygame.image.load(imgPath)
image=pygame.transform.scale(image,(dCon.CUBE_SIZE,dCon.CUBE_SIZE))
return image, label, imgPath

View File

@ -6,6 +6,8 @@ import time
import Ui import Ui
import math import math
import random import random
import neuralnetwork
import Image
stoneList = [(3,3), (3,4), (3,5), (3,6), (4,6), (5,6), (6,6), (7,6), (8,6), (9,6), (10,6), (11,6), (12,6), (13,6), (14,6), (15,6), (16,6), (16,7), (16,8), (16,9)] stoneList = [(3,3), (3,4), (3,5), (3,6), (4,6), (5,6), (6,6), (7,6), (8,6), (9,6), (10,6), (11,6), (12,6), (13,6), (14,6), (15,6), (16,6), (16,7), (16,8), (16,9)]
stoneFlag = False stoneFlag = False
@ -30,7 +32,7 @@ class Pole:
return self.slot_dict return self.slot_dict
#Draw grid and tractor (new one) #Draw grid and tractor (new one)
def draw_grid(self): def draw_grid(self, nn=False):
for x in range(0,dCon.NUM_X): #Draw all cubes in X axis for x in range(0,dCon.NUM_X): #Draw all cubes in X axis
for y in range(0,dCon.NUM_Y): #Draw all cubes in Y axis for y in range(0,dCon.NUM_Y): #Draw all cubes in Y axis
new_slot=Slot.Slot(x,y,Colors.BROWN,self.screen,self.image_loader) #Creation of empty slot new_slot=Slot.Slot(x,y,Colors.BROWN,self.screen,self.image_loader) #Creation of empty slot
@ -48,7 +50,7 @@ class Pole:
st=self.slot_dict[self.gasStation] st=self.slot_dict[self.gasStation]
st.set_gasStation_image() st.set_gasStation_image()
def randomize_colors(self): def randomize_colors(self, nn = False):
pygame.display.update() pygame.display.update()
time.sleep(3) time.sleep(3)
#self.ui.render_text("Randomizing Crops") #self.ui.render_text("Randomizing Crops")
@ -59,7 +61,7 @@ class Pole:
if(coordinates==(0,0)): if(coordinates==(0,0)):
continue continue
else: else:
self.slot_dict[coordinates].set_random_plant() self.slot_dict[coordinates].set_random_plant(nn)
def change_color_of_slot(self,coordinates,color): #Coordinates must be tuple (x,y) (left top slot has cord (0,0) ), color has to be from defined in Colors.py or custom in RGB value (R,G,B) def change_color_of_slot(self,coordinates,color): #Coordinates must be tuple (x,y) (left top slot has cord (0,0) ), color has to be from defined in Colors.py or custom in RGB value (R,G,B)
self.get_slot_from_cord(coordinates).color_change(color) self.get_slot_from_cord(coordinates).color_change(color)

11
Slot.py
View File

@ -16,6 +16,8 @@ class Slot:
self.field=pygame.Rect(self.x_axis*dCon.CUBE_SIZE,self.y_axis*dCon.CUBE_SIZE,dCon.CUBE_SIZE,dCon.CUBE_SIZE) self.field=pygame.Rect(self.x_axis*dCon.CUBE_SIZE,self.y_axis*dCon.CUBE_SIZE,dCon.CUBE_SIZE,dCon.CUBE_SIZE)
self.image_loader=image_loader self.image_loader=image_loader
self.garage_image=None self.garage_image=None
self.label = None
self.imagePath = None
def draw(self): def draw(self):
pygame.draw.rect(self.screen,Colors.BROWN,self.field,0) #Draw field pygame.draw.rect(self.screen,Colors.BROWN,self.field,0) #Draw field
@ -38,9 +40,14 @@ class Slot:
self.plant=color self.plant=color
self.draw() self.draw()
def set_random_plant(self): def set_random_plant(self, nn=False):
if not nn:
(plant_name,self.plant_image)=self.random_plant() (plant_name,self.plant_image)=self.random_plant()
self.plant=Roslina.Roslina(plant_name) self.plant=Roslina.Roslina(plant_name)
else:
self.plant_image, self.label, self.imagePath = self.random_plant_dataset()
# print(self.plant_image)
self.plant=Roslina.Roslina(self.label)
self.set_image() self.set_image()
def set_image(self): def set_image(self):
@ -66,6 +73,8 @@ class Slot:
def random_plant(self): #Probably will not be used later only for demo purpouse def random_plant(self): #Probably will not be used later only for demo purpouse
return self.image_loader.return_random_plant() return self.image_loader.return_random_plant()
def random_plant_dataset(self):
return Image.getRandomImageFromDataBase()
def return_plant(self): def return_plant(self):
return self.plant return self.plant

View File

@ -9,11 +9,13 @@ import Osprzet
import Node import Node
import Condition import Condition
import Drzewo import Drzewo
import neuralnetwork as nn
condition=Condition.Condition() condition=Condition.Condition()
drzewo=Drzewo.Drzewo() drzewo=Drzewo.Drzewo()
format_string = "{:<25}{:<25}{:<25}{:<10}{:<10}{:<10}{:<25}{:<15}{:<20}{:<10}{:<15}" format_string = "{:<25}{:<25}{:<25}{:<10}{:<10}{:<10}{:<25}{:<15}{:<20}{:<10}{:<15}"
format_string_nn="{:<10}{:<20}{:<20}{:<15}{:<20}"
tab = [-1, 0, 0, 0, 0, 1, 1, 1, 1, 1, tab = [-1, 0, 0, 0, 0, 1, 1, 1, 1, 1,
@ -191,6 +193,35 @@ class Tractor:
self.turn_left() self.turn_left()
print("podlanych slotów: ", str(counter)) print("podlanych slotów: ", str(counter))
def snake_move_predict_plant(self, pole, model):
headers=['Coords','Real plant','Predicted plant','Result','Fertilizer']
print(format_string_nn.format(*headers))
initPos = (self.slot.x_axis, self.slot.y_axis)
count = 0
for i in range(initPos[1], dCon.NUM_Y):
for j in range(initPos[0], dCon.NUM_X):
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if self.slot.imagePath != None:
predictedLabel = nn.predictLabel(self.slot.imagePath, model)
#print(str("Coords: ({:02d}, {:02d})").format(self.slot.x_axis, self.slot.y_axis), "real:", self.slot.label, "predicted:", predictedLabel, "correct" if (self.slot.label == predictedLabel) else "incorrect", 'nawożę za pomocą:', nn.fertilizer[predictedLabel])
print(format_string_nn.format(f"{self.slot.x_axis,self.slot.y_axis}",self.slot.label,predictedLabel,"correct" if (self.slot.label == predictedLabel) else "incorrect",nn.fertilizer[predictedLabel]))
if self.slot.label != predictedLabel:
self.slot.mark_visited()
count += 1
self.move_forward(pole, False)
if i % 2 == 0 and i != dCon.NUM_Y - 1:
self.turn_right()
self.move_forward(pole, False)
self.turn_right()
elif i != dCon.NUM_Y - 1:
self.turn_left()
self.move_forward(pole, False)
self.turn_left()
print(f"Dobrze nawiezionych roślin: {20*12-count}, źle nawiezionych roślin: {count}")
def snake_move(self,pole,x,y): def snake_move(self,pole,x,y):
next_slot_coordinates=(x,y) next_slot_coordinates=(x,y)
if(self.do_move_if_valid(pole,next_slot_coordinates)): if(self.do_move_if_valid(pole,next_slot_coordinates)):

BIN
model_2_crops.pth Normal file

Binary file not shown.

BIN
model_500_hidden.pth Normal file

Binary file not shown.

114
neuralnetwork.py Normal file
View File

@ -0,0 +1,114 @@
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import Compose, Lambda, ToTensor
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from PIL import Image
import random
imageSize = (128, 128)
labels = ['carrot','corn', 'potato', 'tomato'] # musi być w kolejności alfabetycznej
fertilizer = {labels[0]: 'kompost', labels[1]: 'saletra amonowa', labels[2]: 'superfosfat', labels[3]:'obornik kurzy'}
#labels = ['corn','tomato'] #uncomment this two lines for 2 crops only
#fertilizer = {labels[0]: 'kompost', labels[1]: 'saletra amonowa'}
torch.manual_seed(42)
#device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device = torch.device("cpu")
# device = torch.device("mps") if torch.backends.mps.is_available() else torch.device('cpu')
# print(device)
def getTransformation():
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
transforms.Resize(imageSize),
Lambda(lambda x: x.flatten())])
return transform
def getDataset(train=True):
transform = getTransformation()
if (train):
trainset = datasets.ImageFolder(root='dataset/train', transform=transform)
return trainset
else:
testset = datasets.ImageFolder(root='dataset/test', transform=transform)
return testset
def train(model, dataset, n_iter=100, batch_size=256):
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
criterion = nn.NLLLoss()
dl = DataLoader(dataset, batch_size=batch_size)
model.train()
for epoch in range(n_iter):
for images, targets in dl:
optimizer.zero_grad()
out = model(images.to(device))
loss = criterion(out, targets.to(device))
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print('epoch: %3d loss: %.4f' % (epoch, loss))
return model
def accuracy(model, dataset):
model.eval()
correct = sum([(model(images.to(device)).argmax(dim=1) == targets.to(device)).sum()
for images, targets in DataLoader(dataset, batch_size=256)])
return correct.float() / len(dataset)
def getModel():
hidden_size = 500
model = nn.Sequential(
nn.Linear(imageSize[0] * imageSize[1] * 3, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, len(labels)),
nn.LogSoftmax(dim=-1)
).to(device)
return model
def saveModel(model, path):
print("Saving model")
torch.save(model.state_dict(), path)
def loadModel(path):
print("Loading model")
model = getModel()
model.load_state_dict(torch.load(path))
return model
def trainNewModel(n_iter=100, batch_size=256):
trainset = getDataset(True)
model = getModel()
model = train(model, trainset)
return model
def predictLabel(imagePath, model):
image = Image.open(imagePath).convert("RGB")
image = preprocess_image(image)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
with torch.no_grad():
model.eval() # Ustawienie modelu w tryb ewaluacji
output = model(image)
# Znalezienie indeksu klasy o największej wartości prawdopodobieństwa
predicted_class = torch.argmax(output).item()
return labels[predicted_class]
# Znalezienie indeksu klasy o największej wartości prawdopodobieństwa
predicted_class = torch.argmax(output).item()
return labels[predicted_class]
def preprocess_image(image):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
transform = getTransformation()
image = transform(image).unsqueeze(0) # Add batch dimension
image = image.to(device) # Move the image tensor to the same device as the model
return image

Binary file not shown.

Binary file not shown.

BIN
testModels/modelMPS.pth Normal file

Binary file not shown.

BIN
testModels/modelMPS650.pth Normal file

Binary file not shown.

BIN
testModels/modelMPS_AL.pth Normal file

Binary file not shown.