MLB Player Digital Engagement Forecasting ทำนายความป้อปปูล่าห์ของนักเบสบอลในลีกอเมริการายวัน  

  RSS
The Neural Engineer
(@neural-engineer)
EfficientNet
นัมโดซานเมืองไทย FB: @Lai Shih Chieh กลับมาแชร์ผลงานใหม่บน Kaggle กับงาน
"Major League Baseball Digital Engagement Forecasting"
ซึ่งก็คือการทำนายความป้อปปูล่าห์ของนักเบสบอลในลีกอเมริการายวัน เพื่อที่จะได้จัดเตรียมสินค้าของนักกีฬายอดนิยมในแต่ละวันไว้ล่วงหน้า
ซึ่งเป็นโจทย์ที่ท้าทายและน่าสนใจมากๆ ครับ
 
ดูการแข่งขันได้ที่
(เพจ machine learning กับทาร์ซาน)
 
สวัสดีครับ กลับมาอีกครั้งกับ EP6. เมื่อผมอยากเป็นนัมโดซาน!!
ขอโทษที่หายไปนาน 🙏 จริงๆ ผมก็แข่ง kaggle เรื่อยมา แต่ผลการแข่งพึ่งจะประกาศเนื่องจากใช้ข้อมูล live จริง 1 เดือน หลังจากส่ง code ไป ก็เลยยังไม่ได้มาเขียนแชร์ประสบการณ์
 
ต้องบอกเลยว่ารายการนี้เป็นการแข่งที่ค่อนข้างสนุก ชุดข้อมูลเป็นอะไรที่น่าสนใจมาก และผมก็ได้เรียนรู้อะไรเยอะมาก ก็เลยอยากจะมาแชร์ให้ทุกคนได้อ่านกัน
รายการที่ผมจะมาแชร์ในวันนี้ก็คือ MLB Player Digital Engagement Forecasting ⚾ แค่หัวข้อก็น่าสนใจแล้วใช่มั๊ยครับ?
 
โจทย์การแข่งครั้งนี้ง่ายมาก คือเราต้องการ predict คะแนน digital engagement (scale 0-100) ของผู้เล่นที่แข่งขันใน MLB ในแต่ละวัน ซึ่งอันนี้สามารถจัดอยู่ในประเภท tabular problem (ซึ่งไม่ใช่สิ่งที่ผมถนัด เพราะนี่เป็นการแข่งครั้งที่ 2 ของผมสำหรับโจทย์ tabular 😅)
 
ผมขออธิบายนิดนึงให้เข้าใจ เพราะเราจะเห็นภาพมากยิ่งขึ้น MLB คือ major league baseball ลีคการแข่งขันเบสบอลของอเมริกา ซึ่งทางผู้จัดได้เก็บข้อมูลของผู้เล่น, สถิติการแข่งขันในในแต่ละเกมส์, ข้อมูลทีม, รางวัลที่ผู้แข่งได้รับ ฯลฯ 📈
 
สิ่งที่ผู้จัดต้องการก็คือ ให้เราคาดเดาว่าจะมี digital engagement สกอร์ 0-100 ของแต่ละผู้เล่นในแต่ละวันเท่าไร โดยที่อิงข้อมูลจากวันก่อนหน้า เช่น สมมุติข้อมูลของวันที่ 10 ก็จะให้เรา predict คะแนนของวันที่ 11 อาจจะฟังดูเหมือนง่าย แต่จริงๆ นั้นแฝงด้วยความยาก ความซับซ้อนที่ผู้จัดได้ซ่อนไว้
 
หลายคนอาจจะสงสัยว่า ทางผู้จัดได้ประโยชน์อะไร ประโยชน์มหาศาลเลย ลองนึกง่ายๆ ว่าสมมุติว่า โรนัลโด้ยิง hat-trick ได้ แน่นอนผลตอบรับในวันต่อไปจาก engagement จะต้องสูงมาก ทำให้แมนยูสามารถที่จะเตรียมความพร้อมสต็อกสินค้าที่เกี่ยวกับของโรนัลโด้เพิ่มขึ้น หรือแม้กระทั่งอัพโฆณาที่เกี่ยวกับโรนัลโด้ เพื่อเพิ่มยอด revenue เอาง่ายๆ คือเพิ่มยอด revenue ให้กับบริษัท หรือ partners ไม่ว่าจะเป็น online 🌐 and offline channels 🏬
เหมือนอย่างเช่นทุกครั้ง ผมจะอธิบายความยากของการแข่งขันครั้งนี้
 
• กีฬาเบสบอลนั้นค่อนข้างซับซ้อน ตำแหน่งของผู้เล่น สถิติผู้เล่นที่มีมากกว่า 50 รายการ ฤดูการแข่งขันที่แยกออกเป็นหลายช่วงๆ ฯลฯ ผมพอรู้เรื่องกฎการเล่นเบสบอลอยู่บ้าง แต่ไม่ได้รู้เรื่องสถิติเฉพาะของผู้เล่นแต่ละตำแหน่ง ทำให้ต้องทำความเข้าใจข้อมูลอยู่นานเพื่อทำ feature engineering
 
• ข้อมูลนั้นถูกสเกลให้เป็น 0-100 ในแต่ละวันโดยที่เราไม่รู้ว่าสเกลยังไง ซึ่งอันนี้คือความยากที่ทำให้เกิดค่า error ในการ prediction ที่สูงมาก หลายคนอาจจะไม่เห็นภาพ โดยปกติแล้วเวลาที่เราทำ forecasting เราจะอิงจากสถิติเดิม pattern เพื่อทำการ predict แต่อันนี้คือ สถิติหรือ pattern 📉 เดิมไม่ได้แปลว่า predict จะเท่าเดิม เพราะมันขึ้นอยู่กับผู้เล่นคนอื่นด้วยในวันนั้น ใครที่ได้คะแนนเยอะสุด ก็จะถูกสเกลให้เป็น 100 ส่วนใครที่ได้น้อยสุดก็เป็น 0 ซึ่งเราไม่สามารถรู้ได้ว่าเค้ามีหลักการณ์สเกลยังไง (standardisation) ซึ่งผมเองได้พยายามลองทำหลายวิธีเพื่อแก้ปัญหานี้ เช่นเอาผู้เล่นที่ได้คะแนนสูงสุด น้อยสุด มาทำ min max scale ซึ่งก็ได้ผลไม่ดี เนื่องจากถ้าเรา predict min or max คาดเคลื่อน ทุกอย่างคือพัง แถมการทำแบบนี้ถ้ามี outliers คือจบ ซึ่งก็ได้ลองใช้ scale แบบอื่นไม่ว่าจะเป็น standard scaler, standard scaler, quantile scaler etc. ก็ล้วนแต่ให้ผลแย่ จริงๆ ถ้าผู้ไม่ทำการสเกล target ในแต่ละวัน ผลที่ได้น่าจะดีกว่านี้ หรือให้ predict rank ก็น่าจะให้ผลที่ถูกต้องกว่า
 
• Digital engagement ที่ให้ predict มี 4 targets แต่ไมได้บอกว่ามาจากไหน อาจจะเป็น twitter, Instagram, facebook, website, app หรืออะไรก็ได้ ซึ่งแต่ละ target มี correlation กับ feature แต่ละอันที่แตกต่างๆกัน
 
มาถึงเรื่องการเทรน model เราบ้าง เนื่องจากการแข่งขันเป็น tabular problem แน่นอน model ที่ใช้กันเยอะๆ ในการแข่ง kaggle ก็จะเป็นพวก LGBM, NN, Catboost, XGBoost แต่จะต้องใช้เป็น regressor เพราะเป็น regression problem
ต้องเกริ่นก่อนเลยว่าผมมีเวลาประมาณเดือนนิดๆ สำหรับการแข่งขันครั้งนี้ และเสียเวลา 3 อาทิตย์ในการทำ feature engineer, clean data โดยไม่มีการเทรนดาต้า พึ่งมาเทรนก่อน deadline 2 อาทิตย์ ซึ่งต้องบอกเลยผิดพลาดมากๆ 😭 เพราะทำให้ผมรู้ปัญหาของโมเดลช้าไป มีเวลาปรับโมเดลน้อยมาก
 
• เคล็ดลับการแข่งขันครั้งนี้อยู่ที่ validation strategy การการเลือกช่วงมาเทรนดาต้ามากกว่า features เพราะผลกระทบต่อ CV นั้นสูงกว่ามาก ข้อมูลที่ผู้จัดให้มาในรอบแรกก็คือ 2018-2021 เดือน 4 ในรอบแรก ก่อนจะอัพเดลข้อมูลให้ถึง กลางเดือน 7 ก่อนเดดไลน์อาทิตย์นึง MLB นั้นมีการแบ่งฤดูกาลการแข่งขันออกเป็นสามช่วงหลักก็คือ pre season (มีนา-เมษา), regular season (เมษา-สิงหา), post season (กันยา – ตุลา) แต่ข้อมูล test คือเดือนสิงหาคมปีนี้ ซึ่งอยู่ในช่วง regular season ดังนั้นถ้าเราตัดข้อมูลนอกช่วงนี้ออก pre-season, post-season ก็จะทำให้คะแนนทั้ง cv and lb ดีขึ้น ความยากต่อมาก็คือ split fold ในการเทรนและ validate ยังไง จะใช้ groupkfold หรือว่าเทรนทั้งหมดแล้วใช้ holdout เดือนล่าสุดเป็น validation set ซึ่งผมก็ต้องได้ลองเล่นหลายๆ strategy ก่อนที่จะใช้ ensemble ของ validate เป็นข้อมูลปีล่าสุดของแต่ละเดือนใน regular season แน่นอนว่าแบบนี้จะให้ model ที่ stable กว่า แต่ก็อาจจะไม่ดีที่สุด เพราะเหมือนเรากระจายความเสี่ยงออกไปในหลายๆเดือนที่ validate ถ้าเดือนที่ทดสอบคล้ายเดือนใดเดือนนึงใน training แล้วเราใช้เดือนนั้นเป็น validate เราก็จะได้คะแนนที่ดีมากๆ (ซึ่งมันคือการ overfit ข้อมูลนั่นเอง)
ก็ต้องบอกว่า ผมเลือก submission 2 อัน (อันนึง overfit ไปยังเดือนล่าสุด 7 หวังว่าคะแนนผู้เล่นเดือน 8 จะคล้ายเดือน 7 เพราะในทางทฤษฎี มันก็มีความเป็นไปได้อยู่ที่ฟอร์มการเล่นของผู้เล่น จะคล้ายกันในเดือนต่อไป submission อีกอันก็คือ stable model (validate months 5,6,7) ซึ่งผล final แบบ stable model ให้ผลที่ดีกว่า ผมอยากฝากไว้ให้กับน้องๆ เวลาที่ทำโมเดล ห้ามมองข้าม validation strategy
 
• Feature engineering ซึ่งต้องบอกเลยว่า features ที่ผมลองทำมีเกือบ 300 features ซึ่งมีประโยชน์จริงๆ น้อยมากทั้งที่ ใช้จริงๆ ประมาณ 100 ตอนที่ผมทำ features ก็ได้พบว่ามันมีค่า correlation ต่อ targets สูงมากๆ แต่พอเอามาเทรนจริงๆ กับมีผลน้อยมากกับ CV 0.001-0.003 ปัญหาคือโมเดลรู้ว่า features สำคัญแต่ไม่สามารถที่จะ convert ออกมาเป็นตัวเลข prediction ได้ดีเพราะโจทย์มันเป็น regression ทีนี้จะแก้ปัญหายังไง ซึ่งก็มีคนใช้ descriptive statistics ของ targets แต่ละผู้เล่น ซึ่งผมได้ใช้เวลานานมากในการลองเล่นและพยายามที่จะทำให้ไม่เกิด overfit กับเทรนนิ่งดาต้า จนสุดท้ายได้ descriptive statistics ที่ให้ผลที่ค่อนข้างดี improve CV มากกว่า 0.1 ต่อ target และไม่ overfit ดาต้าจนเกินไป
เคล็ดลับก็คือแยก descriptive stats ตามปี, แยกตามวันที่ลงแข่งและตำแหน่งที่ลง (เพราะผู้เล่นสามารถเป็นทั้ง pitcher batter ในเกมส์เดียวกันได้ หรือว่าวันนั้นแข่ง 2 เกมส์ เกมส์นึงเป็น pitcher อีกเกมส์เป็น batter). ส่วน features อื่นๆ ที่ทำแล้วมีประโยชน์ก็พวก award, player แบ่งเป็น tier, เพิ่ม stats สำหรับ pitcher, batter โดยทำ feature engineering ฯลฯ
 
• Feature lags จริงๆ อันนี้คือ key สำคัญมากในการแข่งขันครั้งนี้ แต่ก็แลกมากับความเสี่ยง เพราะว่าข้อมูลที่ผู้จัดให้คือถึงกลางเดือน 7 แล้วเริ่มทดสอบเดือน 8 มี gap ของดาต้า 2 อาทิตย์ หลายคนอาจจะไม่เข้าใจว่า feature lags คืออะไร เนื่องจากเป็นเหตุการณ์ที่เป็น Time series นั้นมีโอกาสเกิดเหตุการณ์ lag เกิดขึ้น เช่นอาจจะ lag 3, 5, 7, 10, 14 วัน แล้วลองคิดดูว่า ถ้าข้อมูลขาดหายไป มันก็จะทำให้ feature lag ของเรานั้นคาดเคลื่อนไปทั้งหมด ในเคสนี้ก็คือวันแรกที่ predict ไม่มีดาต้าก่อนหน้านั้น 2 อาทิตย์ทำให้วันหลังๆคาดเคลื่อนไปหมด หลายคนอาจจะถามว่าแล้วทำยังไง จริงๆๆ ผู้จัดก็ไม่ได้ใจร้ายขนาดนั้น เพราะเราสามารถที่จะเทรนดาต้า real time ได้หมายความว่า เราจะไม่ได้ load weight มา predict แต่เทรนดาต้าสดเลย ซึ่งจะมีดาต้าครบทั้งเดือนกรกฎ แต่ความเสี่ยงก็คือถ้าโค้ดรันไม่ได้ หรือมี bug คะแนนเราก็จะ 0 ทันที ซึ่งผมเลือกที่จะไม่ใช้ เพราะตอนที่เขียนโค้ด ทำ feature lags แล้วเจอ bug เยอะมากๆ ทำให้ local กับ submission ได้ค่าไม่ตรงกัน เลยเลือกที่จะไม่เสี่ยง (แทบจะทุกคนใน Top 50 ทำ feature lags กันทั้งหมด)
 
จริงๆ ผมเจอความลับของการแข่งครั้งนี้ แต่ไม่สามารถหาวิธีทำได้ จนกระทั่งจบการแข่งขันแล้วอ่าน solutions ของคนอื่นถึงรู้ว่าเค้าไขความลับของโจทย์นี้ยังไง
ปัญหานั้นมาจากโจทย์ของผู้จัดก็คือ predict วันต่อไป โดยใน code submission เราจะได้ข้อมูล feed เข้ามาทีละวันแล้วทำการ predict คำตอบของวันต่อไป แต่ในความเป็นจริงแล้ว engagement ของผู้เล่นเริ่มมีการเคลื่อนไหวตั้งแต่วันนี้ ซึ่งผมเดาว่าค่า engagement นั้นเก็บตอนเที่ยงคืนของวัน ซึ่งเมื่อการแข่งขันจบตั้งแต่ เย็นหรือค่ำของวันนั้น ผลของการแข่งขันมันกระทบกับ engagement ของวันนั้นด้วย ไม่ใช่มีผลต่อวันต่อไปเท่านั้น ซึ่งหลายคนอาจจะถามว่าก็ไม่เห็นยากเลย เราก็แค่แก้ค่า prediction ของวันนั้นก็จบ ซึ่งมันทำไม่ได้ เพราะผู้จัดต้องการให้ predict วันต่อไป หมายความว่า ผู้จัดให้ข้อมูลเข้ามาทีละวัน เช่นวันที่ 10 ก็ต้อง predict วันที่ 11 แล้วส่ง เราไม่สามารถกลับไปแก้คำตอบของวันที่ 10 ที่เราส่งคำตอบไปแล้วได้ (pipeline จะฟีดดาต้าเข้ามาทีละวัน แล้วให้เราทำการ prediction เลย)
ซึ่งผู้ชนะ ก็ใช้วิธีการใส่ตารางแข่งขันล่วงหน้าของเดือน 8 เข้าไปทำให้โมเดลสามารถที่จะรู้ว่าวันไหนมีแข่งโดยไม่ต้องรอดาต้าที่ฟีดเข้ามา แต่ทำแค่นี้ก็จะแก้ปัญหาได้นิดหน่อย
 
ต้องเข้าใจก่อนว่าในปีนึง แต่ละทีมต้องลงแข่ง 162 เกมส์ หรือแทบจะทุกวัน เพราะฉะนั้นผู้เล่นจะสลับกันลง โดยเฉพาะตำแหน่ง pitchers ทำให้เราไม่สามารถรู้ได้ว่าใครจะเป็นคนลงในเกมส์นั้นๆ เพราะโดยทั่วไปแล้วผู้เล่นที่ไม่ได้ลง engagement แน่นอนก็จะต่ำ แล้วเราจะแก้ปัญหานี้ต่อได้ไง ซึ่งคนชนะก็บอกว่า การที่ใช้ feature lags โมเดลจะสามารถจับ pattern ได้ว่าคนนี้ลงแข่งเมื่อ 4 วันที่แล้ว วันนี้จะเป็นเทิร์นที่จะได้ลงแข่งอีก ซึ่งผมเองก็ลืมคิดจุดนี้ไปเลยว่า ในทีมตำแหน่ง pitcher rotate กันเป็น routine มีโอกาสสลับบ้างแต่น้อย ซึ่งก็คิดว่าถ้าผมแก้ปัญหานี้ได้ก็การันตีเหรียญทองแน่นอน
 
ผลการแข่งขันครั้งนี้ ผมได้อันดับสุดท้าย คือ 30 เหรียญเงิน 🥈 จากผู้เข้าแข่งขันทั้งหมด 852 ทีม
ปล. ขอบคุณน้องพูม 🙏 ที่ช่วยทำ feature engineering ในตอนแรกก่อนที่น้องจะไม่สะดวกแล้วถอนตัวออกไป
ใครที่มีข้อสงสัยอะไร สามารถโพสถามได้เลย ยินดีตอบครับ
ขอบคุณทุกคนที่อ่านจนจบ หวังว่าจะเป็นประโยชน์สำหรับทุกคนน่ะครับ 😄
ทอม
 
 
This topic was modified 1 month ago by The Neural Engineer
อ้างอิง
Posted : 17/09/2021 2:09 pm
Share:

Please Login or Register