https://github.com/fanqingsong/Building-Recommendation-Systems-with-Python/tree/master/Section%205/Video%205.4css
系統包括三個部分:前端
1) 模型產生模塊react
實現主體 model_generator.pygit
使用iris.data數據, 訓練模型,保存模型爲 classifier.joblibgithub
2) 分類API服務模塊npm
使用Flask框架和API庫, 暴露出API庫, 調用分類器模型 classifier.joblib ,將輸入(iris的四個特徵值)feed到模型中,模型給出輸出(iris分類)json
3) 前端界面模塊flask
基於React實現前端界面,提供用戶輸出界面,包括iris四個特徵值, 並調用分類器服務API,獲得iris分類。bootstrap
https://github.com/fanqingsong/Building-Recommendation-Systems-with-Python/tree/master/Section%205/Video%205.4app
到 video 5.4 目錄下,執行如下命令:
service
install && run
- cd service
- pip3 install -r requirement.txt
- export FLASK_APP=app.py
- flask run
ui
install && run
- cd ui
- npm install
- npm start
訪問
提供了 API的測試界面。
訪問
提供了用戶操做界面。
# Import libraries import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix from sklearn.tree import DecisionTreeClassifier from sklearn.externals import joblib from sklearn import datasets # Get the dataset dataset = datasets.load_iris() # Split the dataset into features and labels X = dataset.data y = dataset.target # Split the dataset into training (80%) and testing (20%) data X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0, shuffle = True) # Build the classifier and make prediction classifier = DecisionTreeClassifier() classifier.fit(X_train, y_train) prediction = classifier.predict(X_test) # Print the confusion matrix print("Confusion Matrix:") print(confusion_matrix(y_test, prediction)) # Save the model to disk joblib.dump(classifier, 'classifier.joblib')
from flask import Flask, request, jsonify, make_response from flask_restplus import Api, Resource, fields from sklearn.externals import joblib import numpy as np import sys flask_app = Flask(__name__) app = Api(app=flask_app, version="1.0", title="Iris Plant identifier", description="Predict the type of iris plant") name_space = app.namespace('prediction', description='Prediction APIs') model = app.model('Prediction params', {'sepalLength': fields.Float(required=True, description="Sepal Length", help="Sepal Length cannot be blank"), 'sepalWidth': fields.Float(required=True, description="Sepal Width", help="Sepal Width cannot be blank"), 'petalLength': fields.Float(required=True, description="Petal Length", help="Petal Length cannot be blank"), 'petalWidth': fields.Float(required=True, description="Petal Width", help="Petal Width cannot be blank")}) classifier = joblib.load('classifier.joblib') @name_space.route("/") class MainClass(Resource): def options(self): response = make_response() response.headers.add("Access-Control-Allow-Origin", "*") response.headers.add('Access-Control-Allow-Headers', "*") response.headers.add('Access-Control-Allow-Methods', "*") return response @app.expect(model) def post(self): try: formData = request.json data = [val for val in formData.values()] prediction = classifier.predict(np.array(data).reshape(1, -1)) types = {0: "Iris Setosa", 1: "Iris Versicolour ", 2: "Iris Virginica"} response = jsonify({ "statusCode": 200, "status": "Prediction made", "result": "The type of iris plant is: " + types[prediction[0]] }) response.headers.add('Access-Control-Allow-Origin', '*') return response except Exception as error: return jsonify({ "statusCode": 500, "status": "Could not make prediction", "error": str(error) })
import React, { Component } from 'react'; import './App.css'; import Form from 'react-bootstrap/Form'; import Col from 'react-bootstrap/Col'; import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Button from 'react-bootstrap/Button'; import 'bootstrap/dist/css/bootstrap.css'; class App extends Component { constructor(props) { super(props); this.state = { isLoading: false, formData: { sepalLength: 4, sepalWidth: 2, petalLength: 1, petalWidth: 0 }, result: "" }; } handleChange = (event) => { const value = event.target.value; const name = event.target.name; var formData = this.state.formData; formData[name] = value; this.setState({ formData }); }; handlePredictClick = (event) => { const formData = this.state.formData; this.setState({ isLoading: true }); fetch('http://127.0.0.1:5000/prediction/', { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, method: 'POST', body: JSON.stringify(formData) }) .then(response => response.json()) .then(response => { this.setState({ result: response.result, isLoading: false }); }); }; handleCancelClick = (event) => { this.setState({ result: "" }); }; render() { const isLoading = this.state.isLoading; const formData = this.state.formData; const result = this.state.result; var sepalLengths = []; for (var i = 4; i <= 7; i = +(i + 0.1).toFixed(1)) { sepalLengths.push(<option key = {i} value = {i}>{i}</option>); } var sepalWidths = []; for (var i = 2; i <= 4; i = +(i + 0.1).toFixed(1)) { sepalWidths.push(<option key = {i} value = {i}>{i}</option>); } var petalLengths = []; for (var i = 1; i <= 6; i = +(i + 0.1).toFixed(1)){ petalLengths.push(<option key = {i} value = {i}>{i}</option>); } var petalWidths = []; for (var i = 0.1; i <= 3; i = +(i + 0.1).toFixed(1)) { petalWidths.push(<option key = {i} value = {i}>{i}</option>); } return ( <Container> <div> <h1 className="title">Iris Plant Classifier</h1> </div> <div className="content"> <Form> <Form.Row> <Form.Group as={Col}> <Form.Label>Sepal Length</Form.Label> <Form.Control as="select" value={formData.sepalLength} name="sepalLength" onChange={this.handleChange}> {sepalLengths} </Form.Control> </Form.Group> <Form.Group as={Col}> <Form.Label>Sepal Width</Form.Label> <Form.Control as="select" value={formData.sepalWidth} name="sepalWidth" onChange={this.handleChange}> {sepalWidths} </Form.Control> </Form.Group> </Form.Row> <Form.Row> <Form.Group as={Col}> <Form.Label>Petal Length</Form.Label> <Form.Control as="select" value={formData.petalLength} name="petalLength" onChange={this.handleChange}> {petalLengths} </Form.Control> </Form.Group> <Form.Group as={Col}> <Form.Label>Petal Width</Form.Label> <Form.Control as="select" value={formData.petalWidth} name="petalWidth" onChange={this.handleChange}> {petalWidths} </Form.Control> </Form.Group> </Form.Row> <Row> <Col> <Button block variant="success" disabled={isLoading} onClick={!isLoading ? this.handlePredictClick : null}> { isLoading ? 'Making prediction' : 'Predict' } </Button> </Col> <Col> <Button block variant="danger" disabled={isLoading} onClick={this.handleCancelClick}> Reset prediction </Button> </Col> </Row> </Form> {result === "" ? null : (<Row> <Col className="result-container"> <h5 id="result">{result}</h5> </Col> </Row>) } </div> </Container> ); } } export default App;