SI2020/Raport- drzewa decyzyjne.md

132 lines
5.2 KiB
Markdown

# Podprojekt indywidualny - Szymon Parafiński
## Wykorzystane metody uczenia
Do realizacji podprojektu wykorzystano drzewa decyzyjne do decydowania, co należy zrobić po najechaniu na konkretne pole.
Drzewo decyduje na jakim etapie jest roślina analizując poszczególne stany danego pola:
- Dopiero co zasiana (kiełek)
- 0: "Nie_podejmuj_działania"
- Roślinka kiełkująca (młoda)
- 1: "Zastosuj_nawóz"
- Roślina starzejąca się, bez środka ochrony
- 2: "Zastosuj_środek"
- Roślinka dojrzałam gotowa do zbioru
- 4: "Zbierz"
- Roślina zepsuta, nie nadaje się do użytku
- 5: "Roślina_już_zgniła-zbierz_i_wyrzuć".
Do implementacji drzew decyzyjnych w Pythonie wykorzystane zostały biblioteki
**sklearn** , **pandas** oraz **pickle**.
## Uczenie modelu
#### def loadLearningBase():
Metoda **loadLearningBase** rozpoczyna od utworzenia zbioru uczącego na podstawie tabeli zawierającej informacje wszystkich możliwych stanach roślinki.
*col_names* -> zawiera nagłówki poszczególnych kolumn
*feature_cols* -> zawiera nagłówki z kolumnami w których znajdują się dane do analizy
```
col_names = ['Warzywo', 'Nawoz', 'Srodek', 'Stan', 'Dzialanie']
base = pd.read_csv("Database.csv", header=None, names=col_names)
feature_cols = ['Warzywo', 'Nawoz', 'Srodek', 'Stan']
""" print dataset"""
# print(base.head())
```
Tutaj dzielimy podane kolumny na dwa typy zmiennych:
* zmienne docelowe ---> y
* i zmienne funkcyjne ---> X
Aby móc sprawdzić wydajność modelu, dzielę zestaw danych na zestaw szkoleniowy i zestaw testowy ---> za pomocą funkcji train_test_split ().
```
X = base[feature_cols] # Features
y = base.Dzialanie # Target variable
# Split dataset into training set and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
random_state=1) # 70% training and 30% test
```
Wywołanie funkcji odpowiedzialnej za wygenerowanie drzewa.
```
data = generateDecisionTree(X_train, X_test, y_train, y_test)
```
Dodatkowe elementy pozwalające na wizualizację stworzonego drzewa decyzyjnego poprzez wygenerowanie drzewa zależności if/else lub najpierw do pliku .dot, który następnie poddany odpowiedniej 'obróbce' utworzy obraz.
```
"""generate data for image"""
# tree.export_graphviz(data, out_file='treeData.dot', filled=True, rounded=True, special_characters=True,
# feature_names=feature_cols)
"""Printing if_styled tree to console"""
# tree_to_code(data, feature_cols)
return data
```
---
#### def generateDecisionTree():
Metoda **generateDecisionTree** generuje drzewo decyzyjne na podstawie dostarczonej bazy danych.
Do zmiennej *clf* zapisujemy drzewo decyzyjne z biblioteki **sklearn** utworzone za pomocą metody **DecisionTreeClassifier** z parametrem **criterion** ustawionym na **"entropy"**, który pozwala na uzyskiwanie informacji.
Na drzewie wywołujemy metodę **fit**, która dopasowuje do drzewa zbiór uczący zadany w tablicach **X_train** i **y_train**.
Po dopasowaniu danych możemy przewidzieć przynależność nowych przykładów, co robimy wywołując na drzewie metodę **predict** z parametrami, które zawierają informację o stanie danego pola.
```
def generateDecisionTree(X_train, X_test, y_train, y_test):
# Create Decision Tree classifer object
clf = DecisionTreeClassifier(criterion="entropy")
# Train Decision Tree Classifer
clf = clf.fit(X_train, y_train)
```
Aby ocenić dokładność naszego modelu przewidujemy odpowiedzi dla naszego zestawu testowego, aby móc go porównać z zestawem y_test i otrzymać dokładność wygenerowanego modelu.
```
# Predict the response for test dataset
y_pred = clf.predict(X_test)
"""Model Accuracy, how often is the classifier correct """
# print("Accuracy:", metrics.accuracy_score(y_test, y_pred))
```
---
#### main():
Metoda main wywołuje pozostałe metody oraz zapisuje wygenerowany model do pliku .sav aby nie było trzeba ponownie generować drzewa, tylko wczytać już te wygenerowane.
```
generated = loadLearningBase()
# Save generated tree
filename = 'decisionTree.sav'
pickle.dump(generated, open(filename, 'wb'))
```
## Implementacja
Klasa która będzie wywoływana w **C++** nazywa się *injectCode*.
```
import pickle
import sys
def predict(warzywo, nawoz ,srodek, stan_wzrostu):
filename = 'decisionTree.sav'
tree = pickle.load(open(filename, 'rb'))
print(tree.predict([[warzywo, nawoz, srodek, stan_wzrostu]]))
if __name__ == '__main__':
# Map command line arguments to function arguments.
predict(*sys.argv[1:])
```
Aby otrzymać zalecane działanie dla danego pola należy wywołać kod w wierszu polecenia takim poleceniem:
```
python injectCode.py a b c d
```
Gdzie:
* a -> rodzaj warzywa
* b -> czy roślina była nawożona
* 0: "nie"
* 1: "tak"
* c -> czy na roślinie był stosowany środek ochronny
* 0: "nie"
* 1: "tak"
* d -> stan wzrostu w jakim znajduje się roślina
* [1,20) - kiełek,
* [20,45) - młoda roślina,
* [45,85) - dojrzała,
* [80,100] - starzejąca się.