##Jarosław Zbąski – raport z podprojektu --- #Wybrana metoda: --- Do realizacji podprojektu wykorzystano drzewa decyzyjne wskazujące którą roślinę (jeśli w ogóle) należy posadzić na danym polu. Drzewo decyzję podejmuje na podstawie poszczególnych parametrów gleby: -żyzność (‘z’-żyzna, ‘j’-jałowa) -nawodnienie (‘n’ - nawodniona, ‘s’ - sucha) -nasłonecznienie (‘s’ - w słońcu, ‘c’ – w cieniu) -kwasowość gleby (‘k’ – kwasowa, ‘n’ – neutralna, ‘z’ - zasadowa) #Uczenie modelu: --- Dane treningowe: ``` training_data = [ #zyznosc, nawodnienie, cien, kwasowość, grupa ['z', 'n', 's', 'z', 1], ['z', 'n', 's', 'n', 1], ['j', 'n', 's', 'z', 1], ['z', 's', 's', 'n', 1], ['j', 'n', 'c', 'n', 1], ['z', 'n', 's', 'k', 1], ['z', 'n', 'c', 'k', 2], ['z', 's', 's', 'k', 2], ['z', 's', 'c', 'k', 2], ['j', 'n', 's', 'k', 2], ['z', 's', 'c', 'z', 3], ['j', 'n', 's', 'n', 3] ] ``` Budowanie drzewa decyzyjnego opiera się na podziale gałęzi względem algorytmu CART. Ma ono postać ciągu pytań, na które odpowiedzi determinują kolejne pytania, bądź kończą etap. W wyniku otrzymujemy strukturę drzewa, która w węzłach końcowych nie zawiera już pytań, lecz same odpowiedzi. Dodatkowo wypisuje liczbę zestawów danych pasujących do liścia z zestawu treningowego. ``` def build_tree(rows): gain, question = find_best_split(rows) if gain == 0: return Leaf(rows) true_rows, false_rows = partition(rows, question) true_branch = build_tree(true_rows) false_branch = build_tree(false_rows) return Decision_Node(question, true_branch, false_branch) ``` Znajdowanie najlepszego podziału opiera się głównie na Współczynniku Giniego, który mierzy stopień niejednorodności i dzieli ją przez ilość pozostałych zestawów testowych. ``` def find_best_split(rows): best_gain = 0 best_question = None current_uncertainty = gini(rows) n_features = len(rows[0]) - 1 for col in range(n_features): values = set([row[col] for row in rows]) for val in values: question = Question(col, val) true_rows, false_rows = partition(rows, question) if len(true_rows) == 0 or len(false_rows) == 0: continue gain = info_gain(true_rows, false_rows, current_uncertainty) if gain >= best_gain: best_gain, best_question = gain, question return best_gain, best_question ``` Drzewo powstałe poprzez wykonanie metody print_tree(node,spacing) na zestawie testowym: ``` Czy kwasowosc == k? --> True: Czy cien == s? --> True: Czy nawodnienie == n? --> True: Czy zyznosc == j? --> True: Predict {2: 1} --> False: Predict {1: 1} --> False: Predict {2: 1} --> False: Predict {2: 2} --> False: Czy cien == s? --> True: Czy zyznosc == j? --> True: Czy kwasowosc == n? --> True: Predict {3: 1} --> False: Predict {1: 1} --> False: Predict {1: 3} --> False: Czy kwasowosc == n? --> True: Predict {1: 1} --> False: Predict {3: 1} ``` #Implementacja w C++: --- Komunikacja między pythonem a cpp zachodzi przez pliki dane.txt i decyzje.txt. W pliku dane.txt cpp wypisuje stan całego pola w oddzielonych spacją kolumnach począwszy od indeksu x=1,y=1 aż po x=25,y=25. Decyzje podjęte przez drzewo decyzyjne wypisane w pliku decyzje.txt zawierają symbol rośliny lub pola jakie mają się znajdować na polu (również w całej przestrzeni pola). Zestaw testowych danych: ``` void testSI1() { for (int i = 1; i < 26; i++) { for (int j = 1; j < 26; j++) { if (j % 3 == 0) { pole[i][j][2] = 'z'; //zyzne pole[i][j][3] = 'n'; //nawodnione pole[i][j][4] = 'c'; //w cieniu pole[i][j][5] = 'k'; //kwasne } else { if (j % 3 == 1) { pole[i][j][2] = 'j'; //jalowe pole[i][j][3] = 'n'; //nawodnione pole[i][j][4] = 's'; //w sloncu pole[i][j][5] = 'n'; //neutralne } else { pole[i][j][2] = 'z'; //zyzne pole[i][j][3] = 's'; //suche pole[i][j][4] = 's'; //sloneczne pole[i][j][5] = 'z'; //zasadowe } } } } } ``` Funkcja wysyłająca stan pola: ``` void sendState() { ofstream write("dane.txt"); for (int i = 1; i < 26; i++) { for (int j = 1; j < 26; j++) { string a; a += pole[i][j][2]; a += ' '; a += pole[i][j][3]; a += ' '; a += pole[i][j][4]; a += ' '; a += pole[i][j][5]; write << a << endl; } } write.close(); } ``` Funkcja kierująca traktorem (decyzja co zasiać): ``` void reciveState() { ifstream read("decyzje.txt"); if (read.is_open()) { char plant; int i = 1; int j = 1; while (read >> plant) { if (j == 25) { gogo(1, i+1); } else { gogo(j+1 , i ); } pole[i][j][0] = plant; if (plant == '.') { pole[i][j][1] = '1'; } else { pole[i][j][1] = '9'; } if (j == 25) { j = 1; i += 1; } else { j += 1; } } } } ```