podprojekt
This commit is contained in:
parent
ff6de2c7e4
commit
ecc954719d
77
Justyna.md
Normal file
77
Justyna.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# 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, features, target_attribute_name, parent_node_class=None):
|
||||||
|
|
||||||
|
item_values = [info_gain(data, feature, target_attribute_name) for feature in
|
||||||
|
features]
|
||||||
|
best_feature_index = np.argmax(item_values)
|
||||||
|
best_feature = features[best_feature_index]
|
||||||
|
tree = {best_feature: {}}
|
||||||
|
features = [i for i in features if i != best_feature]
|
||||||
|
for value in np.unique(data[best_feature]):
|
||||||
|
|
||||||
|
sub_data = data.where(data[best_feature] == value).dropna()
|
||||||
|
subtree = ID3(sub_data, data, features, target_attribute_name, parent_node_class)
|
||||||
|
|
||||||
|
tree[best_feature][value] = subtree
|
||||||
|
|
||||||
|
return (tree)
|
||||||
|
```
|
||||||
|
|
||||||
|
Drzewo budowane jest w oparciu o najlepsze możliwe podziały:
|
||||||
|
|
||||||
|
```py
|
||||||
|
#obliczanie wartości przyrostu informacji
|
||||||
|
def info_gain(data, split_attribute_name, target_name):
|
||||||
|
|
||||||
|
# Wartość entropii zbioru
|
||||||
|
total_entropy = entropy(data[target_name])
|
||||||
|
|
||||||
|
# Wyodrębnienie poszczególnych "podzbiorów"
|
||||||
|
vals, counts = np.unique(data[split_attribute_name], 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_name] == vals[i]).dropna()[target_name])
|
||||||
|
for i in range(len(vals))])
|
||||||
|
|
||||||
|
# Przyrost informacji
|
||||||
|
information_gain = total_entropy - weighted_entropy
|
||||||
|
|
||||||
|
return information_gain
|
||||||
|
```
|
||||||
|
|
||||||
|
Entropia:
|
||||||
|
|
||||||
|
```py
|
||||||
|
def entropy(target_col):
|
||||||
|
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 20 przykładów waruków panujących na polu. Atrybyty zapisane są w formacie ['pogoda', 'ile_chwastow', 'ile_burakow', 'czy_chce_pracowac'].
|
||||||
|
|
||||||
|
```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*.
|
||||||
|
|
189
Justyna.py
189
Justyna.py
@ -1,3 +1,122 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pprint import pprint
|
||||||
|
import time
|
||||||
|
import dataset
|
||||||
|
import random
|
||||||
|
|
||||||
|
# obliczenie entropii dla wskazanej kolumny
|
||||||
|
def entropy(target_col):
|
||||||
|
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
|
||||||
|
|
||||||
|
#obliczanie wartości przyrostu informacji
|
||||||
|
def info_gain(data, split_attribute_name, target_name):
|
||||||
|
|
||||||
|
# Wartość entropii zbioru
|
||||||
|
total_entropy = entropy(data[target_name])
|
||||||
|
|
||||||
|
# Wyodrębnienie poszczególnych "podzbiorów"
|
||||||
|
vals, counts = np.unique(data[split_attribute_name], 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_name] == vals[i]).dropna()[target_name])
|
||||||
|
for i in range(len(vals))])
|
||||||
|
|
||||||
|
# Przyrost informacji
|
||||||
|
information_gain = total_entropy - weighted_entropy
|
||||||
|
|
||||||
|
return information_gain
|
||||||
|
|
||||||
|
|
||||||
|
def ID3(data, original_data, features, target_attribute_name, parent_node_class=None):
|
||||||
|
|
||||||
|
|
||||||
|
# Jeżeli wszystkie atrybuty są takie same, zwracamy liść z pierwszą napotkaną wartością
|
||||||
|
|
||||||
|
if len(np.unique(data[target_attribute_name])) <= 1:
|
||||||
|
return np.unique(data[target_attribute_name])[0]
|
||||||
|
|
||||||
|
elif len(data) == 0:
|
||||||
|
return np.unique(original_data[target_attribute_name])[
|
||||||
|
np.argmax(np.unique(original_data[target_attribute_name], return_counts=True)[1])]
|
||||||
|
|
||||||
|
elif len(features) == 0:
|
||||||
|
return parent_node_class
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Aktualizacja nadrzędnej wartości
|
||||||
|
parent_node_class = np.unique(data[target_attribute_name])[
|
||||||
|
np.argmax(np.unique(data[target_attribute_name], return_counts=True)[1])]
|
||||||
|
|
||||||
|
# Obliczenie przyrostu informacji dla każdego potencjalnego atrybutu,
|
||||||
|
# według którego nastąpi podział zbioru
|
||||||
|
item_values = [info_gain(data, feature, target_attribute_name) for feature in
|
||||||
|
features]
|
||||||
|
|
||||||
|
# Najlepszym atrybutem jest ten o największym przyroście informacji
|
||||||
|
best_feature_index = np.argmax(item_values)
|
||||||
|
best_feature = features[best_feature_index]
|
||||||
|
|
||||||
|
# Struktura drzewa
|
||||||
|
tree = {best_feature: {}}
|
||||||
|
|
||||||
|
# Aktualizacja zbioru atrybutów
|
||||||
|
features = [i for i in features if i != best_feature]
|
||||||
|
|
||||||
|
# Dla każdej wartości wybranego atrybutu budujemy kolejne poddrzewo
|
||||||
|
for value in np.unique(data[best_feature]):
|
||||||
|
|
||||||
|
sub_data = data.where(data[best_feature] == value).dropna()
|
||||||
|
subtree = ID3(sub_data, data, features, target_attribute_name, parent_node_class)
|
||||||
|
|
||||||
|
tree[best_feature][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 predict_data(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():
|
class main():
|
||||||
def __init__(self,traktor,field,ui,path):
|
def __init__(self,traktor,field,ui,path):
|
||||||
self.traktor = traktor
|
self.traktor = traktor
|
||||||
@ -6,4 +125,72 @@ class main():
|
|||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
def main(self):
|
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)
|
||||||
|
|
||||||
|
#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 = predict_data(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'
|
35
dataset.py
Normal file
35
dataset.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
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'],
|
||||||
|
['deszcz', 'bardzo_duzo', 'malo', 'nie'],
|
||||||
|
['deszcz', 'srednio', 'srednio', 'srednio'],
|
||||||
|
['deszcz', 'malo', 'bardzo_duzo', 'tak'],
|
||||||
|
['deszcz', 'duzo', 'duzo', 'srednio'],
|
||||||
|
['deszcz', 'malo', 'malo', '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'],
|
||||||
|
['zachmurzenie', 'srednio', 'srednio', 'tak'],
|
||||||
|
['zachmurzenie', 'bardzo_duzo', 'duzo', 'nie'],
|
||||||
|
['zachmurzenie', 'malo', 'srednio', 'tak'],
|
||||||
|
['zachmurzenie', 'duzo', 'malo', 'srednio'],
|
||||||
|
['zachmurzenie', 'malo', 'bardzo_malo', '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']
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user