SI2020/Raport- drzewa decyzyjne.md

187 lines
6.5 KiB
Markdown
Raw Normal View History

2020-05-13 03:06:51 +02:00
# Podprojekt indywidualny - Szymon Parafiński
---
W folderze Sklearn znajduje się wykorzystana baza, wygenerowane drzewo oraz reszta plików związana z podprojektem.
2020-05-13 03:06:51 +02:00
## Wykorzystana metoda uczenia
2020-05-13 03:06:51 +02:00
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"
2020-05-13 03:06:51 +02:00
- Roślinka kiełkująca (młoda)
- 1: "Zastosuj_nawóz"
2020-05-13 03:06:51 +02:00
- Roślina starzejąca się, bez środka ochrony
- 2: "Zastosuj_środek"
2020-05-13 03:06:51 +02:00
- Roślinka dojrzałam gotowa do zbioru
- 4: "Zbierz"
2020-05-13 03:06:51 +02:00
- Roślina zepsuta, nie nadaje się do użytku
- 5: "Roślina_już_zgniła-zbierz_i_wyrzuć".
2020-05-13 03:06:51 +02:00
Do implementacji drzew decyzyjnych w Pythonie wykorzystane zostały biblioteki
**sklearn** , **pandas**,**sys** oraz **pickle**.
2020-05-13 03:06:51 +02:00
## Uczenie modelu
#### loadLearningBase(): [python]
2020-05-13 03:06:51 +02:00
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
```
---
#### generateDecisionTree(): [python]
2020-05-13 03:06:51 +02:00
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(): [python]
2020-05-13 03:06:51 +02:00
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 w projekcie całościowym
Klasa wywoływana w **C++** nazywa się *injectCode*.
Działanie polega na tym że, funkcja **stanPola** sprawdza jakie wartości ma dane pole i generuje odpowiednie polecenie do wykonania.
#### stanPola(): [C++]
2020-05-13 03:06:51 +02:00
```
void stanPola(int x, int y) {
//[x][x][0] = 0 - brak chemii
//[x][x][0] = 1 - tylko nawóz
//[x][x][0] = 2 - tylko środek
//[x][x][0] = 3 - środek i nawóz
//[x][x][1] - wartość wzrostu rośliny
2020-05-13 03:06:51 +02:00
if (stan[x][y][0] == 0)
polecenie.append("0 0 ");
if (stan[x][y][0] == 1)
polecenie.append("1 0 ");
if (stan[x][y][0] == 2)
polecenie.append("0 1 ");
if (stan[x][y][0] == 3)
polecenie.append("1 1 ");
int w = (stan[x][y][1]);
std::string s = std::to_string(w);
polecenie.append(s);
}
2020-05-13 03:06:51 +02:00
```
Następnie funckja **decisionTree** wykonuje wygenerowane zapytanie.
#### decisionTree(): [C++]
```
void decisionTree(string polecenie) {
std::string str = polecenie;
const char* c = str.c_str();
system(c);
}
```
#### injectCode(): [python]
```
import pickle
import sys
def prediction(warzywo, nawoz ,srodek, stan_wzrostu):
filename = 'decisionTree.sav'
tree = pickle.load(open(filename, 'rb'))
val = (tree.predict([[warzywo, nawoz, srodek, stan_wzrostu]]))
print(decision(val))
def decision(prediction):
if prediction == 0:
return "Nie_podejmuj_dzialania"
elif prediction == 1:
return "Zastosuj_nawoz"
elif prediction == 2:
return "Zastosuj_srodek"
elif prediction == 4:
return "Zbierz"
elif prediction == 5:
return "Roslina_juz_zgnila__zbierz_i_wyrzuc"
if __name__ == '__main__':
# Map command line arguments to function arguments.
prediction(*sys.argv[1:])
2020-05-13 03:06:51 +02:00
```
Generowane polecenie wygląda w ten sposób:
2020-05-13 03:06:51 +02:00
```
python injectCode.py a b c d
```
Gdzie:
* a -> rodzaj warzywa
* 1: "burak"
2020-05-13 03:06:51 +02:00
* 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ę.