##### 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 ## #### Import danych: #### Na początku dane są pobierane z pliku "Nowy.csv" gdzie zostało przygotowanych 121 wierszy o kolumnach z kolejno podanymi nazwami. Następnie model zostal podzielony na cechy i etykietę ['number'], która oznacza polecane danie. ```python col_names = ['age', 'sex', 'fat', 'fiber', 'spicy', 'number'] model_tree = pd.read_csv("Nowy.csv", header=None, names=col_names) model_tree.head() feature_cols = ['age', 'sex', 'fat', 'fiber', 'spicy'] X = model_tree[feature_cols] y = model_tree.number ``` #### Dane: #### Aby utworzyć model, stworzyłam 121 wierszy z 6 kolejnych liczb oznaczających: - wiek klienta (7 - 80); - zawartość tłuszczu w daniu (0 - 16); - zawartość błonnika w daniu (0 - 16); - płeć osoby zamawiającej (0 - kobieta lub 1 - mężczyzna); - ostrość dania (0 - 5); - polecane danie o danym numerze: 1. zupa z soczewicy 2. frytki pieczone 3. makaron z sosem brokułowym 4. pikantne skrzydełka zasmażane 5. ostre zasmażane tofu 6. hiszpańska zapiekanka ziemniaczana 7. pieczone warzywa Poszczególne liczby są oddzielone przecinkami, a wiersze znakiem nowej linii. Dane znajdują się w pliku z rozszerzeniem .cvs #### Drzewa decyzyjne: #### Następnie wykonany zostaje podział danych na zestaw treningowy (70%) i testowy (30%). X to zestaw cech, Y zestaw wyników - tutaj etykieta "number". ```python X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) ``` Do stworzenia modelu drzew została wykorzystana funkcja **DecisionTreeClassifier.** Pierwsze przyjmuje jako kryterium indeks Gini (domyślny), drugie entropię. ```python clf = DecisionTreeClassifier() clf = DecisionTreeClassifier(criterion="entropy") ``` Do modelu drzewa zostały wczytane dane, dzięki funkcji **fit**. ```python clf = clf.fit(X_train, y_train) ``` Generowane przewidywania są agregowane w zmiennej y_pred, dzięki funckji **predict**. ```python y_pred = clf.predict(X_test) ``` Następnie wyświetlana jest akuratność dla modelu danych o wybranym kryterium, dzięki funkcji **accuracy_score**. ```python print("Accuracy:", metrics.accuracy_score(y_test, y_pred)) ``` Drzewo decyzyjne ma swoją reprezentację graficzną, która utworzona została dzięki bibliotece IPython, graphviz, StringIO. ```python dot_data = StringIO() export_graphviz(clf, out_file=dot_data, filled=True, rounded=True, special_characters=True, feature_names=feature_cols, class_names=['1', '2', '3', '4', '5', '6', '7']) graph = pydotplus.graph_from_dot_data(dot_data.getvalue()) graph.write_png('polecanie_1.png') Image(graph.create_png()) ``` Na końcu model (z większym wskaźnikiem trafności) zostaje zapisany do pliku z rozszerzeniem sav. ```python file_name = 'final_model.sav' joblib.dump(clf, file_name) ``` ### Integracja z projektem ### Po uruchomieniu programu, należy nacisnąć na przycisk *Polecanie dań*, a wtedy uruchomiona zostaje funkcja *Tree_natalia()*, 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 doborze dania. ```python 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) ``` Następnie przy pomocy funkcji *show_predict()* wyświetlane jest zdjęcie poleconego dania. Funkcja jako parametry przyjmuje obiekty danie, klient i załadowany model. ```python 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 ``` 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, 5) ``` Po zakończeniu trasy wyświetlany jest stosowny komunikat, a aplikacja zostaje wyłączona.