Zaktualizuj 'decisiontree.md'

This commit is contained in:
Kamila Matysiak 2020-05-24 20:14:49 +00:00
parent bbc9b3fc34
commit 905a2d9c1e

View File

@ -2,77 +2,37 @@
**Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka **Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka
**Temat podprojektu:** Wybór trybu pracy traktora za pomocą drzewa decyzyjnego
**Autor podprojektu:** Kamila Matysiak **Autor podprojektu:** Kamila Matysiak
### Drzewo Decyzyjne ### Drzewo Decyzyjne
Projekt wykorzystuje drzewo decyzyjne do wybrania najoptymalniejszego trybu. Uruchamia się go za pomocą klawisza **F6**. Projekt wykorzystuje drzewo decyzyjne do wybrania czynności dla każdego pola, a następnie wysłania traktora do pól zgodnych z obecnie wybranym trybem.
#### Przygotowanie Danych: Projekt używa metody CART (Classification and Regression Tree). Tworzy on drzewo binarne, w którym rozpatruje wszystkie możliwe podziały zbioru wartości cech na dwa rozłączne i uzupełniające się podzbiory dla cech dyskretnych.
Za przygotowanie danych odpowiedzialne są dwie funkcje: Uruchamia się go za pomocą klawisza **F6**.
**find_best_action**, która pobiera macierz pól, tworzy macierz czynności do wykonania, a następnie buduje drzewo.
#### Zbiór uczący:
Zbiorem uczącym jest zestaw danych informujących drzewo jak postępować z polem o danych parametrach.
Kolejne cyfry odpowiadają za: nawodnienie pola, obecność chwastów, czy pole jest puste, czy jest do zbioru.
``` ```
def find_best_action(self): training_data = [[0, 0, 1, 0, "Zasadzic"],
testing_data = [] [0, 1, 1, 0, "Odchwascic"],
matrix = self.field.get_matrix() # pobranie macierzy pól [0, 0, 0, 0, "Podlac"],
matrix_todo = [] [0, 1, 0, 0, "Odchwascic"],
for i in range(10): [1, 0, 1, 0, "Zasadzic"],
matrix_todo.append([]) [1, 1, 1, 0, "Odchwascic"],
verse = matrix[i] [1, 0, 0, 0, "Czekac"],
for j in range(len(verse)): [1, 1, 0, 0, "Odchwascic"],
coord = (i, j) [0, 0, 0, 1, "Zebrac"]]
current_field = check(verse[j]) # czynnosci ktore trzeba jeszcze zrobic na kazdym polu self.tree = build_tree(training_data)
matrix_todo[i].append([]) print_tree(self.tree)
for action in current_field:
matrix_todo[i][j].append(action[-1])
testing_data.extend(current_field)
if len(testing_data) > 0:
x = build_tree(testing_data) # zbudowanie drzewa
print_tree(x)
if isinstance(x, Leaf): # wybór najlepszej czynności do wykonania
self.best_action = self.find_remaining_action(matrix_todo)
return
self.best_action = x.question.column
print(header[x.question.column])
print(x.question.value)
else:
self.best_action = self.find_remaining_action(matrix_todo)
return
```
Drugą funkcją jest **check**, która interpretuje pola z macierzy na podstawie numerów, dodając stringa z czynnością do wykonania na danym polu.
```
def check(field):
if field == 0:
return [[0, 0, 1, 0, "Zasadzic"], [0, 0, 1, 0, "Podlac"]]
elif field == 1:
return [[0, 1, 1, 0, "Odchwascic"], [0, 1, 1, 0, "Podlac"], [0, 1, 1, 0, "Zasadzic"]]
elif field == 2:
return [[0, 0, 0, 0, "Podlac"]]
elif field == 3:
return [[0, 1, 0, 0, "Odchwascic"], [0, 1, 0, 0, "Podlac"]]
elif field == 4:
return [[1, 0, 1, 0, "Zasadzic"]]
elif field == 5:
return [[1, 1, 1, 0, "Odchwascic"], [1, 1, 1, 0, "Zasadzic"]]
elif field == 6:
return []
elif field == 7:
return [[1, 1, 0, 0, "Odchwascic"]]
elif field == 8:
return [[0, 0, 0, 1, "Zebrac"], [0, 0, 0, 1, "Potem podlac"], [0, 0, 0, 1, "Potem zasadzic"]]
else:
print("Błąd: Zły numer pola.")
``` ```
#### Budowanie Drzewa: #### Algotytm tworzenia drzewa:
Budowanie drzewa zaczynamy od stworzenia klasy **Question**, w której będziemy tworzyć zapytanie, na podstawie którego będziemy dzielić nasze dane. Następnie tworzymy funkcję **partition**, która na podstawie zapytania dzieli nam dane na spełnione i niespełnione wiersze: Budowanie drzewa zaczynamy od stworzenia klasy **Question**, w której będziemy tworzyć zapytanie, na podstawie którego będziemy dzielić nasze dane. Następnie tworzymy funkcję **partition**, która na podstawie zapytania dzieli nam dane na spełnione i niespełnione wiersze:
@ -88,9 +48,9 @@ def partition(rows, question):
return true_rows, false_rows return true_rows, false_rows
``` ```
Następnie wyokrzystujemy **Index Gini** i **Info Gain**. Następnie wyokrzystujemy **Index Gini**, który mierzy jak często losowo wybrany element będzie źle zindentyfikowany. Gdy jest równy 0, oznacza to, że element zostanie właściwie oznaczony.
Index Gini mierzy jak często losowo wybrany element będzie źle zindentyfikowany.
Information gain mierzy zmianę entropii, która powstaje na skutek podziału zestawu danych testowych na mniejsze części.
``` ```
# funkcja implementująca indeks gini # funkcja implementująca indeks gini
@ -102,7 +62,6 @@ def gini(rows):
impurity -= prob_of_lbl ** 2 impurity -= prob_of_lbl ** 2
return impurity return impurity
#information gain
def info_gain(left, right, current_uncertainty): def info_gain(left, right, current_uncertainty):
p = float(len(left)) / (len(left) + len(right)) p = float(len(left)) / (len(left) + len(right))
return current_uncertainty - p * gini(left) - (1 - p) * gini(right) return current_uncertainty - p * gini(left) - (1 - p) * gini(right)
@ -148,22 +107,20 @@ def build_tree(rows):
#### Integracja: #### Integracja:
Gdy za pomocą funkcji **find_best_action** zostanie wybrana najbardziej opłacalna czynność wykorzystujemy algorytm A* zaimplementowany w pliku **pathfinding.py**. Ustawiamy tryb traktora i w pętli każemy znajdować mu pola. Program sczytuje dane z głównego projektu, następnie interpretuje je za pomocą prostej funkcji **translate**, która zwraca informacje o stanie pola. Następnie za pomocą drzewa określamy czynność, jaka powinna zostać wykonana na tym polu. Wykonanie pracy zlecamy klasie **pathfinding**, która za pomocą algorytmu A* wysyła traktor na pola odpowiadające wybranemu trybowi.
``` ```
def do_best_action(self): def search_field(self):
self.traktor.set_mode(self.best_action) matrix = self.field.get_matrix()
while self.path.pathfinding(self.traktor, self.field, self.ui) != 0: for i in range(len(matrix)):
pass for j in range(len(matrix[i])):
print("Pole (%d,%d) Przewidziania czynnosc: %s"
% (i, j, print_leaf(classify(translate(matrix[i][j]), self.tree))))
if work[self.traktor.get_mode()] in self.work_field(classify(translate(matrix[i][j]), self.tree)):
print("Zgodna z aktualnym trybem, czynnosc wykonywana")
self.path.find_path(self.traktor, self.field, self.ui, [j, i])
self.ui.update()
time.sleep(0.5)
``` ```
Kiedy zostanie już tylko jedna czynność do wykonania przypisujemy jej **find_remaining_action**, dzięki czemu nasze pole zostanie w pełni oprawione.
```
def find_remaining_action(self, matrix_todo):
for row in matrix_todo:
for field in row:
for action in field:
print(action)
return work.index(action)
return -1
```