Ich habe das durch maschinelles Lernen generierte Lernmodell als API-Server verwendet, Daten vom Browser über JSON-Kommunikation gesendet und den vorhergesagten Wert zurückgegeben. Dieser maschinell erlernte API-Server wird von drei Hauptprogrammen implementiert. Führen Sie zunächst ein Maschinentraining auf XGBoost durch, um das Trainingsmodell zu generieren und zu speichern. Implementieren Sie als Nächstes den Lernmodell-API-Server in Flask. Schreiben Sie abschließend das Formular-Tag in die HTML-Datei, damit die vom Formular-Tag erhaltenen Daten von Ajax aus Javascript mit JSON kommuniziert werden können. Mit diesen drei Programmen können Sie etwas erstellen, das Daten vom Browser an den API-Server sendet und den vorhergesagten Wert zurückgibt.
Bibliotheken wie Anaconda, XGBoost, joblib, Flask und flask-cors sind installiert.
Diese API-Kommunikation durch maschinelles Lernen kann wie folgt implementiert werden.
--Erstellen Sie ein Lernmodell mit maschinellem Lernen --Erstellen Sie einen API-Server mit Flask --API-Kommunikation vom Browser
Hier wird XGBoost verwendet, um ein Trainingsmodell zu generieren. Die Trainingsdaten verwenden den Titanic-Datensatz von Kaggle.
Bevor wir mit XGBoost maschinelles Lernen durchführen, führen wir einige Vorverarbeitungen durch. Der Titanic-Datensatz von Kaggle ist in Zug- und Testdaten unterteilt, sodass sie mit concat verkettet werden, um gemeinsam eine Vorverarbeitung durchzuführen. Die Vorverarbeitung umfasst die Verarbeitung fehlender Werte, das Ersetzen kategorialer Daten durch numerische Werte und das Löschen unnötiger Funktionen.
Laden Sie die für die Vorverarbeitung erforderliche Bibliothek. Wir laden den Datensatz auch als Pandas-Datenrahmen.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
train_df = pd.read_csv('titanic/train.csv')
test_df = pd.read_csv('titanic/test.csv')
train_df.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
test_df.head()
PassengerId | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 892 | 3 | Kelly, Mr. James | male | 34.5 | 0 | 0 | 330911 | 7.8292 | NaN | Q |
1 | 893 | 3 | Wilkes, Mrs. James (Ellen Needs) | female | 47.0 | 1 | 0 | 363272 | 7.0000 | NaN | S |
2 | 894 | 2 | Myles, Mr. Thomas Francis | male | 62.0 | 0 | 0 | 240276 | 9.6875 | NaN | Q |
3 | 895 | 3 | Wirz, Mr. Albert | male | 27.0 | 0 | 0 | 315154 | 8.6625 | NaN | S |
4 | 896 | 3 | Hirvonen, Mrs. Alexander (Helga E Lindqvist) | female | 22.0 | 1 | 1 | 3101298 | 12.2875 | NaN | S |
Da ich die Vorverarbeitung gemeinsam durchführen möchte, verkette ich Zugdaten und Testdaten mit concat.
all_df = pd.concat((train_df.loc[:, 'Pclass' : 'Embarked'], test_df.loc[:, 'Pclass' : 'Embarked']))
all_df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1309 entries, 0 to 417
Data columns (total 10 columns):
Pclass 1309 non-null int64
Name 1309 non-null object
Sex 1309 non-null object
Age 1046 non-null float64
SibSp 1309 non-null int64
Parch 1309 non-null int64
Ticket 1309 non-null object
Fare 1308 non-null float64
Cabin 295 non-null object
Embarked 1307 non-null object
dtypes: float64(2), int64(3), object(5)
memory usage: 112.5+ KB
Da die Werte für Alter, Tarif und Einschiffung fehlen, werden sie mit den durchschnittlichen und häufigsten Werten gefüllt.
all_df['Age'] = all_df['Age'].fillna(all_df['Age'].mean())
all_df['Fare'] = all_df['Fare'].fillna(all_df['Fare'].mean())
all_df['Embarked'] = all_df['Embarked'].fillna(all_df['Embarked'].mode()[0])
all_df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1309 entries, 0 to 417
Data columns (total 10 columns):
Pclass 1309 non-null int64
Name 1309 non-null object
Sex 1309 non-null object
Age 1309 non-null float64
SibSp 1309 non-null int64
Parch 1309 non-null int64
Ticket 1309 non-null object
Fare 1309 non-null float64
Cabin 295 non-null object
Embarked 1309 non-null object
dtypes: float64(2), int64(3), object(5)
memory usage: 112.5+ KB
all_df.head()
Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
Geschlecht und Eingeschifft sind kategoriale Daten, daher ersetzt LabelEncoder sie durch Zahlen.
cat_features = ['Sex', 'Embarked']
for col in cat_features:
lbl = LabelEncoder()
all_df[col] = lbl.fit_transform(list(all_df[col].values))
all_df.head()
Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 3 | Braund, Mr. Owen Harris | 1 | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | 2 |
1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | 0 | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | 0 |
2 | 3 | Heikkinen, Miss. Laina | 0 | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | 2 |
3 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | 0 | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | 2 |
4 | 3 | Allen, Mr. William Henry | 1 | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | 2 |
Name und Ticket sind kategoriale und eindeutige Werte. Löschen Sie sie daher. Außerdem fehlen in Cabin viele Werte. Löschen Sie sie daher.
all_df = all_df.drop(columns = ['Name', 'Ticket', 'Cabin'])
all_df.head()
Pclass | Sex | Age | SibSp | Parch | Fare | Embarked | |
---|---|---|---|---|---|---|---|
0 | 3 | 1 | 22.0 | 1 | 0 | 7.2500 | 2 |
1 | 1 | 0 | 38.0 | 1 | 0 | 71.2833 | 0 |
2 | 3 | 0 | 26.0 | 0 | 0 | 7.9250 | 2 |
3 | 1 | 0 | 35.0 | 1 | 0 | 53.1000 | 2 |
4 | 3 | 1 | 35.0 | 0 | 0 | 8.0500 | 2 |
Da Zug und Test verbunden waren, werden Zug und Test getrennt, so dass sie zu Trainingsdaten werden. Sie können Zug und Test trennen, indem Sie den Formwert von train_df verwenden.
train = all_df[:train_df.shape[0]]
test = all_df[train_df.shape[0]:]
train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 0 to 890
Data columns (total 7 columns):
Pclass 891 non-null int64
Sex 891 non-null int64
Age 891 non-null float64
SibSp 891 non-null int64
Parch 891 non-null int64
Fare 891 non-null float64
Embarked 891 non-null int64
dtypes: float64(2), int64(5)
memory usage: 55.7 KB
Nachdem die Vorverarbeitung abgeschlossen ist, werden wir weiterhin maschinelles Lernen mit XGBoost durchführen. Anstatt die Genauigkeit des Lernmodells zu verbessern, besteht diesmal der Zweck darin, einen API-Server unter Verwendung des Lernmodells zu erstellen, sodass Parameter usw. mit fast Standardwerten gelernt werden.
y = train_df['Survived']
X_train, X_test, y_train, y_test = train_test_split(train, y, random_state = 0)
import xgboost as xgb
params = {
"objective": "binary:logistic",
"eval_metric": "auc",
"eta": 0.1,
"max_depth": 6,
"subsample": 1,
"colsample_bytree": 1,
"silent": 1
}
dtrain = xgb.DMatrix(X_train, label = y_train)
dtest = xgb.DMatrix(X_test, label = y_test)
model = xgb.train(params = params,
dtrain = dtrain,
num_boost_round = 100,
early_stopping_rounds = 10,
evals = [(dtest, 'test')])
[0] test-auc:0.886905
Will train until test-auc hasn't improved in 10 rounds.
[1] test-auc:0.89624
[2] test-auc:0.893243
[3] test-auc:0.889603
[4] test-auc:0.892857
[5] test-auc:0.886005
[6] test-auc:0.890673
[7] test-auc:0.894741
[8] test-auc:0.889603
[9] test-auc:0.888832
[10] test-auc:0.889431
[11] test-auc:0.89153
Stopping. Best iteration:
[1] test-auc:0.89624
Es gibt verschiedene Möglichkeiten, ein maschinell geschultes Trainingsmodell zu speichern. Hier verwenden wir jedoch joblib, um es als pkl-Datei zu speichern. Da die gespeicherte pkl-Datei am angegebenen Speicherort gespeichert ist, kopieren Sie sie anschließend in den Ordner des API-Servers und verwenden Sie sie.
from sklearn.externals import joblib
joblib.dump(model, 'titanic_model.pkl')
['titanic_model.pkl']
Hier versuchen wir, das durch maschinelles Lernen erzeugte Lernmodell als API-Server zu verwenden. Flask, ein Python-Microservice-Framework, wird für die API-Serverentwicklung verwendet. Der Entwicklungsfluss besteht darin, eine virtuelle Umgebung mit conda zu erstellen, einen einfachen API-Server zu testen und das mit XGBoost erstellte Lernmodell darauf zu setzen.
Die virtuelle Umgebung verwendet Anacondas Conda. Erstellen Sie im Terminal einen Ordner für die App-Entwicklung (in diesem Fall titanic_api) und verschieben Sie ihn in diesen Ordner. Dann erstellt conda create die virtuelle Umgebung und conda enable aktiviert die virtuelle Umgebung.
mkdir titanic_api
cd titanic_api
conda create -n titanictenv
conda activate titanictenv
Um einen API-Server mit Flask zu entwickeln, erstellen und testen Sie zunächst einen einfachen API-Server. Erstellen Sie die folgenden Ordner und Dateien in dem zuvor erstellten Ordner. Wenn Sie den folgenden Code in jede Datei schreiben, den API-Server starten und über Curl kommunizieren können, ist der einfache API-Servertest erfolgreich.
Erstellen Sie Ordner und Dateien so, dass sie die folgende Hierarchie haben. Wenn Sie eine leere Datei erstellen möchten, können Sie bequem den Befehl touch verwenden.
titanic_api
├── api
│ ├── __init__.py
│ └── views
│ └── user.py
├── titanic_app.py
└── titanic_model.pkl
Schreiben Sie den folgenden Code in die zuvor erstellte Datei. Zum Testen eines einfachen API-Servers sind drei Dateien erforderlich: api / views / user.py, api / __ init__.py und titanic_app.py. Es ist praktisch, beim Schreiben im Terminal vim und beim Schreiben in der GUI Atom zu verwenden.
api/views/user.py
from flask import Blueprint, request, make_response, jsonify
#Routing-Einstellungen
user_router = Blueprint('user_router', __name__)
#Geben Sie den Pfad und die HTTP-Methode an
@user_router.route('/users', methods=['GET'])
def get_user_list():
return make_response(jsonify({
'users': [
{
'id': 1,
'name': 'John'
}
]
}))
api/__init__.py
from flask import Flask, make_response, jsonify
from .views.user import user_router
def create_app():
app = Flask(__name__)
app.register_blueprint(user_router, url_prefix='/api')
return app
app = create_app()
titanic_app.py
from api import app
if __name__ == '__main__':
app.run()
Starten Sie den Server nach dem Schreiben des obigen Codes mit python titanic_app.py. Wenn es erfolgreich gestartet wurde, öffnen Sie ein anderes Terminal und testen Sie die Kommunikation mit dem Befehl curl wie folgt. Wenn die Kommunikation erfolgreich ist, werden die folgenden Daten zurückgegeben.
curl http://127.0.0.1:5000/api/users
{
"users": [
{
"id": 1,
"name": "John"
}
]
}
Schreiben Sie titanic_app.py, die Startdatei des einfachen API-Servers, wie folgt neu. Zu diesem Zeitpunkt muss das Lernmodell direkt unter titanic_api gespeichert werden.
titanic_app.py
import json
from flask import Flask
from flask import request
from flask import abort
import pandas as pd
from sklearn.externals import joblib
import xgboost as xgb
model = joblib.load("titanic_model.pkl")
app = Flask(__name__)
# Get headers for payload
headers = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
@app.route('/titanic', methods=['POST'])
def titanic():
if not request.json:
abort(400)
payload = request.json['data']
values = [float(i) for i in payload.split(',')]
data1 = pd.DataFrame([values], columns=headers, dtype=float)
predict = model.predict(xgb.DMatrix(data1))
return json.dumps(str(predict[0]))
if __name__ == "__main__":
app.run(debug=True, port=5000)
Starten Sie den API-Server nach dem Umschreiben des Codes erneut mit python titanic_app.py. Nach dem Start des API-Servers wird der Kommunikationstest mit dem Befehl curl wie unten gezeigt durchgeführt. Es ist erfolgreich, wenn für die gesendeten JSON-Daten ein Wert mit einem Dezimalpunkt von 1 oder weniger zurückgegeben wird. Sie haben das durch maschinelles Lernen generierte Lernmodell nun in einen API-Server umgewandelt.
curl http://localhost:5000/titanic -s -X POST -H "Content-Type: application/json" -d '{"data": "3, 1, 22.0, 1, 0, 7.2500, 2"}'
Zusätzlich zur Kommunikation mit dem Befehl curl vom Terminal erstellen wir etwas, das den vorhergesagten Wert zurückgibt, wenn ein Wert vom Browser eingegeben wird. Hier müssen wir die Ajax-Kommunikation mit dem zuvor erstellten API-Server aktivieren und die Kommunikation vom Browser zum API-Server mit einer HTML-Datei aktivieren.
Um mit Javascript Ajax aus HTML kommunizieren zu können, muss die in Flask geschriebene API-Server-Startdatei wie folgt hinzugefügt werden. Ich werde eine Bibliothek namens flask_cors und verwandten Code hinzufügen. flask_cors muss vorinstalliert sein.
titanic_app.py
import json
from flask import Flask
from flask import request
from flask import abort
from flask_cors import CORS #hinzufügen
import pandas as pd
from sklearn.externals import joblib
import xgboost as xgb
model = joblib.load("titanic_model.pkl")
app = Flask(__name__)
#hinzufügen
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return response
#↑ Hier addieren
# Get headers for payload
headers = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
@app.route('/titanic', methods=['POST'])
def titanic():
if not request.json:
abort(400)
payload = request.json['data']
values = [float(i) for i in payload.split(',')]
data1 = pd.DataFrame([values], columns=headers, dtype=float)
predict = model.predict(xgb.DMatrix(data1))
return json.dumps(str(predict[0]))
if __name__ == "__main__":
app.run(debug=True, port=5000)
In der HTML-Datei ist der Schnittstellenteil das Eingabe-Tag innerhalb des
-Tags usw. und erstellt ein Dateneingabeformular. Die Eingabedaten werden per Javascript empfangen, formatiert, in das JSON-Format konvertiert und per Ajax-Kommunikation POST. Wenn die Kommunikation erfolgreich ist, wird der vorhergesagte Wert vom API-Server empfangen und im Bereich des Textbereichs-Tags angezeigt.index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Senden Sie JSON-Daten per POST aus einer HTML-Datei</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#response").html("Response Values");
$("#button").click( function(){
var url = $("#url_post").val();
var feature1 =
$("#value1").val() + "," +
$("#value2").val() + "," +
$("#value3").val() + "," +
$("#value4").val() + "," +
$("#value5").val() + "," +
$("#value6").val() + "," +
$("#value7").val();
var JSONdata = {
data: feature1
};
alert(JSON.stringify(JSONdata));
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(JSONdata),
contentType: 'application/JSON',
dataType: 'JSON',
scriptCharset: 'utf-8',
success : function(data) {
// Success
alert("success");
alert(JSON.stringify(JSONdata));
$("#response").html(JSON.stringify(data));
},
error : function(data) {
// Error
alert("error");
alert(JSON.stringify(JSONdata));
$("#response").html(JSON.stringify(data));
}
});
})
})
</script>
</head>
<body>
<h1>Senden Sie JSON-Daten per POST aus einer HTML-Datei</h1>
<p>URL: <input type="text" id="url_post" name="url" size="100" value="http://localhost:5000/titanic"></p>
<p>Pclass: <input type="number" id="value1" size="30" value=3></p>
<p>Sex: <input type="number" id="value2" size="30" value=1></p>
<p>Age: <input type="number" id="value3" size="30" value="22.0"></p>
<p>SibSp: <input type="number" id="value4" size="30" value="1"></p>
<p>Parch: <input type="number" id="value5" size="30" value="0"></p>
<p>Fare: <input type="number" id="value6" size="30" value="7.2500"></p>
<p>Embarked: <input type="number" id="value7" size="30" value="2"></p>
<p><button id="button" type="button">submit</button></p>
<textarea id="response" cols=120 rows=10 disabled></textarea>
</body>
</html>
Referenz Erstellen Sie eine virtuelle Umgebung mit conda: https://code-graffiti.com/how-to-build-a-virtual-environment-with-conda/ Entwickeln Sie die API mit der Flasche: https://swallow-incubate.com/archives/blog/20190819 Machen Sie das xgboost-Modell zu einem API-Server: https://towardsdatascience.com/publishing-machine-learning-api-with-python-flask-98be46fb2440 Ermöglichen Sie, dass json über Ajax-Kommunikation an den API-Server gesendet wird: https://www.hands-lab.com/tech/entry/3716.html Senden Sie JSON-Daten per POST aus der HTML-Datei: https://qiita.com/kidatti/items/21cc5c5154dbbb1aa27f
Recommended Posts