użycie drzewa decyzyjnego w kodzie

This commit is contained in:
Weranda 2023-06-16 12:46:47 +02:00
parent 749f87a428
commit 936e0d7f4d
13 changed files with 226 additions and 196 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -47,7 +47,7 @@ class Agent(pygame.sprite.Sprite):
self._layer = AGENT_LAYER
self.damage = 50*self.level
self.artifact = True
self.artifact = "tak"
def update(self):

View File

@ -34,7 +34,7 @@ class Astar():
def a_star(self, goal):
path = []
start = (self.g.agent.rect.x//TILE_SIZE, self.g.agent.rect.y//TILE_SIZE)
print(start,goal)
#print(start,goal)
open_set = []
heapq.heappush(open_set, (0, start)) # Priority queue with the start position
came_from = {}

View File

@ -1,5 +1,5 @@
zdrowie_bohatera,moc_bohatera,moc_moba,lvl_wiekszy_bohater,mob_jest_strzelcem,zdrowie_moba,artefakt,akcja
100,tak,tak,tak,tak,100,tak,zmien_kierunek
100,tak,tak,tak,tak,100,tak,walcz
100,tak,tak,tak,tak,100,nie,zmien_kierunek
100,tak,tak,tak,tak,50,tak,zmien_kierunek
100,tak,tak,tak,tak,50,nie,zmien_kierunek

150
drzewo_decyzyjne.py Normal file
View File

@ -0,0 +1,150 @@
import pandas as pd
import numpy as np
class Tree():
# Obliczanie entropii dla całego zbioru danych
def oblicz_calkowita_entropie(self,dane_treningowe, etykieta, lista_klas):
liczba_wierszy = dane_treningowe.shape[0]
calkowita_entropia = 0
for klasa in lista_klas:
liczba_wystapien_klasy = dane_treningowe[dane_treningowe[etykieta] == klasa].shape[0]
entropia_klasy = - (liczba_wystapien_klasy / liczba_wierszy) * np.log2(liczba_wystapien_klasy / liczba_wierszy)
calkowita_entropia += entropia_klasy
return calkowita_entropia
# Obliczanie entropii dla przefiltrowanego zbioru danych
def oblicz_entropie(self,dane_wartosci_cechy, etykieta, lista_klas):
liczba_wystapien_cechy = dane_wartosci_cechy.shape[0]
entropia = 0
for klasa in lista_klas:
liczba_wystapien_klasy = dane_wartosci_cechy[dane_wartosci_cechy[etykieta] == klasa].shape[0]
entropia_klasy = 0
if liczba_wystapien_klasy != 0:
prawdopodobienstwo_klasy = liczba_wystapien_klasy / liczba_wystapien_cechy
entropia_klasy = - prawdopodobienstwo_klasy * np.log2(prawdopodobienstwo_klasy)
entropia += entropia_klasy
return entropia
# Obliczanie przyrostu informacji dla danej cechy
def oblicz_przyrost_informacji(self,nazwa_cechy, dane_treningowe, etykieta, lista_klas):
unikalne_wartosci_cechy = dane_treningowe[nazwa_cechy].unique()
liczba_wierszy = dane_treningowe.shape[0]
informacja_cechy = 0.0
for wartosc_cechy in unikalne_wartosci_cechy:
dane_wartosci_cechy = dane_treningowe[dane_treningowe[nazwa_cechy] == wartosc_cechy]
liczba_wystapien_wartosci_cechy = dane_wartosci_cechy.shape[0]
entropia_wartosci_cechy = self.oblicz_entropie(dane_wartosci_cechy, etykieta, lista_klas)
prawdopodobienstwo_wartosci_cechy = liczba_wystapien_wartosci_cechy / liczba_wierszy
informacja_cechy += prawdopodobienstwo_wartosci_cechy * entropia_wartosci_cechy
return self.oblicz_calkowita_entropie(dane_treningowe, etykieta, lista_klas) - informacja_cechy
# Znajdowanie najbardziej informatywnej cechy (cechy o najwyższym przyroście informacji)
def znajdz_najbardziej_informatywna_ceche(self,dane_treningowe, etykieta, lista_klas):
lista_cech = dane_treningowe.columns.drop(etykieta)
# Etykieta nie jest cechą, więc ją usuwamy
max_przyrost_informacji = -1
najbardziej_informatywna_cecha = None
for cecha in lista_cech:
przyrost_informacji_cechy = self.oblicz_przyrost_informacji(cecha, dane_treningowe, etykieta, lista_klas)
if max_przyrost_informacji < przyrost_informacji_cechy:
max_przyrost_informacji = przyrost_informacji_cechy
najbardziej_informatywna_cecha = cecha
return najbardziej_informatywna_cecha
# Dodawanie węzła do drzewa
def generuj_poddrzewo(self,nazwa_cechy, dane_treningowe, etykieta, lista_klas):
slownik_licznosci_wartosci_cechy = dane_treningowe[nazwa_cechy].value_counts(sort=False)
drzewo = {}
for wartosc_cechy, liczba in slownik_licznosci_wartosci_cechy.items():
dane_wartosci_cechy = dane_treningowe[dane_treningowe[nazwa_cechy] == wartosc_cechy]
przypisany_do_wezla = False
for klasa in lista_klas:
liczba_klasy = dane_wartosci_cechy[dane_wartosci_cechy[etykieta] == klasa].shape[0]
if liczba_klasy == liczba:
drzewo[wartosc_cechy] = klasa
dane_treningowe = dane_treningowe[dane_treningowe[nazwa_cechy] != wartosc_cechy]
przypisany_do_wezla = True
if not przypisany_do_wezla:
drzewo[wartosc_cechy] = "?"
return drzewo, dane_treningowe
# Wykonywanie algorytmu ID3 i generowanie drzewa
def generuj_drzewo(self,korzen, poprzednia_wartosc_cechy, dane_treningowe, etykieta, lista_klas):
if dane_treningowe.shape[0] != 0:
najbardziej_informatywna_cecha = self.znajdz_najbardziej_informatywna_ceche(dane_treningowe, etykieta, lista_klas)
drzewo, dane_treningowe = self.generuj_poddrzewo(najbardziej_informatywna_cecha, dane_treningowe, etykieta, lista_klas)
nastepny_korzen = None
if poprzednia_wartosc_cechy is not None:
korzen[poprzednia_wartosc_cechy] = dict()
korzen[poprzednia_wartosc_cechy][najbardziej_informatywna_cecha] = drzewo
nastepny_korzen = korzen[poprzednia_wartosc_cechy][najbardziej_informatywna_cecha]
else:
korzen[najbardziej_informatywna_cecha] = drzewo
nastepny_korzen = korzen[najbardziej_informatywna_cecha]
for wezel, galezie in list(nastepny_korzen.items()):
if galezie == "?":
dane_wartosci_cechy = dane_treningowe[dane_treningowe[najbardziej_informatywna_cecha] == wezel]
self.generuj_drzewo(nastepny_korzen, wezel, dane_wartosci_cechy, etykieta, lista_klas)
# Znajdowanie unikalnych klas etykiety i rozpoczęcie algorytmu
def id3(self,nasze_dane, etykieta):
dane_treningowe = nasze_dane.copy()
drzewo = {}
lista_klas = dane_treningowe[etykieta].unique()
self.generuj_drzewo(drzewo, None, dane_treningowe, etykieta, lista_klas)
return drzewo
# Przewidywanie na podstawie drzewa
def przewiduj(self,drzewo, instancja):
if not isinstance(drzewo, dict):
return drzewo
else:
korzen = next(iter(drzewo))
wartosc_cechy = instancja[korzen]
if wartosc_cechy in drzewo[korzen]:
return self.przewiduj(drzewo[korzen][wartosc_cechy], instancja)
else:
return 'walcz'
def tree(self,przyklad):
# Wczytywanie danych
nasze_dane = pd.read_csv("data")
drzewo = self.id3(nasze_dane, 'akcja')
return self.przewiduj(drzewo, przyklad)
#print(przewiduj(drzewo, przyklad))
#print(drzewo)

View File

@ -1,148 +0,0 @@
import pandas as pd
import numpy as np
# Wczytywanie danych
nasze_dane = pd.read_csv("drzewo_decyzyjne\data")
# Obliczanie entropii dla całego zbioru danych
def oblicz_calkowita_entropie(dane_treningowe, etykieta, lista_klas):
liczba_wierszy = dane_treningowe.shape[0]
calkowita_entropia = 0
for klasa in lista_klas:
liczba_wystapien_klasy = dane_treningowe[dane_treningowe[etykieta] == klasa].shape[0]
entropia_klasy = - (liczba_wystapien_klasy / liczba_wierszy) * np.log2(liczba_wystapien_klasy / liczba_wierszy)
calkowita_entropia += entropia_klasy
return calkowita_entropia
# Obliczanie entropii dla przefiltrowanego zbioru danych
def oblicz_entropie(dane_wartosci_cechy, etykieta, lista_klas):
liczba_wystapien_cechy = dane_wartosci_cechy.shape[0]
entropia = 0
for klasa in lista_klas:
liczba_wystapien_klasy = dane_wartosci_cechy[dane_wartosci_cechy[etykieta] == klasa].shape[0]
entropia_klasy = 0
if liczba_wystapien_klasy != 0:
prawdopodobienstwo_klasy = liczba_wystapien_klasy / liczba_wystapien_cechy
entropia_klasy = - prawdopodobienstwo_klasy * np.log2(prawdopodobienstwo_klasy)
entropia += entropia_klasy
return entropia
# Obliczanie przyrostu informacji dla danej cechy
def oblicz_przyrost_informacji(nazwa_cechy, dane_treningowe, etykieta, lista_klas):
unikalne_wartosci_cechy = dane_treningowe[nazwa_cechy].unique()
liczba_wierszy = dane_treningowe.shape[0]
informacja_cechy = 0.0
for wartosc_cechy in unikalne_wartosci_cechy:
dane_wartosci_cechy = dane_treningowe[dane_treningowe[nazwa_cechy] == wartosc_cechy]
liczba_wystapien_wartosci_cechy = dane_wartosci_cechy.shape[0]
entropia_wartosci_cechy = oblicz_entropie(dane_wartosci_cechy, etykieta, lista_klas)
prawdopodobienstwo_wartosci_cechy = liczba_wystapien_wartosci_cechy / liczba_wierszy
informacja_cechy += prawdopodobienstwo_wartosci_cechy * entropia_wartosci_cechy
return oblicz_calkowita_entropie(dane_treningowe, etykieta, lista_klas) - informacja_cechy
# Znajdowanie najbardziej informatywnej cechy (cechy o najwyższym przyroście informacji)
def znajdz_najbardziej_informatywna_ceche(dane_treningowe, etykieta, lista_klas):
lista_cech = dane_treningowe.columns.drop(etykieta)
# Etykieta nie jest cechą, więc ją usuwamy
max_przyrost_informacji = -1
najbardziej_informatywna_cecha = None
for cecha in lista_cech:
przyrost_informacji_cechy = oblicz_przyrost_informacji(cecha, dane_treningowe, etykieta, lista_klas)
if max_przyrost_informacji < przyrost_informacji_cechy:
max_przyrost_informacji = przyrost_informacji_cechy
najbardziej_informatywna_cecha = cecha
return najbardziej_informatywna_cecha
# Dodawanie węzła do drzewa
def generuj_poddrzewo(nazwa_cechy, dane_treningowe, etykieta, lista_klas):
slownik_licznosci_wartosci_cechy = dane_treningowe[nazwa_cechy].value_counts(sort=False)
drzewo = {}
for wartosc_cechy, liczba in slownik_licznosci_wartosci_cechy.items():
dane_wartosci_cechy = dane_treningowe[dane_treningowe[nazwa_cechy] == wartosc_cechy]
przypisany_do_wezla = False
for klasa in lista_klas:
liczba_klasy = dane_wartosci_cechy[dane_wartosci_cechy[etykieta] == klasa].shape[0]
if liczba_klasy == liczba:
drzewo[wartosc_cechy] = klasa
dane_treningowe = dane_treningowe[dane_treningowe[nazwa_cechy] != wartosc_cechy]
przypisany_do_wezla = True
if not przypisany_do_wezla:
drzewo[wartosc_cechy] = "?"
return drzewo, dane_treningowe
# Wykonywanie algorytmu ID3 i generowanie drzewa
def generuj_drzewo(korzen, poprzednia_wartosc_cechy, dane_treningowe, etykieta, lista_klas):
if dane_treningowe.shape[0] != 0:
najbardziej_informatywna_cecha = znajdz_najbardziej_informatywna_ceche(dane_treningowe, etykieta, lista_klas)
drzewo, dane_treningowe = generuj_poddrzewo(najbardziej_informatywna_cecha, dane_treningowe, etykieta, lista_klas)
nastepny_korzen = None
if poprzednia_wartosc_cechy is not None:
korzen[poprzednia_wartosc_cechy] = dict()
korzen[poprzednia_wartosc_cechy][najbardziej_informatywna_cecha] = drzewo
nastepny_korzen = korzen[poprzednia_wartosc_cechy][najbardziej_informatywna_cecha]
else:
korzen[najbardziej_informatywna_cecha] = drzewo
nastepny_korzen = korzen[najbardziej_informatywna_cecha]
for wezel, galezie in list(nastepny_korzen.items()):
if galezie == "?":
dane_wartosci_cechy = dane_treningowe[dane_treningowe[najbardziej_informatywna_cecha] == wezel]
generuj_drzewo(nastepny_korzen, wezel, dane_wartosci_cechy, etykieta, lista_klas)
# Znajdowanie unikalnych klas etykiety i rozpoczęcie algorytmu
def id3(nasze_dane, etykieta):
dane_treningowe = nasze_dane.copy()
drzewo = {}
lista_klas = dane_treningowe[etykieta].unique()
generuj_drzewo(drzewo, None, dane_treningowe, etykieta, lista_klas)
return drzewo
# Przewidywanie na podstawie drzewa
def przewiduj(drzewo, instancja):
if not isinstance(drzewo, dict):
return drzewo
else:
korzen = next(iter(drzewo))
wartosc_cechy = instancja[korzen]
if wartosc_cechy in drzewo[korzen]:
return przewiduj(drzewo[korzen][wartosc_cechy], instancja)
else:
return 'walcz'
drzewo = id3(nasze_dane, 'akcja')
przyklad = {'zdrowie_bohatera': '100',
'moc_bohatera': 'nie',
'moc_moba': 'nie',
'lvl_wiekszy_bohater': 'tak',
'mob_jest_strzelcem': 'nie',
'zdrowie_moba': '1',
'artefakt': 'tak'}
print(przewiduj(drzewo, przyklad))
print(drzewo)

86
main.py
View File

@ -9,7 +9,7 @@ from nn import *
from astar import *
import math
import random
from drzewo_decyzyjne import *
class Game:
@ -31,7 +31,7 @@ class Game:
self.bfs = Bfs(self)
self.nn = NeuralN()
self.astar = Astar(self)
self.tree = Tree()
self.cell_costs = [[1 for _ in range(TILE_SIZE)] for _ in range(TILE_SIZE)]
self.obstacles = [[False for _ in range(TILE_SIZE)] for _ in range(TILE_SIZE)]
@ -277,30 +277,7 @@ class Game:
self.obstacles[self.najlepszaGeneracja[y+11][0]][self.najlepszaGeneracja[y+11][1]] = True
self.bfs.wall_cells.append(self.bfs.get_cell_number(self.rock.x,self.rock.y))
""" to jest tak jak bylo zmieniam tylko pozycje elementow
self.agent = Agent(self,1,1)
self.archer_ork = Archer_ork(self,10,10)
self.obstacles[10][10] = True
self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.archer_ork.x,self.archer_ork.y))
self.infantry_ork = Infantry_ork(self,10,4)
self.obstacles[10][4] = True
self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.infantry_ork.x,self.infantry_ork.y))
self.sauron = Sauron(self, 1, 10)
self.obstacles[1][10] = True
self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.sauron.x,self.sauron.y))
self.flower = Health_flower(self, 8,2)
for y in range (2,5):
for x in range (2):
self.grass = Grass(self,x,y)
self.cell_costs[x][y] = 5
for y in range(5):
self.rock = Rocks(self,3,y)
self.obstacles[3][y] = True
self.bfs.wall_cells.append(self.bfs.get_cell_number(self.rock.x,self.rock.y))
"""
def update(self):
self.all_sprites.update()
@ -327,19 +304,48 @@ class Game:
mob_image = self.sauron.image_path
prediction = self.prediction_road(x,y,mob_image)
prediction = "SAURON"
while True: #do poprawienia poprawne rozpoznawanie póki co nie będzie działać dobrze, program się będzie zawieszać
if prediction == "SAURON" and self.agent.level < 3:
while True: #do poprawienia poprawne rozpoznawanie
print("goal: ",goal)
if prediction == "SAURON":
if self.agent.level < self.sauron.level:
lvl = 'nie'
else:
lvl = 'tak'
przyklad = {'zdrowie_bohatera': '100',
'moc_bohatera': 'tak',
'moc_moba': 'tak',
'lvl_wiekszy_bohater': lvl,
'mob_jest_strzelcem': self.sauron.archer,
'zdrowie_moba': '50',
'artefakt': self.agent.artifact}
decision = self.tree.tree(przyklad)
print(decision)
if decision == "walcz":
self.obstacles[self.najlepszaGeneracja[3][0]][self.najlepszaGeneracja[3][1]] = False
self.move_agent(self.astar.a_star(goal))
else:
x = self.archer_ork.x
y = self.archer_ork.y
goal = x//TILE_SIZE,y//TILE_SIZE
mob_image = self.archer_ork.image_path
prediction = self.prediction_road(x,y,mob_image)
prediction = "ORK_ARCHER"
elif prediction == "SAURON" and self.agent.level >= 3:
self.obstacles[self.najlepszaGeneracja[3][0]][self.najlepszaGeneracja[3][1]] = False
self.move_agent(self.astar.a_star(goal))
elif prediction == "ORK_INFANTRY":
if self.agent.level < self.infantry_ork.level:
lvl = 'nie'
else:
lvl = 'tak'
przyklad = {'zdrowie_bohatera': '100',
'moc_bohatera': 'tak',
'moc_moba': 'tak',
'lvl_wiekszy_bohater': lvl,
'mob_jest_strzelcem': self.infantry_ork.archer,
'zdrowie_moba': '50',
'artefakt': self.agent.artifact}
decision = self.tree.tree(przyklad)
print(decision)
if decision == "walcz":
self.obstacles[self.najlepszaGeneracja[2][0]][self.najlepszaGeneracja[2][1]] = False
self.move_agent(self.astar.a_star(goal))
if self.agent.current_health < self.agent.max_health:
@ -352,8 +358,24 @@ class Game:
prediction = self.prediction_road(x,y,mob_image)
prediction = "SAURON"
elif prediction == "ORK_ARCHER":
if self.agent.level < self.archer_ork.level:
lvl = 'nie'
else:
lvl = 'tak'
przyklad = {'zdrowie_bohatera': '100',
'moc_bohatera': 'tak',
'moc_moba': 'tak',
'lvl_wiekszy_bohater': lvl,
'mob_jest_strzelcem': self.archer_ork.archer,
'zdrowie_moba': '50',
'artefakt': self.agent.artifact}
decision = self.tree.tree(przyklad)
print(decision)
if decision == "walcz":
self.obstacles[self.najlepszaGeneracja[1][0]][self.najlepszaGeneracja[1][1]] = False
self.move_agent(self.astar.a_star(goal))
if self.agent.current_health < self.agent.max_health:
goal = (self.flower.x//TILE_SIZE, self.flower.y//TILE_SIZE)
self.move_agent(self.astar.a_star(goal))
@ -387,7 +409,7 @@ class Game:
print("PATH:::::",path)
for cell_to_move in path:
x, y = self.bfs.get_coordinates(cell_to_move)
print("Ruch do kratki : ", cell_to_move, " z x: ", x, ", y: ", y, ", agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y)
#print("Ruch do kratki : ", cell_to_move, " z x: ", x, ", y: ", y, ", agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y)
if(self.bfs.get_cell_number(self.agent.rect.x,self.agent.rect.y)!=cell_to_move):
if x > self.agent.rect.x:
self.agent.direction = 0
@ -414,7 +436,7 @@ class Game:
self.update()
self.map()
print("Polozenie agenta: agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y)
#print("Polozenie agenta: agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y)
self.clock.tick(2)
def map(self): # tworzenie mapy

View File

@ -30,6 +30,8 @@ class Archer_ork(pygame.sprite.Sprite):
self.damage = 50*self.level
self.health = 50
self.archer = 'tak'
class Infantry_ork(pygame.sprite.Sprite):
@ -59,6 +61,8 @@ class Infantry_ork(pygame.sprite.Sprite):
self.damage = 50*self.level
self.health = 100
self.archer = 'nie'
class Sauron(pygame.sprite.Sprite):
@ -88,3 +92,5 @@ class Sauron(pygame.sprite.Sprite):
self.level = 3
self.damage = 50*self.level
self.health = 150
self.archer = 'nie'