การทำนายการเรียนรู้ของเครื่อง Python ด้วย Flask REST API

เผยแพร่แล้ว: 2022-03-11

บทความนี้เกี่ยวกับการใช้ Python ในบริบทของระบบการเรียนรู้ของเครื่องหรือปัญญาประดิษฐ์ (AI) สำหรับการทำนายแบบเรียลไทม์ด้วย Flask REST API สถาปัตยกรรมที่เปิดเผยที่นี่สามารถเห็นได้ว่าเป็นวิธีการเปลี่ยนจากการพิสูจน์แนวคิด (PoC) ไปสู่ผลิตภัณฑ์ที่ทำงานได้น้อยที่สุด (MVP) สำหรับแอปพลิเคชันการเรียนรู้ของเครื่อง

Python ไม่ใช่ตัวเลือกแรกที่เรานึกถึงเมื่อออกแบบโซลูชันแบบเรียลไทม์ แต่เนื่องจาก Tensorflow และ Scikit-Learn เป็นไลบรารีแมชชีนเลิร์นนิงที่มีการใช้งานมากที่สุดบางส่วนซึ่งสนับสนุนโดย Python จึงมีการใช้งานที่สะดวกใน Jupyter Notebook PoC จำนวนมาก

สิ่งที่ทำให้โซลูชันนี้ทำได้คือการฝึกอบรมใช้เวลานานเมื่อเทียบกับการคาดการณ์ หากคุณคิดว่าการฝึกเป็นกระบวนการในการชมภาพยนตร์และคาดเดาคำตอบของคำถามเกี่ยวกับภาพยนตร์ การจะไม่ต้องดูภาพยนตร์ซ้ำหลังจากมีคำถามใหม่แต่ละข้อก็ดูเหมือนจะมีประสิทธิภาพทีเดียว

การฝึกอบรมเป็นมุมมองที่บีบอัดของ "ภาพยนตร์" และการคาดการณ์กำลังดึงข้อมูลจากมุมมองที่บีบอัด มันควรจะเร็วจริงๆ ไม่ว่าหนังจะซับซ้อนหรือยาว

มาปรับใช้กับตัวอย่าง [Flask] อย่างรวดเร็วใน Python!

สถาปัตยกรรมการเรียนรู้ของเครื่องทั่วไป

เริ่มต้นด้วยการร่างโครงร่างการฝึกอบรมทั่วไปและโฟลว์สถาปัตยกรรมการทำนาย:

ข้อความแสดงแทนรูปภาพ

ขั้นแรก ไปป์ไลน์การฝึกอบรมถูกสร้างขึ้นเพื่อเรียนรู้เกี่ยวกับข้อมูลที่ผ่านมาตามฟังก์ชันวัตถุประสงค์

สิ่งนี้ควรแสดงองค์ประกอบหลักสองประการ:

  1. ฟังก์ชันทางวิศวกรรมคุณลักษณะ : การแปลงที่ใช้ในเวลาฝึกอบรมควรใช้ซ้ำในเวลาคาดการณ์
  2. พารามิเตอร์แบบจำลอง : อัลกอริทึมและไฮเปอร์พารามิเตอร์ที่ถูกเลือกในที่สุดควรถูกบันทึก ดังนั้นจึงสามารถนำกลับมาใช้ใหม่ได้ในเวลาคาดการณ์

โปรดทราบว่าวิศวกรรมคุณลักษณะที่ทำขึ้นระหว่างเวลาฝึกอบรมควรได้รับการบันทึกอย่างระมัดระวังเพื่อให้สามารถนำไปใช้กับการคาดการณ์ได้ ปัญหาหนึ่งที่มักเกิดขึ้นระหว่างทางคือการ ปรับขนาดคุณลักษณะ ซึ่งจำเป็นสำหรับอัลกอริธึมจำนวนมาก

หากคุณสมบัติ X1 ถูกปรับขนาดจากค่า 1 ถึง 1,000 และถูกปรับขนาดใหม่เป็นช่วง [0,1] ด้วยฟังก์ชัน f(x) = x/max(X1) จะเกิดอะไรขึ้นหากชุดการคาดการณ์มีค่า 2000

ควรพิจารณาการปรับอย่างรอบคอบบางอย่างล่วงหน้า เพื่อให้ฟังก์ชันการทำแผนที่ส่งกลับผลลัพธ์ที่สอดคล้องกันซึ่งจะถูกคำนวณอย่างถูกต้องในเวลาคาดการณ์

การฝึกแมชชีนเลิร์นนิงกับการทำนาย

มีคำถามสำคัญที่จะกล่าวถึงที่นี่ เหตุใดเราจึงเริ่มแยกการฝึกอบรมและการทำนายก่อน

เป็นความจริงอย่างยิ่งที่ในบริบทของตัวอย่างและหลักสูตรการเรียนรู้ของเครื่อง โดยที่ข้อมูลทั้งหมดทราบล่วงหน้า (รวมถึงข้อมูลที่จะคาดการณ์) วิธีง่ายๆ ในการสร้างตัวทำนายคือการ ซ้อนข้อมูลการฝึกและการคาดการณ์ (ปกติเรียกว่า ชุดทดสอบ)

จากนั้นจึงจำเป็นต้องฝึกใน "ชุดฝึกอบรม" และคาดการณ์ใน "ชุดทดสอบ" เพื่อให้ได้ผลลัพธ์ ในขณะเดียวกันก็ทำวิศวกรรมคุณลักษณะทั้งข้อมูลการฝึกอบรมและข้อมูลการทดสอบ การฝึกอบรมและการทำนายในไปป์ไลน์เดียวกันและไม่ซ้ำใคร .

อย่างไรก็ตาม ในระบบในชีวิตจริง คุณมักจะมีข้อมูลการฝึกอบรม และข้อมูลที่จะคาดการณ์ก็เข้ามาในขณะที่กำลังประมวลผล กล่าวอีกนัยหนึ่ง คุณดูหนังในคราวเดียวและมีคำถามเกี่ยวกับเรื่องนี้ในภายหลัง ซึ่งหมายความว่าคำตอบควรจะง่ายและรวดเร็ว

ยิ่งไปกว่านั้น ปกติไม่จำเป็นต้องฝึกโมเดลใหม่ทั้งหมดทุกครั้งที่มีข้อมูลใหม่ เนื่องจากการฝึกอบรมต้องใช้เวลา (อาจเป็นสัปดาห์สำหรับชุดภาพบางชุด) และควรมีเสถียรภาพเพียงพอเมื่อเวลาผ่านไป

นั่นคือเหตุผลที่การฝึกอบรมและการคาดการณ์สามารถแยกออกได้อย่างชัดเจนหรือควรแยกจากกันในหลายระบบ และสิ่งนี้ยังสะท้อนให้เห็นได้ดียิ่งขึ้นว่าระบบอัจฉริยะ (เทียมหรือไม่) เรียนรู้อย่างไร

การเชื่อมต่อกับ Overfitting

การแยกการฝึกอบรมและการทำนายยังเป็นวิธีที่ดีในการแก้ไขปัญหาการใส่มากเกินไป

ในสถิติ การใส่มากเกินไปคือ "การผลิตของการวิเคราะห์ที่สอดคล้องมากเกินไปหรือตรงกับชุดข้อมูลเฉพาะ และอาจไม่สามารถใส่ข้อมูลเพิ่มเติมหรือคาดการณ์การสังเกตในอนาคตได้อย่างน่าเชื่อถือ"

ข้อความแสดงแทนรูปภาพ

เส้นสีเขียวแสดงถึงแบบจำลองที่สวมใส่มากเกินไป และเส้นสีดำแสดงถึงแบบจำลองที่ปรับให้เป็นมาตรฐาน แม้ว่าเส้นสีเขียวจะติดตามข้อมูลการฝึกได้ดีที่สุด แต่ก็ขึ้นอยู่กับข้อมูลนั้นมากเกินไป และมีแนวโน้มว่าจะมีอัตราข้อผิดพลาดที่สูงกว่าในข้อมูลที่มองไม่เห็นใหม่ เมื่อเทียบกับเส้นสีดำ_

มีให้เห็นเป็นพิเศษในชุดข้อมูลที่มีคุณสมบัติมากมาย หรือชุดข้อมูลที่มีข้อมูลการฝึกที่จำกัด ในทั้งสองกรณี ข้อมูลมีข้อมูลมากเกินไปเมื่อเทียบกับข้อมูลที่ตัวทำนายตรวจสอบความถูกต้องได้ และบางส่วนอาจไม่ได้เชื่อมโยงกับตัวแปรที่คาดการณ์ด้วยซ้ำ ในกรณีนี้ เสียงรบกวนสามารถตีความได้ว่าเป็นสัญญาณ

วิธีที่ดีในการควบคุมการสวมใส่มากเกินไปคือการฝึกข้อมูลบางส่วนและคาดการณ์ในส่วนอื่นที่เรามีความจริงพื้นฐาน ดังนั้นข้อผิดพลาดที่คาดหวังของข้อมูลใหม่จึงเป็นข้อผิดพลาดที่วัดได้บนชุดข้อมูลนั้นโดยคร่าวๆ โดยที่ข้อมูลที่เราฝึกอบรมนั้นเป็นตัวแทนของความเป็นจริงของระบบและสถานะในอนาคต

ดังนั้น หากเราออกแบบการฝึกอบรมและไปป์ไลน์การทำนายที่เหมาะสมร่วมกับการแบ่งข้อมูลที่ถูกต้อง ไม่เพียงแต่เราจะแก้ไขปัญหาการโอเวอร์ฟิตเท่านั้น แต่ยังสามารถใช้สถาปัตยกรรมนั้นซ้ำเพื่อคาดการณ์ข้อมูลใหม่ได้อีกด้วย

ขั้นตอนสุดท้ายจะเป็นการควบคุมว่าข้อผิดพลาดในข้อมูลใหม่เป็นไปตามที่คาดไว้ มีการเปลี่ยนแปลงอยู่เสมอ (ข้อผิดพลาดจริงมักจะต่ำกว่าที่คาดไว้) และควรกำหนดว่าอะไรคือการเปลี่ยนแปลงที่ยอมรับได้—แต่นั่นไม่ใช่หัวข้อของบทความนี้

REST API สำหรับการทำนาย

นั่นเป็นจุดที่การแยกการฝึกและการคาดคะเนนั้นสะดวกอย่างชัดเจน หากเราบันทึกวิธีวิศวกรรมคุณลักษณะและพารามิเตอร์แบบจำลองของเรา เราก็สามารถสร้าง REST API อย่างง่ายด้วยองค์ประกอบเหล่านี้

ข้อความแสดงแทนรูปภาพ

สิ่งสำคัญคือต้องโหลดโมเดลและพารามิเตอร์เมื่อเปิดใช้ API เมื่อเปิดใช้งานและจัดเก็บไว้ในหน่วยความจำ การเรียก API แต่ละครั้งจะทริกเกอร์การคำนวณทางวิศวกรรมคุณลักษณะและวิธีการ "คาดการณ์" ของอัลกอริทึม ML ทั้งสองมักจะเร็วพอที่จะตอบสนองแบบเรียลไทม์

API สามารถออกแบบให้ยอมรับตัวอย่างเฉพาะที่จะคาดการณ์ได้ หรือตัวอย่างต่างๆ (การคาดการณ์แบบกลุ่ม)

นี่คือโค้ด Python/Flask ขั้นต่ำที่ใช้หลักการนี้ โดยมี JSON เข้าและ JSON ออก (คำถามเข้า ตอบออก):

 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)

โปรดทราบว่า API สามารถใช้สำหรับการทำนายจากข้อมูลใหม่ได้ แต่ฉันไม่แนะนำให้ใช้สำหรับการฝึกโมเดล สามารถใช้ได้ แต่สิ่งนี้จะทำให้โค้ดการฝึกโมเดลซับซ้อนและอาจต้องใช้ทรัพยากรหน่วยความจำมากขึ้น

ตัวอย่างการใช้งาน - การแชร์จักรยาน

ลองใช้ชุดข้อมูล Kaggle การแชร์จักรยาน เป็นตัวอย่าง สมมติว่าเราเป็นบริษัทแบ่งปันจักรยานที่ต้องการคาดการณ์จำนวนการเช่าจักรยานในแต่ละวัน เพื่อจัดการการบำรุงรักษาจักรยาน การขนส่ง และแง่มุมอื่นๆ ของธุรกิจได้ดียิ่งขึ้น

ข้อความแสดงแทนรูปภาพ

การเช่าส่วนใหญ่ขึ้นอยู่กับสภาพอากาศ ดังนั้นด้วยการพยากรณ์อากาศ บริษัทดังกล่าวอาจได้รับความคิดที่ดีขึ้นว่าเมื่อใดที่การเช่าจะถึงจุดสูงสุด และพยายามหลีกเลี่ยงการบำรุงรักษาในวันเหล่านี้

ขั้นแรก เราฝึกโมเดลและบันทึกเป็นวัตถุดองซึ่งสามารถเห็นได้ในสมุดบันทึก Jupyter

การฝึกอบรมแบบจำลองและประสิทธิภาพไม่ได้กล่าวถึงในที่นี้ นี่เป็นเพียงตัวอย่างเพื่อให้เข้าใจกระบวนการทั้งหมด

จากนั้นเราเขียนการแปลงข้อมูลที่จะทำในการเรียก 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

นี่เป็นเพียงการคำนวณตัวแปร (วันของปี) เพื่อรวมทั้งเดือนและวันที่แน่นอน นอกจากนี้ยังมีการเลือกคอลัมน์และลำดับที่จะเก็บไว้

เราต้องเขียน REST API ด้วย 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)

เรียกใช้โปรแกรมนี้ มันจะให้บริการ API บนพอร์ต 5000 โดยค่าเริ่มต้น

หากเราทดสอบคำขอในเครื่อง ยังคงใช้ 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}})

คำขอมีข้อมูลทั้งหมดที่ป้อนให้กับโมเดล ดังนั้น โมเดลของเราจะตอบสนองด้วยการคาดการณ์การเช่าจักรยานสำหรับวันที่ระบุ (ในที่นี้ เรามี 3 รายการ)

 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 }

แค่นั้นแหละ! บริการนี้สามารถนำไปใช้ในแอปพลิเคชันของบริษัทใดๆ ได้อย่างง่ายดาย สำหรับการวางแผนการบำรุงรักษาหรือเพื่อให้ผู้ใช้รับทราบสภาพการจราจรของจักรยาน ความต้องการ และความพร้อมในการเช่าจักรยาน

วางมันทั้งหมดเข้าด้วยกัน

ข้อบกพร่องที่สำคัญของระบบแมชชีนเลิร์นนิงจำนวนมาก โดยเฉพาะอย่างยิ่ง PoC คือการผสมผสานการฝึกอบรมและการทำนาย

หากแยกอย่างระมัดระวัง การทำนายแบบเรียลไทม์สามารถทำได้ค่อนข้างง่ายสำหรับ MVP ด้วยต้นทุนและความพยายามในการพัฒนาที่ค่อนข้างต่ำด้วย Python/Flask โดยเฉพาะอย่างยิ่งหากสำหรับ PoC หลายๆ ตัว มันถูกพัฒนาในขั้นต้นด้วย Scikit-learn, Tensorflow หรือไลบรารีแมชชีนเลิร์นนิงอื่นๆ ของ Python

อย่างไรก็ตาม สิ่งนี้อาจใช้ไม่ได้กับทุกแอปพลิเคชัน โดยเฉพาะแอปพลิเคชันที่วิศวกรรมคุณลักษณะมีจำนวนมาก หรือแอปพลิเคชันที่ดึงข้อมูลที่ใกล้เคียงที่สุดซึ่งจำเป็นต้องมีข้อมูลล่าสุดในการโทรแต่ละครั้ง

คุณจำเป็นต้องดูหนังซ้ำแล้วซ้ำเล่าเพื่อตอบคำถามเกี่ยวกับพวกเขาหรือไม่? กฎเดียวกันกับการเรียนรู้ของเครื่อง!