“ … ถ้าฉันต้องนั่งตรงนั้นและเผชิญหน้ากับตัวเองแล้วบอกตัวเองว่า ‘คุณล้มเหลว’ ฉันคิดว่ามันแย่กว่านั้น เกือบจะแย่ยิ่งกว่าความตาย”

- โคบี้ บีน ไบรอันท์

ฉันอยู่บนรถไฟตอนที่รู้เรื่องอุบัติเหตุเฮลิคอปเตอร์ตกที่น่าสลดใจซึ่งคร่าชีวิตผู้โดยสารทั้ง 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 ได้