Prediksi Machine Learning Python dengan Flask REST API
Diterbitkan: 2022-03-11Artikel ini tentang menggunakan Python dalam konteks pembelajaran mesin atau sistem kecerdasan buatan (AI) untuk membuat prediksi waktu nyata, dengan Flask REST API. Arsitektur yang diekspos di sini dapat dilihat sebagai cara untuk beralih dari proof of concept (PoC) ke produk yang layak minimal (MVP) untuk aplikasi pembelajaran mesin.
Python bukanlah pilihan pertama yang dapat dipikirkan saat merancang solusi waktu nyata. Tetapi karena Tensorflow dan Scikit-Learn adalah beberapa perpustakaan pembelajaran mesin yang paling banyak digunakan yang didukung oleh Python, itu digunakan dengan nyaman di banyak PoC Notebook Jupyter.
Apa yang membuat solusi ini dapat dilakukan adalah kenyataan bahwa pelatihan membutuhkan banyak waktu dibandingkan dengan memprediksi. Jika Anda menganggap pelatihan sebagai proses menonton film dan memprediksi jawaban atas pertanyaan tentangnya, maka tampaknya cukup efisien untuk tidak harus menonton ulang film setelah setiap pertanyaan baru.
Pelatihan adalah semacam tampilan terkompresi dari "film" itu dan memprediksi adalah mengambil informasi dari tampilan terkompresi. Itu harus sangat cepat, apakah filmnya rumit atau panjang.
Mari kita terapkan itu dengan contoh [Flask] cepat dengan Python!
Arsitektur Pembelajaran Mesin Umum
Mari kita mulai dengan menguraikan alur arsitektur pelatihan dan prediksi umum:
Pertama, jalur pelatihan dibuat untuk mempelajari data masa lalu menurut fungsi tujuan.
Ini harus menampilkan dua elemen kunci:
- Fungsi rekayasa fitur : transformasi yang digunakan pada waktu pelatihan harus digunakan kembali pada waktu prediksi.
- Parameter model : algoritme dan hyperparameter yang akhirnya dipilih harus disimpan, sehingga dapat digunakan kembali pada waktu prediksi
Perhatikan bahwa rekayasa fitur yang dilakukan selama waktu pelatihan harus disimpan dengan hati-hati agar dapat diterapkan pada prediksi. Salah satu masalah umum di antara banyak masalah lain yang dapat muncul di sepanjang jalan adalah penskalaan fitur yang diperlukan untuk banyak algoritma.
Jika fitur X1 diskalakan dari nilai 1 hingga 1000 dan diskalakan ulang ke rentang [0,1] dengan fungsi f(x) = x/max(X1)
, apa yang akan terjadi jika kumpulan prediksi memiliki nilai 2000?
Beberapa penyesuaian yang cermat harus dipikirkan terlebih dahulu sehingga fungsi pemetaan mengembalikan output yang konsisten yang akan dihitung dengan benar pada waktu prediksi.
Pelatihan Pembelajaran Mesin vs Memprediksi
Ada pertanyaan besar yang harus dijawab di sini. Mengapa kita memisahkan pelatihan dan prediksi untuk memulai?
Memang benar bahwa dalam konteks contoh dan kursus pembelajaran mesin, di mana semua data diketahui sebelumnya (termasuk data yang akan diprediksi), cara yang sangat sederhana untuk membangun prediktor adalah dengan menumpuk data pelatihan dan prediksi (biasanya disebut satu set tes).
Kemudian, perlu melatih pada “training set” dan memprediksi pada “test set” untuk mendapatkan hasil, sementara pada saat yang sama melakukan rekayasa fitur pada data train dan test, pelatihan dan prediksi dalam pipeline yang sama dan unik. .
Namun, dalam sistem kehidupan nyata, Anda biasanya memiliki data pelatihan, dan data yang akan diprediksi masuk tepat saat sedang diproses. Dengan kata lain, Anda menonton film pada satu waktu dan Anda memiliki beberapa pertanyaan tentangnya nanti, yang berarti jawabannya harus mudah dan cepat.
Selain itu, biasanya tidak perlu melatih ulang seluruh model setiap kali data baru masuk karena pelatihan membutuhkan waktu (bisa berminggu-minggu untuk beberapa set gambar) dan harus cukup stabil dari waktu ke waktu.
Itulah sebabnya pelatihan dan prediksi dapat, atau bahkan seharusnya, dipisahkan dengan jelas pada banyak sistem, dan ini juga lebih mencerminkan bagaimana sistem cerdas (buatan atau tidak) belajar.
Hubungan Dengan Overfitting
Pemisahan pelatihan dan prediksi juga merupakan cara yang baik untuk mengatasi masalah overfitting.
Dalam statistik, overfitting adalah "produksi analisis yang berhubungan terlalu dekat atau persis dengan kumpulan data tertentu, dan oleh karena itu, mungkin gagal untuk menyesuaikan data tambahan atau memprediksi pengamatan di masa depan dengan andal".
Overfitting terutama terlihat pada kumpulan data dengan banyak fitur, atau dengan kumpulan data dengan data pelatihan terbatas. Dalam kedua kasus, data memiliki terlalu banyak informasi dibandingkan dengan apa yang dapat divalidasi oleh prediktor, dan beberapa di antaranya bahkan mungkin tidak terkait dengan variabel yang diprediksi. Dalam hal ini, noise itu sendiri dapat diartikan sebagai sinyal.
Cara yang baik untuk mengontrol overfitting adalah dengan melatih sebagian data dan memprediksi bagian lain yang memiliki kebenaran dasar. Oleh karena itu kesalahan yang diharapkan pada data baru kira-kira merupakan kesalahan terukur pada kumpulan data itu, asalkan data yang kami latih mewakili realitas sistem dan keadaan masa depannya.
Jadi, jika kita merancang jalur pelatihan dan prediksi yang tepat bersama dengan pemisahan data yang benar, kita tidak hanya mengatasi masalah overfitting tetapi juga kita dapat menggunakan kembali arsitektur itu untuk memprediksi data baru.
Langkah terakhir adalah mengontrol bahwa kesalahan pada data baru sama dengan yang diharapkan. Selalu ada pergeseran (kesalahan yang sebenarnya selalu di bawah yang diharapkan), dan orang harus menentukan pergeseran yang dapat diterima—tetapi bukan itu topik artikel ini.
REST API untuk Memprediksi
Di situlah memisahkan pelatihan dan prediksi dengan jelas berguna. Jika kami menyimpan metode rekayasa fitur dan parameter model kami, maka kami dapat membangun REST API sederhana dengan elemen-elemen ini.
Kuncinya di sini adalah memuat model dan parameter pada peluncuran API. Setelah diluncurkan dan disimpan dalam memori, setiap panggilan API memicu perhitungan rekayasa fitur dan metode "prediksi" dari algoritme ML. Keduanya biasanya cukup cepat untuk memastikan respons waktu nyata.

API dapat dirancang untuk menerima contoh unik yang akan diprediksi, atau beberapa contoh yang berbeda (prediksi batch).
Berikut adalah kode Python/Flask minimal yang mengimplementasikan prinsip ini, dengan JSON masuk dan JSON keluar (pertanyaan masuk, jawab keluar):
app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call No need to re-load the model """ # reads the received json jsonfile = request.get_json() res = dict() for key in jsonfile.keys(): # calculates and predicts res[key] = model.predict(doTheCalculation(key)) # returns a json file return jsonify(res) if __name__ == '__main__': # Model is loaded when the API is launched model = pickle.load(open('modelfile', 'rb')) app.run(debug=True)
Perhatikan bahwa API dapat digunakan untuk memprediksi dari data baru, tetapi saya tidak menyarankan menggunakannya untuk melatih model. Itu bisa digunakan, tetapi ini memperumit kode pelatihan model dan bisa lebih menuntut dalam hal sumber daya memori.
Contoh Implementasi - Berbagi Sepeda
Mari kita ambil dataset Kaggle, berbagi sepeda, sebagai contoh. Katakanlah kami adalah perusahaan berbagi sepeda yang ingin memperkirakan jumlah persewaan sepeda setiap hari untuk mengelola perawatan sepeda, logistik, dan aspek bisnis lainnya dengan lebih baik.
Penyewaan terutama bergantung pada kondisi cuaca, jadi dengan prakiraan cuaca, perusahaan itu bisa mendapatkan ide yang lebih baik kapan persewaan akan mencapai puncaknya, dan mencoba menghindari pemeliharaan pada hari-hari ini.
Pertama, kita melatih model dan menyimpannya sebagai objek acar yang dapat dilihat di notebook Jupyter.
Pelatihan model dan kinerja tidak dibahas di sini, ini hanya contoh untuk memahami proses penuh.
Kemudian kita tulis transformasi data yang akan dilakukan pada setiap panggilan API:
import numpy as np import pandas as pd from datetime import date def doTheCalculation(data): data['dayofyear']=(data['dteday']- data['dteday'].apply(lambda x: date(x.year,1,1)) .astype('datetime64[ns]')).apply(lambda x: x.days) X = np.array(data[['instant','season','yr','holiday','weekday','workingday', 'weathersit','temp','atemp','hum','windspeed','dayofyear']]) return X
Ini hanyalah perhitungan variabel (hari dalam setahun) untuk memasukkan bulan dan hari yang tepat. Ada juga pilihan kolom dan urutannya masing-masing untuk disimpan.
Kita perlu, kemudian, untuk menulis REST API dengan Flask:
from flask import Flask, request, redirect, url_for, flash, jsonify from features_calculation import doTheCalculation import json, pickle import pandas as pd import numpy as np app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call """ jsonfile = request.get_json() data = pd.read_json(json.dumps(jsonfile),orient='index',convert_dates=['dteday']) print(data) res = dict() ypred = model.predict(doTheCalculation(data)) for i in range(len(ypred)): res[i] = ypred[i] return jsonify(res) if __name__ == '__main__': modelfile = 'modelfile.pickle' model = pickle.load(open(modelfile, 'rb')) print("loaded OK") app.run(debug=True)
Jalankan program ini, itu akan melayani API pada port 5000 secara default.
Jika kami menguji permintaan secara lokal, masih dengan Python:
import requests, json url = '[http://127.0.0.1:5000/api/makecalc/](http://127.0.0.1:5000/api/makecalc/)' text = json.dumps({"0":{"instant":1,"dteday":"2011-01-01T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":6,"workingday":0,"weathersit":2,"temp":0.344167,"atemp":0.363625,"hum":0.805833,"windspeed":0.160446}, "1":{"instant":2,"dteday":"2011-01-02T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":3,"workingday":0,"weathersit":2,"temp":0.363478,"atemp":0.353739,"hum":0.696087,"windspeed":0.248539}, "2":{"instant":3,"dteday":"2011-01-03T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":1,"workingday":1,"weathersit":1,"temp":0.196364,"atemp":0.189405,"hum":0.437273,"windspeed":0.248309}})
Permintaan berisi semua informasi yang diumpankan ke model. Oleh karena itu, model kami akan merespons dengan perkiraan persewaan sepeda untuk tanggal yang ditentukan (di sini kami memiliki tiga di antaranya).
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} r = requests.post(url, data=text, headers=headers) print(r,r.text) <Response [200]> { "0": 1063, "1": 1028, "2": 1399 }
Itu dia! Layanan ini dapat digunakan di aplikasi perusahaan mana pun dengan mudah, untuk perencanaan perawatan atau agar pengguna mengetahui lalu lintas sepeda, permintaan, dan ketersediaan sepeda sewaan.
Menyatukan semuanya
Kelemahan utama dari banyak sistem pembelajaran mesin, dan terutama PoC, adalah menggabungkan pelatihan dan prediksi.
Jika mereka dipisahkan dengan hati-hati, prediksi real-time dapat dilakukan dengan cukup mudah untuk MVP, dengan biaya pengembangan dan upaya yang cukup rendah dengan Python/Flask, terutama jika, untuk banyak PoC, awalnya dikembangkan dengan Scikit-learn, Tensorflow, atau perpustakaan pembelajaran mesin Python lainnya.
Namun, ini mungkin tidak layak untuk semua aplikasi, terutama aplikasi yang membutuhkan rekayasa fitur yang berat, atau aplikasi yang mengambil kecocokan terdekat yang perlu memiliki data terbaru yang tersedia di setiap panggilan.
Bagaimanapun, apakah Anda perlu menonton film berulang kali untuk menjawab pertanyaan tentangnya? Aturan yang sama berlaku untuk pembelajaran mesin!