SI2020/RaportJaroslawZbaski.md

209 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

##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 zestaw 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 (entropia), co daje nam przyrost informacji.
```
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;
}
}
}
}
```