मुख्य सामग्री पर जाएँ

Scikit-Learn ट्यूटोरियल: बेसबॉल एनालिटिक्स भाग 1

एक scikit-learn ट्यूटोरियल जिसमें KMeans क्लस्टरिंग मॉडल और लीनियर रिग्रेशन मॉडलों पर डेटा मॉडलिंग करके प्रति सीजन MLB जीत की भविष्यवाणी की जाती है।
· 14 मि॰ पढ़ें

AI के साथ खोजें

Python प्रोग्रामिंग भाषा डेटा साइंस और प्रेडिक्टिव एनालिटिक्स के लिए बेहतरीन विकल्प है, क्योंकि यह कई ऐसे पैकेजों के साथ आती है जो आपके अधिकांश डेटा विश्लेषण की ज़रूरतें पूरी करते हैं। पायथन में मशीन लर्निंग के लिए, Scikit-learn (sklearn) एक बढ़िया विकल्प है और यह NumPy, SciPy, और Matplotlib पर आधारित है (क्रमशः N-डायमेंशनल एरेज़, वैज्ञानिक कंप्यूटिंग, और डेटा विज़ुअलाइजेशन)।

इस ट्यूटोरियल में, आप देखेंगे कि कैसे आप sqlite3 के साथ किसी डेटाबेस से आसानी से डेटा लोड कर सकते हैं, कैसे आप pandas और matplotlib के साथ अपने डेटा का अन्वेषण कर उसकी गुणवत्ता सुधार सकते हैं, और फिर Scikit-Learn पैकेज का उपयोग कर डेटा से उपयोगी इनसाइट्स निकाल सकते हैं।

यदि आप कोई मशीन लर्निंग कोर्स करना चाहते हैं, तो DataCamp का Supervised Learning with scikit-learn कोर्स देखें।

भाग 1: प्रति सीजन MLB टीम की जीत की भविष्यवाणी

इस प्रोजेक्ट में, आप sklearn के कई मशीन लर्निंग मॉडल आज़माएँगे ताकि किसी मेजर-लीग बेसबॉल टीम ने उस सीजन में कितने गेम जीते, यह टीम की सांख्यिकीय जानकारी और अन्य चर पर आधारित होकर भविष्यवाणी की जा सके। यदि मैं सट्टा लगाता (और मैं निश्चित रूप से सट्टा लगाता हूँ), तो मैं पिछले सीजनों के ऐतिहासिक डेटा का उपयोग कर आने वाले सीजन का पूर्वानुमान लगाने के लिए मॉडल बना सकता था। डेटा की टाइम-सीरीज़ प्रकृति को देखते हुए, आप संकेतक बना सकते हैं जैसे पिछले पाँच वर्षों में औसत जीत, और ऐसे अन्य कारक, ताकि एक अत्यंत सटीक मॉडल बनाया जा सके। हालांकि यह इस ट्यूटोरियल के दायरे से बाहर है और आप यहाँ प्रत्येक पंक्ति को स्वतंत्र मानेंगे। हमारे डेटा की प्रत्येक पंक्ति किसी विशेष वर्ष की एक टीम का प्रतिनिधित्व करेगी।

Sean Lahman ने यह डेटा अपनी वेबसाइट पर संकलित किया है और इसे यहाँ sqlite डेटाबेस में रूपांतरित किया गया है।

डेटा आयात करना

आप sqlite3 पैकेज का उपयोग कर sqlite डेटाबेस पर क्वेरी चलाकर डेटा पढ़ेंगे और pandas के साथ उसे DataFrame में बदलेंगे। आपका डेटा फिल्टर होकर केवल वर्तमान में सक्रिय आधुनिक टीमों और वे वर्ष शामिल करेगा जिनमें टीम ने 150 या अधिक गेम खेले।

सबसे पहले, फ़ाइल “lahman2016.sqlite” डाउनलोड करें (यहाँ)। फिर, Pandas लोड करें और दक्षता के लिए उसका नाम pd रखें। आपको याद होगा कि pd Pandas का सामान्य उपनाम है। अंत में, sqlite3 लोड करें और डेटाबेस से इस प्रकार कनेक्ट करें:

# import `pandas` and `sqlite3`import pandas as pdimport sqlite3# Connecting to SQLite Databaseconn = sqlite3.connect('lahman2016.sqlite')

अगले चरण में, आप एक क्वेरी लिखेंगे, उसे चलाएँगे और परिणाम प्राप्त करेंगे।

# Querying Database for all seasons where a team played 150 or more games and is still active today. query = '''select * from Teams inner join TeamsFranchiseson Teams.franchID == TeamsFranchises.franchIDwhere Teams.G >= 150 and TeamsFranchises.active == 'Y';'''# Creating dataframe from query.Teams = conn.execute(query).fetchall()

टिप: यदि आप Python के साथ SQL का उपयोग करना सीखना चाहते हैं, तो DataCamp का Introduction to Databases in Python कोर्स देखें।

pandas का उपयोग करके, आप फिर परिणामों को एक DataFrame में बदलेंगे और head() मेथड का उपयोग कर पहली 5 पंक्तियाँ प्रिंट करेंगे:

# Convert `Teams` to DataFrame
teams_df = pd.DataFrame(_____)

# Print out first 5 rows
print(_______________)

प्रत्येक कॉलम में किसी विशेष टीम और वर्ष से संबंधित डेटा होता है। कुछ अधिक महत्वपूर्ण वेरिएबल नीचे सूचीबद्ध हैं। वेरिएबल्स की पूरी सूची यहाँ मिल सकती है।

  • yearID - वर्ष
  • teamID - टीम
  • franchID - फ्रैंचाइज़ (TeamsFranchise टेबल से लिंक)
  • G - खेले गए गेम
  • W - जीत
  • LgWin - लीग चैंपियन (Y या N)
  • WSWin - वर्ल्ड सीरीज़ विजेता (Y या N)
  • R - बनाए गए रन
  • AB - एट बैट्स
  • H - बल्लेबाज़ों के हिट
  • HR - बल्लेबाज़ों के होमरन
  • BB - बल्लेबाज़ों के वॉक्स
  • SO - बल्लेबाज़ों के स्ट्राइकआउट
  • SB - चोरी किए गए बेस
  • CS - पकड़े जाने पर चोरी
  • HBP - पिच से टकराए बल्लेबाज़
  • SF - सैक्रिफाइस फ्लाईज़
  • RA - विरोधियों द्वारा बनाए गए रन
  • ER - दिए गए अर्न्ड रन
  • ERA - अर्न्ड रन एवरेज
  • CG - कंप्लीट गेम्स
  • SHO - शटआउट्स
  • SV - सेव्स
  • IPOuts - आउट्स पिच्ड (इन्निंग्स पिच्ड x 3)
  • HA - दिए गए हिट्स
  • HRA - दिए गए होमरन
  • BBA - दिए गए वॉक्स
  • SOA - पिचर्स द्वारा स्ट्राइकआउट
  • E - एरर्स
  • DP - डबल प्ले
  • FP - फील्डिंग प्रतिशत
  • name - टीम का पूरा नाम

जो लोग बेसबॉल से बहुत परिचित नहीं हैं, उनके लिए यहाँ खेल के काम करने का संक्षिप्त विवरण है, जिसमें कुछ वेरिएबल भी शामिल हैं।

बेसबॉल दो टीमों के बीच खेला जाता है (जिसे आप डेटा में name या teamID से पहचानेंगे), प्रत्येक में नौ खिलाड़ी होते हैं। ये दोनों टीमें बारी-बारी से बैटिंग और फील्डिंग करती हैं। बैटिंग टीम का लक्ष्य रन बनाना होता है: फील्डिंग टीम के पिचर द्वारा फेंकी गई गेंद को बारी-बारी से हिट करते हैं, फिर चार बेसों—पहला, दूसरा, तीसरा और होम प्लेट—के चारों ओर घड़ी की सुई की विपरीत दिशा में दौड़ते हैं। फील्डिंग टीम हिटर्स या बेस रनर्स को कई तरीकों से आउट कर रन बनने से रोकने की कोशिश करती है, और जब कोई खिलाड़ी बेसों के चारों ओर बढ़कर होम प्लेट पर लौटता है, तो एक रन (R) दर्ज होता है। बैटिंग टीम का कोई खिलाड़ी जो सुरक्षित रूप से बेस पहुँच जाता है, वह साथियों की बैटिंग के दौरान अगली बेसों तक बढ़ने की कोशिश करेगा, जैसे हिट (H), चोरी किया हुआ बेस (SB) या अन्य तरीकों से।

baseball

जब भी फील्डिंग टीम तीन आउट कर देती है, टीमें बैटिंग और फील्डिंग के बीच अदला-बदली कर लेती हैं। दोनों टीमों के लिए एक-एक बैटिंग टर्न, जो मेज़बान टीम से शुरू होता है, एक इन्निंग बनता है। एक खेल नौ इन्निंग्स का होता है, और अंत में जिसके पास अधिक रन होते हैं, वह टीम जीतती है। बेसबॉल में कोई गेम क्लॉक नहीं होता और यद्यपि अधिकांश खेल नौवीं इन्निंग में समाप्त हो जाते हैं, यदि नौ इन्निंग्स के बाद मैच टाई है तो यह अतिरिक्त इन्निंग्स में चला जाता है और तब तक चलता है जब तक किसी टीम को अतिरिक्त इन्निंग के अंत में बढ़त नहीं मिल जाती।

बेसबॉल खेल के विस्तृत विवरण के लिए, मेजर लीग बेसबॉल के आधिकारिक नियम देखें।

डेटा की सफाई और तैयारी

जैसा कि आप ऊपर देख सकते हैं, DataFrame में कॉलम हेडर नहीं हैं। आप pandas के columns एट्रिब्यूट में अपनी हेडर लिस्ट पास करके हेडर जोड़ सकते हैं।

# Adding column names to dataframe
cols = ['yearID','lgID','teamID','franchID','divID','Rank','G','Ghome','W','L','DivWin','WCWin','LgWin','WSWin','R','AB','H','2B','3B','HR','BB','SO','SB','CS','HBP','SF','RA','ER','ERA','CG','SHO','SV','IPouts','HA','HRA','BBA','SOA','E','DP','FP','name','park','attendance','BPF','PPF','teamIDBR','teamIDlahman45','teamIDretro','franchID','franchName','active','NAassoc']
teams_df.columns = ____

# Print the first rows of `teams_df`
print(______________)

# Print the length of `teams_df`
print(len(________))

len() फ़ंक्शन आपको बताएगा कि आप कितनी पंक्तियों से निपट रहे हैं: 2,287 कोई बहुत बड़ा डेटा सेट नहीं है, इसलिए उम्मीद है कि बहुत सारे null मान नहीं होंगे।

डेटा गुणवत्ता का आकलन करने से पहले, चलिए पहले उन कॉलमों को हटा दें जो आवश्यक नहीं हैं या जो लक्ष्य कॉलम (Wins) से व्युत्पन्न हैं। यही वह जगह है जहाँ उस डेटा का ज्ञान बहुत मूल्यवान हो जाता है जिसके साथ आप काम कर रहे हैं। यदि आपको अपने डेटा के बारे में जानकारी ही नहीं है, तो यह मायने नहीं रखता कि आपको कोडिंग या सांख्यिकी के बारे में कितना ज्ञान है। जीवन भर का बेसबॉल प्रशंसक होना निश्चित रूप से इस प्रोजेक्ट में मेरे लिए सहायक रहा।

# Dropping your unnecesary column variables.
drop_cols = ['lgID','franchID','divID','Rank','Ghome','L','DivWin','WCWin','LgWin','WSWin','SF','name','park','attendance','BPF','PPF','teamIDBR','teamIDlahman45','teamIDretro','franchID','franchName','active','NAassoc']

df = teams_df.drop(drop_cols, axis=1)

# Print out first rows of `df`
print(_________)

जैसा कि आपने ऊपर पढ़ा, null मान डेटा गुणवत्ता को प्रभावित करते हैं, जो आगे चलकर मशीन लर्निंग एल्गोरिद्म के साथ समस्याएँ पैदा कर सकता है।

इसीलिए आप अब उन्हें हटाएँगे। null मानों को हटाने के कुछ तरीके हैं, लेकिन पहले प्रत्येक कॉलम में null मानों की गिनती प्रदर्शित करना बेहतर विचार हो सकता है ताकि आप तय कर सकें कि उन्हें सबसे अच्छी तरह कैसे संभालना है।

# Print out null values of all columns of `df`
print(_________.sum(axis=0).tolist())

और यहीं आप एक ट्रेड-ऑफ देखेंगे: आपको स्वच्छ डेटा चाहिए, पर आपके पास अतिरिक्त डेटा भी बहुत नहीं है। दो कॉलम में तुलनात्मक रूप से कम null मान हैं। SO (स्ट्राइक आउट्स) कॉलम में 110 और DP (डबल प्ले) कॉलम में 22 null मान हैं। दो कॉलम में अपेक्षाकृत अधिक null मान हैं। CS (कॉट स्टीलिंग) कॉलम में 419 और HBP (हिट बाय पिच) कॉलम में 1777 null मान हैं।

यदि आप उन पंक्तियों को हटा देते हैं जिनमें कम null मान वाले कॉलम हैं, तो आप हमारे डेटा का पाँच प्रतिशत से थोड़ा अधिक खो देंगे। चूँकि आप जीत की भविष्यवाणी करने की कोशिश कर रहे हैं, बनाए गए रन और दिए गए रन लक्ष्य से काफ़ी सहसंबद्ध हैं। आप चाहते हैं कि उन कॉलमों में डेटा बहुत सटीक हो।

स्ट्राइक आउट्स (SO) और डबल प्ले (DP) उतने महत्वपूर्ण नहीं हैं।

मुझे लगता है, पंक्तियाँ बनाए रखना और fillna() मेथड से प्रत्येक कॉलम के माध्यिका मान से null मानों को भरना बेहतर रहेगा। कॉट स्टीलिंग (CS) और हिट बाय पिच (HBP) भी बहुत महत्वपूर्ण वेरिएबल नहीं हैं। इन कॉलमों में इतने सारे null मान होने पर, इन्हें पूरी तरह से हटा देना ही बेहतर है।

# Eliminating columns with null values
df = df.drop(['CS','HBP'], axis=1)

# Filling null values
df['SO'] = df['SO'].fillna(df['SO'].median())
df['DP'] = df['DP'].fillna(df['DP'].median())

# Print out null values of all columns of `df`
print(df.isnull().sum(axis=0).tolist())

डेटा का अन्वेषण और विज़ुअलाइज़ेशन

अब जब आपने डेटा साफ़ कर लिया है, तो आप कुछ अन्वेषण कर सकते हैं। कुछ सरल विज़ुअलाइज़ेशन से आप डेटा सेट को बेहतर तरीके से समझ सकते हैं। matplotlib डेटा विज़ुअलाइज़ेशन के लिए एक उत्कृष्ट लाइब्रेरी है।

आप matplotlib.pyplot इम्पोर्ट करेंगे और दक्षता के लिए उसे plt नाम देंगे। यदि आप Jupyter नोटबुक के साथ काम कर रहे हैं, तो आपको %matplotlib inline मैजिक का उपयोग करना होगा।

आप लक्ष्य कॉलम का एक हिस्टोग्राम प्लॉट करके शुरू करेंगे ताकि आप जीत के वितरण को देख सकें।

# import the pyplot module from matplotlibimport matplotlib.pyplot as plt# matplotlib plots inline  %matplotlib inline# Plotting distribution of winsplt.hist(df['W'])plt.xlabel('Wins')plt.title('Distribution of Wins')plt.show()

distribution graph

ध्यान दें कि यदि आप Jupyter नोटबुक का उपयोग नहीं कर रहे हैं, तो प्लॉट दिखाने के लिए आपको plt.show() का उपयोग करना होगा।

प्रति वर्ष औसत जीत (W) प्रिंट करें। इसके लिए आप mean() मेथड का उपयोग कर सकते हैं।

print(df['_'].______)

डेटा का अन्वेषण करते समय लक्ष्य कॉलम के लिए बिन बनाना उपयोगी हो सकता है, लेकिन आपको यह सुनिश्चित करना चाहिए कि मॉडल को ट्रेन करते समय आप लक्ष्य कॉलम से जनरेट की गई किसी भी फीचर को शामिल न करें। प्रशिक्षण सेट में लक्ष्य कॉलम से जनरेट हुए लेबल का कॉलम शामिल करना ऐसे होगा जैसे आप अपने मॉडल को टेस्ट के जवाब दे दें।

अपने विन लेबल्स बनाने के लिए, आप assign_win_bins नाम का एक फ़ंक्शन बनाएँगे जो एक पूर्णांक मान (जीत) लेगा और इनपुट मान के आधार पर 1-5 का एक पूर्णांक लौटाएगा।

इसके बाद, आप apply() मेथड का उपयोग कर wins कॉलम पर assign_win_bins() फ़ंक्शन पास करके एक नया कॉलम win_bins बनाएँगे।

# Creating bins for the win column
def assign_win_bins(_):
    if W < 50:
        return 1
    if W >= 50 and W <= 69:
        return 2
    if W >= 70 and W <= 89:
        return 3
    if W >= 90 and W <= 109:
        return 4
    if W >= 110:
        return 5
        
# Apply `assign_win_bins` to `df['W']`    
df['win_bins'] = df['_'].apply(______________)

अब आइए एक स्कैटर ग्राफ बनाते हैं जिसमें x-अक्ष पर वर्ष और y-अक्ष पर जीत होगी और win_bins कॉलम को रंगों से हाइलाइट करेंगे।

# Plotting scatter graph of Year vs. Winsplt.scatter(df['yearID'], df['W'], c=df['win_bins'])plt.title('Wins Scatter Plot')plt.xlabel('Year')plt.ylabel('Wins')plt.show()

scikit-learn project

जैसा कि आप ऊपर दिए स्कैटर प्लॉट में देख सकते हैं, 1900 से पहले के बहुत कम सीजन हैं और उस समय खेल काफी अलग था। इसलिए, उन पंक्तियों को डेटा सेट से हटाना समझदारी है।

# Filter for rows where 'yearID' is greater than 1900
df = df[___________________]

सतत (continuous) डेटा और लीनियर मॉडल के साथ काम करते समय, वर्ष जैसे पूर्णांक मान समस्याएँ पैदा कर सकते हैं। यह संभव नहीं है कि 1950 का संख्या मान बाकी डेटा के साथ वैसा ही संबंध रखे जैसा मॉडल निष्कर्ष निकालेगा।

आप yearID मान के आधार पर डेटा को लेबल करने वाले नए वेरिएबल बनाकर इन समस्याओं से बच सकते हैं।

जो भी बेसबॉल का खेल फॉलो करता है, जानता है कि मेजर लीग बेसबॉल (MLB) के विकास के साथ, अलग-अलग युग (eras) आए जहाँ प्रति गेम बने रन की मात्रा में काफ़ी बढ़ोतरी या कमी हुई। 1900 के शुरुआती वर्षों का डेड बॉल एरा एक लो-स्कोरिंग एरा का उदाहरण है और 21वीं सदी की शुरुआत का स्टेरॉइड एरा हाई-स्कोरिंग एरा का उदाहरण है।

आइए नीचे एक ग्राफ बनाते हैं जो दर्शाता है कि प्रत्येक वर्ष कितना स्कोरिंग हुआ।

आप runs_per_year और games_per_year नामक डिक्शनरी बनाकर शुरू करेंगे। iterrows() मेथड का उपयोग करके डेटा फ्रेम पर लूप चलाएँ। runs_per_year डिक्शनरी को वर्षों को कुंजी (keys) और उस वर्ष में बने कुल रन को मान (value) के रूप में भरें। games_per_year डिक्शनरी को वर्षों को कुंजी और उस वर्ष खेले गए कुल गेम को मान के रूप में भरें।

# Create runs per year and games per year dictionaries
runs_per_year = {}
games_per_year = {}

for i, row in df.iterrows():
    year = row['yearID']
    runs = row['R']
    games = row['G']
    if year in runs_per_year:
        runs_per_year[year] = runs_per_year[year] + runs
        games_per_year[year] = games_per_year[year] + games
    else:
        runs_per_year[year] = runs
        games_per_year[year] = games
        
print(runs_per_year)
print(games_per_year)

अब mlb_runs_per_game नामक एक डिक्शनरी बनाएँ। items() मेथड के साथ games_per_year डिक्शनरी पर इटरेट करें। mlb_runs_per_game डिक्शनरी को वर्षों को कुंजी और लीग स्तर पर प्रति गेम बनाए गए रन की संख्या को मान के रूप में भरें।

अंत में, mlb_runs_per_game डिक्शनरी से अपना प्लॉट बनाएँ, जिसमें x-अक्ष पर वर्ष और y-अक्ष पर प्रति गेम रन हों।

# Create lists from mlb_runs_per_game dictionarylists = sorted(mlb_runs_per_game.items())x, y = zip(*lists)# Create line plot of Year vs. MLB runs per Gameplt.plot(x, y)plt.title('MLB Yearly Runs per Game')plt.xlabel('Year')plt.ylabel('MLB Runs per Game')plt.show()

baseball analytics scikit-learn

नई फ़ीचर जोड़ना

अब जब आपको स्कोरिंग ट्रेंड्स का बेहतर अंदाज़ा हो गया है, तो आप yearID के आधार पर यह दर्शाने वाले नए वेरिएबल बना सकते हैं कि डेटा की प्रत्येक पंक्ति किस युग (era) में आती है। आप वही प्रक्रिया अपनाएँगे जो आपने ऊपर win_bins कॉलम बनाते समय की थी।

लेकिन इस बार, आप डमी कॉलम बनाएँगे; प्रत्येक युग के लिए एक नया कॉलम। इसके लिए आप get_dummies() मेथड का उपयोग कर सकते हैं।

# Creating "year_label" column, which will give your algorithm information about how certain years are related 
# (Dead ball eras, Live ball/Steroid Eras)

def assign_label(____):
    if year < 1920:
        return 1
    elif year >= 1920 and year <= 1941:
        return 2
    elif year >= 1942 and year <= 1945:
        return 3
    elif year >= 1946 and year <= 1962:
        return 4
    elif year >= 1963 and year <= 1976:
        return 5
    elif year >= 1977 and year <= 1992:
        return 6
    elif year >= 1993 and year <= 2009:
        return 7
    elif year >= 2010:
        return 8
        
# Add `year_label` column to `df`    
df['year_label'] = df['yearID'].apply(___________)

dummy_df = pd.get_dummies(df['year_label'], prefix='era')

# Concatenate `df` and `dummy_df`
df = pd.concat([df, dummy_df], axis=1)

print(df.head())

क्योंकि आपने पहले ही प्रत्येक वर्ष के लिए MLB रन प्रति गेम निर्धारित करने का काम कर लिया है, उस डेटा को डेटा सेट में जोड़ें।

# Create column for MLB runs per game from the mlb_runs_per_game dictionary
def assign_mlb_rpg(year):
    return mlb_runs_per_game[year]

df['mlb_rpg'] = df['yearID'].apply(assign_mlb_rpg)

अब आप वर्षों को दशकों में बदलेंगे और प्रत्येक दशक के लिए डमी कॉलम बनाएँगे। फिर वे कॉलम हटा दें जिनकी अब आवश्यकता नहीं है।

बेसबॉल खेल में अंतिम हिसाब यह है कि आपने कितने रन बनाए और कितने रन दिए। आप ऐसे कॉलम बनाकर अपने मॉडल की सटीकता में काफी बढ़ोतरी कर सकते हैं जो अन्य कॉलमों के रेश्यो हों। प्रति गेम रन और प्रति गेम दिए गए रन हमारे डेटा सेट में जोड़ने के लिए शानदार फ़ीचर होंगे।

Pandas यह बेहद सरल बनाता है: R कॉलम को G कॉलम से विभाजित करके R_per_game कॉलम बना दें।

अब देखें कि नए दोनों वेरिएबल्स का लक्ष्य जीत कॉलम से क्या संबंध है, इसके लिए दो स्कैटर ग्राफ बनाएँ। एक ग्राफ के x-अक्ष पर प्रति गेम रन और दूसरे के x-अक्ष पर प्रति गेम दिए गए रन प्लॉट करें। प्रत्येक y-अक्ष पर W कॉलम प्लॉट करें।

# Create scatter plots for runs per game vs. wins and runs allowed per game vs. winsfig = plt.figure(figsize=(12, 6))ax1 = fig.add_subplot(1,2,1)ax2 = fig.add_subplot(1,2,2)ax1.scatter(df['R_per_game'], df['W'], c='blue')ax1.set_title('Runs per Game vs. Wins')ax1.set_ylabel('Wins')ax1.set_xlabel('Runs per Game')ax2.scatter(df['RA_per_game'], df['W'], c='red')ax2.set_title('Runs Allowed per Game vs. Wins')ax2.set_xlabel('Runs Allowed per Game')plt.show()

clusters

किसी भी मशीन लर्निंग मॉडल में जाने से पहले, यह देखना उपयोगी हो सकता है कि प्रत्येक वेरिएबल लक्ष्य वेरिएबल के साथ कितना सहसंबद्ध है। Pandas इसे corr() मेथड से आसान बनाता है।

df.corr()['W']

एक और फ़ीचर जो आप डेटा सेट में जोड़ सकते हैं, वह है sklearn द्वारा प्रदान किए गए K-means क्लस्टर एल्गोरिद्म से निकले लेबल। K-means एक सरल क्लस्टरिंग एल्गोरिद्म है जो आपके द्वारा दिए गए k सेंट्रॉइड्स की संख्या के आधार पर डेटा को विभाजित करता है। प्रत्येक डेटा पॉइंट को उस क्लस्टर में असाइन किया जाता है जिसका सेंट्रॉइड उस पॉइंट से सबसे कम यूक्लिडियन दूरी पर होता है।

K-means क्लस्टरिंग के बारे में अधिक जानें यहाँ।

सबसे पहले, एक DataFrame बनाएँ जिसमें लक्ष्य वेरिएबल शामिल न हो:

attributes = ['G','R','AB','H','2B','3B','HR','BB','SO','SB','RA','ER','ERA','CG',
'SHO','SV','IPouts','HA','HRA','BBA','SOA','E','DP','FP','era_1','era_2','era_3','era_4','era_5','era_6','era_7','era_8','decade_1910','decade_1920','decade_1930','decade_1940','decade_1950','decade_1960','decade_1970','decade_1980','decade_1990','decade_2000','decade_2010','R_per_game','RA_per_game','mlb_rpg']

data_attributes = df[attributes]

# Print the first rows of `df`
print(df.head())

K-means क्लस्टरिंग का एक पहलू जिसे आपको मॉडल इस्तेमाल करने से पहले तय करना होता है, वह है क्लस्टर्स की संख्या। आप sklearn के silhouette_score() फ़ंक्शन का उपयोग कर अपने आदर्श क्लस्टर की संख्या का बेहतर अंदाज़ा लगा सकते हैं। यह फ़ंक्शन सभी सैम्पल्स पर औसत सिल्हूट गुणांक लौटाता है। आप अधिक सिल्हूट स्कोर चाहते हैं, और जैसे-जैसे अधिक क्लस्टर जोड़े जाते हैं, स्कोर घटता जाता है।

# Import necessary modules from `sklearn` 
from sklearn.cluster import KMeans
from sklearn import metrics

# Create silhouette score dictionary
s_score_dict = {}
for i in range(2,11):
    km = KMeans(n_clusters=j, random_state=1)
    l = km.fit_predict(data_attributes)
    s_s = metrics.silhouette_score(data_attributes, l)
    s_score_dict[i] = [s_s]

# Print out `s_score_dict`
print(s_score_dict)

अब आप मॉडल को इनिशियलाइज़ कर सकते हैं। क्लस्टर्स की संख्या 6 और रैंडम स्टेट 1 सेट करें। fit_transform() मेथड का उपयोग कर प्रत्येक डेटा पॉइंट के लिए यूक्लिडियन दूरी निर्धारित करें और फिर स्कैटर प्लॉट से क्लस्टर विज़ुअलाइज़ करें।

# Create K-means model and determine euclidian distances for each data pointkmeans_model = KMeans(n_clusters=6, random_state=1)distances = kmeans_model.fit_transform(data_attributes)# Create scatter plot using labels from K-means model as colorlabels = kmeans_model.labels_plt.scatter(distances[:,0], distances[:,1], c=labels)plt.title('Kmeans Clusters')plt.show()

clusters

अब अपने क्लस्टर्स से लेबल्स को डेटा सेट में एक नए कॉलम के रूप में जोड़ें। साथ ही attributes लिस्ट में स्ट्रिंग “labels” भी जोड़ें, ताकि बाद में उपयोग कर सकें।

मॉडल बनाने से पहले, आपको अपने डेटा को ट्रेन और टेस्ट सेट में बाँटना होगा। आप ऐसा इसलिए करते हैं क्योंकि यदि आप ट्रेन और टेस्ट के लिए एक ही डेटा का उपयोग करते हैं, तो आपका मॉडल आसानी से ओवरफिट हो सकता है: मॉडल सीखने के बजाय डेटा को याद कर लेगा, जिससे आपके डेटा के लिए अत्यधिक जटिल मॉडल बनते हैं। यही वजह है कि ओवरफिट मॉडल नए डेटा पर भविष्यवाणी करते समय अक्सर खराब प्रदर्शन करते हैं।

लेकिन अभी चिंता न करें, अपने मॉडल को क्रॉस-वैलिडेट करने के कई तरीके हैं।

इस बार, आप यादृच्छिक रूप से 75 प्रतिशत डेटा को train डेटा सेट के लिए लेंगे और बाकी 25 प्रतिशत को test डेटा सेट के लिए उपयोग करेंगे। अपनी मॉडल में इस्तेमाल होने वाले सभी कॉलमों की सूची numeric_cols बनाएँ। फिर, df DataFrame से numeric_cols सूची में मौजूद कॉलमों के साथ एक नया DataFrame data बनाएँ। इसके बाद, DataFrame data से सैम्पल लेकर अपने train और test डेटा सेट भी बनाएँ।

# Create new DataFrame using only variables to be included in models
numeric_cols = ['G','R','AB','H','2B','3B','HR','BB','SO','SB','RA','ER','ERA','CG','SHO','SV','IPouts','HA','HRA','BBA','SOA','E','DP','FP','era_1','era_2','era_3','era_4','era_5','era_6','era_7','era_8','decade_1910','decade_1920','decade_1930','decade_1940','decade_1950','decade_1960','decade_1970','decade_1980','decade_1990','decade_2000','decade_2010','R_per_game','RA_per_game','mlb_rpg','labels','W']
data = df[numeric_cols]
print(data.head())

# Split data DataFrame into train and test sets
train = data.sample(frac=0.75, random_state=1)
test = data.loc[~data.index.isin(train.index)]

x_train = train[attributes]
y_train = train['W']
x_test = test[attributes]
y_test = test['W']

एरर मेट्रिक और मॉडल चुनना

Mean Absolute Error (MAE) वह मेट्रिक होगा जिसका उपयोग आप अपने मॉडल की सटीकता निर्धारित करने के लिए करेंगे। यह मापता है कि भविष्यवाणियाँ वास्तविक परिणामों के कितने करीब हैं। विशेष रूप से, इस डेटा के लिए, इसका अर्थ यह है कि यह एरर मेट्रिक आपको औसत परिमाण (absolute value) बताएगा जितना आपकी भविष्यवाणी लक्ष्य से चूकी।

इसका मतलब है कि यदि औसतन आपकी भविष्यवाणियाँ लक्ष्य मात्रा से 5 जीत से चूकती हैं, तो आपका एरर मेट्रिक 5 होगा।

पहला मॉडल जो आप ट्रेन करेंगे, वह लीनियर रिग्रेशन मॉडल होगा। आप क्रमशः sklearn.linear_model और sklearn.metrics से LinearRegression और mean_absolute_error इम्पोर्ट कर सकते हैं, और फिर lr मॉडल बना सकते हैं। इसके बाद, आप मॉडल फिट करेंगे, भविष्यवाणी करेंगे और मॉडल का mean absolute error निर्धारित करेंगे।

यदि आपको याद हो, औसत जीत लगभग 79 थी। औसतन, मॉडल केवल 2.687 जीत से चूक रहा है।

अब एक Ridge रिग्रेशन मॉडल आज़माएँ। sklearn.linear_model से RidgeCV इम्पोर्ट करें और rrm मॉडल बनाएँ। RidgeCV मॉडल आपको alpha पैरामीटर सेट करने देता है, जो एक जटिलता पैरामीटर है और श्रिंकिज की मात्रा को नियंत्रित करता है (यहाँ और पढ़ें)। मॉडल क्रॉस-वैलिडेशन का उपयोग कर आपके द्वारा दिए गए alpha पैरामीटरों में से कौन-सा आदर्श है, यह निर्धारित करेगा।

फिर से, अपना मॉडल फिट करें, भविष्यवाणियाँ करें और mean absolute error निर्धारित करें।

यह मॉडल थोड़ा बेहतर रहा, और औसतन 2.673 जीत से चूक रहा है।

स्पोर्ट्स एनालिटिक्स और Scikit-Learn

यह इस ट्यूटोरियल श्रृंखला का पहला भाग समाप्त करता है, जिसमें आपने देखा कि आप scikit-learn का उपयोग करके स्पोर्ट्स डेटा का विश्लेषण कैसे कर सकते हैं। आपने SQLite डेटाबेस से डेटा इम्पोर्ट किया, उसे साफ़ किया, उसके कुछ पहलुओं का विज़ुअल अन्वेषण किया, और कई नए फ़ीचर इंजीनियर किए। आपने K-means क्लस्टरिंग मॉडल, कुछ अलग-अलग लीनियर रिग्रेशन मॉडल बनाना सीखा, और mean absolute error मेट्रिक से अपनी भविष्यवाणियों का परीक्षण करना सीखा।

दूसरे भाग में, आप देखेंगे कि किस प्रकार क्लासिफिकेशन मॉडल का उपयोग कर यह भविष्यवाणी की जाए कि कौन-से खिलाड़ी MLB हॉल ऑफ फ़ेम में शामिल होंगे।

विषय