บทความ Machine Learning
ไม่ว่าจะ ข่าวสาร บทสัมภาษณ์ และ Digital Skill บนสื่อ
มีให้คุณได้อ่านบทความดี ๆ มากมายแล้วที่นี่
โดย: Kan Ouivirach
| Machine Learning
การจัดการ Imbalanced Data ใน Machine Learning
Imbalanced data เป็นปัญหาด้วยเหรอ? ทำไมถึงต้องสนใจด้วยไปจัดการมันด้วย?เป็นครับ! ต้องสนใจด้วย! ปัญหานี้เป็นปัญหาที่เจอตลอดเวลากับแทบจะทุกชุดข้อมูลเลยก็ว่าได้ และจะเป็นปัญหามากกับการทำ Classification เพราะว่าสิ่งที่จะเกิดขึ้นก็คือว่า จำนวน Class ที่เราจะทำนายหรือจะจำแนกมีไม่เท่ากันทำให้ความแม่นยำตอนที่เราจะทำนายหรือจำแนกมีค่าคลาดเคลื่อนไป ไม่น่าเชื่อถือ ค่า Null Accuracy จะสูงมาก อาจจะมากกว่า 90% เลยด้วยซ้ำถ้าใครงงว่า Null Accuracy คืออะไร ลองอ่าน ใช้ Null Accuracy เป็น Baseline ในการวัดผลโมเดลของเรา ก่อนเนอะทีนี้เรามาดูวิธีจัดการกันบ้าง บทความนี้จะมาเสนอวิธี 2 วิธีครับ ที่เราไม่ต้องไปยุ่งกับตัวข้อมูลเลยวิธีแรก.. จัดให้เป็นปัญหา Anomaly Detection ซะจากที่เราพยายามจะใช้วิธี Classification ในการแก้ปัญหา ให้เราเปลี่ยนวิธีคิดครับ ซึ่งว่ากันง่ายๆ เลย ก็ประมาณว่าให้เราจับเอาคลาสที่มีจำนวนมากที่สุด แล้วบอกว่ามันคือ Normal Profile (Pattern) ซะ แล้วนอกนั้นคือ Abnormal หมด ยกตัวอย่างๆ ถ้าสมมุติว่าเราต้องการที่จะจำแนกว่าอีเมลไหนเป็นสแปมหรือไม่ใช่สแปม แล้วเรามีข้อมูล 100 อีเมล เป็นสแปม 2 อีเมล แล้วอีก 98 เป็นอีเมลที่ไม่ใช่สแปมสิ่งที่เราจะทำก็คือให้เราโมเดลแค่ 98 อีเมลที่ไม่ใช่สแปมพอครับ แล้วคิดซะว่ามันคือ Normal Profile แล้วอะไรที่ไม่ใช่ Normal เราก็ตอบว่ามันคือสแปมครับการทำที่ง่ายสุดน่าจะเป็นการนำเอา Normal Profile มาทำ Clustering ครับ แล้วกำหนด Threshold เอาว่า ถ้าระยะห่างระหว่างข้อมูลที่เข้ามาใหม่เกิด Threshold ที่เรากำหนดไว้ เราก็พิจารณาว่าข้อมูลนั้นเป็นสแปมครับผมวิธีที่ 2.. เอา Metric อื่นมาช่วยในการวัดผลโมเดลในกรณีของ Imbalanced Data เราจะใช้ค่า Accuracy อย่างเดียวมาวัดผลไม่ได้ เนื่องจาก Null Accuracy มีค่าสูงเกินไป เราจะหา Metric อื่นมาช่วยในการวัดผลของเราครับ Metric นั้นคือค่า Area Under Curve (AUC) ครับผม ซึ่งค่า AUC นี่จะได้มาจากกราฟ Receiver Operating Characteristic (ROC) กราฟนี้จะมีลักษณะตามรูปด้านล่างนี้ครับรูป ROC จาก Wikiจากรูปถ้าโมเดลเราดี กราฟมันจะโค้งเข้ามุมซ้ายบนครับ คือมีค่า True Positive Rate (TPR) สูง และมีค่า False Positive Rate (FPR) ต่ำ ทีนี้ค่า AUC มันก็คือค่าพื้นที่ใต้กราฟนี่แหละ ถ้าโมเดลเราจำแนกหรือทำนายแม่น ค่า AUC นี้ก็จะมีค่าเข้าใกล้ 1 ครับผมค่า AUC นี่จะออกมาเป็นความน่าจะเป็นที่โมเดลเราจะสามารถแบ่งจำแนก Class ของเราได้ดีขนาดไหนครับ คือเราอาจจะได้ค่า Accuracy ประมาณ 98% แต่ได้ค่า AUC ประมาณ 0.1 ก็เป็นได้ครับ คือมี FPR สูงมากนั่นเอง หน้าที่ของเราคือหาวิธีทำให้ค่า AUC มันสูงขึ้นมาให้ได้ครับ 💪จริงๆ ก็ยังมีวิธีอื่นอีกนะครับ เช่นการ Upsampling หรือ Downsampling ข้อมูลของเรา แต่วิธี 2 วิธีจะเป็นการเพิ่มข้อมูลของเราขึ้นมา (อย่างมีหลักการ) ซึ่งก็สามารถไปใช้ได้เช่นกันโดยไม่ผิดอะไรครับ สุดท้ายถ้าโมเดลของเราให้ผลออกมาดี น่าเชื่อถือ ก็น่าจะแฮปปี้กันทุกฝ่าย 🤗
โดย: Kan Ouivirach
| Machine Learning
ปัญหา Regression ต่างกับ Classification อย่างไร?
ทั้งปัญหา Regression และปัญหา Classification ทั้งคู่อยู่จัดอยู่ในการเรียนรู้แบบ Supervised Learning เราลองมาดูปัญหาทีละปัญหากันว่ามันคืออะไรกันบ้างนะปัญหา Regressionลองนึกถึงแอพพลิเคชั่นที่เราใช้กันในปัจจุบันเช่น เราอาจจะมีระบบทำนายการเติบโต ทำนายยอดขาย ทำนายราคาสินค้าหรือบ้าน รวมไปถึงการทำนายระดับความดันเลือด ระบบพวกนี้จะมีสิ่งที่เหมือนกันก็คือเราจะมีข้อมูลและเราจะนำข้อมูลนั้นๆ ไปทำนายค่าๆ หนึ่งในอนาคต ทีนี้ประเด็นสำคัญคือ ค่าๆ หนึ่งในอนาคตเนี่ย จะเป็นค่าแบบ Continuous ครับให้โค้ดเป็นคนอธิบายครับ สมมุติว่าผมมีข้อมูลของเวลาที่ใช้ในการอ่านหนังสือและคะแนนสอบที่ได้ของนักเรียน ผมก็จะสามารถที่จะพอทำนายได้ว่า เช่นถ้ามีนักเรียนคนหนึ่งใช้เวลาอ่านหนังสือ 3.2 ชม. นักเรียนคนนั้นควรจะได้คะแนนประมาณเท่าไหร่ สังเกตตรงว่าค่าคะแนน ซึ่งค่านี้เป็นแบบ Continuousimport pandas as pddf = pd.DataFrame(data={ 'hours': [2.5, 5.1, 3.2, 8.5, 3.5, 9.2, 8.9, 6.9, 7.8, 2.7], 'scores': [21, 47, 27, 75, 30, 88, 95, 76, 86, 25]})dfข้อมูลจำนวนชั่วโมงที่ใช้ในการอ่านหนังสือกับคะแนนสอบที่ได้ผมจะลองมาสร้างโมเดล Regression ครับ ในที่นี้ขอใช้ Linear Regression นะครับ เป็น Regression ที่ง่ายที่สุดX = df[['hours']]y = df.scoresfrom sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)from sklearn.linear_model import LinearRegression regressor = LinearRegression() regressor.fit(X_train, y_train)ลองเทสดูregressor.predict(X_test)ได้ผลประมาณนี้ผลที่ได้จากโมเดล Regression (Linear Regression)จะเห็นได้ว่าถ้านักเรียนคนหนึ่งใช้เวลาอ่านหนังสือ 3.2 ชั่วโมง เค้าน่าจะได้คะแนนประมาณ 28.97 ส่วนถ้านักเรียนอีกคนหนึ่งใช้เวลาอ่านหนังสือประมาณ 7.8 ชั่วโมง เค้าน่าจะได้คะแนนประมาณ 76.72นี่แหละครับปัญหา Regression เป็นปัญหาที่เราอยากจะทำนายค่าในอนาคต หรือค่าที่เราอยากจะประมาณการเป็น Continuousปัญหา Classificationมาดูปัญหา Classification กันบ้าง มีข้อแตกต่างจาก Regression ก็คือ.. ค่าที่เราจะทำนายจะเป็นค่าแบบ Discrete ครับ! ต่างกันแค่นี้จริงเหรอ? 🤔จริงครับ! แค่นี้แหละ เรามาใช้โค้ดเป็นคนอธิบายเช่นเดิม ผมต้องการสร้างโมเดลขึ้นมาเพื่อทำนายว่าคนๆ นี้เป็นเป็นโรคมะเร็งเต้านมหรือเปล่า (Healthy controls หรือ Patients) สังเกตตรงว่าค่าที่จะทำนายนี้ จะเป็นแบบ Discreteสำหรับข้อมูลชุดนี้เค้ากำหนดให้เลข 1 คือ Healthy controls ส่วนเลข 2 คือ Patientsimport pandas as pddf = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/00451/dataR2.csv')df.head()อ่านข้อมูล Breast Cancer จาก UCI Machine Learning Repositoryต่อไปเราจะสร้างโมเดล Classification ขึ้นมาครับ ขอใช้ k-Nearest Neighbors (k-NNs) เนอะX = df.drop('Classification', axis='columns')y = df.Classificationfrom sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)from sklearn import neighborsknn = neighbors.KNeighborsClassifier(n_neighbors=5)knn.fit(X_train, y_train)แล้วเราลองเทสดูknn.predict(X_test)ได้ผลลัพธ์ผลที่ได้จากโมเดล Classification (k-NNs)ผลลัพธ์ทางด้านบนจะออกมาเป็นแบบ Discrete ครับ คือถ้าไม่ตอบว่า Healthy controls ก็จะตอบว่า Patients นั่นเองClassification เป็นปัญหาที่เราอยากจะทำนายค่าในอนาคต หรือที่เราอยากจะจำแนกเป็น Discreteสรุปสั้นๆRegression กับ Classification จะต่างกันที่ตรงค่าที่เราอยากจะทำนายหรือจำแนกครับ ถ้าค่านั้นเป็นแบบ Continuous เราควรจะจัดเป็นปัญหา Regression ส่วนถ้าเป็น Discrete ก็จะเป็นปัญหา Classification ดังนั้นเวลาที่เราเจอคำถามทาง Business หรือ Use Case ที่เราจะนำไปใช้ ก็อยากให้คิดก่อนว่าเราจะใช้ Regression หรือ Classification ครับ 😎
โดย: Kan Ouivirach
| Machine Learning
ใช้ Null Accuracy เป็น Baseline ในการวัดผลโมเดลของเรา
ในกรณีที่เราสร้างโมเดลขึ้นมาเพื่อทำนายผลอะไรสักอย่าง เราก็อยากที่จะวัดผลโมเดลนั้นๆ ว่ามีประสิทธิภาพดีแค่ไหน ส่วนใหญ่แล้วเราก็จะเลือกค่าที่คำนวณง่ายๆ มาอย่างเช่นค่า Accuracy เป็นต้นค่า Accuracy คือ ค่าอัตราส่วนระหว่างจำนวนข้อมูลที่เราทำนายถูก กับจำนวนที่เราต้องการจะทำนายทั้งหมดเช่น สมมุติว่า เรามีข้อมูลที่เราอยากจะทำนายว่าลูกค้าคนไหนของเราจะยกเลิกการใช้บริการของเราหรือเปล่าอยู่เป็นจำนวน 100 ข้อมูล และเราทำนายว่า 75 คนจะยกเลิก และ 75 คนนั้นยกเลิกจริงๆ ดังนั้นค่า Accuracy ของโมเดลของเราก็คือ 75% แล้วถ้าเราทำนายว่ามี 75 คนที่จะยกเลิก แต่ว่ามียกเลิกจริงๆ คือ 50 คน ก็แปลว่าค่า Accuracy ของโมเดลคือ 50% 🤓ทีนี้คำถามที่เราจะต้องถามตัวเองก็คือว่า “ค่า Accuracy เท่าไหร่ถึงจะดี?” ถ้าให้ตอบแบบไม่คิดเลยก็จะตอบประมาณว่า 90% ขึ้นไปครับ ดีแน่นอน!🛑 ช้าก่อน! วางเหยือกเบียร์ลงแล้วหายใจลึกๆ สัก 1–2 ที จริงๆ แล้วเราไม่ควรตอบไปทันทีแบบนั้น สิ่งที่เราควรทำคือย้อนกลับมาดูข้อมูลของเรา และคำนวณค่า Null Accuracy ก่อนครับแล้วค่า Null Accuracy คืออะไร?Baseline accuracy that can be achieved by always predicting the most frequent classตามนั้นเลยครับ มาดูตัวอย่างการคำนวณดีกว่าจะได้เห็นภาพกันมากขึ้นยกตัวอย่างเช่นผมมีข้อมูลอยู่ 100 ข้อมูล และมีจำนวนคนที่ยกเลิกการใช้บริการจริงๆ อยู่ 90 และมีจำนวนคนที่ใช้บริการอยู่ 10 คน ถ้าผมบอกว่าให้โมเดลของผมมีคำตอบเดียวคือทำนายว่าทุกคนยกเลิกการใช้บริการ (เพราะจำนวนคนที่ยกเลิกการใช้บริการมีมากกว่า) ผมก็จะได้ค่า Accuracy คือ 90% แล้วครับ ซึ่งค่า Accuracy นี้แหละ เราเรียกว่าค่า Null Accuracy 😎แปลว่าถ้าเราสร้างโมเดลของเราขึ้นมา ไม่ว่าจะใช้โมเดลอะไรก็ตาม ถ้าได้ค่า Accuracy ไม่เกินค่า Null Accuracy ก็แปลว่าโมเดลนั้นยังทำงานได้ไม่ดีจริง และห้ามนำไปใช้งานจริงครับอาจจะเกิดผลเสียต่อธุรกิจได้สรุปสั้นๆ ว่าค่า Null Accuracy เนี่ย นอกจากจะช่วยวัดผลโมเดลของเราได้แบบไวๆ แล้วยังจะช่วยเป็น Baseline ให้เรารู้ว่าเราควรจะทำโมเดลให้ดียิ่งขึ้นไปอีกหรือไม่ ลองเอาไปใช้กันดูนะครับ ส่วนตัวผมนี่คำนวณค่านี้ตลอดเลย เวลาที่สร้างโมเดลขึ้นมาเพื่อทำนายผล 🎉
โดย: Kan Ouivirach
| Machine Learning
เอาผลของโมเดลมารวมกันแบบนี้ก็ได้เหรอ? มาเรียนรู้เทคนิคง่ายๆ อย่าง Ensemble กัน
ลองนึกถึงเวลาที่เราตัดสินใจจะทำอะไรสักอย่าง เช่น การเลือกซื้อสินค้าสักอย่างหนึ่ง เราคงจะไม่ได้เชื่อทุกอย่างที่เซลส์บอก เราก็คงจะไปตามอ่านรีวีว หรือไม่ก็สอบถามจากเพื่อนๆ ก่อน จนสุดท้ายได้ข้อสรุปของตัวเองมาจึงถึงตัดสินใจที่จะซื้อสินค้านั้นๆเทคนิค Ensemble (อ่านว่า ออน-ซั่ม-เบิล) ใน Machine Learning ก็มีแนวคิดที่คล้ายๆ กัน ซึ่งแนวคิดนั้นก็จะประมาณว่าการตัดสินใจสุดท้ายจะมาจากหลายๆ โมเดลทที่เราสร้าง ซึ่งการทำแบบนี้มีจุดประสงค์เพื่อเพิ่มประสิทธิภาพในการทำนายผลนั่นเองถ้าสมมุติว่าเรามี 5 โมเดล แล้วมีโค้ดประมาณนี้ เราก็เทรนทั้ง 5 โมเดลนั้นเลย# instantiatemodel_1 = tree.DecisionTreeClassifier()model_2 = KNeighborsClassifier()model_3 = LogisticRegression()model_4 = GaussianNB()model_5 = SGDClassifier()# fitmodel_1.fit(X_train, y_train)model_2.fit(X_train, y_train)model_3.fit(X_train, y_train)model_4.fit(X_train, y_train)model_5.fit(X_train, y_train)ส่วนขั้นตอนที่เราจะทำ Prediction นั้น จะมีวิธีทำ 3 วิธีง่ายๆ ที่เราสามารถเอาไปลองใช้ได้ครับMax VotingAveragingWeighted Averagingวิธีแรก Max Votingค่าอะไรที่โมเดลเราตอบมามีจำนวนมากสุด เราก็ตอบค่านั้น 😃 ยกตัวอย่างเป็นโค้ดที่ใช้ Scikit-Learn ดีกว่า ประมาณนี้เลย# predictresults = np.array([ model_1.predict_proba(X_test), model_2.predict_proba(X_test), model_3.predict_proba(X_test), model_4.predict_proba(X_test), model_5.predict_proba(X_test),])mode(results)ใช้ค่า Mode ตอบได้ครับ หรือใครจะเขียนโค้ดให้นับจำนวนก็ได้เช่นกันวิธีที่ 2 Averagingตอบโดยใช้ค่าเฉลี่ย# predictresults = np.array([ model_1.predict_proba(X_test), model_2.predict_proba(X_test), model_3.predict_proba(X_test), model_4.predict_proba(X_test), model_5.predict_proba(X_test),])results.mean()วิธีที่ 3 Weighted Averageวิธีนี้จะคล้ายๆ กับ วิธีที่ 2 แต่จะเป็นการให้ค่า Weight กับแต่ละโมเดลตามนี้# predictresults = np.array([ model_1.predict_proba(X_test) * 0.55, model_2.predict_proba(X_test) * 0.1, model_3.predict_proba(X_test) * 0.15, model_4.predict_proba(X_test) * 0.1, model_5.predict_proba(X_test) * 0.1,])results.sum()ซึ่ง Weight ทุกตัวให้รวมกันให้ได้ 1 นะครับการใช้เทคนิค Ensemble นี้มีโอกาสที่เราจะได้โมเดลที่มีประสิทธิภาพมากขึ้นครับ ซึ่งเป็นอีกเทคนิคหนึ่งที่คนส่วนใหญ่ใช้กันอย่างแพร่หลาย ลองเอาไปใช้ดูนะครับ 😎
โดย: Kan Ouivirach
| Machine Learning
สร้าง Machine Learning โมเดลมาทำ Image Recognition
Image Recogniton คือความสามารถของโปรแกรมในการระบุได้ว่าวัตถุ สถานที่ ผู้คน หรือข้อความต่างๆ ในรูปภาพ ว่าคืออะไร อยู่ที่ไหน ใครเป็นใคร และข้อความนั้นเขียนว่าอะไรถ้าเราอยากจะลองสร้าง (traditional) Machine Learning โมเดลขึ้นมาสักตัวหนึ่งเอามาทำ Image Recognition เราต้องทำอย่างไรบ้างนะ? ปกติแล้วเวลานำข้อมูลเข้าไปสอนโมเดล ข้อมูลนั้นๆ จะอยู่ในรูปแบบ Tabular เนอะ คือแบ่งเป็น Column แต่ละ Column ก็จะมีค่าตัวเลขต่างๆ ทีนี้ถ้าเรามีข้อมูลเป็นรูปภาพล่ะ?ไม่ต้องคิดมากเลยครับ เราก็แปลงรูปให้เป็นข้อมูลแบบ Tabular เลย เช่นถ้ารูปขนาด 2x2 เราก็แปลงให้เป็น Vector ขนาด 1x4 ตามรูปข้างล่างนี้เลยครับแปลงรูป 2x2 ให้เป็น Vector ขนาด 1x4โดยเราจะเอาแถวที่ 2 เป็นต้นไป ขึ้นมาต่อด้านหลังของแถวที่ 1 ไปเรื่อยๆ ครับ เท่านี้เราก็จะมีข้อมูแบบ Tabular ที่ Represent รูป 1 รูปแล้วเรียบร้อย 🎉ถ้ารูปมีขนาดไม่เท่ากัน? วิธีแก้คือเราต้องทำให้ขนาดของรูปทุกรูปเท่ากันก่อนก็พอ ทีนี้ก็แล้วแต่ว่าเราจะ Crop รูป หรือ Resize รูปครับผมเรามาลองเล่นกันบ้างดีกว่า จะได้เข้าใจมากขึ้นครับ เราจะนำข้อมูล Optical Recognition of Handwritten Digits จากเว็บ UCI Machine Learning Repository มาสร้างโมเดลกันPhoto by Green Chameleon on Unsplashโหลดข้อมูลมาก่อนครับimport pandas as pddigits_train = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tra', header=None)digits_train.head()ข้อมูลที่ได้หน้าตาจะประมาณนี้ครับลักษณะข้อมูล Optical Recognition of Handwritten Digitsจะเห็นได้ว่า UCI ได้แปลงข้อมูลให้เรามาแล้ว แต่ถ้าเราจับข้อมูลมาเรียงกลับมาเป็นรูปขนาด 8x8 จะได้แบบนี้first_digit = digits_train.loc[0, :][:-1].values.reshape(8, 8)first_digitแปลงข้อมูล Tabular (Feature Vector) ให้กลับมาอยู่ในรูปขนาด 8x8ถ้าอยากเห็นเป็นรูปจริงๆ เราสามารถใช้ Matplotlib ช่วยได้ครับ%matplotlib inlineimport matplotlib.pyplot as pltplt.figure(1, figsize=(3, 3))plt.imshow(first_digit, cmap=plt.cm.gray_r, interpolation='nearest')plt.show()ใช้ Matplotlib ช่วยแสดงค่าจากอาเรย์ 8x8 ออกมาเป็นรูปภาพถึงแม้ว่าบทความนี้จะแปลงข้อมูลจาก Tabular เป็นรูปขนาด 8x8 แต่จริงๆ เราก็สามารถแปลงรูปขนาด 8x8 ให้อยู่ในรูปแบบของ Feature Vector ขนาด 1x64 ได้ไม่ยากครับ แปลงไปแปลงกลับไม่โกง 😝ทีนี้ขั้นตอนการสร้างโมเดล เราก็สามารถทำตามปกติได้เลยครับ เพราะข้อมูลอยู่ในรูปแบบของ Tabular แล้ว โค้ดทั้งหมดมีตามนี้เลยครับ 👇 (ใช้โมเดล SVM)import pandas as pdfrom sklearn import svmdigits_train = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tra', header=None)X_train = digits_train.drop([64], axis=1)y_train = digits_train[64]clf = svm.SVC()clf.fit(X_train, y_train)digits_test = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tes', header=None)X_test = digits_test.drop([64], axis=1)y_test = digits_test[64]y_pred_class = clf.predict(X_test)clf.score(X_test, y_test)เป็นอันเสร็จสิ้น ที่เหลือก็เป็นขั้นตอนการปรับให้โมเดลของเราเก่งขึ้นครับผม 😎
โดย: Kan Ouivirach
| Machine Learning
ใช้ Pickle เซฟและโหลด ML โมเดลใน Scikit-Learn ไปใช้งานต่อ
คำถาม? เวลาที่เราสอนโมเดลเสร็จแล้ว อยากเอาโมเดลนี้ไปใช้งานต่อที่อื่น หรือเอาไป deploy ใช้บน server เพื่อใช้งานจริงๆ ต้องทำอย่างไร?คำถามนี้เจอค่อนข้างบ่อย เมื่อก่อนอาจจะยังไม่ค่อยมีคำถามนี้เพราะว่า Machine Learning ยังอยู่ฝั่ง Academia ซะเป็นส่วนใหญ่ แต่ปัจจุบันนี้ออกมาทางฝั่ง Industry เยอะมากแล้ว และแน่นอนว่าจะต้องมีการใช้งานโมเดลจริงๆ จังๆ ไม่ใช่แค่สอนโมเดล ดูผลการทดลองแล้วก็จบเนอะ 😎แน่นอนว่าเราไม่ควรไปสอนโมเดลอีกรอบบน server เพราะน่าใช้เวลานานมาก ถ้าเป็นโมเดลเล็กๆ ก็อาจจะใช้เวลา 2–3 วินาที แต่ในชีวิตจริง เราน่าจะใช้เวลาในการเทรนประมาณ 2–3 ชม. หรือ อาจจะเป็นอาทิตย์ก็เป็นได้ 😱บทความนี้จะมาสอนให้เราสามารถสอนโมเดลใน Scikit-Learn ครั้งเดียว แล้วเซฟไปใช้งานที่ไหนต่อก็ได้ครับ เรามาสร้างโมเดล K-means แบบง่ายๆ กันimport pandas as pdfrom sklearn import clusterdata = { 'data': [2, 3, 4, 10, 12, 20, 30, 11, 25]}df = pd.DataFrame(data)kmeans = cluster.KMeans(n_clusters=2)kmeans.fit(df)พอเสร็จแล้วเราจะได้ Centroid มาcentroids = kmeans.cluster_centers_print(centroids)จุด Centroid ที่ได้จาก K-meansถ้าเราอยากนำโมเดล (ตัวแปร kmeans) ไปใช้งานต่อ เราจะใช้ตัวช่วยที่ชื่อว่า Pickle ครับ วิธีใช้ก็ตามนี้import picklef = open('kmeans.pkl', 'wb')pickle.dump(kmeans, f)f.close()เราจะเปิดไฟล์มาเขียนให้เป็น Binary mode และสั่ง pickle.dump ครับ เสร็จแล้วเราก็จะได้ไฟล์ kmeans.pkl เอาไปใช้ที่ไหนก็ได้!!วิธีเอาไปใช้ก็เอาไฟล์นั้นขึ้นไปวางบน server ครับ หรือที่เราเรียกกันว่า Model Deployment นั่นแหละ ทีนี้การโหลดโมเดลขึ้นมาใช้งาน เราก็จะใช้ Pickle เช่นกัน ตามนี้ครับimport picklef = open('kmeans.pkl', 'rb')stored_kmeans = pickle.load(f)f.close()ยืนยันสักหน่อยว่าเราได้โมเดลเดียวกันprint(stored_kmeans.cluster_centers_)จุด Centroid ที่ได้จาก K-means ที่เราโหลดขึ้นมาใหม่น่าจะพอเห็นภาพกันนะครับ 😉
โดย: Kan Ouivirach
| Machine Learning
ปรับ Parameters ของโมเดล ML ด้วย GridSearchCV ใน Scikit-Learn
ปกติเวลาที่เราอยากจะปรับโมเดล หรือหา Parameters ที่ดีที่สุดของโมเดลที่เหมาะสมกับข้อมูลที่เรานำมาสอน เราจะใช้วิธี Cross Validation และกำหนดว่าเราจะ Vary ค่าต่างๆ ของ Parameters ของเราอย่างไร หน้าตาโค้ดของเราก็จะประมาณนี้from sklearn import datasetsfrom sklearn.model_selection import cross_val_scorefrom sklearn.neighbors import KNeighborsClassifieriris = datasets.load_iris()X = iris.datay = iris.targetknn = KNeighborsClassifier(n_neighbors=5)scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy')print(scores)แล้วถ้าเราต้องการที่จะ Vary ค่าต่างๆ เราอาจจะใช้ Loop ได้ประมาณนี้from sklearn import datasetsfrom sklearn.model_selection import cross_val_scorefrom sklearn.neighbors import KNeighborsClassifieriris = datasets.load_iris()X = iris.datay = iris.targetn_neighbors = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]weights = ['uniform', 'distance']algorithms = ['auto', 'kd_tree']score_collection = []for n in n_neighbors: for w in weights: for a in algorithms: knn = KNeighborsClassifier(n_neighbors=n, weights=w, algorithm=a) scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy') score_collection.append(scores) print(score_collection)แล้วถ้าเราอยากรู้ว่าค่า Parameters ชุดไหนที่ทำให้โมเดลเราได้ผลที่ดีที่สุด เราก็อาจจะต้องเก็บ Index ของแต่ละรอบไว้ และเขียนโค้ดเพื่อหาว่ารอบไหนที่ให้ผลที่ดีที่สุดให้ผลดีที่สุด แต่ถ้าเราใช้ GridSearchCV ก็จะได้ประมาณนี้from sklearn import datasetsfrom sklearn.model_selection import GridSearchCVfrom sklearn.neighbors import KNeighborsClassifieriris = datasets.load_iris()X = iris.datay = iris.targetparam_grid = dict( n_neighbors=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], weights=['uniform', 'distance'], algorithm=['auto', 'kd_tree'])knn = KNeighborsClassifier()clf = GridSearchCV(knn, param_grid=param_grid, cv=10)clf.fit(X, y)print(clf.best_params_)โค้ดเราดูเป็นระเบียบมากขึ้นเยอะ 😎 ถ้าเราอยากจะ Vary ค่า Parameter เพิ่ม เราก็แค่เพิ่มเข้าไปใน dict นั้นพอ ไม่ต้องไปเพิ่ม Loop แบบตัวอย่างด้านบนวิธี GridSearchCV ยังมีข้อดีอีกข้อคือ เราสามารถเอาผลลัพธ์ที่ได้ไปทำนายผลต่อได้ครับclf.predict([[3, 5, 4, 2],])ชีวิตสบายขึ้นไม่รู้กี่เท่า 😚ทีนี้ถ้าข้อมูลเราเยอะมากๆ การที่จะทำให้วิธีวนลูปวิธีแรกทำงานได้เร็วขึ้น หรือเอาไปแยก Process ทำงาน ก็อาจจะต้องเหนื่อยเขียนโค้ดปรับๆ กัน ทีนี้ทีม Databricks ได้พัฒนาต่อยอด GridSearchCV ให้สามารถมารันบน Apache Spark ได้databricks/spark-sklearnScikit-learn integration package for Apache Spark. Contribute to databricks/spark-sklearn development by creating an…github.comเราแค่แก้ตรง Import!! ไม่ต้องมาแก้โค้ดตรงส่วนที่เขียน GridSearchCV เลย เด็ดมาก! 🎉 ตามนี้เลยครับ โค้ดส่วนที่แก้ไขคือส่วนที่เป็นตัวหนาfrom sklearn import datasetsfrom spark_sklearn import GridSearchCVfrom sklearn.neighbors import KNeighborsClassifieriris = datasets.load_iris()X = iris.datay = iris.targetparam_grid = dict( n_neighbors=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], weights=['uniform', 'distance'], algorithm=['auto', 'kd_tree'])knn = KNeighborsClassifier()clf = GridSearchCV(knn, param_grid=param_grid, cv=10)clf.fit(X, y)print(clf.best_params_)Happy Tuning ครับ 🎉
โดย: Kan Ouivirach
| Machine Learning
มาเล่น Sentiment Analysis โดยใช้ Python กัน
How is it going? Positive, Neutral, or Negative?เกริ่นก่อน Sentiment Analysis เนี่ย มันคือกระบวนการที่เราสามารถบอกและแยกแยะอารมณ์ที่แสดงออกมาในข้อความหนึ่งๆ ซึ่งในข้อความนั้นๆ อาจจะออกมาเป็นแง่บวก (positive) แง่ลบ (negative) หรือแบบเฉยๆ (neutral) ก็ได้ปัญหาของเราคือ ถ้าเรามีข้อมูลประมาณด้านล่างนี้ เราจะเอาไปสร้างโมเดล Sentiment Analysis อย่างไร?ข้อมูล Feedback จากระบบหนึ่งเอ๊ะ ที่เราเรียนมาข้อมูลมันจะออกแนวแบ่งเป็น Column ไม่ใช่เหรอ แต่ละ Column คือ 1 Feature ไม่ใช่เหรอ แล้วถ้าเป็นข้อความแบบนี้เราจะทำอย่างไรดีนะ 🤔มีวิธี Preprocessing อยู่หลายแบบครับ แบบที่ง่ายๆ ที่เราจะมาลองกันในบทความนี้เรียกว่า Bag-of-words model ครับผม ขอเอาตัวอย่างจากใน Wiki มาอธิบายนะครับ ถ้าข้อความเราคือJohn likes to watch movies. Mary likes movies too.เราจะแปลงให้อยู่ในรูปแบบของ JSON ได้แบบนี้bag_of_words_1 = {"John": 1, "likes": 2, "to": 1, "watch": 1, "movies": 2, "Mary":1, "too": 1}สังเกตไหมว่าจริงๆ แล้วมันคือการนับคำนั่นเอง!! 😎 แล้วแต่ละ Key คือคำที่อยู่ในข้อความ และ Value คือจำนวนคำๆ นั้นในข้อความนั่นเอง ถ้ายังไม่คุ้น ลองมาดูในรูปแบบที่เราคุ้นเคยกันดีกว่าBag of Words จากข้อความ “John likes to watch movies. Mary likes movies too.”Key ใน JSON เราสามารถมองเป็นหัว Column ได้เลย ถ้ายังมึนๆ อยู่ ลองดูรูปด้านล่างนี้ครับ น่าจะช่วยให้เข้าใจมากขึ้น 👍รูป Bag of Words จาก https://slideplayer.com/slide/7073400/ทีนี้ปัญหาของเราก็จะอยู่ที่ว่าเราจะเลือกคำอะไรบ้างเอามาสร้างโมเดล ซึ่งตรงจุดนี้เป็นจุดที่ยากที่สุดครับ.. วิธีการเลือกคำนี่สามารถเป็นอีกศาสตร์หนึ่งได้เลย ศาสตร์นั้นคือ Natural language processing ครับผม ลองไปศึกษาเพิ่มเติมกันดูเนอะกลับมาที่ข้อมูลเราบ้าง เราจะใช้ตัวช่วยนับ CountVectorizer จาก Scikit-Learn ครับ ง่ายมาก! ตามนี้เลยimport pandas as pdfrom sklearn.feature_extraction.text import CountVectorizertext = [ 'Promptly answer to my request.', 'great turnaround time!', 'Fast response and great service!', 'As usual you took the request and completed in as few steps as possible and well done!', 'Very quick turnaround time and great communication. Thank you!', 'Really quick turnaround. Thanks!!', 'reduce the turn around time and increase/upgrade the interaction ability between the client and the pronto team during the building of the website.', 'Better turn around time for changes and updates. Better copywriting talents for web content rewrite requests.', 'Get back to us faster', 'Be more careful when fixing our site to not break the other coding on other pages', 'All of the information for this listing is already on the website that Pronto built. It is disappointing that this has taken so many tries to get right.', 'slow communication regarding SEO questions, emailing SEO team direct has been slower that going through my account rep- vague and incomplete answers wasting time', 'The time difference and language barrier are my main complaints. Otherwise our website looks great.', 'Process is way too slow. Working with another country seems to really slow things down alot.',]label = [ 'positive', 'positive', 'positive', 'positive', 'positive', 'positive', 'neutral', 'neutral', 'neutral', 'neutral', 'negative', 'negative', 'negative', 'negative',]df = pd.DataFrame(data={ 'text': text, 'label': label})vectorizer = CountVectorizer(stop_words='english')X_train = df.texty_train = df.labelX_train_vectorized = vectorizer.fit_transform(X_train)เพียงเท่านี้เราจะได้ข้อมูลของเราอยู่ในรูปแบบที่เราต้องการแล้ววววข้อมูลข้อความหลังจากที่ทำ Bag of Wordsถ้าเราอยากดูว่า CounterVectorizer เลือกคำอะไรมาให้เราบ้าง เราจะสั่งฟังก์ชั่น get_feature_names ตามนี้กับตัว vectorizer ของเราครับคำที่ CountVectorizer เลือกมาเท่านี้เราก็สามารถนำเข้าโมเดลของเราได้แล้วครับ จัดกันเลย~ ลอง Naive Bayes ละกัน# importfrom sklearn import naive_bayes# instantiateclf = naive_bayes.MultinomialNB()# fitclf.fit(X_train_vectorized, y_train)แล้วถ้าเราอยากจะลองทดสอบกับข้อความใหม่ เพื่อดูว่าจะเป็น Positive, Neutral หรือ Negative สิ่งที่เราต้องทำก่อนคือ เราต้องแปลงข้อความใหม่นั้นให้อยู่ใน Bag of Words แบบเดียวกับที่เราเอาเข้าไปสอนโมเดลของเราก่อนครับ ซึ่งวิธีการแปลงเราจะ “ต้อง” เอาตัว vectorizer ที่เราสร้างไว้กับข้อมูลที่ใช้สอนมาใช้ตรงนี้ครับ จุดนี้สำคัญเลย“เราแปลงข้อมูลที่เราใช้สอนด้วยวิธีไหน เราต้องแปลงข้อมูลที่เราจะใช้ทดสอบด้วยวิธีเดียวกัน”ทำได้ตามนี้ (ข้อความแรกเป็น Positive ข้อความที่ 2 เป็น Neutral ส่วนข้อความที่ 3 เป็น Negative)# positive, neutral, negativeX_test = [ 'Fast service! Thank you', 'wish it could have been resolved sooner as it was simple', 'Cannot get my website where I want because repeated requests are misunderstood, requests are simply not honored.',]X_test_vectorized = vectorizer.transform(X_test)ตัวแปร X_test_vectorized จะเป็นตัวแปรที่แปลงข้อความ 3 ข้อความนั้นให้อยู่ในรูปแบบของ Bag of Words ให้เรา ต่อจากนี้เราก็เอาไปทดสอบกับโมเดลของเราได้เลยโค้ดส่วนการสร้างโมเดล Sentiment Analysisเราเพิ่งจะสร้างโมเดลทำ Sentiment Analysis ไปเรียบร้อยแล้ว 🎉ผลที่ได้ออกมาก็ดูพอไปวัดไปวาได้ครับ แต่อย่าเพิ่งเชื่อถือมากไปนะ 😂 เราควรปรับโมเดลของเราให้ดีขึ้นเรื่อยๆ ทำให้น่าเชื่อถือมากขึ้น ข้อมูลเพิ่ม เลือกคำให้ดีขึ้น ทำ Cross Validation ทำ ฯลฯขอให้สนุกกับการทำ Sentiment Analysis ครับผม 😙
โดย: Kan Ouivirach
| Machine Learning
Visualize โมเดล Tree ใน Scikit-Learn
เวลาที่เราสร้างโมเดลประเภท Tree อย่างเช่น Decision Tree จะมีข้อดีอย่างหนึ่งคือโมเดลพวกนี้สามารถนำมาวาดรูปให้คนอ่านรู้เรื่องได้ (จริงๆ โมเดลอื่นก็วาดรูปได้นะ แต่ไม่ user friendly เท่ากับโมเดลประเภท Tree) ถ้าเราใช้ Scikit-Learn แล้วเราอยากจะดูว่าโมเดลเราหน้าตาเป็นแบบไหน เราจะทำอย่างไร?เริ่มด้วยการสร้างโมเดลแบบ Tree สักโมเดลหนึ่งมาก่อน ขอเป็น Decision Tree ละกันเนอะ เขียนโค้ดได้ตามนี้เลยfrom sklearn import tree, datasetsfrom sklearn.metrics import accuracy_scorefrom sklearn.model_selection import train_test_splitiris = datasets.load_iris()X, y = iris.data, iris.targetX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)clf = tree.DecisionTreeClassifier()clf.fit(X_train, y_train)y_pred = clf.predict(X_test)print(accuracy_score(y_test, y_pred))ทีนี้ใน Module ที่ชื่อ tree ที่เรา import มาตอนแรกจะมีฟังก์ชั่นชื่อ export_graphviz ครับ เราจะใช้ฟังก์ชั่นนี้แหละสร้าง Graph ออกมา โดยฟังก์ชั่นนี้ใช้ Graphviz ครับ ซึ่งใช้ไฟล์ DOT language ในการอธิบายหน้าตาของ Graphให้เราเขียนโค้ดเพิ่มเพื่อเรียกใช้ export_graphviz ตามนี้tree.export_graphviz(clf,out_file=’tree.dot’,feature_names=iris.feature_names,class_names=iris.target_names,filled=True,rounded=True)เราจะใส่โมเดลที่เราสอน (clf) เข้าไป ตั้งชื่อ output file ว่า tree.dot ในไฟล์นั้นจะมีชื่อ feature (feature_names=iris.feature_names) มีชื่อ class (class_names=iris.target_names) แต่ละโหนดจะมีสี (filled=True) แล้วก็แต่ละโหนดจะเป็นสี่เหลี่ยมมนๆ (rounded=True)หลังจากรันโค้ดด้านบนเสร็จเราก็จะได้ไฟล์ tree.dot ออกมา หน้าตาเนื้อหาในไฟล์ก็จะประมาณนี้รูปแสดงข้อมูลในไฟล์ tree.dotอ่านไม่ค่อยรู้เรื่องเนอะ >_< เรามาทำให้เป็นรูปกันดีกว่า ให้เราติดตั้ง Graphviz ก่อนครับ ถ้าเป็นเครื่อง Mac ก็สั่งbrew install graphvizแต่ถ้าใช้เครื่องแบบอื่นลองตามไปดูวิธีที่หน้า Download ได้เลยครับผม พอติดตั้งเสร็จ เราสามารถแปลงเป็นไฟล์ PNG โดยใช้คำสั่งdot -Tpng tree.dot -o tree.pngเปิดรูปมาดูควรจะเห็นตามรูปด้านล่างนี้เลยครับรูปโมเดล Decision Tree กับข้อมูล Irisทีนี้ใครที่ทำโมเดลประเภทนี้ก็สามารถเอารูปนี้ไปช่วยเรื่อง communication ได้แล้ว~ เด็ด!ถ้าใครอยากเห็นโค้ดเต็มๆ สามารถดูได้ที่ intro-to-machine-learning/tree.ipynb ครับ ;)
โดย: Kan Ouivirach
| Machine Learning
มารู้จัก Mean Shift Clustering กัน
บทความก่อนหน้านี้เราพูดถึงวิธี Clustering กันไปแล้ววิธีหนึ่งคือ K-Means บทความนี้เรามารู้จักวิธี Clustering อีกวิธีหนึ่งที่ชื่อว่า Mean shift กันครับข้อแตกต่างระหว่าง Mean Shift กับ K-Meansที่เห็นได้ชัดๆ คือMean shift เป็น density-based clustering ส่วน k-means เป็น centroid-based clustering กล่าวคือ Mean shift จะใช้คอนเซปของ kernel density estimation (KDE) ในการหาตัวแทนกลุ่มของข้อมูล หรือ centroid ในขณะที่ k-means จะใช้ค่าเฉลี่ยระหว่างจุดกับ centroid ในการขยับ centroid ไปเรื่อยๆMean shift ไม่จำเป็นต้องรู้จำนวนกลุ่มของข้อมูลก่อน ส่วน k-means จำเป็นที่ต้องรู้ก่อน แต่ Mean shift ก็มีค่า parameter ที่เราต้องปรับเองตามการใช้งานครับ เค้าเรียกกันว่า kernel bandwidthหลักการทำงานของ Mean Shiftให้จุดทุกจุดเป็น cluster ของตัวมันเองก่อนเลย ถ้ามี 10 จุดข้อมูล ก็แปลว่าเรามี 10 clusters ก่อนเลยครับให้เราเลือก kernel ที่เหมาะสมกับข้อมูล ซึ่งโดยปกติแล้วจะเป็นฟังก์ชั่น Gaussian ครับ ตามสูตรของ Gaussian แล้ว เราจะได้ว่า kernel bandwidth ของเราคือ standard deviation นั่นเอง :Dคัดลอกจุดทุกจุดเก็บไว้ก่อนเป็น 2 ชุดข้อมูล แล้วนำจุดทุกจุดในชุดข้อมูลใดข้อมูลหนึ่ง ผมเรียกว่าเป็นข้อมูลชุดที่ 1 กับข้อมูลชุดที่ 2 ละกัน แล้วทำไมต้องแยกเป็น 2 ชุด? นี่เป็นเหตุผลทางด้านการเขียนโปรแกรมล้วนๆ ครับ :Pเสร็จแล้วเราจะมา estimate กับจุดทุกจุดในข้อมูลชุดที่ 2 โดยใช้ kernel ที่เราเลือกมากับจุดทุกจุดในข้อมูลชุดที่ 1 ครับ หรือพูดง่ายๆ ว่าเราใช้จุดทุกจุดในการอัพเดท cluster แต่ละ cluster ครับ ซึ่งจุดแต่ละจุดในข้อมูลชุดที่ 2 จะถูก estimate แล้วจะค่อยๆ เลื่อนเข้าสู่จุด convergence หรือจุดสูงสุดของ Gaussian (นึกภาพระฆังคว่ำ) แล้วเราอัพเดท cluster อย่างไรล่ะ? ขอยกไปอธิบายคร่าวๆ ต่อด้านล่างหลังจากที่ converge แล้ว ถ้าข้อมูลของเรามีการกระจายตัวหน้าตาแบบมี 3 ระฆังคว่ำ (หรือ 3 clusters) จุดข้อมูลของเราก็จะย้ายไปสู่จุดสูงสุดของ 3 ระฆังคว่ำนั้นโดยอัตโนมัติเองครับท้ายที่สุดคือการ assign จุดเหล่านั้นว่าควรจะอยู่ cluster ไหน ยังจำข้อมูลที่เราคัดลอกไว้ในข้อ 3 ได้ใช่ไหมครับ? เราก็เอาจุดเหล่านั้นมาทีละจุด เทียบระยะห่างระหว่างจุดสูงสุดของระฆังคว่ำที่เราได้มา จุดไหนใกล้ก็ assign จุดนั้นให้เข้าไปกับระฆังอันนั้นครับเป็นอันเสร็จสิ้น!สำหรับการ shift หรืออัพเดทค่า mean (เป็นเหตุผลที่เค้าเรียกว่า mean shift) ทำได้โดยใช้เทคนิค gradient ascent ครับ ซึ่งจริงๆ คือ gradient descent แต่แค่มีทิศตรงข้าม ลองดูสมการในรูป 1 ด้านล่างนี้ครับ เป็นรูปจากงานวิจัยของ Dorin Comaniciu กับ Peter Meerรูปพจน์ของ Mean Shiftสมการที่ 17 นี้เป็นพจน์ของ mean shift ครับ ซึ่งเราสามารถนำเอาส่วนที่ผมตีกรอบเส้นประสีแดงมาเป็นค่า mean ที่โดน shift แล้ว ส่วนฟังก์ชั่น g ในทีนี้ก็คือ kernel ของเรานั่นเอง ซึ่งในงานวิจัยนี้เค้าพิสูจน์ว่ามันเพียงพอสำหรับการ converge ลองตามไปอ่านกันดูนะครับ math เยอะสะใจดี >_<การเลือกค่า kernel bandwidth นั้นมีผลต่อจำนวน cluster ที่เราจะได้ ถ้าเราใช้ค่า bandwidth ที่ต่ำมากๆ เราอาจจะได้จำนวน cluster เท่ากับจำนวนจุดเลยก็ได้ แต่ถ้าเราเลือกค่าที่สูงเกินไป เราอาจจะได้แค่ 1 cluster ดังนั้นค่านี้ควรจะปรับให้เหมาะสมเองครับโดยการทดลองหรืออะไรก็แล้วแต่

พบบทสัมภาษณ์ได้ที่นี่เร็ว ๆ นี้

พบDigital Skill บนสื่อ ได้ที่นี่เร็ว ๆ นี้

หมวดหมู่

พบหมวดหมู่ ได้ที่นี่เร็ว ๆ นี้

พบหมวดหมู่ ได้ที่นี่เร็ว ๆ นี้

Tags

พบคำสำคัญ ได้ที่นี่เร็ว ๆ นี้

พบคำสำคัญ ได้ที่นี่เร็ว ๆ นี้

พบคำสำคัญ ได้ที่นี่เร็ว ๆ นี้