SzIProjekt/Natalia_Wiśniewska_drzewa_decyzyjne.md

3.0 KiB

Sztuczna inteligencja - projekt zespołowy - Autonomiczny Traktor

autorzy: Aleksandra Werda, Natalia Wiśniewska, Kinga Jagodzińska, Aleksandra Jonas


Natalia Wiśniewska - podprojekt: drzewa decyzyjne


Celem podprojektu jest ustalenie czy traktor powinien podlać dane pole. Wykorzystałam do tego drzewa decyzyjne w oparciu o algorytm CART.

Zbiór uczący

Zbiorem uczącym jest tablica, która składa się z 25 przykładów w których dane kolejno to:

  • informacja o tym czy gleba jest sucha lub nawodniona
  • ile dni temu ostatnio podlewano pole
  • co ile dni należy podlewać dane pole
  • czy ma tego dnia padać
  • kiedy ostatnio padało.
training_data = [
    ['n', 2, 3, 't', 1],
    ['s', 1, 3, 't', 1],
    ['s', 5, 2, 'n', 1],
    ['n', 3, 5, 'n', 1],

Tworzenie drzewa

Na samym początku program sprawdza czy odpowiednia wartość w danym przykładzie to liczba czy też litera.

def is_numeric(value):
    return isinstance(value, int) or isinstance(value, float)

Dzięki temu w klasie Question ustalamy w jaki sposób porównujemy ze sobą dane oraz budujemy takie pytanie.

class Question:
    def __init__(self, column, value):
        self.column = column
        self.value = value

    def match(self, example):
        val = example[self.column]
        if is_numeric(val):
            return val >= self.value
        else:
            return val == self.value

    def __repr__(self):
        condition = "=="
        if is_numeric(self.value):
            condition = ">="
        return "Czy %s %s %s?" % (
            header[self.column], condition, str(self.value))

Funkcja partition tworzy kolejne gałęzie poprzez podział odpowiedzi na fałszywe i prawdziwe.

Następnie obliczamy wartość gini oraz przyrost informacji:

def gini(rows):
    counts = class_counts(rows)
    impurity = 1
    for lbl in counts:
        prob_of_lbl = counts[lbl] / float(len(rows))
        impurity -= prob_of_lbl**2
    return impurity
    
def info_gain(left, right, current_uncertainty):
    p = float(len(left)) / (len(left) + len(right))
    return current_uncertainty - p * gini(left) - (1 - p) * gini(right)

Dzięki temu program ile informacji uzyska po podziale na podzbiory i może zadecydować, o które dane powinien zapytać.

Na sam koniec tworzymy nasze drzewo:

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)

Zawiera ono najbardziej opłacalne pytanie w korzeniu, a następnie dzieli drzewo na dwa podrzewa- takie, w którym odpowiedzią na pierwsze pytanie była prawda i takie, w którym był to fałsz. Następnie w tych węzłach program zadaje kolejne pytania tak jak w korzeniu. Odpowiedzi na ostatnie pytania nazywamy liśćmi. Na ich podstawie ustalamy czy pole należy podlać czy nie.