“ … ถ้าฉันต้องนั่งตรงนั้นและเผชิญหน้ากับตัวเองแล้วบอกตัวเองว่า ‘คุณล้มเหลว’ ฉันคิดว่ามันแย่กว่านั้น เกือบจะแย่ยิ่งกว่าความตาย”
- โคบี้ บีน ไบรอันท์
ฉันอยู่บนรถไฟตอนที่รู้เรื่องอุบัติเหตุเฮลิคอปเตอร์ตกที่น่าสลดใจซึ่งคร่าชีวิตผู้โดยสารทั้ง 9 คน ฉันจำได้ว่าพลาดการหยุดและจ้องมองโทรศัพท์เมื่อเรื่องราวทั้งหมดหลั่งไหลเข้ามา ดูเหมือนไม่ใช่เรื่องจริงในตอนแรก
การเป็นแฟนของ Toronto Raptors หมายความว่าคุณมีความสัมพันธ์ที่น่าสนใจกับ Kobe Bryant ติดอยู่ในความธรรมดาในช่วงกลางทศวรรษ 2000 สิ่งต่างๆ ไม่ได้เป็นเพียง "พวกเราชาวเหนือ" เสมอไปสำหรับทีม Raptors ที่ซื่อสัตย์ เมื่อวันที่ 22 มกราคม พ.ศ. 2549 เราผูกพันกับโกเบตลอดไป เกม 81 แต้มของเขาจะกลายเป็นผลงานที่ทำคะแนนสูงสุดเป็นอันดับสองในประวัติศาสตร์ลีก มันทำให้ฉันคิดถึงช่วงปีแรกๆ ของเขาในลีก และวิธีที่ดูเหมือนว่ามือใหม่ที่ไร้ตัวตนกลายมาเป็นหนึ่งในผู้ทำประตูที่มีผลงานมากที่สุดตลอดกาลของ NBA
อาจเป็นเรื่องที่น่าแปลกใจที่ปีใหม่ของ Bean แทบจะไม่เกินความคาดหมายของลีกเลย เมื่อเปรียบเทียบกับจอร์แดน ความแตกต่างก็ชัดเจน...
โปรเจ็กต์นี้มีศูนย์กลางอยู่ที่คำถามว่าเราสามารถใช้ข้อมูลในอดีตจาก NBA ตั้งแต่ปี 1980 เพื่อทำนายผลงานอาชีพของผู้เล่นได้หรือไม่ โดยเฉพาะอย่างยิ่ง เราสามารถใช้สถิติปีใหม่ของผู้เล่นเพื่อตัดสินว่าคะแนนรวมสุดท้ายของพวกเขาจะเป็นอย่างไร? คะแนนเป็นตัวชี้วัดที่ครอบคลุมถึงมูลค่าเชิงรุกของผู้เล่นในลีก
ท้ายที่สุด ฉันตัดสินใจใช้ข้อมูลเพื่อดูว่าเราสามารถใช้สถิติปีใหม่ของผู้เล่นเพื่อทำนายผลลัพธ์แบบไบนารี่ได้หรือไม่: ผู้เล่นนั้นจะ สูงกว่าค่าเฉลี่ย หรือ ต่ำกว่าค่าเฉลี่ยในการทำประตูเมื่อสิ้นสุดอาชีพการงาน ด้วยวิธีนี้ ทีมสามารถรับรู้ถึง 'การตกต่ำของนักเรียนปีที่สอง' และ 'การล้มเหลว' ที่อาจเกิดขึ้นในมือใหม่ที่เพิ่งร่างใหม่
https://www.kaggle.com/drgilermo/nba-players-stats?select=Seasons_Stats.csv
ชุดข้อมูล ของ Goldstein เป็นชุดข้อมูล NBA ที่ครอบคลุมมากที่สุดที่คัดลอกมาจาก Basketball Reference ชุดข้อมูลประกอบด้วยตัวชี้วัดการวิเคราะห์ขั้นสูงเกือบทั้งหมดสำหรับผู้เล่นทุกคนในลีกตั้งแต่ปี 1950 ถึง 2017
หลังจากประมวลผลล่วงหน้าและทำความสะอาดแล้ว ฉันแยกผู้เล่นหน้าใหม่ทุกคนออกตั้งแต่ปี 1980 ปีที่เฉพาะเจาะจงนี้ได้รับเลือกเนื่องจากเป็นปีที่เส้น 3 จุดถูกนำมาใช้อย่างเต็มที่ในการติดตามสถิติ สำหรับการอ้างอิง นั่นทำให้เรามีผู้เล่น 2,331 คนและข้อมูล 37 ฤดูกาล นอกจากนี้ ฉันตัดสินใจรวมเฉพาะตัวแปร 22 ตัวที่เกี่ยวข้องกับสถิติโดยรวมของผู้เล่น ซึ่งรวมถึง:
'FG', 'FGA', 'FG%', '3P', '3PA', '3P%', '2P', '2PA', '2P%', 'eFG%', 'FT' , 'เขตการค้าเสรี', 'FT%', 'ORB', 'DRB', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PF', 'PTS'
ตัวแปรที่ 23 ซึ่งเป็นคะแนนอาชีพทั้งหมด ได้ถูกเพิ่มต่อท้ายดาต้าเฟรมเป็น 'total_pts' นี่คือสิ่งที่เราจะพยายามให้แบบจำลองของเราทำนาย
การเลือกคุณลักษณะ การถดถอยเชิงเส้น มีการเลือกตัวแปร 9 ตัวให้มีความเกี่ยวข้องกับการทำนายผลรวมมากที่สุด
array = stats_df.values X = array[:,0:21] Y = array[:,21] #feature selection model = LinearRegression() rfe = RFE(model, 9) fit = rfe.fit(X, Y) print("Num Features: %d" % fit.n_features_) print("Selected Features: %s" % fit.support_) print("Feature Ranking: %s" % fit.ranking_)
คุณสมบัติ 9 อันดับแรกที่เลือกจะแสดงอยู่ด้านล่างพร้อมกับ Total_pts:
ขั้นตอนต่อไปเปิดให้ตีความได้ แต่เพื่อความง่าย ฉันจึงตัดสินใจแปลงคอลัมน์ Total_pts เป็นคอลัมน์ไบนารี่ที่สูงกว่า Total_pts เฉลี่ยหรือต่ำกว่า Total_pts เฉลี่ย
คะแนนรวมเฉลี่ยที่ผู้เล่นทำได้ในช่วงเวลา 37 ปีนี้คือ 3523 ดังนั้นอะไรก็ตามที่สูงกว่าค่าเฉลี่ยจะจัดเป็น (1) และต่ำกว่าค่าเฉลี่ยจะเป็น (0)
final_df['TOTAL_PTS'].values[final_df['TOTAL_PTS'] < 3522] = 0 final_df['TOTAL_PTS'].values[final_df['TOTAL_PTS'] >= 3523] = 1 final_df.head()
ด้านล่างนี้ฉันได้รวมการแบ่งการฝึกอบรม/การทดสอบตลอดจนโค้ดการสุ่มตัวอย่างใหม่:
#split into TRAIN/TEST msk = np.random.rand(len(final_df)) < 0.70 train_df = final_df[msk] test_df = final_df[~msk] #split test into X_test and y_test for later y_test = test_df['TOTAL_PTS'] X_test = test_df.drop('TOTAL_PTS',axis=1) #class count count_class_0, count_class_1 = train_df.TOTAL_PTS.value_counts() #divide by class df_class_0 = train_df[train_df['TOTAL_PTS'] == 0] df_class_1 = train_df[train_df['TOTAL_PTS'] == 1] df_class_1_over = df_class_1.sample(count_class_0, replace=True) df_test_over = pd.concat([df_class_1_over, df_class_0], axis=0) print('Random over-sampling:') print(df_test_over.TOTAL_PTS.value_counts()) df_test_over.TOTAL_PTS.value_counts().plot(kind='bar', title='Count (TOTAL_PTS)')
ต่อไป ฉันจะปรับข้อมูลที่มีการสุ่มตัวอย่างเกินให้เข้ากับอัลกอริธึม ML ที่แตกต่างกันสองสามตัว ด้านล่างนี้ ฉันได้รวมสคริปต์สำหรับโมเดลที่มีประสิทธิภาพดีที่สุด นั่นคือตัวแยกประเภทการถดถอยลอจิซิติก:
df2_test_over = pd.DataFrame(df_test_over) #split into X_train and y_train X_over_train = df2_test_over.drop('TOTAL_PTS',axis=1) y_over_train = df2_test_over['TOTAL_PTS'] #fitting Logistic Regression to the training set reg_classifier = LogisticRegression(penalty = 'l2', solver = 'liblinear') reg_classifier.fit(X_over_train, y_over_train) #predicting the test set results predictions = reg_classifier.predict(X_test) #confusion matrix conf_mat = confusion_matrix(y_true=y_test, y_pred=predictions) print('Confusion matrix:\n', conf_mat) labels = ['Class 0', 'Class 1'] fig = plt.figure() ax = fig.add_subplot(111) cax = ax.matshow(conf_mat, cmap=plt.cm.Blues) fig.colorbar(cax) ax.set_xticklabels([''] + labels) ax.set_yticklabels([''] + labels) plt.xlabel('Predicted') plt.ylabel('Expected') plt.show()
#calculate accuracy/precision/recall/f1 # accuracy: (tp + tn) / (p + n) accuracy = (accuracy_score(y_test, predictions)).astype('float64') print('{:>10}: {:0.2%}'.format('Accuracy',accuracy)) # precision tp / (tp + fp) precision = (precision_score(y_test, predictions)).astype('float64') print('{:>10}: {:0.2%}'.format('Precision',precision)) # recall: tp / (tp + fn) recall = (recall_score(y_test, predictions)).astype('float64') print('{:>10}: {:0.2%}'.format('Recall',recall)) # f1: 2 tp / (2 tp + fp + fn) f1 = (f1_score(y_test, predictions)).astype('float64') print('{:>10}: {:0.2%}'.format('F1 score',f1)) #ROC curve false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, predictions) roc_auc = (auc(false_positive_rate, true_positive_rate)).astype('float64') print('{:>10}: {:0.2%}'.format('ROC score',roc_auc))
แม้ว่าโมเดลจะไม่สมบูรณ์แบบ แต่โมเดลก็ทำงานได้ดี และเราสามารถพูดได้ด้วยความแม่นยำประมาณ 76.69% และ ROC ที่ 75.7% ซึ่งเราสามารถคาดเดาได้ว่ามือใหม่จะเป็นผู้ทำประตูโดยเฉลี่ยที่สูงกว่าใน NBA หรือไม่เมื่อถึงเวลาที่อาชีพของพวกเขาเสร็จสิ้น .
เมื่อมองไปข้างหน้า ฉันต้องการดูว่าฉันสามารถใช้ ML เพื่อทำนายคะแนนของผู้เล่นในปีถัดไปสำหรับทุกๆ ปีที่พวกเขาอยู่ใน NBA และเพื่อให้แบบจำลองทำนายตัวแปรหลายคลาสได้ (เช่น ค่าที่แน่นอนของพวกเขาคืออะไร การให้คะแนนจะเป็นของปีหน้า) ไม่ใช่แค่ตัวแปรไบนารี่ 1|0
สามารถดูสมุดบันทึกฉบับเต็มได้ที่นี่:
ติดตามฉันบน Github ได้ที่ @vladtheladd, ส่งอีเมลถึงฉันโดยตรง หรือพบกับฉันบน Linkedin ฉันอยากได้ยินจากคุณหากคุณคิดว่าฉันสามารถช่วยคุณหรือทีมของคุณในการทำงานที่เกี่ยวข้องกับ Data Science ได้