Merge remote-tracking branch 'origin/master'

This commit is contained in:
xkamikoo 2020-06-03 14:14:33 +02:00
commit fab7c34909
9 changed files with 548 additions and 8 deletions

92
Justyna.md Normal file
View File

@ -0,0 +1,92 @@
# Drzewa decyzyjne, algorytm ID3
### autor Justyna Zarzycka
## Opis projektu
Projekt implementuje tworzenie drzewa decyzyjnego wykorzystującego algorytm ID3, ktióre pomaga określić chęci do pracy agenta na podstawie warunków panujących na planszy.
### Tworzenie drzewa decyzyjnego
Funkcja budująca drzewo za pomocą algorymu ID3:
```py
def ID3(data, original_data, attributes, target, parent_node_class=None):
if len(np.unique(data[target])) <= 1:
return np.unique(data[target])[0]
elif len(data) == 0:
return np.unique(original_data[target])[
np.argmax(np.unique(original_data[target], return_counts=True)[1])]
elif len(attributes) == 0:
return parent_node_class
else:
parent_node_class = np.unique(data[target])[
np.argmax(np.unique(data[target], return_counts=True)[1])]
item_values = [info_gain(data, i, target) for i in
attributes]
best_attribute_index = np.argmax(item_values)
best_attribute = attributes[best_attribute_index]
tree = {best_attribute: {}}
attributes = [i for i in attributes if i != best_attribute]
for value in np.unique(data[best_attribute]):
sub_data = data.where(data[best_attribute] == value).dropna()
subtree = ID3(sub_data, data, attributes, target, parent_node_class)
tree[best_attribute][value] = subtree
return (tree)
```
Cechą charakterystyczną algorytmu jest wybór atrybutów dla których kolejno przeprowadzane są testy taki, aby końcowe drzewo było jak najprostsze i jak najefektywniejsze. Wybór atrybutów opiera się na liczeniu entropii, co pozwala obliczyć, wybór którego z atrybutów da największy przyrost informacji.
Obliczanie wartości przyrostu informacji:
Funkcja oblicza który atrybut najlepiej rozdziela zbiór danych (dzieli zbiór przykładów na jak najbardziej równe podzbiory).
```py
def info_gain(data, split_attribute, target):
_entropy = entropy(data[target])
vals, counts = np.unique(data[split_attribute], return_counts=True)
weighted_entropy = np.sum(
[(counts[i] / np.sum(counts)) * entropy(data.where(data[split_attribute] == vals[i]).dropna()[target])
for i in range(len(vals))])
information_gain = _entropy - weighted_entropy
return information_gain
```
Entropia:
Entropia jest miarą ilości informacji - im mniejsza entropia, tym więcej informacji. W przypadku problemu klasyfikacji przykładów do dwóch odrębnych klas, wzór na entropię przedstawia się następująco:
Entropy(S) = - ∑ pᵢ * log₂(pᵢ) ; i = 1 to n
gdzie:
Z - źródło informacji
p - prawdopodobieństwo wystąpienia przykładu pozytywnego w zbiorze trenującym
(1-p) - prawdopodobieństwo wystąpienia przykładu negatywnego w zbiorze trenującym
```py
def entropy(attribute):
values, counts = np.unique(target_col, return_counts=True)
entropy = np.sum(
[(-counts[i] / np.sum(counts)) * np.log2(counts[i] / np.sum(counts)) for i in range(len(values))])
return entropy
```
### Zestaw uczący
Zestaw budujący drzewo to lista zawierająca 24 przykładów waruków panujących na polu. Atrybyty zapisane są w formacie ['pogoda', 'ile_chwastow', 'ile_burakow', 'czy_chce_pracowac']. Przykłady ze zbioru:
```py
['slonecznie', 'duzo', 'bardzo_malo', 'srednio'],
['deszcz', 'bardzo_duzo', 'malo', 'nie'],
['grad', 'bardzo_duzo', 'bardzo_malo', 'nie'],
['zachmurzenie', 'srednio', 'srednio', 'tak']
```
### Implementacja w projekcie
Podprojet uruchamiany jest za pomocą klawisza *F5*. Pobierane są inforamcje o warunkach panujących na polu, na podstawie których oceniana jest chęć do pracy.

View File

@ -1,3 +1,120 @@
import pandas as pd
import numpy as np
from pprint import pprint
import dataset
import random
# obliczenie entropii dla wskazanej kolumny
def entropy(attribute):
values, counts = np.unique(attribute, return_counts=True)
entropy = np.sum(
[(-counts[i] / np.sum(counts)) * np.log2(counts[i] / np.sum(counts)) for i in range(len(values))])
return entropy
#obliczanie wartości przyrostu informacji
def info_gain(data, split_attribute, target):
# Wartość entropii zbioru
_entropy = entropy(data[target])
# Wyodrębnienie poszczególnych podzbiorów
vals, counts = np.unique(data[split_attribute], return_counts=True)
# Średnia ważona entropii każdego podzbioru
weighted_entropy = np.sum(
[(counts[i] / np.sum(counts)) * entropy(data.where(data[split_attribute] == vals[i]).dropna()[target])
for i in range(len(vals))])
# Przyrost informacji
information_gain = _entropy - weighted_entropy
return information_gain
def ID3(data, original_data, attributes, target, parent_node_class=None):
# Jeżeli wszystkie atrybuty są takie same, zwracamy liść z pierwszą napotkaną wartością
if len(np.unique(data[target])) <= 1:
return np.unique(data[target])[0]
elif len(data) == 0:
return np.unique(original_data[target])[
np.argmax(np.unique(original_data[target], return_counts=True)[1])]
elif len(attributes) == 0:
return parent_node_class
else:
# nadrzędna wartość
parent_node_class = np.unique(data[target])[
np.argmax(np.unique(data[target], return_counts=True)[1])]
# obliczenie przyrostu informacji dla każdego atrybutu
item_values = [info_gain(data, i, target) for i in
attributes]
# Wybór najlepszego atrybutu
best_attribute_index = np.argmax(item_values)
best_attribute = attributes[best_attribute_index]
# Struktura drzewa
tree = {best_attribute: {}}
# Aktualizacja zbioru atrybutów
attributes = [i for i in attributes if i != best_attribute]
# Budowa poddrzewa dla każdej wartości wybranego atrybutu
for value in np.unique(data[best_attribute]):
sub_data = data.where(data[best_attribute] == value).dropna()
subtree = ID3(sub_data, data, attributes, target, parent_node_class)
tree[best_attribute][value] = subtree
return (tree)
#tesownie drzewa
def test(data, tree):
queries = data.iloc[:, :-1].to_dict(orient="records")
predicted = pd.DataFrame(columns=["predicted"])
for i in range(len(data)):
predicted.loc[i, "predicted"] = search(queries[i], tree, 'nie')
print('Precyzja przewidywań: ', (np.sum(predicted["predicted"] == data['czy_chce_pracowac']) / len(data)) * 100, '%')
#dostowanie danych (lista na słownik) i wywolanie na nich funkcji serach
def data_to_dict(data, tree):
queries = pd.DataFrame(data=data, columns=dataset.header)
predicted = pd.DataFrame(columns=["predicted"])
dict = queries.iloc[:, :-1].to_dict(orient="records")
for i in range(len(data)):
predicted.loc[i, "predicted"] = search(dict[i], tree, 'nie')
predicted_list = predicted.values.tolist()
return predicted_list[0][0]
#przeszukwianie drzewa
def search(query, tree, default='nie'):
for key in list(query.keys()):
if key in list(tree.keys()):
try:
result = tree[key][query[key]]
except:
return default
result = tree[key][query[key]]
if isinstance(result, dict):
return search(query, result)
else:
return result
class main():
def __init__(self,traktor,field,ui,path):
self.traktor = traktor
@ -6,4 +123,75 @@ class main():
self.path = path
def main(self):
pass
training_data = pd.DataFrame(data=dataset.training_data, columns=dataset.header)
testing_data = pd.DataFrame(data=dataset.testing_data, columns=dataset.header)
# Utworzenie drzewa
tree = ID3(training_data, training_data, training_data.columns[:-1], 'czy_chce_pracowac')
pprint(tree)
# Testowanie drzewa
print(test(testing_data, tree))
# Uzyskanie danych od agenta
ocena_burakow = self.ocen_ile_burakow()
ocena_chwastow = self.ocen_ile_chwastow()
pogoda = self.pogoda()
print('chwasty: ' + ocena_chwastow)
print('buraki: ' + ocena_burakow)
print('pogoda: ' + pogoda)
data = [[pogoda, ocena_chwastow, ocena_burakow, '']]
#podjecie decyzji
result = data_to_dict(data, tree)
print('czy traktor chce pracowac: ' + result)
def licz_chwasty_buraki(self):
chwasty = 0
buraki = 0
for i in self.field.field_matrix:
for j in i:
if(j==8):
buraki = buraki + 1
elif(j%2==1):
chwasty = chwasty + 1
return chwasty, buraki
def ocen_ile_burakow(self):
chwasty, buraki = self.licz_chwasty_buraki()
if buraki < 5:
return 'bardzo_malo'
elif buraki >= 5 and buraki<10:
return 'malo'
elif buraki >=10 and buraki<15:
return 'srednio'
elif buraki >=15 and buraki<20:
return 'duzo'
elif buraki >=20:
return 'bardzo_duzo'
def ocen_ile_chwastow(self):
chwasty, buraki = self.licz_chwasty_buraki()
if chwasty < 40:
return 'bardzo_malo'
elif chwasty >= 40 and chwasty<42:
return 'malo'
elif chwasty >=42 and chwasty<45:
return 'srednio'
elif chwasty >=45 and chwasty<48:
return 'duzo'
elif chwasty >=48:
return 'bardzo_duzo'
def pogoda(self):
number = random.randrange(0, 4)
if number==0:
return 'slonecznie'
elif number==1:
return 'deszcz'
elif number==2:
return 'grad'
elif number==3:
return 'zachmurzenie'

View File

@ -74,3 +74,14 @@ class main():
return 3
elif self.mode_value in [6]:
return 10
def main_collective(self,poz):
self.pole = self.ui.field_images[self.field.get_value(poz)]
self.img = pygame.surfarray.array3d(self.pole)
self.img = self.img.transpose([1, 0, 2])
self.img = cv2.cvtColor(self.img, cv2.COLOR_RGB2BGR)
self.reco = self.mode(self.recognition(self.img))
if self.reco == 10:
print("Nic nie trzeba robić")
else:
self.traktor.set_mode(self.reco)

15
collective.py Normal file
View File

@ -0,0 +1,15 @@
class main():
def __init__(self,marcin, justyna, kamila, piotrek, traktor, pole, UI, path):
self.marcin = marcin
self.justyna = justyna
self.kamila = kamila
self.piotrek = piotrek
self.traktor = traktor
self.pole = pole
self.UI = UI
self.path = path
def main(self):
# self.marcin.main_collective(pozycja) To podaje jakie jest pole jest na danym miejscu
pass

39
dataset.py Normal file
View File

@ -0,0 +1,39 @@
header = ['pogoda', 'ile_chwastow', 'ile_burakow', 'czy_chce_pracowac']
training_data = [
['slonecznie', 'duzo', 'malo', 'tak'],
['slonecznie', 'srednio', 'srdenio', 'tak'],
['slonecznie', 'bardzo_duzo', 'malo', 'srednio'],
['slonecznie', 'malo', 'bardzo_duzo', 'tak'],
['slonecznie', 'duzo', 'bardzo_malo', 'srednio'],
['slonecznie', 'malo', 'bardzo_malo', 'srednio'],
['deszcz', 'bardzo_duzo', 'malo', 'nie'],
['deszcz', 'srednio', 'srednio', 'srednio'],
['deszcz', 'malo', 'bardzo_duzo', 'tak'],
['deszcz', 'duzo', 'duzo', 'srednio'],
['deszcz', 'malo', 'malo', 'tak'],
['deszcz', 'srednio', 'bardzo_duzo', 'tak'],
['grad', 'srednio', 'malo', 'nie'],
['grad', 'bradzo_malo', 'bardzo_duzo', 'srednio'],
['grad', 'duzo', 'srednio', 'nie'],
['grad', 'malo', 'bardzo_malo', 'srednio'],
['grad', 'bardzo_duzo', 'bardzo_malo', 'nie'],
['grad', 'srednio', 'bardzo_malo', 'nie'],
['zachmurzenie', 'srednio', 'srednio', 'tak'],
['zachmurzenie', 'bardzo_duzo', 'duzo', 'nie'],
['zachmurzenie', 'malo', 'srednio', 'tak'],
['zachmurzenie', 'duzo', 'malo', 'srednio'],
['zachmurzenie', 'malo', 'bardzo_malo', 'tak'],
['zachmurzenie', 'malo', 'srednio', 'tak']
]
testing_data = [
['slonecznie', 'srednio', 'srednio', 'tak'],
['deszcz', 'duzo', 'malo', 'nie'],
['deszcz', 'duzo', 'duzo', 'srednio'],
['grad', 'srednio', 'duzo', 'nie'],
['zachmurzenie', 'bardzo_duzo', 'malo', 'nie'],
['zachmurzenie', 'bardzo_duzo', 'malo', 'nie']
]

18
main.py
View File

@ -1,5 +1,5 @@
import pygame, sys
import tractor, pathfinding, field, ui, Justyna, Kamila, Marcin, Piotrek, pathfinding_decision
import tractor, pathfinding, field, ui, Justyna, Kamila, Marcin, Piotrek, pathfinding_decision, collective
from pygame.locals import *
pole = field.field()
@ -10,6 +10,7 @@ j = Justyna.main(traktor,pole,UI,path)
k = Kamila.main(traktor,pole,UI,pathfinding_decision.pathfinding_dec())
neuro = Marcin.main(traktor,pole,UI,path)
p = Piotrek.main(traktor,pole,UI,path)
c = collective.main(neuro,j,k,p,traktor,pole,UI,path)
pygame.init()
UI.update()
UI.update()
@ -41,12 +42,6 @@ while True:
traktor.set_mode(3)
if key[K_p]:
path.pathfinding(traktor,pole,UI)
if key[K_F9]:
print(pole.if_value(traktor.get_modes_values()))
if key[K_F10]:
print(traktor.get_poz())
if key[K_F11]:
print(traktor.get_field_value())
if key[K_F5]:
#Dla projektu Justyny
j.main()
@ -59,6 +54,15 @@ while True:
if key[K_F8]:
# Dla projektu Piotrka
p.main()
if key[K_F9]:
print(pole.if_value(traktor.get_modes_values()))
if key[K_F10]:
print(traktor.get_poz())
if key[K_F11]:
print(traktor.get_field_value())
if key[K_12]:
c.main()
UI.update()
UI.update()

182
si.cfg Normal file
View File

@ -0,0 +1,182 @@
[net]
# Testing
batch=24
subdivisions=8
# Training
# batch=64
# subdivisions=2
width=416
height=416
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
learning_rate=0.001
burn_in=1000
max_batches = 500200
policy=steps
steps=400000,450000
scales=.1,.1
[convolutional]
batch_normalize=1
filters=16
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=1
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
###########
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=42
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=9
num=6
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 8
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=42
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=9
num=6
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

9
si.names Normal file
View File

@ -0,0 +1,9 @@
0
1
2
3
4
5
6
7
8

BIN
si_20000.weights Normal file

Binary file not shown.