From 3c8c66359771f548c929d5b8af1d9f86114432f5 Mon Sep 17 00:00:00 2001 From: Natalia Date: Sun, 24 May 2020 18:06:58 +0200 Subject: [PATCH] commit_natalia2 --- .idea/DSZI.iml | 2 +- .idea/misc.xml | 2 +- Restaurant/Natalia/__init__.py | 2 +- Restaurant/main.py | 74 ++++++++++++++++- polecanie_dań_Natalia_Plitta.md | 131 +++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 polecanie_dań_Natalia_Plitta.md diff --git a/.idea/DSZI.iml b/.idea/DSZI.iml index 0267347..252f3ef 100644 --- a/.idea/DSZI.iml +++ b/.idea/DSZI.iml @@ -5,7 +5,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index a2e120d..d209534 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Restaurant/Natalia/__init__.py b/Restaurant/Natalia/__init__.py index 67ffc7c..4c7ce97 100644 --- a/Restaurant/Natalia/__init__.py +++ b/Restaurant/Natalia/__init__.py @@ -25,7 +25,7 @@ def main(): X = model_tree[feature_cols] #separacja danych etykieta y = model_tree.number - # Target variable + #podział danych na zestaw treningowy i testowy; 70% trening 30% test X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, diff --git a/Restaurant/main.py b/Restaurant/main.py index 11984e4..30d5597 100644 --- a/Restaurant/main.py +++ b/Restaurant/main.py @@ -437,6 +437,41 @@ def predictDigest(dish, client, model): messagebox.showinfo("opinia", "Z tym nie będzie tak źle! " + str(data)) return prediction +def ShowImg(file): + zdjęcie = Image.open(file) + zdjęcie.show() + +def show_predict(dish, client, model): + data = [] + data.append(client.age) + data.append(dish.fatContent) + data.append(dish.fiberContent) + data.append(client.sex) + data.append(dish.spicy) + prediction = model.predict([data]) + + + if prediction == 1: + ShowImg("Natalia/danie1.png") + return prediction + elif prediction == 2: + ShowImg("Natalia/danie2.png") + return prediction + elif prediction == 3: + ShowImg("Natalia/danie3.png") + return prediction + elif prediction == 4: + ShowImg("Natalia/danie4.png") + return prediction + elif prediction == 5: + ShowImg("Natalia/danie5.png") + return prediction + elif prediction == 6: + ShowImg("Natalia/danie6.png") + return prediction + else: + ShowImg("Natalia/danie7.png") + return prediction def evaluate(b): @@ -564,6 +599,43 @@ def payment(c): else: pass +def Tree_natalia(d): + if d == 1: + loaded_model = joblib.load('Natalia/final_model.sav') + messagebox.showinfo("Zaczynamy!", "Zaczynamy!") + + prefer1 = Dish("prefer1", 40, 20, 15) + prefer2 = Dish("prefer2", 25, 10, 10) + prefer3 = Dish("prefer3", 55, 25, 28) + + plate1 = Plate(prefer1, "Natalia/danie1.png") + plate2 = Plate(prefer2, "Natalia/danie2.png") + plate3 = Plate(prefer3, "Natalia/danie3.png") + + client1 = Client(25, 1, 45, 1) + client2 = Client(41, 0, 22, 4) + client3 = Client(10, 0, 32, 8) + + client1.takePlateAndEat(plate1) + client2.takePlateAndEat(plate2) + client3.takePlateAndEat(plate3) + + bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1])) + opinion = show_predict(prefer1, client1, loaded_model) + + bot.goByAStar((tables[3].pos[0] + 1, tables[3].pos[1])) + opinion = show_predict(prefer2, client2, loaded_model) + + bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1])) + opinion = show_predict(prefer3, client3, loaded_model) + + messagebox.showinfo("Informacja końcowa", "Zakończono trasę.") + + pygame.quit() + exit() + else: + pass + def text_objects(text, font): textSurface = font.render(text, True, black) return textSurface, textSurface.get_rect() @@ -741,7 +813,7 @@ def main(): button("Rozpoznawanie talerzy", 0, width + 1, 150, 48, light_beige, white, classify) button("Ciężkostrawność dań", 150, width + 1, 150, 48, light_beige, white, evaluate) button("Rozpoznawanie banknotów", 300, width + 1, 150, 48, light_beige, white, payment) - button("Polecanie dań", 450, width + 1, 150, 48, light_beige, white) #Natalia tu dopisz swoją funkcję :) + button("Polecanie dań", 450, width + 1, 150, 48, light_beige, white, Tree_natalia) redrawWindow(window) pygame.quit() diff --git a/polecanie_dań_Natalia_Plitta.md b/polecanie_dań_Natalia_Plitta.md new file mode 100644 index 0000000..e200b22 --- /dev/null +++ b/polecanie_dań_Natalia_Plitta.md @@ -0,0 +1,131 @@ +##### Raport przygotowała: Natalia Plitta + +##### Raportowany okres: 11 maja - 25 maja 2020 + +##### Niniejszy raport poświęcony jest przekazaniu informacji na temat stanu mini-projektu indywidualnego w ramach projektu grupowego realizowanego na przedmiot Sztuczna Inteligencja w roku akademickim 2019/2020. + +Tematem realizowanego projektu indywidualnego jest stworzenie sztucznej inteligencji, która na podstawie podanych parametrów poleca jedno z siedmiu dań. Wykorzystane zostały poniższe biblioteki: + +- scikit - learn +- joblib +- IPython +- pandas +- pydotplus +- StringIO +##Realizacja projektu ## + +#### Dane wejściowe: #### + +Do utworzenia modelu przygotowałam zestaw danych składający się z 60 krotek, każda składająca się z 6 liczb oznaczających odpowiednio: + +- wiek osoby zamawiającej danie (z przedziału 10 do 60); +- zawartość tłuszczu w daniu (z przedziału 0 do 16); +- zawartość błonnika w daniu (z przedziału 0 do 16); +- płeć osoby zamawiającej (0 - mężczyzna lub 1 - kobieta); +- wskazanie czy danie jest ostre czy nie (0 - nieostre lub 1 - ostre); +- wskazanie czy danie jest ciężkostrawne czy nie (0 - nie lub 1 - tak); + +Liczby oddzielone są przecinkami i zapisane w pliku z rozszerzeniem .csv. + +#### Proces uczenia: #### + +Na początku dane są importowane do programu: + +```python +def dataImport(): + dataset = pd.read_csv('learnData4.csv', sep=',', header=None) + return dataset +``` + +Następnie dane są dzielone odpowiednio na zestaw cech (*X*) i zestaw klas - "wyników" (*Y*). Zbiory te są jeszcze, przy pomocy funkcji **train_test_split** (z biblioteki scikit - learn) dodatkowo dzielone na zestawy do uczenia i zestawy do testowania (*x_train*, *x_test*, *y_train*, *y_test*): + +```python +def splitDataSet(dataset): + X = dataset.values[:, 0:5] + Y = dataset.values[:, 5] + x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=100) + return X, Y, x_train, x_test, y_train, y_test +``` + +Zbiór danych testowych składa się z 0.3 krotek zestawu początkowego. + +Korzystając z funkcji **DecisionTreeClassifier** utworzony zostaje model w postaci drzewa, do którego następnie zostają załadowane uprzednio przygotowane zbiory danych: + +```python +model = tree.DecisionTreeClassifier() +model2 = tree.DecisionTreeClassifier(criterion="entropy") + +model.fit(x_train, y_train) +model2.fit(x_train, y_train) +``` + +Funkcja **DecisionTreeClassifier** domyślnie wykorzystuje indeks Gini jako kryterium podziału. Ja jednakże, wygenerowałam dodatkowo model, gdzie jako kryterium podziału została przyjęta entropia. + +Następnie modele zostają poddane testowi i obliczony zostaje wskaźnik trafności wygenerowanych, na zbiorze testowym, wyników: + +```python +pred = model.predict(x_test) +pred2 = model2.predict(x_test) + +acc = accuracy_score(y_test, pred) * 100 +acc2 = accuracy_score(y_test, pred2) * 100 + +print("akuratnosc dla modelu Gini: " + str(acc)) # aprox. 77.78% +print("akuratnosc dla modelu Entropy: " + str(acc2)) # aprox. 83.33% +``` + +#### Operacje na wygenerowanym modelu: #### + +W tym przypadku, model z entropią daje nam większą trafność. Zatem to on zostanie wykorzystany w głównym programie. Model drzewa zostaje zapisany w pliku .sav: + +```python +filename = 'finalized_model.sav' +joblib.dump(model2, filename) +``` + +Dodatkowo zostaje wygenerowane (przy pomocy biblioteki Graphviz i IPython) graficzne przedstawienie drzewa i zapisane w pliku .png: + +```python +dot_data2 = tree.export_graphviz(model2, out_file=None, feature_names=["age", "fat", "fiber", "sex", "spicy"], class_names=["easty to digest", "hard to digest"], filled=True, rounded=True, special_characters=True) + +graph2 pydotplus.graph_from_dot_data(dot_data2) +Image(graph2.create_png()) +graph2.write_png("digest_entropy.png") +``` + + + + + +## Integracja z projektem ## + +Po uruchomieniu programu i wybraniu na ekranie głównym opcji *Ciężkostrawność dań*, uruchomiona zostaje funkcja *Evaluate()*, która ładuje z pliku model drzewa. Zainicjowany zostaje również przykładowy stan restauracji (dodanie kilku klientów, przypisanie im stołów i talerzy). Wywoływany jest też przykładowy ruch kelnera, który podchodzi do kilku stolików i pomaga w ocenie strawności dania, przy pomocy funkcji *predictDigest()*: + +```python +def predictDigest(dish, client, model): + data = [] + data.append(client.age) + data.append(dish.fatContent) + data.append(dish.fiberContent) + data.append(client.sex) + data.append(dish.spicy) + prediction = model.predict([data]) + if prediction == 1: + messagebox.showinfo("opinia", "Z tym może być ciężko. " + str(data)) + return prediction + else: + messagebox.showinfo("opinia", "Z tym nie będzie tak źle! " + str(data)) + return prediction +``` + +Funkcja jako parametry przyjmuje obiekty danie, klient i załadowany model. Parametry potrzebne modelowi do wyznaczenia wyniku pobierane są z odpowiednich obiektów i jako tablica przekazywane do funkcji *predict()*. Następnie, w zależności od otrzymanego wyniku wyświetlany jest odpowiedni komunikat i dane jakie podlegały ocenie. + +Pola *fatContent*, *fiberContent*, *spicy* klasy *Dish* w momencie tworzenia instancji klasy są ustawiane na losowo wygenerowaną liczbę z odpowiednich przedziałów: + +```python +self.fatContent = random.randint(0, 16) +self.fiberContent = random.randint(0, 16) +self.spicy = random.randint(0, 1) +``` + +Po zakończeniu trasy wyświetlany jest stosowny komunikat, a aplikacja zostaje wyłączona. \ No newline at end of file