Bahasa pemrograman Python adalah pilihan yang sangat baik untuk data science dan analitik prediktif, karena dilengkapi dengan banyak paket yang mencakup sebagian besar kebutuhan analisis data Anda. Untuk machine learning di Python, Scikit-learn (sklearn) adalah pilihan yang sangat baik dan dibangun di atas NumPy, SciPy, dan Matplotlib (masing-masing untuk array N-dimensi, komputasi ilmiah, dan visualisasi data).
Dalam tutorial ini, Anda akan melihat cara mudah memuat data dari basis data dengan sqlite3, bagaimana mengeksplorasi data dan meningkatkan kualitasnya dengan pandas dan matplotlib, dan bagaimana kemudian menggunakan paket Scikit-Learn untuk mengekstrak wawasan yang valid dari data Anda.
Bagian 1: Memprediksi Kemenangan Tim MLB per Musim
Pada proyek ini, Anda akan menguji beberapa model machine learning dari sklearn untuk memprediksi jumlah pertandingan yang dimenangkan oleh tim Major League Baseball pada musim tersebut, berdasarkan statistik tim dan variabel lain dari musim itu. Jika saya seorang penjudi (dan saya jelas seorang penjudi), saya bisa membangun model menggunakan data historis dari musim-musim sebelumnya untuk memproyeksikan musim yang akan datang. Mengingat sifat deret waktunya, Anda dapat menghasilkan indikator seperti rata-rata kemenangan per tahun selama lima tahun sebelumnya, dan faktor-faktor lain semacam itu, untuk membuat model yang sangat akurat. Namun itu di luar cakupan tutorial ini, dan Anda akan memperlakukan setiap baris sebagai independen. Setiap baris data kita akan berisi satu tim untuk satu tahun tertentu.
Anda akan membaca data dengan mengeksekusi kueri pada basis data sqlite menggunakan paket sqlite3 dan mengonversinya menjadi DataFrame dengan pandas. Data Anda akan difilter untuk hanya memasukkan tim modern yang saat ini aktif dan hanya tahun ketika tim bermain 150 pertandingan atau lebih.
Pertama, unduh berkas “lahman2016.sqlite” (di sini). Lalu, muat Pandas dan ubah namanya menjadi pd demi efisiensi. Anda mungkin ingat bahwa pd adalah alias umum untuk Pandas. Terakhir, muat sqlite3 dan hubungkan ke basis data, seperti ini:
# import`pandas` and `sqlite3`import pandas as pdimport sqlite3# Connecting to SQLite Databaseconn = sqlite3.connect('lahman2016.sqlite')Didukung oleh
Berikutnya, tulis kueri, eksekusi, dan ambil hasilnya.
# 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()Didukung oleh
Tip: Jika Anda ingin mempelajari lebih lanjut tentang penggunaan SQL dengan Python, pertimbangkan untuk mengambil kursus DataCamp Introduction to Databases in Python.
Menggunakan pandas, Anda kemudian mengonversi hasil ke DataFrame dan mencetak 5 baris pertama menggunakan metode head():
# Convert `Teams` to DataFrame
teams_df = pd.DataFrame(_____)
# Print out first 5 rows
print(_______________)
Setiap kolom berisi data terkait satu tim dan tahun tertentu. Beberapa variabel yang lebih penting tercantum di bawah. Daftar lengkap variabel dapat ditemukan di sini.
yearID - Tahun
teamID - Tim
franchID - Waralaba (terhubung ke tabel TeamsFranchise)
G - Jumlah pertandingan dimainkan
W - Kemenangan
LgWin - Juara Liga (Y atau N)
WSWin - Pemenang World Series (Y atau N)
R - Run dicetak
AB - At bat
H - Hit oleh pemukul
HR - Home run oleh pemukul
BB - Walk oleh pemukul
SO - Strikeout oleh pemukul
SB - Basis tercuri
CS - Tertangkap mencuri
HBP - Pemukul terkena lemparan
SF - Sacrifice fly
RA - Run lawan yang dicetak
ER - Earned run yang diizinkan
ERA - Rata-rata earned run
CG - Complete game
SHO - Shutout
SV - Save
IPOuts - Out yang dilempar (inning dilempar x 3)
HA - Hit yang diizinkan
HRA - Home run yang diizinkan
BBA - Walk yang diizinkan
SOA - Strikeout oleh pitcher
E - Error
DP - Double play
FP - Persentase fielding
name - Nama lengkap tim
Bagi Anda yang mungkin kurang akrab dengan baseball, berikut penjelasan singkat cara permainan ini berjalan, beserta beberapa variabel yang disertakan.
Baseball dimainkan antara dua tim (yang bisa Anda temukan kembali di data dengan name atau teamID) yang masing-masing terdiri dari sembilan pemain. Kedua tim ini bergantian menjadi tim pemukul dan tim bertahan. Tim pemukul berupaya mencetak run dengan bergiliran memukul bola yang dilemparkan oleh pitcher dari tim bertahan, lalu berlari berlawanan arah jarum jam mengelilingi empat base: pertama, kedua, ketiga, dan home plate. Tim bertahan berusaha mencegah run dengan mengeliminasi pemukul atau pelari base dengan berbagai cara dan sebuah run (R) dicetak ketika seorang pemain berkeliling base dan kembali ke home plate. Seorang pemain dari tim pemukul yang mencapai base dengan selamat akan berusaha maju ke base berikutnya saat giliran rekan setimnya memukul, misalnya pada sebuah hit (H), basis tercuri (SB), atau dengan cara lain.
Kedua tim bertukar antara memukul dan bertahan setiap kali tim bertahan mencatat tiga out. Satu giliran memukul untuk kedua tim, dimulai dari tim tamu, merupakan satu inning. Satu pertandingan terdiri dari sembilan inning, dan tim dengan jumlah run lebih banyak di akhir pertandingan menjadi pemenang. Baseball tidak memiliki jam pertandingan dan meskipun sebagian besar pertandingan berakhir pada inning kesembilan, jika pertandingan imbang setelah sembilan inning maka akan dilanjutkan ke extra innings dan akan berlanjut tanpa batas hingga salah satu tim unggul di akhir inning tambahan.
Seperti yang Anda lihat di atas, DataFrame belum memiliki header kolom. Anda dapat menambahkan header dengan meneruskan daftar header Anda ke atribut columns dari pandas.
Fungsi len() akan memberi tahu berapa banyak baris yang Anda hadapi: 2.287 bukan jumlah titik data yang besar untuk dikerjakan, jadi semoga tidak terlalu banyak nilai null.
Sebelum menilai kualitas data, mari singkirkan terlebih dahulu kolom yang tidak diperlukan atau yang diturunkan dari kolom target (Wins). Di sinilah pengetahuan tentang data yang Anda kerjakan menjadi sangat berharga. Tidak masalah seberapa banyak Anda tahu tentang pengkodean atau statistik jika Anda tidak memiliki pengetahuan tentang data yang Anda kerjakan. Menjadi penggemar baseball seumur hidup jelas membantu saya dalam proyek ini.
# 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(_________)
Seperti yang Anda baca di atas, nilai null memengaruhi kualitas data, yang pada gilirannya dapat menyebabkan masalah pada algoritme machine learning.
Itulah mengapa Anda akan menghapusnya berikutnya. Ada beberapa cara untuk mengeliminasi nilai null, tetapi mungkin lebih baik untuk terlebih dahulu menampilkan jumlah nilai null untuk setiap kolom agar Anda dapat memutuskan cara terbaik menanganinya.
# Print out null values of all columns of `df`
print(_________.sum(axis=0).tolist())
Dan di sinilah Anda akan melihat trade-off: Anda butuh data bersih, tetapi Anda juga tidak memiliki banyak data untuk dibuang. Dua kolom memiliki jumlah nilai null yang relatif kecil. Ada 110 nilai null di kolom SO (Strike Out) dan 22 di kolom DP (Double Play). Dua kolom lainnya memiliki jumlah yang relatif besar. Ada 419 nilai null di kolom CS (Caught Stealing) dan 1777 di kolom HBP (Hit by Pitch).
Jika Anda menghapus baris di mana kolom memiliki sejumlah kecil nilai null, Anda kehilangan sedikit di atas lima persen data kita. Karena Anda mencoba memprediksi kemenangan, run yang dicetak dan run yang diizinkan sangat berkorelasi dengan target. Anda ingin data di kolom-kolom tersebut sangat akurat.
Strike out (SO) dan double play (DP) tidak sepenting itu.
Menurut saya, lebih baik Anda mempertahankan baris-baris tersebut dan mengisi nilai null dengan nilai median dari masing-masing kolom menggunakan metode fillna(). Tertangkap mencuri (CS) dan terkena lemparan (HBP) juga bukan variabel yang sangat penting. Dengan begitu banyak nilai null di kolom-kolom ini, sebaiknya hilangkan kolom-kolom tersebut semuanya.
# 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())
Mengeksplorasi dan Memvisualisasikan Data
Sekarang setelah Anda membersihkan data, Anda dapat melakukan eksplorasi. Anda bisa mendapatkan pemahaman yang lebih baik tentang himpunan data dengan beberapa visualisasi sederhana. matplotlib adalah pustaka yang sangat baik untuk visualisasi data.
Anda mengimpor matplotlib.pyplot dan menamainya ulang menjadi plt demi efisiensi. Jika Anda bekerja dengan Jupyter notebook, Anda perlu menggunakan magic %matplotlib inline.
Anda akan mulai dengan membuat histogram kolom target agar dapat melihat distribusi kemenangan.
# 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()Didukung oleh
Perhatikan bahwa jika Anda tidak menggunakan Jupyter notebook, Anda harus menggunakan plt.show() untuk menampilkan plot.
Cetak rata-rata kemenangan (W) per tahun. Anda dapat menggunakan metode mean() untuk ini.
print(df['_'].______)
Membuat bin untuk kolom target bisa berguna saat mengeksplorasi data Anda, tetapi Anda perlu memastikan untuk tidak memasukkan fitur apa pun yang Anda hasilkan dari kolom target saat melatih model. Menyertakan kolom label yang dihasilkan dari kolom target dalam set pelatihan Anda seperti memberikan jawaban ujian kepada model.
Untuk membuat label kemenangan Anda, Anda akan membuat fungsi bernama assign_win_bins yang akan menerima nilai integer (kemenangan) dan mengembalikan integer 1–5 tergantung pada nilai input.
Selanjutnya, Anda akan membuat kolom baru win_bins dengan menggunakan metode apply() pada kolom kemenangan dan meneruskan fungsi assign_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(______________)
Sekarang mari buat grafik sebar dengan tahun pada sumbu x dan kemenangan pada sumbu y serta sorot kolom win_bins dengan warna.
# 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()Didukung oleh
Seperti yang Anda lihat pada plot sebar di atas, sangat sedikit musim sebelum 1900 dan permainan pada masa itu sangat berbeda. Karena itu, masuk akal untuk menghapus baris-baris tersebut dari himpunan data.
# Filter for rows where 'yearID' is greater than 1900
df = df[___________________]
Ketika bekerja dengan data kontinu dan membuat model linear, nilai integer seperti tahun dapat menimbulkan masalah. Kemungkinan kecil angka 1950 akan memiliki hubungan yang sama dengan data lain seperti yang akan disimpulkan model.
Anda dapat menghindari masalah ini dengan membuat variabel baru yang memberi label data berdasarkan nilai yearID.
Siapa pun yang mengikuti permainan baseball tahu bahwa seiring berjalannya Major League Baseball (MLB), muncul era-era berbeda di mana jumlah run per pertandingan meningkat atau menurun secara signifikan. Era dead ball pada awal 1900-an adalah contoh era dengan skor rendah dan era steroid pada pergantian abad ke-21 adalah contoh era dengan skor tinggi.
Mari buat grafik di bawah yang menunjukkan seberapa banyak skor pada tiap tahun.
Anda akan mulai dengan membuat kamus runs_per_year dan games_per_year. Lakukan perulangan melalui dataframe menggunakan metode iterrows(). Isi kamus runs_per_year dengan tahun sebagai kunci dan berapa banyak run yang dicetak pada tahun tersebut sebagai nilai. Isi kamus games_per_year dengan tahun sebagai kunci dan berapa banyak pertandingan yang dimainkan pada tahun tersebut sebagai nilai.
# 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)
Berikutnya, buat kamus bernama mlb_runs_per_game. Lakukan iterasi melalui kamus games_per_year dengan metode items(). Isi kamus mlb_runs_per_game dengan tahun sebagai kunci dan jumlah run per pertandingan, di seluruh liga, sebagai nilai.
# Create MLB runs per game (per year) dictionary
mlb_runs_per_game = {}
for k, v in games_per_year.items():
year = k
games = v
runs = runs_per_year[year]
mlb_runs_per_game[year] = runs / games
print(mlb_runs_per_game)
Terakhir, buat plot dari kamus mlb_runs_per_game dengan menempatkan tahun pada sumbu x dan run per pertandingan pada sumbu 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()Didukung oleh
Menambahkan Fitur Baru
Sekarang setelah Anda memiliki gambaran yang lebih baik tentang tren perolehan skor, Anda dapat membuat variabel baru yang menunjukkan era tertentu tempat setiap baris data berada berdasarkan yearID. Anda akan mengikuti proses yang sama seperti saat membuat kolom win_bins di atas.
Kali ini, Anda akan membuat kolom dummy; satu kolom baru untuk setiap era. Anda dapat menggunakan metode get_dummies() untuk ini.
# 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())
Karena Anda sudah menghitung jumlah run MLB per pertandingan untuk setiap tahun, tambahkan data tersebut ke set data.
# 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)
Sekarang Anda akan mengonversi tahun menjadi dekade dengan membuat kolom dummy untuk setiap dekade. Lalu Anda dapat menghapus kolom yang tidak lagi dibutuhkan.
# Convert years into decade bins and creating dummy variables
def assign_decade(year):
if year < 1920:
return 1910
elif year >= 1920 and year <= 1929:
return 1920
elif year >= 1930 and year <= 1939:
return 1930
elif year >= 1940 and year <= 1949:
return 1940
elif year >= 1950 and year <= 1959:
return 1950
elif year >= 1960 and year <= 1969:
return 1960
elif year >= 1970 and year <= 1979:
return 1970
elif year >= 1980 and year <= 1989:
return 1980
elif year >= 1990 and year <= 1999:
return 1990
elif year >= 2000 and year <= 2009:
return 2000
elif year >= 2010:
return 2010
df['decade_label'] = df['yearID'].apply(assign_decade)
decade_df = pd.get_dummies(df['decade_label'], prefix='decade')
df = pd.concat([df, decade_df], axis=1)
# Drop unnecessary columns
df = df.drop(['yearID','year_label','decade_label'], axis=1)
Inti dari permainan bisbol adalah berapa banyak run yang Anda cetak dan berapa banyak run yang Anda biarkan. Anda dapat secara signifikan meningkatkan akurasi model dengan membuat kolom yang merupakan rasio dari kolom data lain. Run per pertandingan dan run yang diizinkan per pertandingan akan menjadi fitur yang sangat baik untuk ditambahkan ke set data kita.
Pandas membuat ini sangat sederhana karena Anda membuat kolom baru dengan membagi kolom R dengan kolom G untuk membuat kolom R_per_game.
# Create new features for Runs per Game and Runs Allowed per Game
df['R_per_game'] = df['R'] / df['G']
df['RA_per_game'] = df['RA'] / df['G']
Sekarang lihat bagaimana masing-masing dari dua variabel baru tersebut berkaitan dengan kolom target kemenangan dengan membuat dua grafik sebar. Plot run per pertandingan pada sumbu x untuk satu grafik dan run yang diizinkan per pertandingan pada sumbu x untuk grafik lainnya. Plot kolom W pada masing-masing sumbu y.
# 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()Didukung oleh
Sebelum masuk ke model machine learning apa pun, ada baiknya melihat bagaimana setiap variabel berkorelasi dengan variabel target. Pandas memudahkan hal ini dengan metode corr().
df.corr()['W']
Fitur lain yang dapat Anda tambahkan ke dataset adalah label yang diturunkan dari algoritme klaster K-means yang disediakan oleh sklearn. K-means adalah algoritme klaster sederhana yang membagi data berdasarkan jumlah centroid k yang Anda tentukan. Setiap titik data ditetapkan ke sebuah klaster berdasarkan centroid mana yang memiliki jarak Euclidean terendah dari titik data tersebut.
Anda dapat mempelajari lebih lanjut tentang pengklasteran K-means di sini.
Pertama, buat DataFrame yang mengecualikan variabel target:
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())
Satu hal yang harus Anda tentukan sebelum menggunakan model K-means adalah berapa banyak klaster yang Anda inginkan. Anda bisa mendapatkan gambaran yang lebih baik tentang jumlah klaster ideal dengan menggunakan fungsi silhouette_score() dari sklearn. Fungsi ini mengembalikan koefisien siluet rata-rata untuk semua sampel. Anda menginginkan skor siluet yang lebih tinggi, dan skor akan menurun saat lebih banyak klaster ditambahkan.
# 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=i, 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)
Sekarang Anda dapat menginisialisasi model. Tetapkan jumlah klaster ke 6 dan random state ke 1. Tentukan jarak Euclidean untuk setiap titik data dengan menggunakan metode fit_transform() lalu visualisasikan klaster dengan grafik sebar.
# 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 fromK-means model as colorlabels = kmeans_model.labels_plt.scatter(distances[:,0], distances[:,1], c=labels)plt.title('Kmeans Clusters')plt.show()Didukung oleh
Sekarang tambahkan label dari klaster Anda ke set data sebagai kolom baru. Tambahkan juga string “labels” ke daftar attributes, untuk digunakan nanti.
# Add labels from K-means model to `df` DataFrame and attributes list
df['labels'] = labels
attributes.append('labels')
# Print the first rows of `df`
print(_________)
Sebelum Anda dapat membangun model, Anda perlu membagi data menjadi set train dan test. Anda melakukan ini karena jika Anda memutuskan untuk melatih model pada data yang sama dengan yang digunakan untuk menguji model, model Anda dapat dengan mudah overfit terhadap data: model akan lebih menghafal data daripada belajar darinya, yang menghasilkan model yang terlalu kompleks untuk data Anda. Hal itu juga menjelaskan mengapa model yang overfit akan berkinerja buruk saat Anda mencoba membuat prediksi dengan data baru.
Tetapi jangan khawatir dulu, ada sejumlah cara untuk melakukan cross-validation pada model Anda.
Kali ini, Anda akan mengambil sampel acak sebesar 75 persen dari data kita untuk set data train dan menggunakan 25 persen sisanya untuk set data test. Buat daftar numeric_cols berisi semua kolom yang akan Anda gunakan dalam model. Selanjutnya, buat DataFrame baru data dari DataFrame df dengan kolom-kolom dalam daftar numeric_cols. Lalu, buat juga set data train dan test dengan melakukan sampling pada DataFrame data.
# 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']
Memilih Metrik Galat dan Model
Mean Absolute Error (MAE) adalah metrik yang akan Anda gunakan untuk menentukan seberapa akurat model Anda. Metrik ini mengukur seberapa dekat prediksi terhadap hasil akhirnya. Secara khusus, untuk data ini, metrik galat ini akan memberi Anda nilai absolut rata-rata seberapa jauh prediksi Anda meleset dari sasarannya.
Artinya, jika rata-rata prediksi Anda meleset dari jumlah target sebesar 5 kemenangan, metrik galat Anda adalah 5.
Model pertama yang akan Anda latih adalah model regresi linear. Anda dapat mengimpor LinearRegression dan mean_absolute_error masing-masing dari sklearn.linear_model dan sklearn.metrics, lalu membuat model lr. Selanjutnya, Anda akan melakukan fitting pada model, membuat prediksi, dan menentukan mean absolute error dari model tersebut.
# Import `LinearRegression` from `sklearn.linear_model`
from sklearn.linear_model import ___________________
# Import `mean_absolute_error` from `sklearn.metrics`
from sklearn.metrics import mean_absolute_error
# Create Linear Regression model, fit model, and make predictions
lr = LinearRegression(normalize=True)
lr.fit(x_train, y_train)
predictions = lr.predict(x_test)
# Determine mean absolute error
mae = mean_absolute_error(y_test, predictions)
# Print `mae`
print(___)
Jika Anda ingat dari penjelasan di atas, rata-rata jumlah kemenangan adalah sekitar 79 kemenangan. Rata-rata, model meleset hanya sebesar 2,687 kemenangan.
Sekarang coba model regresi Ridge. Impor RidgeCV dari sklearn.linear_model dan buat model rrm. Model RidgeCV memungkinkan Anda menyetel parameter alpha, yaitu parameter kompleksitas yang mengontrol besarnya shrinkage (baca selengkapnya di sini). Model ini akan menggunakan cross-validation untuk menentukan parameter alpha mana yang paling ideal dari yang Anda sediakan.
Sekali lagi, lakukan fitting pada model Anda, buat prediksi, dan tentukan mean absolute error-nya.
# Import `RidgeCV` from `sklearn.linear_model`
from sklearn.linear_model import _______
# Create Ridge Linear Regression model, fit model, and make predictions
rrm = RidgeCV(alphas=(0.01, 0.1, 1.0, 10.0), normalize=True)
rrm.fit(x_train, y_train)
predictions_rrm = rrm.predict(x_test)
# Determine mean absolute error
mae_rrm = mean_absolute_error(y_test, predictions_rrm)
print(________)
Model ini berkinerja sedikit lebih baik, dengan rata-rata meleset sebesar 2,673 kemenangan.
Analitik Olahraga & Scikit-Learn
Bagian pertama dari seri tutorial ini berakhir di sini, di mana Anda telah melihat bagaimana menggunakan scikit-Learn untuk menganalisis data olahraga. Anda mengimpor data dari basis data SQLite, membersihkannya, mengeksplorasi aspeknya secara visual, dan merekayasa sejumlah fitur baru. Anda mempelajari cara membuat model klastering K-means, beberapa model Regresi Linear, dan cara menguji prediksi menggunakan metrik mean absolute error.
Pada bagian kedua, Anda akan melihat cara menggunakan model klasifikasi untuk memprediksi pemain mana yang masuk ke MLB Hall of Fame.
Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Selami ilmu data dengan Python dan pelajari cara menganalisis serta memvisualisasikan data Anda secara efektif. Tak perlu pengalaman atau keterampilan coding.
Bahasa pemrograman Python adalah pilihan yang sangat baik untuk data science dan analitik prediktif, karena dilengkapi dengan banyak paket yang mencakup sebagian besar kebutuhan analisis data Anda. Untuk machine learning di Python, Scikit-learn (
sklearn) adalah pilihan yang sangat baik dan dibangun di atas NumPy, SciPy, dan Matplotlib (masing-masing untuk array N-dimensi, komputasi ilmiah, dan visualisasi data).Dalam tutorial ini, Anda akan melihat cara mudah memuat data dari basis data dengan
sqlite3, bagaimana mengeksplorasi data dan meningkatkan kualitasnya denganpandasdanmatplotlib, dan bagaimana kemudian menggunakan paket Scikit-Learn untuk mengekstrak wawasan yang valid dari data Anda.Jika Anda ingin mengikuti kursus machine learning, lihat kursus DataCamp Supervised Learning with scikit-learn.
Bagian 1: Memprediksi Kemenangan Tim MLB per Musim
Pada proyek ini, Anda akan menguji beberapa model machine learning dari
sklearnuntuk memprediksi jumlah pertandingan yang dimenangkan oleh tim Major League Baseball pada musim tersebut, berdasarkan statistik tim dan variabel lain dari musim itu. Jika saya seorang penjudi (dan saya jelas seorang penjudi), saya bisa membangun model menggunakan data historis dari musim-musim sebelumnya untuk memproyeksikan musim yang akan datang. Mengingat sifat deret waktunya, Anda dapat menghasilkan indikator seperti rata-rata kemenangan per tahun selama lima tahun sebelumnya, dan faktor-faktor lain semacam itu, untuk membuat model yang sangat akurat. Namun itu di luar cakupan tutorial ini, dan Anda akan memperlakukan setiap baris sebagai independen. Setiap baris data kita akan berisi satu tim untuk satu tahun tertentu.Sean Lahman mengompilasi data ini di situs webnya dan data tersebut diubah menjadi sebuah basis data sqlite di sini.
Impor Data
Anda akan membaca data dengan mengeksekusi kueri pada basis data sqlite menggunakan paket
sqlite3dan mengonversinya menjadi DataFrame denganpandas. Data Anda akan difilter untuk hanya memasukkan tim modern yang saat ini aktif dan hanya tahun ketika tim bermain 150 pertandingan atau lebih.Pertama, unduh berkas “lahman2016.sqlite” (di sini). Lalu, muat
Pandasdan ubah namanya menjadipddemi efisiensi. Anda mungkin ingat bahwapdadalah alias umum untuk Pandas. Terakhir, muatsqlite3dan hubungkan ke basis data, seperti ini:Berikutnya, tulis kueri, eksekusi, dan ambil hasilnya.
Tip: Jika Anda ingin mempelajari lebih lanjut tentang penggunaan SQL dengan Python, pertimbangkan untuk mengambil kursus DataCamp Introduction to Databases in Python.
Menggunakan
pandas, Anda kemudian mengonversi hasil ke DataFrame dan mencetak 5 baris pertama menggunakan metodehead():Setiap kolom berisi data terkait satu tim dan tahun tertentu. Beberapa variabel yang lebih penting tercantum di bawah. Daftar lengkap variabel dapat ditemukan di sini.
yearID- TahunteamID- TimfranchID- Waralaba (terhubung ke tabel TeamsFranchise)G- Jumlah pertandingan dimainkanW- KemenanganLgWin- Juara Liga (Y atau N)WSWin- Pemenang World Series (Y atau N)R- Run dicetakAB- At batH- Hit oleh pemukulHR- Home run oleh pemukulBB- Walk oleh pemukulSO- Strikeout oleh pemukulSB- Basis tercuriCS- Tertangkap mencuriHBP- Pemukul terkena lemparanSF- Sacrifice flyRA- Run lawan yang dicetakER- Earned run yang diizinkanERA- Rata-rata earned runCG- Complete gameSHO- ShutoutSV- SaveIPOuts- Out yang dilempar (inning dilempar x 3)HA- Hit yang diizinkanHRA- Home run yang diizinkanBBA- Walk yang diizinkanSOA- Strikeout oleh pitcherE- ErrorDP- Double playFP- Persentase fieldingname- Nama lengkap timBagi Anda yang mungkin kurang akrab dengan baseball, berikut penjelasan singkat cara permainan ini berjalan, beserta beberapa variabel yang disertakan.
Baseball dimainkan antara dua tim (yang bisa Anda temukan kembali di data dengan
nameatauteamID) yang masing-masing terdiri dari sembilan pemain. Kedua tim ini bergantian menjadi tim pemukul dan tim bertahan. Tim pemukul berupaya mencetak run dengan bergiliran memukul bola yang dilemparkan oleh pitcher dari tim bertahan, lalu berlari berlawanan arah jarum jam mengelilingi empat base: pertama, kedua, ketiga, dan home plate. Tim bertahan berusaha mencegah run dengan mengeliminasi pemukul atau pelari base dengan berbagai cara dan sebuah run (R) dicetak ketika seorang pemain berkeliling base dan kembali ke home plate. Seorang pemain dari tim pemukul yang mencapai base dengan selamat akan berusaha maju ke base berikutnya saat giliran rekan setimnya memukul, misalnya pada sebuah hit (H), basis tercuri (SB), atau dengan cara lain.Kedua tim bertukar antara memukul dan bertahan setiap kali tim bertahan mencatat tiga out. Satu giliran memukul untuk kedua tim, dimulai dari tim tamu, merupakan satu inning. Satu pertandingan terdiri dari sembilan inning, dan tim dengan jumlah run lebih banyak di akhir pertandingan menjadi pemenang. Baseball tidak memiliki jam pertandingan dan meskipun sebagian besar pertandingan berakhir pada inning kesembilan, jika pertandingan imbang setelah sembilan inning maka akan dilanjutkan ke extra innings dan akan berlanjut tanpa batas hingga salah satu tim unggul di akhir inning tambahan.
Untuk penjelasan mendetail mengenai permainan baseball, lihat peraturan resmi Major League Baseball.
Membersihkan dan Menyiapkan Data
Seperti yang Anda lihat di atas, DataFrame belum memiliki header kolom. Anda dapat menambahkan header dengan meneruskan daftar header Anda ke atribut
columnsdaripandas.Fungsi
len()akan memberi tahu berapa banyak baris yang Anda hadapi: 2.287 bukan jumlah titik data yang besar untuk dikerjakan, jadi semoga tidak terlalu banyak nilai null.Sebelum menilai kualitas data, mari singkirkan terlebih dahulu kolom yang tidak diperlukan atau yang diturunkan dari kolom target (
Wins). Di sinilah pengetahuan tentang data yang Anda kerjakan menjadi sangat berharga. Tidak masalah seberapa banyak Anda tahu tentang pengkodean atau statistik jika Anda tidak memiliki pengetahuan tentang data yang Anda kerjakan. Menjadi penggemar baseball seumur hidup jelas membantu saya dalam proyek ini.Seperti yang Anda baca di atas, nilai null memengaruhi kualitas data, yang pada gilirannya dapat menyebabkan masalah pada algoritme machine learning.
Itulah mengapa Anda akan menghapusnya berikutnya. Ada beberapa cara untuk mengeliminasi nilai null, tetapi mungkin lebih baik untuk terlebih dahulu menampilkan jumlah nilai null untuk setiap kolom agar Anda dapat memutuskan cara terbaik menanganinya.
Dan di sinilah Anda akan melihat trade-off: Anda butuh data bersih, tetapi Anda juga tidak memiliki banyak data untuk dibuang. Dua kolom memiliki jumlah nilai null yang relatif kecil. Ada 110 nilai null di kolom
SO(Strike Out) dan 22 di kolomDP(Double Play). Dua kolom lainnya memiliki jumlah yang relatif besar. Ada 419 nilai null di kolomCS(Caught Stealing) dan 1777 di kolomHBP(Hit by Pitch).Jika Anda menghapus baris di mana kolom memiliki sejumlah kecil nilai null, Anda kehilangan sedikit di atas lima persen data kita. Karena Anda mencoba memprediksi kemenangan, run yang dicetak dan run yang diizinkan sangat berkorelasi dengan target. Anda ingin data di kolom-kolom tersebut sangat akurat.
Strike out (
SO) dan double play (DP) tidak sepenting itu.Menurut saya, lebih baik Anda mempertahankan baris-baris tersebut dan mengisi nilai null dengan nilai median dari masing-masing kolom menggunakan metode
fillna(). Tertangkap mencuri (CS) dan terkena lemparan (HBP) juga bukan variabel yang sangat penting. Dengan begitu banyak nilai null di kolom-kolom ini, sebaiknya hilangkan kolom-kolom tersebut semuanya.Mengeksplorasi dan Memvisualisasikan Data
Sekarang setelah Anda membersihkan data, Anda dapat melakukan eksplorasi. Anda bisa mendapatkan pemahaman yang lebih baik tentang himpunan data dengan beberapa visualisasi sederhana.
matplotlibadalah pustaka yang sangat baik untuk visualisasi data.Anda mengimpor
matplotlib.pyplotdan menamainya ulang menjadipltdemi efisiensi. Jika Anda bekerja dengan Jupyter notebook, Anda perlu menggunakan magic%matplotlib inline.Anda akan mulai dengan membuat histogram kolom target agar dapat melihat distribusi kemenangan.
Perhatikan bahwa jika Anda tidak menggunakan Jupyter notebook, Anda harus menggunakan
plt.show()untuk menampilkan plot.Cetak rata-rata kemenangan (
W) per tahun. Anda dapat menggunakan metodemean()untuk ini.Membuat bin untuk kolom target bisa berguna saat mengeksplorasi data Anda, tetapi Anda perlu memastikan untuk tidak memasukkan fitur apa pun yang Anda hasilkan dari kolom target saat melatih model. Menyertakan kolom label yang dihasilkan dari kolom target dalam set pelatihan Anda seperti memberikan jawaban ujian kepada model.
Untuk membuat label kemenangan Anda, Anda akan membuat fungsi bernama
assign_win_binsyang akan menerima nilai integer (kemenangan) dan mengembalikan integer 1–5 tergantung pada nilai input.Selanjutnya, Anda akan membuat kolom baru
win_binsdengan menggunakan metodeapply()pada kolom kemenangan dan meneruskan fungsiassign_win_bins().Sekarang mari buat grafik sebar dengan tahun pada sumbu x dan kemenangan pada sumbu y serta sorot kolom
win_binsdengan warna.Seperti yang Anda lihat pada plot sebar di atas, sangat sedikit musim sebelum 1900 dan permainan pada masa itu sangat berbeda. Karena itu, masuk akal untuk menghapus baris-baris tersebut dari himpunan data.
Ketika bekerja dengan data kontinu dan membuat model linear, nilai integer seperti tahun dapat menimbulkan masalah. Kemungkinan kecil angka 1950 akan memiliki hubungan yang sama dengan data lain seperti yang akan disimpulkan model.
Anda dapat menghindari masalah ini dengan membuat variabel baru yang memberi label data berdasarkan nilai
yearID.Siapa pun yang mengikuti permainan baseball tahu bahwa seiring berjalannya Major League Baseball (MLB), muncul era-era berbeda di mana jumlah run per pertandingan meningkat atau menurun secara signifikan. Era dead ball pada awal 1900-an adalah contoh era dengan skor rendah dan era steroid pada pergantian abad ke-21 adalah contoh era dengan skor tinggi.
Mari buat grafik di bawah yang menunjukkan seberapa banyak skor pada tiap tahun.
Anda akan mulai dengan membuat kamus
runs_per_yeardangames_per_year. Lakukan perulangan melalui dataframe menggunakan metodeiterrows(). Isi kamusruns_per_yeardengan tahun sebagai kunci dan berapa banyak run yang dicetak pada tahun tersebut sebagai nilai. Isi kamusgames_per_yeardengan tahun sebagai kunci dan berapa banyak pertandingan yang dimainkan pada tahun tersebut sebagai nilai.Berikutnya, buat kamus bernama
mlb_runs_per_game. Lakukan iterasi melalui kamusgames_per_yeardengan metodeitems(). Isi kamusmlb_runs_per_gamedengan tahun sebagai kunci dan jumlah run per pertandingan, di seluruh liga, sebagai nilai.Terakhir, buat plot dari kamus
mlb_runs_per_gamedengan menempatkan tahun pada sumbu x dan run per pertandingan pada sumbu y.Menambahkan Fitur Baru
Sekarang setelah Anda memiliki gambaran yang lebih baik tentang tren perolehan skor, Anda dapat membuat variabel baru yang menunjukkan era tertentu tempat setiap baris data berada berdasarkan
yearID. Anda akan mengikuti proses yang sama seperti saat membuat kolomwin_binsdi atas.Kali ini, Anda akan membuat kolom dummy; satu kolom baru untuk setiap era. Anda dapat menggunakan metode
get_dummies()untuk ini.Karena Anda sudah menghitung jumlah run MLB per pertandingan untuk setiap tahun, tambahkan data tersebut ke set data.
Sekarang Anda akan mengonversi tahun menjadi dekade dengan membuat kolom dummy untuk setiap dekade. Lalu Anda dapat menghapus kolom yang tidak lagi dibutuhkan.
Inti dari permainan bisbol adalah berapa banyak run yang Anda cetak dan berapa banyak run yang Anda biarkan. Anda dapat secara signifikan meningkatkan akurasi model dengan membuat kolom yang merupakan rasio dari kolom data lain. Run per pertandingan dan run yang diizinkan per pertandingan akan menjadi fitur yang sangat baik untuk ditambahkan ke set data kita.
Pandasmembuat ini sangat sederhana karena Anda membuat kolom baru dengan membagi kolomRdengan kolomGuntuk membuat kolomR_per_game.Sekarang lihat bagaimana masing-masing dari dua variabel baru tersebut berkaitan dengan kolom target kemenangan dengan membuat dua grafik sebar. Plot run per pertandingan pada sumbu x untuk satu grafik dan run yang diizinkan per pertandingan pada sumbu x untuk grafik lainnya. Plot kolom
Wpada masing-masing sumbu y.Sebelum masuk ke model machine learning apa pun, ada baiknya melihat bagaimana setiap variabel berkorelasi dengan variabel target.
Pandasmemudahkan hal ini dengan metodecorr().Fitur lain yang dapat Anda tambahkan ke dataset adalah label yang diturunkan dari algoritme klaster K-means yang disediakan oleh
sklearn. K-means adalah algoritme klaster sederhana yang membagi data berdasarkan jumlah centroid k yang Anda tentukan. Setiap titik data ditetapkan ke sebuah klaster berdasarkan centroid mana yang memiliki jarak Euclidean terendah dari titik data tersebut.Anda dapat mempelajari lebih lanjut tentang pengklasteran K-means di sini.
Pertama, buat DataFrame yang mengecualikan variabel target:
Satu hal yang harus Anda tentukan sebelum menggunakan model K-means adalah berapa banyak klaster yang Anda inginkan. Anda bisa mendapatkan gambaran yang lebih baik tentang jumlah klaster ideal dengan menggunakan fungsi
silhouette_score()dari sklearn. Fungsi ini mengembalikan koefisien siluet rata-rata untuk semua sampel. Anda menginginkan skor siluet yang lebih tinggi, dan skor akan menurun saat lebih banyak klaster ditambahkan.Sekarang Anda dapat menginisialisasi model. Tetapkan jumlah klaster ke 6 dan random state ke
1. Tentukan jarak Euclidean untuk setiap titik data dengan menggunakan metodefit_transform()lalu visualisasikan klaster dengan grafik sebar.Sekarang tambahkan label dari klaster Anda ke set data sebagai kolom baru. Tambahkan juga string “labels” ke daftar
attributes, untuk digunakan nanti.Sebelum Anda dapat membangun model, Anda perlu membagi data menjadi set train dan test. Anda melakukan ini karena jika Anda memutuskan untuk melatih model pada data yang sama dengan yang digunakan untuk menguji model, model Anda dapat dengan mudah overfit terhadap data: model akan lebih menghafal data daripada belajar darinya, yang menghasilkan model yang terlalu kompleks untuk data Anda. Hal itu juga menjelaskan mengapa model yang overfit akan berkinerja buruk saat Anda mencoba membuat prediksi dengan data baru.
Tetapi jangan khawatir dulu, ada sejumlah cara untuk melakukan cross-validation pada model Anda.
Kali ini, Anda akan mengambil sampel acak sebesar 75 persen dari data kita untuk set data
traindan menggunakan 25 persen sisanya untuk set datatest. Buat daftarnumeric_colsberisi semua kolom yang akan Anda gunakan dalam model. Selanjutnya, buat DataFrame barudatadari DataFramedfdengan kolom-kolom dalam daftarnumeric_cols. Lalu, buat juga set datatraindantestdengan melakukan sampling pada DataFramedata.Memilih Metrik Galat dan Model
Mean Absolute Error (MAE) adalah metrik yang akan Anda gunakan untuk menentukan seberapa akurat model Anda. Metrik ini mengukur seberapa dekat prediksi terhadap hasil akhirnya. Secara khusus, untuk data ini, metrik galat ini akan memberi Anda nilai absolut rata-rata seberapa jauh prediksi Anda meleset dari sasarannya.
Artinya, jika rata-rata prediksi Anda meleset dari jumlah target sebesar 5 kemenangan, metrik galat Anda adalah 5.
Model pertama yang akan Anda latih adalah model regresi linear. Anda dapat mengimpor
LinearRegressiondanmean_absolute_errormasing-masing darisklearn.linear_modeldansklearn.metrics, lalu membuat modellr. Selanjutnya, Anda akan melakukan fitting pada model, membuat prediksi, dan menentukan mean absolute error dari model tersebut.Jika Anda ingat dari penjelasan di atas, rata-rata jumlah kemenangan adalah sekitar 79 kemenangan. Rata-rata, model meleset hanya sebesar 2,687 kemenangan.
Sekarang coba model regresi Ridge. Impor
RidgeCVdarisklearn.linear_modeldan buat modelrrm. ModelRidgeCVmemungkinkan Anda menyetel parameter alpha, yaitu parameter kompleksitas yang mengontrol besarnya shrinkage (baca selengkapnya di sini). Model ini akan menggunakan cross-validation untuk menentukan parameter alpha mana yang paling ideal dari yang Anda sediakan.Sekali lagi, lakukan fitting pada model Anda, buat prediksi, dan tentukan mean absolute error-nya.
Model ini berkinerja sedikit lebih baik, dengan rata-rata meleset sebesar 2,673 kemenangan.
Analitik Olahraga & Scikit-Learn
Bagian pertama dari seri tutorial ini berakhir di sini, di mana Anda telah melihat bagaimana menggunakan scikit-Learn untuk menganalisis data olahraga. Anda mengimpor data dari basis data SQLite, membersihkannya, mengeksplorasi aspeknya secara visual, dan merekayasa sejumlah fitur baru. Anda mempelajari cara membuat model klastering K-means, beberapa model Regresi Linear, dan cara menguji prediksi menggunakan metrik mean absolute error.
Pada bagian kedua, Anda akan melihat cara menggunakan model klasifikasi untuk memprediksi pemain mana yang masuk ke MLB Hall of Fame.