SI2020/Raport- drzewa decyzyjne.md

5.2 KiB

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ę.