Projekt Dawid

This commit is contained in:
Dawid 2020-05-20 09:45:59 +02:00
parent bde9e1d776
commit 8c8843df7e
5 changed files with 164 additions and 24 deletions

View File

@ -4,6 +4,7 @@ import numpy as np
from models.__house__ import House
from models.__trash__ import Trash
from config import MAP_HEIGHT, MAP_WIDTH, MAP
from dawid import predict_houses
class AStar:
@ -73,6 +74,45 @@ class AStar:
return route
def best_move_mlp(self):
houses, trashes = self.houses_with_trash()
score = []
for t_type in self.TRASH_TYPES:
if getattr(self.__gc__, t_type) == self.__gc__.limit or len(houses) == 0:
for trash in trashes:
if trash.trash_type == t_type and getattr(self.__gc__, t_type) != 0:
return (trash.col, trash.row)
for house in houses:
house_trash_ammount = 0
for trash in self.TRASH_TYPES:
house_trash_ammount += getattr(house, trash)
distance = fabs(self.__gc__.col - house.col) + \
fabs(self.__gc__.row - house.row)
if house.size > 1:
score.append({"score": house_trash_ammount * 100 / distance,
"position": (house.col, house.row)})
else:
score.append({"score": (house_trash_ammount / distance) * 0.01 ,
"position": (house.col, house.row)})
return sorted(score, key=lambda i: i['score'], reverse=True)[0]["position"]
def get_to_dest_mlp(self):
road_pos_array = np.zeros((MAP_HEIGHT, MAP_WIDTH))
for __x__, __y__ in self.__draw_items__:
if MAP[__y__][__x__] == "Road":
road_pos_array[__y__, __x__] = 1
start = (self.__gc__.col, self.__gc__.row)
route = astar(array=road_pos_array, start=start,
goal=self.best_move_mlp())
return route
def astar(array, start, goal):
def heuristic(__a__, __b__):
return fabs((__b__[0] - __a__[0])) + fabs((__b__[1] - __a__[1]))

View File

@ -1,7 +1,6 @@
import random
import joblib
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from models.__house__ import House
@ -54,7 +53,6 @@ def main():
#usunięcie wartości "size", aby móc je przewidzieć
labels = [x[4] for x in data]
for x in range(len(data)):
del data[x][4]
@ -73,13 +71,14 @@ def main():
#stworzenie raportu pokazującego m.in. precyzje dla poszczególnych "size'ów"
#print(classification_report(y_test, pred))
#Macierz konfuzji w postacji wykresu gradientowego (użyta w raporcie)
#plot_confusion_matrix(mlp, X_test, y_test)
#gi tstplt.show()
#plt.show()
# przekazanie wygenerowanego modelu do pliku
@ -88,22 +87,49 @@ def main():
## Funkcja
##def predict_houses(houses_data):
# mlp = MLPClassifier()
# mlp.fit(X_train, y_train)
#red = mlp.predict(houses_data)
#return pred
def predict_houses(houses_data):
data = []
for size in range(4):
for x in range(40000):
if size == 0:
budget = random.randint(300, 450)
population = random.randint(2, 4)
income = random.randint(2000, 3000)
children = random.randint(0, 2)
elif size == 1:
budget = random.randint(400, 600)
population = random.randint(3, 5)
income = random.randint(3000, 5000)
children = random.randint(0, 3)
elif size == 2:
budget = random.randint(550, 800)
population = random.randint(4, 6)
income = random.randint(4500, 7000)
children = random.randint(0, 4)
else:
budget = random.randint(700, 1000)
population = random.randint(4, 7)
income = random.randint(6800, 11000)
children = random.randint(1, 4)
# wywolanie funkcji, wrzucam liste obiektow klasy House
data.append([
budget,
population,
income,
children,
size
])
labels = [x[4] for x in data]
for x in range(len(data)):
del data[x][4]
#house = House(1, 3)
#house.data = [1000, 4, 10000, 2]
#house_2 = House(1, 3)
#house_2.data = [1000, 4, 11000, 2]
#houses = [house, house_2]
#predictions = predict_houses([house.data for house in houses])
#for x in range(len(houses)):
# houses[x].size = predictions[x]
mlp = MLPClassifier()
X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.3)
mlp.fit(X_train, y_train)
#print([(x.col, x.row, x.size, x.data) for x in houses])
main()
pred = mlp.predict(houses_data)
print(accuracy_score(y_test, pred))
return pred
#main()

View File

@ -87,5 +87,39 @@ pred = mlp.predict(X_test)
print(accuracy_score(y_test, pred))
```
Wkonałem test dla 20 zbiorów po 40000 tysięcy wyników w każdym "size" i średnia trafności to 96,2%.
Biblioteka z której korzystam (sklearn) umożliwia stworzenie macierzy, która pokazuje nam trafność uczenia się z faktycznym stanem. Poniżej jest macierz, która przestawia wyniki uczenia się dla 1 miliona rezultatów w każym size(czyli przeprowadzono nauke dla 300k wyników w każdym size)
<img src="milion_tests.png" >
Tutaj macierz dla naszych danych wejściowych, czyli dla 40k rezultatów w każdym size (czyli przeprowadzono naukę dla 12k wyników w każdym z 4. rozmiarów śmieci)
<img src="model_testowy_dla_40k.png">
## Integracja z projektem ##
Po urucchomieniu programu, należy nacisnąć klawisz *d* na klawiaturze, dzięki czemu zostanie uruchomiony następujący kod w *main.py*
```python
messagebox.showinfo("Powitanie", "Witaj. Zaraz rozpocznie się uczenie programu do zbierania śmieci wielkogabarytowych, a potem mniejszych śmieci. Prosimy o cierpliwość)
HOUSES, _ = __a_star__.houses_with_trash()
predictions = predict_houses([house.data for house in HOUSES])
for x in range(len(HOUSES)):
HOUSES[x].size = predictions[x]
messagebox.showinfo("Koniec nauki", "Zakończono nauke. Teraz wykorzystując zmodyfikowany algorytm A* śmieciarka zbierze śmieci")
RUN_D = True
messagebox.showinfo("Koniec", "Dziękujemy za skorzystnie z naszych usług! Zapewniamy bezpieczny wywóz śmieci wielkogabarytowych")
```
Idąc od góry, wyświetlamy okienko z powitaniem, następnie wykorzystuje zdefiniowaną wcześniej (w algorytmie a_star) funkcję do zapisywania wszystkich domów w tablicy, a następnie funkcja *predict_houses* wywołuje uczenie się. Zdefiniowana jest ona w *dawid.py*
W funkcji tej, początkowo dzieje się to samo co opisałem wyżej w uczeniu się. Potem natomiast jest taka linijka, która jest dla nas bardzo istotna:
```python
pred = mlp.predict(houses_data)
```
Wyznaczamy wynik proponowany przez nauczone sieci neuronowe dla naszej tablicy z houses_data. Jest to tablica, która jest przyjmowana jako parametr naszej funkcji *predict_houses*. A jej wartość ustawiana jest w *model/__house.py__* W terminalu wyświetlany jest zawsze procent skuteczności naszego modelu.
Następnie ustawiamy zmienną *RUN_D* na *True*, dzięki czemu możemy wywołać zmpdyfikowany algorytm A* dla tego modelu i zebrać śmieci potencjalnie największe (względem gabarytu), czyli dla których nasz uczący się program, przypisał wartość 2 lub 3.

48
main.py
View File

@ -13,6 +13,7 @@ from Tree.part_map import part_map, save_to_file, save_to_file_1, read_table, ch
from Tree.decision_tree import make_tree
import joblib
from tkinter import messagebox
from dawid import predict_houses
MOVES_DICT = {
@ -78,6 +79,7 @@ MODEL = None
# Game Loop
RUN_A = False
RUN_D = False
RUN_A_LEARN = False
RUN_TREE = False
RUN_Q = False
@ -121,10 +123,15 @@ while RUNNING:
RUN_TREE = True
if event.key == pygame.K_d:
loaded_model = joblib.load('finalized_model.sav')
messagebox.showinfo("zaczynamy", "Zaczynamy!")
messagebox.showinfo("Informacja końcowa", "Zakończono")
pygame.quit()
messagebox.showinfo("Powitanie", "Witaj. Zaraz rozpocznie się uczenie programu do zbierania śmieci wielkogabarytowych, a potem mniejszych śmieci. Prosimy o cierpliwość)
HOUSES, _ = __a_star__.houses_with_trash()
predictions = predict_houses([house.data for house in HOUSES])
for x in range(len(HOUSES)):
HOUSES[x].size = predictions[x]
messagebox.showinfo("Koniec nauki", "Zakończono nauke. Teraz wykorzystując zmodyfikowany algorytm A* śmieciarka zbierze śmieci")
RUN_D = True
messagebox.showinfo("Koniec", "Dziękujemy za skorzystnie z naszych usług! Zapewniamy bezpieczny wywóz śmieci wielkogabarytowych")
if event.key == pygame.K_q:
if DQN_ENV.is_done(__gc__=GC, draw_items=DRAW_ITEMS):
print('Done')
@ -185,6 +192,39 @@ while RUNNING:
refresh_screen()
if RUN_D:
HOUSES, _ = __a_star__.houses_with_trash()
if len(HOUSES) == 0 and GC.mixed == 0 and GC.paper == 0 \
and GC.glass == 0 and GC.plastic == 0:
RUN_D = False
else:
if not ROUTE:
ROUTE = __a_star__.get_to_dest_mlp()
if len(ROUTE) > 0:
X, Y = ROUTE.pop(0)
if X - GC.col != 0:
if X - GC.col < 0:
ENV.step(2)
else:
ENV.step(3)
elif Y - GC.row != 0:
if Y - GC.row < 0:
ENV.step(0)
else:
ENV.step(1)
# time.sleep(0.3)
elif len(ROUTE) == 0:
ENV.step(4)
ENV.step(5)
GC.update()
GC.render()
refresh_screen()
if RUN_A_LEARN:
HOUSES, _ = __a_star__.houses_with_trash()
if len(HOUSES) == 0 and GC.mixed == 0 and GC.paper == 0 \

View File

@ -14,7 +14,7 @@ class House(Numbers):
self.glass = randint(0, self.limit)
self.plastic = randint(0, self.limit)
self.update()
self.data = [120, 20, 20, 10]
self.data = [randint(300, 1000), randint(2, 7), randint(2000, 11000), randint(0, 4)]
self.size = None
def update(self):