23 KiB
ตัวจำแนกประเภทอาหาร 1
ในบทเรียนนี้ คุณจะใช้ชุดข้อมูลที่คุณบันทึกไว้จากบทเรียนก่อน ซึ่งเต็มไปด้วยข้อมูลที่สมดุลและสะอาดเกี่ยวกับอาหารหลากหลายประเภท
คุณจะใช้ชุดข้อมูลนี้ร่วมกับตัวจำแนกประเภทหลากหลายชนิดเพื่อ ทำนายประเภทอาหารของชาติใดชาติหนึ่งจากกลุ่มของส่วนผสม ในขณะที่ทำเช่นนั้น คุณจะได้เรียนรู้เพิ่มเติมเกี่ยวกับวิธีการที่อัลกอริทึมสามารถนำมาใช้ในงานการจำแนกประเภท
แบบทดสอบก่อนเรียน
การเตรียมตัว
สมมติว่าคุณได้ทำ บทเรียนที่ 1 เสร็จแล้ว ตรวจสอบให้แน่ใจว่าไฟล์ cleaned_cuisines.csv มีอยู่ในโฟลเดอร์ /data
หลักสำหรับบทเรียนทั้งสี่นี้
แบบฝึกหัด - ทำนายประเภทอาหารของชาติ
-
ทำงานในโฟลเดอร์ notebook.ipynb ของบทเรียนนี้ นำเข้าไฟล์นั้นพร้อมกับไลบรารี Pandas:
import pandas as pd cuisines_df = pd.read_csv("../data/cleaned_cuisines.csv") cuisines_df.head()
ข้อมูลจะมีลักษณะดังนี้:
Unnamed: 0 | cuisine | almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 1 | indian | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 2 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 3 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 4 | indian | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
-
ตอนนี้นำเข้าไลบรารีเพิ่มเติม:
from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split, cross_val_score from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve from sklearn.svm import SVC import numpy as np
-
แบ่งพิกัด X และ y ออกเป็นสอง DataFrame สำหรับการฝึก
cuisine
สามารถเป็น DataFrame ของป้ายกำกับ:cuisines_label_df = cuisines_df['cuisine'] cuisines_label_df.head()
จะมีลักษณะดังนี้:
0 indian 1 indian 2 indian 3 indian 4 indian Name: cuisine, dtype: object
-
ลบคอลัมน์
Unnamed: 0
และคอลัมน์cuisine
โดยใช้drop()
และบันทึกข้อมูลที่เหลือเป็นคุณสมบัติที่สามารถฝึกได้:cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1) cuisines_feature_df.head()
คุณสมบัติของคุณจะมีลักษณะดังนี้:
almond | angelica | anise | anise_seed | apple | apple_brandy | apricot | armagnac | artemisia | artichoke | ... | whiskey | white_bread | white_wine | whole_grain_wheat_flour | wine | wood | yam | yeast | yogurt | zucchini | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
ตอนนี้คุณพร้อมที่จะฝึกโมเดลของคุณแล้ว!
การเลือกตัวจำแนกประเภท
เมื่อข้อมูลของคุณสะอาดและพร้อมสำหรับการฝึก คุณต้องตัดสินใจว่าจะใช้อัลกอริทึมใดสำหรับงานนี้
Scikit-learn จัดกลุ่มการจำแนกประเภทไว้ในหมวดการเรียนรู้แบบมีผู้สอน และในหมวดหมู่นี้คุณจะพบวิธีการจำแนกประเภทมากมาย ความหลากหลาย อาจดูน่าตกใจในตอนแรก วิธีการต่อไปนี้ล้วนมีเทคนิคการจำแนกประเภท:
- โมเดลเชิงเส้น
- Support Vector Machines
- Stochastic Gradient Descent
- Nearest Neighbors
- Gaussian Processes
- Decision Trees
- Ensemble methods (voting Classifier)
- อัลกอริทึมแบบหลายคลาสและหลายผลลัพธ์ (multiclass และ multilabel classification, multiclass-multioutput classification)
คุณสามารถใช้ neural networks เพื่อจำแนกข้อมูล ได้เช่นกัน แต่สิ่งนี้อยู่นอกขอบเขตของบทเรียนนี้
จะเลือกตัวจำแนกประเภทใด?
แล้วคุณควรเลือกตัวจำแนกประเภทใด? บ่อยครั้ง การลองใช้หลายตัวและมองหาผลลัพธ์ที่ดีเป็นวิธีการทดสอบ Scikit-learn มี การเปรียบเทียบแบบเคียงข้างกัน บนชุดข้อมูลที่สร้างขึ้น โดยเปรียบเทียบ KNeighbors, SVC สองวิธี, GaussianProcessClassifier, DecisionTreeClassifier, RandomForestClassifier, MLPClassifier, AdaBoostClassifier, GaussianNB และ QuadraticDiscrinationAnalysis พร้อมแสดงผลลัพธ์ในรูปแบบภาพ:
กราฟที่สร้างขึ้นจากเอกสารของ Scikit-learn
AutoML แก้ปัญหานี้ได้อย่างง่ายดายโดยการรันการเปรียบเทียบเหล่านี้ในคลาวด์ ทำให้คุณสามารถเลือกอัลกอริทึมที่ดีที่สุดสำหรับข้อมูลของคุณ ลองใช้ ที่นี่
วิธีที่ดีกว่า
วิธีที่ดีกว่าการเดาแบบสุ่มคือการปฏิบัติตามแนวคิดใน ML Cheat sheet ที่สามารถดาวน์โหลดได้ ที่นี่เราพบว่า สำหรับปัญหาแบบหลายคลาส เรามีตัวเลือกบางอย่าง:
ส่วนหนึ่งของ Algorithm Cheat Sheet ของ Microsoft ที่แสดงตัวเลือกการจำแนกประเภทแบบหลายคลาส
✅ ดาวน์โหลด cheat sheet นี้ พิมพ์ออกมา และติดไว้บนผนังของคุณ!
การใช้เหตุผล
ลองดูว่าเราสามารถใช้เหตุผลเพื่อเลือกวิธีการต่าง ๆ ได้หรือไม่ โดยพิจารณาจากข้อจำกัดที่เรามี:
- Neural networks หนักเกินไป เนื่องจากชุดข้อมูลของเราสะอาดแต่มีขนาดเล็ก และเรากำลังฝึกโมเดลในเครื่องผ่านโน้ตบุ๊ก Neural networks จึงหนักเกินไปสำหรับงานนี้
- ไม่ใช้ตัวจำแนกประเภทแบบสองคลาส เราไม่ใช้ตัวจำแนกประเภทแบบสองคลาส ดังนั้นจึงไม่ใช้ one-vs-all
- Decision tree หรือ logistic regression อาจใช้ได้ Decision tree อาจใช้ได้ หรือ logistic regression สำหรับข้อมูลแบบหลายคลาส
- Multiclass Boosted Decision Trees แก้ปัญหาอื่น Multiclass Boosted Decision Tree เหมาะสมที่สุดสำหรับงานที่ไม่ใช่พารามิเตอร์ เช่น งานที่ออกแบบมาเพื่อสร้างการจัดอันดับ ดังนั้นจึงไม่เหมาะสำหรับเรา
การใช้ Scikit-learn
เราจะใช้ Scikit-learn เพื่อวิเคราะห์ข้อมูลของเรา อย่างไรก็ตาม มีหลายวิธีในการใช้ logistic regression ใน Scikit-learn ลองดู พารามิเตอร์ที่ต้องส่ง
โดยพื้นฐานแล้วมีสองพารามิเตอร์สำคัญ - multi_class
และ solver
- ที่เราต้องระบุเมื่อเราขอให้ Scikit-learn ทำ logistic regression ค่า multi_class
จะกำหนดพฤติกรรมบางอย่าง ส่วนค่าของ solver คืออัลกอริทึมที่จะใช้ ไม่ใช่ทุก solver ที่สามารถจับคู่กับค่าของ multi_class
ได้
ตามเอกสาร ในกรณีแบบหลายคลาส อัลกอริทึมการฝึก:
- ใช้ one-vs-rest (OvR) หากตัวเลือก
multi_class
ถูกตั้งค่าเป็นovr
- ใช้ cross-entropy loss หากตัวเลือก
multi_class
ถูกตั้งค่าเป็นmultinomial
(ปัจจุบันตัวเลือกmultinomial
รองรับเฉพาะ solver ‘lbfgs’, ‘sag’, ‘saga’ และ ‘newton-cg’)
🎓 'scheme' ในที่นี้สามารถเป็น 'ovr' (one-vs-rest) หรือ 'multinomial' เนื่องจาก logistic regression ถูกออกแบบมาเพื่อรองรับการจำแนกประเภทแบบไบนารี scheme เหล่านี้ช่วยให้มันจัดการงานการจำแนกประเภทแบบหลายคลาสได้ดีขึ้น source
🎓 'solver' ถูกกำหนดว่าเป็น "อัลกอริทึมที่จะใช้ในปัญหาการเพิ่มประสิทธิภาพ" source.
Scikit-learn มีตารางนี้เพื่ออธิบายว่า solver จัดการกับความท้าทายต่าง ๆ ที่เกิดจากโครงสร้างข้อมูลประเภทต่าง ๆ อย่างไร:
แบบฝึกหัด - แบ่งข้อมูล
เราสามารถมุ่งเน้นไปที่ logistic regression สำหรับการทดลองฝึกครั้งแรกของเรา เนื่องจากคุณเพิ่งเรียนรู้เกี่ยวกับเรื่องนี้ในบทเรียนก่อนหน้า
แบ่งข้อมูลของคุณออกเป็นกลุ่มการฝึกและการทดสอบโดยเรียกใช้ train_test_split()
:
X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)
แบบฝึกหัด - ใช้ logistic regression
เนื่องจากคุณกำลังใช้กรณีแบบหลายคลาส คุณจำเป็นต้องเลือกว่าจะใช้ scheme ใดและตั้งค่า solver อย่างไร ใช้ LogisticRegression พร้อมการตั้งค่าแบบหลายคลาสและ solver liblinear เพื่อฝึก
-
สร้าง logistic regression โดยตั้งค่า multi_class เป็น
ovr
และ solver เป็นliblinear
:lr = LogisticRegression(multi_class='ovr',solver='liblinear') model = lr.fit(X_train, np.ravel(y_train)) accuracy = model.score(X_test, y_test) print ("Accuracy is {}".format(accuracy))
✅ ลองใช้ solver อื่น เช่น
lbfgs
ซึ่งมักถูกตั้งค่าเป็นค่าเริ่มต้น
หมายเหตุ ใช้ฟังก์ชัน Pandas
ravel
เพื่อแปลงข้อมูลของคุณให้อยู่ในรูปแบบแบนเมื่อจำเป็น ความแม่นยำดีเกินกว่า 80%!
-
คุณสามารถดูการทำงานของโมเดลนี้ได้โดยการทดสอบข้อมูลหนึ่งแถว (#50):
print(f'ingredients: {X_test.iloc[50][X_test.iloc[50]!=0].keys()}') print(f'cuisine: {y_test.iloc[50]}')
ผลลัพธ์จะถูกพิมพ์ออกมา:
ingredients: Index(['cilantro', 'onion', 'pea', 'potato', 'tomato', 'vegetable_oil'], dtype='object') cuisine: indian
✅ ลองใช้หมายเลขแถวอื่นและตรวจสอบผลลัพธ์
-
เจาะลึกลงไปอีก คุณสามารถตรวจสอบความแม่นยำของการทำนายนี้ได้:
test= X_test.iloc[50].values.reshape(-1, 1).T proba = model.predict_proba(test) classes = model.classes_ resultdf = pd.DataFrame(data=proba, columns=classes) topPrediction = resultdf.T.sort_values(by=[0], ascending = [False]) topPrediction.head()
ผลลัพธ์จะถูกพิมพ์ออกมา - อาหารอินเดียเป็นการคาดเดาที่ดีที่สุด พร้อมความน่าจะเป็นที่ดี:
0 indian 0.715851 chinese 0.229475 japanese 0.029763 korean 0.017277 thai 0.007634 ✅ คุณสามารถอธิบายได้ไหมว่าทำไมโมเดลถึงมั่นใจว่านี่คืออาหารอินเดีย?
-
ดูรายละเอียดเพิ่มเติมโดยการพิมพ์รายงานการจำแนกประเภท เช่นเดียวกับที่คุณทำในบทเรียนการถดถอย:
y_pred = model.predict(X_test) print(classification_report(y_test,y_pred))
precision recall f1-score support chinese 0.73 0.71 0.72 229 indian 0.91 0.93 0.92 254 japanese 0.70 0.75 0.72 220 korean 0.86 0.76 0.81 242 thai 0.79 0.85 0.82 254 accuracy 0.80 1199 macro avg 0.80 0.80 0.80 1199 weighted avg 0.80 0.80 0.80 1199
🚀ความท้าทาย
ในบทเรียนนี้ คุณใช้ข้อมูลที่ทำความสะอาดแล้วเพื่อสร้างโมเดลการเรียนรู้ของเครื่องที่สามารถทำนายอาหารประจำชาติได้จากชุดของส่วนผสม ใช้เวลาสักครู่เพื่ออ่านตัวเลือกมากมายที่ Scikit-learn มีให้สำหรับการจำแนกข้อมูล เจาะลึกลงไปในแนวคิดของ 'solver' เพื่อทำความเข้าใจสิ่งที่เกิดขึ้นเบื้องหลัง
แบบทดสอบหลังบทเรียน
ทบทวนและศึกษาด้วยตนเอง
เจาะลึกลงไปอีกในคณิตศาสตร์เบื้องหลังการถดถอยโลจิสติกใน บทเรียนนี้
งานที่ได้รับมอบหมาย
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ แนะนำให้ใช้บริการแปลภาษาจากผู้เชี่ยวชาญ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้