From 458bae1027edbdee50ae140521d1c6f2de9d9afd Mon Sep 17 00:00:00 2001 From: softchris Date: Wed, 23 Jun 2021 17:58:32 +0100 Subject: [PATCH] editorial --- 4-Classification/4-Applied/README.md | 430 +++++++++++++++------------ 1 file changed, 234 insertions(+), 196 deletions(-) diff --git a/4-Classification/4-Applied/README.md b/4-Classification/4-Applied/README.md index 258b635ad5..0e20f6c37f 100644 --- a/4-Classification/4-Applied/README.md +++ b/4-Classification/4-Applied/README.md @@ -7,107 +7,138 @@ One of the most useful practical uses of machine learning is building recommenda [![Recommendation Systems Introduction](https://img.youtube.com/vi/giIXNoiqO_U/0.jpg)](https://youtu.be/giIXNoiqO_U "Recommendation Systems Introduction") > 🎥 Click the image above for a video: Andrew Ng introduces recommendation system design + ## [Pre-lecture quiz](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/25/) In this lesson you will learn: + - How to build a model and save it as an Onnx model - How to use Netron to inspect the model - How to use your model in a web app for inference ## Build your model -Building applied ML systems is an important part of leveraging these technologies for your business systems. You can use models within your web applications (and thus use them in an offline context if needed) by using Onnx. In a [previous lesson](../../3-Web-App/1-Web-App/README.md), you built a Regression model about UFO sightings, "pickled" it, and used it in a Flask app. While this architecture is very useful to know it is a full-stack Python app, and your requirements may include the use of a JavaScript application. In this lesson, you can build a basic JavaScript-based system for inference. First, however, you need to train a model and convert it for use with Onnx. +Building applied ML systems is an important part of leveraging these technologies for your business systems. You can use models within your web applications (and thus use them in an offline context if needed) by using Onnx. + +In a [previous lesson](../../3-Web-App/1-Web-App/README.md), you built a Regression model about UFO sightings, "pickled" it, and used it in a Flask app. While this architecture is very useful to know, it is a full-stack Python app, and your requirements may include the use of a JavaScript application. + +In this lesson, you can build a basic JavaScript-based system for inference. First, however, you need to train a model and convert it for use with Onnx. + +## Exercise - train classification model + +First, train a classification model using the cleaned cuisines dataset we used. + +1. Start by importing useful libraries: + + ```python + pip install skl2onnx + import pandas as pd + ``` + + You need '[skl2onnx](https://onnx.ai/sklearn-onnx/)' to help convert your Scikit-learn model to Onnx format. + +1. Then, work with your data in the same way you did in previous lessons, by reading a CSV file using `read_csv()`: + + ```python + data = pd.read_csv('../data/cleaned_cuisine.csv') + data.head() + ``` + +1. Remove the first two unnecessary columns and save the remaining data as 'X': -First, train a classification model using the cleaned cuisines dataset we used. Start by importing useful libraries: + ```python + X = data.iloc[:,2:] + X.head() + ``` -```python -pip install skl2onnx -import pandas as pd -``` -You need '[skl2onnx](https://onnx.ai/sklearn-onnx/)' to help convert your Scikit-learn model to Onnx format. +1. Save the labels as 'y': -Then, work with your data in the same way you did in previous lessons: + ```python + y = data[['cuisine']] + y.head() + + ``` -```python -data = pd.read_csv('../data/cleaned_cuisine.csv') -data.head() -``` +### Commence the training routine -Remove the first two unnecessary columns and save the remaining data as 'X': +We will use the 'SVC' library which has good accuracy. -```python -X = data.iloc[:,2:] -X.head() -``` +1. Import the appropriate libraries from Scikit-learn: -Save the labels as 'y': + ```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 + ``` -```python -y = data[['cuisine']] -y.head() +1. Separate training and test sets: -``` + ```python + X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3) + ``` -Commence the training routine. We will use the 'SVC' library which has good accuracy. Import the appropriate libraries from Scikit-learn: +1. Build an SVC Classification model as you did in the previous lesson: -```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 -``` -Separate training and test sets: + ```python + model = SVC(kernel='linear', C=10, probability=True,random_state=0) + model.fit(X_train,y_train.values.ravel()) + ``` -```python -X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3) -``` -Build an SVC Classification model as you did in the previous lesson: +1. Now, test your model, calling `predict()`: -```python -model = SVC(kernel='linear', C=10, probability=True,random_state=0) -model.fit(X_train,y_train.values.ravel()) -``` -Now, test your model: + ```python + y_pred = model.predict(X_test) + ``` -```python -y_pred = model.predict(X_test) -``` -Print out a classification report to check the model's quality: +1. Print out a classification report to check the model's quality: -```python -print(classification_report(y_test,y_pred)) -``` -As we saw before, the accuracy is good: + ```python + print(classification_report(y_test,y_pred)) + ``` -``` - precision recall f1-score support + As we saw before, the accuracy is good: - 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 + ```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 + ``` - accuracy 0.79 1199 - macro avg 0.79 0.79 0.79 1199 -weighted avg 0.79 0.79 0.79 1199 -``` -Now, convert your model to Onnx. Make sure to do the conversion with the proper Tensor number. This dataset has 380 ingredients listed, so you need to notate that number in `FloatTensorType`: +### Convert your model to Onnx -```python -from skl2onnx import convert_sklearn -from skl2onnx.common.data_types import FloatTensorType +Make sure to do the conversion with the proper Tensor number. This dataset has 380 ingredients listed, so you need to notate that number in `FloatTensorType`: -initial_type = [('float_input', FloatTensorType([None, 380]))] -options = {id(model): {'nocl': True, 'zipmap': False}} -onx = convert_sklearn(model, initial_types=initial_type, options=options) -with open("./model.onnx", "wb") as f: - f.write(onx.SerializeToString()) -``` +1. Convert using a tensor number of 380. -> Note, you can pass in [options](https://onnx.ai/sklearn-onnx/parameterized.html) in your conversion script. In this case, we passed in 'nocl' to be True and 'zipmap' to be False. Since this is a classification model, you have the option to remove ZipMap which produces a list of dictionaries (not necessary). `nocl` refers to class information being included in the model. Reduce your model's size by setting `nocl` to 'True'. + ```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. Create the onx and store as a file **model.onnx**: + + ```python + onx = convert_sklearn(model, initial_types=initial_type, options=options) + with open("./model.onnx", "wb") as f: + f.write(onx.SerializeToString()) + ``` + + > Note, you can pass in [options](https://onnx.ai/sklearn-onnx/parameterized.html) in your conversion script. In this case, we passed in 'nocl' to be True and 'zipmap' to be False. Since this is a classification model, you have the option to remove ZipMap which produces a list of dictionaries (not necessary). `nocl` refers to class information being included in the model. Reduce your model's size by setting `nocl` to 'True'. Running the entire notebook will now build an Onnx model and save it to this folder. + ## View your model Onnx models are not very visible in Visual Studio code, but there's a very good free software that many researchers use to visualize the model to ensure that it is properly built. Download [Netron](https://github.com/lutzroeder/Netron) and open your model.onnx file. You can see your simple model visualized, with its 380 inputs and classifier listed: @@ -117,150 +148,155 @@ Onnx models are not very visible in Visual Studio code, but there's a very good Netron is a helpful tool to view your models. Now you are ready to use this neat model in a web app. Let's build an app that will come in handy when you look in your refrigerator and try to figure out which combination of your leftover ingredients you can use to cook a given cuisine, as determined by your model. + ## Build a recommender web application You can use your model directly in a web app. This architecture also allows you to run it locally and even offline if needed. Start by creating an `index.html` file in the same folder where you stored your `model.onnx` file. -In this file, add the following markup: - -```html - - -
- Cuisine Matcher -
- - ... - - -``` - -Now, working within the `body` tags, add a little markup to show a list of checkboxes reflecting some ingredients: - -```html -

Check your refrigerator. What can you create?

-
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - +1. In this file _index.html_, add the following markup: + + ```html + + +
+ Cuisine Matcher +
+ + ... + + + ``` + +1. Now, working within the `body` tags, add a little markup to show a list of checkboxes reflecting some ingredients: + + ```html +

Check your refrigerator. What can you create?

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ ``` -
- - -
+ Notice that each checkbox is given a value. This reflects the index where the ingredient is found according to the dataset. Apple, for example, in this alphabetic list, occupies the fifth column, so its value is '4' since we start counting at 0. You can consult the [ingredients spreadsheet](../data/ingredient_indexes.csv) to discover a given ingredient's index. -
- - -
-
-
- -
-``` -Notice that each checkbox is given a value. This reflects the index where the ingredient is found according to the dataset. Apple, for example, in this alphabetic list, occupies the fifth column, so its value is '4' since we start counting at 0. You can consult the [ingredients spreadsheet](../data/ingredient_indexes.csv) to discover a given ingredient's index. + Continuing your work in the index.html file, add a script block where the model is called after the final closing `
`. -Continuing your work in the index.html file, add a script block where the model is called after the final closing ``. First, import the [Onnx Runtime](https://www.onnxruntime.ai/): +1. First, import the [Onnx Runtime](https://www.onnxruntime.ai/): -```html - -``` -> Onnx Runtime is used to enable running your Onnx models across a wide range of hardware platforms, including optimizations and an API to use. + ```html + + ``` -Once the Runtime is in place, you can call it: + > Onnx Runtime is used to enable running your Onnx models across a wide range of hardware platforms, including optimizations and an API to use. -```javascript - -``` + init(); + + + ``` In this code, there are several things happening: @@ -269,7 +305,7 @@ In this code, there are several things happening: 3. You created a `testCheckboxes` function that checks whether any checkbox was checked. 4. You use that function when the button is pressed and, if any checkbox is checked, you start inference. 5. The inference routine includes: - 1. Setting up an asyncronous load of the model + 1. Setting up an asynchronous load of the model 2. Creating a Tensor structure to send to the model 3. Creating 'feeds' that reflects the `float_input` input that you created when training your model (you can use Netron to verify that name) 4. Sending these 'feeds' to the model and waiting for a response @@ -280,12 +316,13 @@ Open a terminal session in Visual Studio Code in the folder where your index.htm ![ingredient web app](images/web-app.png) -Congratulations, you have created a simple web app recommendation with a few fields. Take some time to build out this system! +Congratulations, you have created a 'recommendation' web app with a few fields. Take some time to build out this system! ## 🚀Challenge Your web app is very minimal, so continue to build it out using ingredients and their indexes from the [ingredient_indexes](../data/ingredient_indexes.csv) data. What flavor combinations work to create a given national dish? ## [Post-lecture quiz](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/26/) + ## Review & Self Study While this lesson just touched on the utility of creating a recommendation system for food ingredients, this area of ML applications is very rich in examples. Read some more about how these systems are built: @@ -293,6 +330,7 @@ While this lesson just touched on the utility of creating a recommendation syste - https://www.sciencedirect.com/topics/computer-science/recommendation-engine - https://www.technologyreview.com/2014/08/25/171547/the-ultimate-challenge-for-recommendation-engines/ - https://www.technologyreview.com/2015/03/23/168831/everything-is-a-recommendation/ + ## Assignment [Build a new recommender](assignment.md)