Marcin Dobrowolski - podprojekt

This commit is contained in:
Marcin Dobrowolski 2020-05-27 10:28:47 +02:00
parent d89e37e6eb
commit 55b9625189
2 changed files with 139 additions and 169 deletions

View File

@ -4,47 +4,36 @@
**Temat:** Sugerowanie potraw
**Metoda uczenia:** Decision Tree(CART)
**Autor:** Marcin Jerzy Dobrowolski
**Okres trwwania prac:** 29 kwietnia - 27 maja 2020
**Źródła:** https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb
**Link do repozytorium projektu:** https://git.wmi.amu.edu.pl/s444427/Sztuczna_Inteligencja_2020
## Wstęp
Tematem realizowanego projektu jest stworzenie sztucznej inteligencji, która na podstawie podanych atrybutów stwierdzi jaka potrawa będzie najlepszym wyborem dla gościa restauaracji. Atrybuty odpowiadają na takie pytania jak:
* czy gość jest wegetarianinem? - {meat, vege}
* jak bardzo chce się najeść/jak wielka ma być potrawa? - {small, regular, large}
* ile gotówki może przeznaczyć na ten cel? - {<10;20>, <20;30>, <30;40>, <40;50>, <50;60>}
* jak jaki jest jego apetyt? - {<10;25>, <25;40>, <40;55>}
Powyższymi atrybutami rządzą pewne zależności. Apetyt gościa ma wpływ na to jaka potrawa będzie dla niego mała, średnia bądź duża.
Do osiągnięcia celu wykorzystałem metodę drzew decyzyjnych CART oraz następujące biblioteki języka python:
* csv
* random
## Uczenie modelu
### Zbiór uczący
Do zbudowania drzewa decyzyjnego wykorzystałem spreparowany przez siebie zbiór przykładów atrybutów gości z odpowiadającymi im daniami. Zawarte jest w nim 213 przykładów dotyczących 20 różnych potraw. Całość znajduje się w pliku: [trainingData.csv](src/SubprojectMarcinDobrowolski/Data/trainingData.csv)
### Moduły
Projekt rozwiązuje problem zasugerowania dania przez kelnera na podstawie danych reprezentujących preferencje gościa. W tym celu wykorzystałem metodę uczenia drzew decyzyjnych CART, którą zaprogramowałem w czystym języku python. Struktura podprojektu:
* [suggestionDecisionTree.py](src/SubprojectMarcinDobrowolski/suggestionDecisionTree.py) - klasa drzew decyzyjnego
* [question.py](src/SubprojectMarcinDobrowolski/question.py) - klasa pytania
* [leaf.py](src/SubprojectMarcinDobrowolski/leaf.py) - klasa liścia
* [decisionNode.py](src/SubprojectMarcinDobrowolski/decisionNode.py) - klasa wierzchołka
* [decisionNode.py](src/SubprojectMarcinDobrowolski/decisionNode.py) - klasa wierzchołka pytającego
* [utility.py](src/SubprojectMarcinDobrowolski/utility.py) - klasa użytkowa
* [testData.csv](src/SubprojectMarcinDobrowolski/Data/testData.csv) - zbiór testowy
* [trainingData.csv](src/SubprojectMarcinDobrowolski/Data/trainingData.csv) - zbiór uczący
* [testData.csv](src/SubprojectMarcinDobrowolski/Data/testData.csv) - klasa użytkowa
Struktura danych reprezentujących preferencje gościa:
type, size, money, appetite, name
['meat', 'small', 31, 55, 'schabowy']
### Opis modułów
* type - typ potrawy: wegańska lub z mięsem
* appetite - apetyt gościa, świadczy o tym jak duża potrawa spełni jego oczekiwania,
np. duże danie będzie inne dla osób o dużym i małym apetycie
* size - rozmiar dania
* money - zawartość portfela gościa, czyli na jak dużo może sobie pozwolić
* name - etykieta potrawy, dopasowana w taki sposób by spełnić powyższe wymagania
## Opis modułów
W pliku *utility* znajdują się podręczne funkcje użytkowe wykorzystywane przez pozostałe moduły programu.
@ -97,7 +86,7 @@ Generuje zbiór danych testowych o zadanej wielkości i zapisuje go w pliku o po
Działa na takiej samej zasadzie jak jej poprzedniczka. Z tym wyjątkiem, że generuje pojedynczy przykład.
Klasa *Question* reprezentuje pytanie, które służy do podziału danych w wierzchołkach decyzyjnych drzewa. Jej atrybuty oznajczają kolejno: etykiete kolumny zbioru danych, indeks wspomnianej kolumny oraz wartość, której dotyczy pytanie.
Klasa *Question* reprezentuje pytanie, które służy do podziału danych w wierzchołkach decyzyjnych drzewa. Jej atrybuty oznajczają kolejno: etykiete kolumny zbioru danych, indeks wspomnianej kolumny oraz wartość, której dotyczyy pytanie.
class Question:
def __init__(self, columnLabel, column, value):
@ -112,7 +101,7 @@ Klasa *Question* reprezentuje pytanie, które służy do podziału danych w wier
else:
return val == self.value
Metoda match wskazuje jak na pytanie odpowiada zadany przykład.
Metoda match decyduje jak na pytanie odpowiada zadany przykład.
Jądro algorytmu znajduje się w klasie *suggestionTree* w pilku *suggestionDecisionTree*. Metoda *readTrainingData* służy do odczytania zbioru uczącego z pliku *trainingData.csv* i zwrócenia przechowywanych w nim danych wraz z ich etykietami.
@ -193,7 +182,7 @@ Metoda *findBestSplit* znajduje pytanie, które w danej chwili spowoduje jak naj
return bestGain, bestQuestion
Klasa *Leaf* jest reprezentacją liścia drzewa czyli najbardziej zewnętrznego wierzchołka. W atrybucie *predictions* przechowuje oszacowanie etykiet/y, które może przyjąć przykład, który do niego trafi. Metoda *printLeaf* służy do eleganckiego wyświetlania oszacowania.
Klasa *Leaf* jest reprezentacją liścia drzewa czyli najbardziej zewnętrznego wierzchołka. W atrybucie *predictions* przechowuje oszacowanie etykiet/y, które może przyjąć przykład, który doń trafi. Metoda *printLeaf* służy do eleganckiego wyświetlania oszacowania.
class Leaf:
def __init__(self, rows):
@ -261,52 +250,33 @@ Metoda *printTree* wyświetla strukturę drzewa w postaci tekstu w wierszu polec
Metoda *classify* przyporządkowuje danemu przykładowi odpowiadającą mu etykiete w drzewie.
### Działanie
## Działanie
Drzewo jest budowane na podstawie zbioru uczącego. Algorytm podejmuje decyzje o tym jak podzielić zbiór na podstawie przyrostu informacji wynikającego z potencjalnego podziału. Przerywa działanie gdy przyrost wynosi *0*, co oznacza, że dotarł do liścia drzewa i dalszy podział nie jest możliwy. Kończąc swoje działanie zwraca korzeń klasy *DecisionNode*, który zawiera w atrybutach potomków> Umożliwia to rekurencyjne schodzenie po drzewie, które jest realizowane przez metodę *classify*.
Drzewo jest budowane na podstawie zbioru uczącego. Algorytm podejmuje decyzje o tym jak podzielić zbiór na podstawie przyrostu informacji wynikającego z potencjalnego podziału. Przerywa działanie gdy przyrost wynosi *0*, co oznacza, że dotarł do liścia drzewa i podział nie jest możliwy. Kończąc swoje działanie zwraca korzeń klasy *DecisionNode*, który zawiera w atrybutach potomków co umożliwia rekurencyjne schodzenie po drzewie.
### Integracja z projektem
Deklaracja oraz inicjalizacja korzenia drzewa:
suggestionTreeRoot = SuggestionTree.buildTree(trainingData)
W projekcie można sprawdzić działanie podprojektu poprzez wciśnięcie, któregoś z klawiszy:
* 0 - sprawdzenie poprawności algorytmu na losowo wygenerowanym zbiorze testowym.
generateTestData('testData.csv', 100)
testData = []
with open('src/SubprojectMarcinDobrowolski/Data/testData.csv') as csv_file:
csvReader = csv.reader(csv_file, delimiter=',')
lineCount = 0
for row in csvReader:
example = []
for column in row:
if column.isdigit():
example.append(int(column))
else:
example.append(column)
if lineCount > 0:
testData.append(example)
lineCount += 1
print('Processed lines: ', lineCount)
print('Test examples predictions:')
for example in testData:
print('{} - {}'.format(example, SuggestionTree.classify(
example, suggestionTreeRoot).printLeaf()))
W projekcie można je wykorzystać poprzez wciśnięcie, któregoś z klawiszy:
* 0 - sprawdzenie poprawności algorytmu na losowo wygenerowanym zbiorze testowym. =
* 1 - sprawdzenie poprawności algorytmu na losowo wygenerowanym przykładzie.
example = generateTestExample()
print('Test example prediction: ')
print('{} - {}'.format(example, SuggestionTree.classify(
example, suggestionTreeRoot).printLeaf()))
* 2 - wyświetlenie struktury drzewa
SuggestionTree.printTree(suggestionTreeRoot)
Rezultaty zostają wypisane w konsoli.
Rezultaty zostają wypisane w konsoli.
```
module: pygames
Python: 3.7.7
```
macOS / Linux
```
pygames
python main.py
```
Windows
```
pygames
python main.py
```

196
path
View File

@ -1,101 +1,101 @@
type,size,money,appetite
meat,regular,40,46
meat,regular,38,15
meat,regular,35,50
meat,little,42,25
meat,regular,29,34
meat,little,38,47
meat,regular,33,34
meat,regular,54,29
meat,regular,47,44
meat,regular,27,15
meat,regular,32,13
meat,little,53,39
meat,little,40,44
meat,regular,25,39
meat,regular,50,52
meat,regular,29,20
meat,little,58,31
meat,regular,36,45
meat,regular,59,20
meat,regular,54,48
meat,regular,25,32
meat,regular,36,23
meat,regular,57,29
meat,little,13,54
meat,little,43,52
meat,little,58,24
meat,little,30,35
meat,little,24,33
meat,regular,24,30
meat,regular,41,48
meat,regular,35,37
meat,little,36,11
meat,regular,22,24
meat,regular,58,14
meat,little,34,29
meat,little,30,38
meat,regular,54,45
meat,regular,31,43
meat,little,58,46
meat,little,48,38
meat,regular,44,44
meat,regular,51,49
meat,little,53,34
meat,regular,51,48
meat,regular,46,35
meat,little,32,22
meat,little,14,37
meat,little,14,37
meat,little,46,13
meat,regular,40,16
meat,regular,40,49
meat,little,47,40
meat,little,56,48
meat,little,53,11
meat,regular,45,25
meat,little,17,34
meat,regular,39,41
meat,little,31,30
meat,little,14,14
meat,regular,38,38
meat,regular,51,28
meat,little,58,22
meat,little,35,17
meat,regular,47,36
meat,little,55,20
meat,regular,36,10
meat,regular,53,22
meat,regular,23,33
meat,regular,27,29
meat,regular,49,32
meat,regular,36,15
meat,regular,59,25
meat,little,17,43
meat,regular,39,49
meat,little,35,33
meat,little,10,32
meat,little,11,49
meat,regular,53,15
meat,regular,29,13
meat,little,12,14
meat,little,27,31
meat,regular,31,21
meat,regular,58,13
meat,little,46,19
meat,little,11,27
meat,regular,44,28
meat,regular,40,14
meat,little,57,24
meat,regular,38,52
meat,little,37,31
meat,regular,34,15
meat,little,41,25
meat,regular,30,22
meat,little,58,15
meat,regular,22,12
meat,little,46,44
meat,regular,47,11
meat,little,52,30
meat,little,49,24
meat,little,28,30
meat,regular,27,19
meat,regular,51,43
meat,little,59,10
meat,regular,38,44
meat,regular,30,37
meat,little,44,24
meat,regular,34,45
meat,regular,50,49
meat,regular,36,50
meat,little,13,22
meat,little,28,25
meat,regular,29,14
meat,regular,56,17
meat,regular,31,45
meat,regular,57,42
meat,regular,44,30
meat,regular,33,45
meat,little,52,25
meat,little,48,15
meat,regular,44,53
meat,little,30,28
meat,little,39,23
meat,little,52,28
meat,little,16,17
meat,little,22,54
meat,little,51,50
meat,regular,51,25
meat,little,14,28
meat,little,51,25
meat,regular,26,27
meat,regular,26,35
meat,little,41,24
meat,regular,22,38
meat,regular,37,25
meat,regular,41,28
meat,little,54,12
meat,regular,31,22
meat,regular,38,17
meat,little,51,32
meat,little,20,54
meat,little,36,30
meat,regular,33,46
meat,little,43,16
meat,regular,30,10
meat,little,14,36
meat,little,51,24
meat,little,11,13
meat,little,53,54
meat,regular,27,12
meat,regular,41,30
meat,little,13,25
meat,little,34,43
meat,regular,51,45
meat,regular,39,37
meat,little,44,54
meat,regular,37,12
meat,regular,46,13
meat,regular,25,21
meat,regular,37,13
meat,little,45,32
meat,little,28,46
meat,little,11,22
meat,little,37,32
meat,little,26,20
meat,regular,21,35
meat,regular,40,18
meat,regular,59,42
meat,regular,36,42
meat,regular,57,16
meat,little,20,47
meat,little,18,34
meat,regular,23,30
meat,regular,44,23
meat,little,41,28
meat,little,12,49
meat,regular,33,10
meat,regular,44,21
meat,little,57,51
meat,regular,49,45
meat,regular,36,40
meat,little,24,11
meat,little,45,45
meat,little,59,30
meat,little,16,23
meat,little,57,13
meat,little,58,36
meat,little,35,16
meat,little,44,54
meat,regular,21,21
meat,little,57,31
meat,little,50,34
meat,regular,25,40
meat,regular,57,45
meat,little,28,22
meat,regular,41,53
meat,little,10,19
meat,little,32,53
meat,little,29,22