# 요리 추천 Web App 만들기
이 강의에서, 이전 강의에서 배웠던 몇 기술과 이 계열에서 사용했던 맛있는 요리 데이터셋으로 classification 모델을 만들 예정입니다. 추가로, Onnx의 웹 런타임을 활용해서, 저장된 모델로 작은 웹 앱을 만들 것입니다.
머신러닝의 유용하고 실용적인 사용 방식 중에 하나인 recommendation system을 만들고, 오늘 이 쪽으로 처음 걷습니다!
[![Recommendation Systems Introduction](https://img.youtube.com/vi/giIXNoiqO_U/0.jpg)](https://youtu.be/giIXNoiqO_U "Recommendation Systems Introduction")
> 🎥 영상 보려면 이미지 클릭: Andrew Ng introduces recommendation system design
## [강의 전 퀴즈](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/25/)
이 강의에서 다음을 배우게 됩니다:
- 모델을 만들고 Onnx 모델로 저장하는 방식
- Netron 사용해서 모델 검사하는 방식
- 추론을 위한 웹 앱에서 모델을 사용하는 방식
## 모델 만들기
Applied ML 시스템을 만드는 것은 비지니스 시스템에서 이 기술을 활용하는 부분이 중요합니다. Onnx로 웹 애플리케이션에서 (필요하면 오프라인 컨텍스트에서 사용하기도 합니다) 모델을 사용할 수 있습니다.
[previous lesson](../../../3-Web-App/1-Web-App/README.md)에서, UFO 목격에 대한 Regression 모델을 만들었고, "pickled" 한 것을, Flask 앱에서 사용했습니다. 이 구조는 알고 있다면 매우 유용하지만, full-stack Python 앱이므로, JavaScript 애플리케이션을 포함해야 된다고 요구될 수 있습니다.
이 강의에서, 추론할 기초 JavaScript-기반 시스템을 만듭니다. 그러나 먼저, 모델을 훈련하고 Onnx와 같이 사용하기 위해서 변환할 필요가 있습니다.
## 연습 - classification 모델 훈련
먼저, 이미 사용했던 깨끗한 요리 데이터셋으로 classification 모델을 훈련합니다.
1. 유용한 라이브러리를 가져와서 시작합니다:
```python
pip install skl2onnx
import pandas as pd
```
Scikit-learn 모델을 Onnx 포맷으로 변환할 때 도움을 주는 '[skl2onnx](https://onnx.ai/sklearn-onnx/)' 가 필요합니다.
1. 그리고, `read_csv()` 사용해서 CSV 파일을 읽어보면, 이전 강의에서 했던 같은 방식으로 데이터를 작업합니다:
```python
data = pd.read_csv('../data/cleaned_cuisine.csv')
data.head()
```
1. 첫 2개의 필요없는 열을 제거하고 'X'로 나머지 데이터를 저장합니다:
```python
X = data.iloc[:,2:]
X.head()
```
1. 'y'로 라벨을 저장합니다:
```python
y = data[['cuisine']]
y.head()
```
### 훈련 루틴 개시하기
좋은 정확도의 'SVC' 라이브러리를 사용할 예정입니다.
1. Scikit-learn에서 적합한 라이브러리를 Import 합니다:
```python
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report
```
1. 훈련과 테스트 셋으로 가릅니다:
```python
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)
```
1. 이전 강의에서 했던 것처럼 SVC Classification model 모델을 만듭니다:
```python
model = SVC(kernel='linear', C=10, probability=True,random_state=0)
model.fit(X_train,y_train.values.ravel())
```
1. 지금부터, `predict()`를 불러서, 모델을 테스트합니다:
```python
y_pred = model.predict(X_test)
```
1. 모델의 품질을 확인하기 위해서 classification 리포트를 출력합니다:
```python
print(classification_report(y_test,y_pred))
```
전에 본 것처럼, 정확도는 좋습니다:
```output
precision recall f1-score support
chinese 0.72 0.69 0.70 257
indian 0.91 0.87 0.89 243
japanese 0.79 0.77 0.78 239
korean 0.83 0.79 0.81 236
thai 0.72 0.84 0.78 224
accuracy 0.79 1199
macro avg 0.79 0.79 0.79 1199
weighted avg 0.79 0.79 0.79 1199
```
### 모델을 Onnx로 변환하기
적절한 Tensor 숫자로 변환할 수 있어야 합니다. 데이터셋은 380개 성분이 나열되며, `FloatTensorType`에 숫자를 적어야 합니다:
1. 380개의 tensor 숫자로 변환하기.
```python
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([None, 380]))]
options = {id(model): {'nocl': True, 'zipmap': False}}
```
1. onx를 생성하고 **model.onnx** 파일로 저장합니다:
```python
onx = convert_sklearn(model, initial_types=initial_type, options=options)
with open("./model.onnx", "wb") as f:
f.write(onx.SerializeToString())
```
> 노트, 변환 스크립트에서 [options](https://onnx.ai/sklearn-onnx/parameterized.html)을 줄 수 있습니다. 이 케이스에서, 'nocl'는 True, 'zipmap'은 False로 줬습니다. (필수는 아니지만) classification 모델이라서, 사전의 리스트를 만드는 ZipMap을 지울 옵션이 있습니다. `nocl`은 모델에 있는 클래스 정보를 나타냅니다. `nocl`을 'True'로 설정해서 모델의 크기를 줄입니다.
전체 노트북을 실행하면 Onnx 모델이 만들어지고 폴더에 저장됩니다.
## 모델 보기
Onnx 모델은 Visual Studio code에서 잘 볼 수 없지만, 많은 연구원들이 모델을 잘 만들었는지 보고 싶어서 모델을 시각화할 때 사용하기 매우 좋은 자유 소프트웨어가 있습니다. [Netron](https://github.com/lutzroeder/Netron)을 내려받고 model.onnx 파일을 엽니다. 380개 입력과 나열된 classifier로 간단한 모델을 시각화해서 볼 수 있습니다:
![Netron visual](../images/netron.png)
Netron은 모델을 보게 도와주는 도구입니다.
지금부터 웹 앱에서 neat 모델을 사용할 준비가 되었습니다. 냉장고를 볼 때 편리한 앱을 만들고 모델이 결정해서 건내준 요리를 조리할 수 있게 남은 재료 조합을 찾아봅니다.
## recommender 웹 애플리케이션 만들기
웹 앱에서 바로 모델을 사용할 수 있습니다. 이 구조를 사용한다면 로컬에서 실행할 수 있고 필요하면 오프라인으로 가능합니다. `model.onnx` 파일을 저장한 동일 폴더에서 `index.html` 파일을 만들기 시작합니다.
1. _index.html_ 파일에서, 다음 마크업을 추가합니다:
```html