175 lines
6.5 KiB
Markdown
175 lines
6.5 KiB
Markdown
##### 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)
|
|
```
|
|
|
|
<img src="https://git.wmi.amu.edu.pl/s444412/DSZI_2020_Projekt/raw/master/Restaurant/Natalia/polecanie_1.png" >
|
|
|
|
|
|
### 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. |