Titanic Verisi ile No Free Lunch Teoremi ve Algoritmaların Kaggle’daki Başarısı
No Free Lunch Teoremi kısaca Makine Öğrenmesi algoritmalarının birbirlerine üstün olmadıklarını belirtir. Bir iş probleminin çözümü, kullanılan algoritmaya bağlı değildir veri setine bağlıdır!
Bu uygulamada herkesin nefret ettiği Titanic verisi ile sadece algoritmaların varsayılan hiperparametrelerini kullanarak tahmin değerleri üreteceğim ve her bir algoritmanın çıktılarını (submission) Kaggle’a yükleyeceğim ve ardından Kaggle’daki skorlarımı sizler ile paylaşacağım.
İlerideki zamanlarda bu çalışmayı genişletmeyi planlıyorum. Her bir algoritma için Öznitelik Mühendisliği (Feature Engineering) ve Hiperparametre Ayarlamaları (Hyperparameter Tuning) yaparak model performanslarını arttırmaya çalışabilirim ve bu işlemler sonucunda da Kaggle’daki skorumun ne kadar değiştiğini görebiliriz.
Bu çalışma içerisinde Lojistik Regresyon, Naive Bayes, KNN – En Yakın Komşu, SVC – Karar Destek Sınıflandırıcı, CART – Sınıflandırma ve Regresyon Ağaçları, Topluluk Öğrenme (Bagging, Voting, Random Forest), Boosting (Ada Boost, GBM – Gradient Boosting Machine, XGBoost, LightGBM, CatBoost) algoritmaları kullanılmıştır ve en sonunda her bir modelin başarı oranları karşılaştırılmıştır. Ayrıca vakit buldukça yeni ve farklı algoritmaları da buraya ekleyeceğim.
1. Kütühaneler
# Base import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt ########## Sklearn ############# # Ön İşleme from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import train_test_split # Metrikler from sklearn.metrics import confusion_matrix, accuracy_score, classification_report from sklearn.metrics import roc_auc_score, roc_curve # Modeller from sklearn.linear_model import LogisticRegression # Lojistik Regresyon from sklearn.naive_bayes import GaussianNB # Naive Bayes from sklearn.neighbors import KNeighborsClassifier # KNN - En Yakın Komşu from sklearn.svm import SVC # SVC - Karar Destek Sınıflandırıcı from sklearn import tree # CART - Sınıflandırma ve Regresyon Ağaçları from sklearn.tree import DecisionTreeClassifier # CART - Sınıflandırma ve Regresyon Ağaçları from sklearn.ensemble import BaggingClassifier # Bagging from sklearn.ensemble import VotingClassifier # Voting from sklearn.ensemble import RandomForestClassifier # Random Forest from sklearn.ensemble import AdaBoostClassifier # Ada Boost from sklearn.ensemble import GradientBoostingClassifier # GBM - Gradient Boosting Machine from xgboost import XGBClassifier # XGBoost | !pip install xgboost from lightgbm import LGBMClassifier # LightGBM | !conda install -c conda-forge lightgbm from catboost import CatBoostClassifier # CatBoost | !pip install catboost # Warnings import warnings warnings.filterwarnings("ignore")
2. Veri
Kaggle’dan alınan Titanic verisi Train ve Test setleri olmak üzere iki tanedir.
train = pd.read_csv("train.csv") test = pd.read_csv("test.csv") tr = train.copy() ts = test.copy()
train.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th… | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
NOT: Bu çalışmada sadece ham Titanic verisinin algoritmalardaki başarısının nasıl olduğu gözlenecektir. Bu yüzden bir Keşifçi Veri Analizi (EDA) yapılmayacaktır. Başka bir çalışmada hem keşifçi veri analizi ve hem de öznitelik mühendisliği yapılarak modelin başarısı arttırılabilir.
3. Eksik Gözlemler
train.isnull().sum(), test.isnull().sum()
(PassengerId 0 Survived 0 Pclass 0 Name 0 Sex 0 Age 177 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 Embarked 2 dtype: int64, PassengerId 0 Pclass 0 Name 0 Sex 0 Age 86 SibSp 0 Parch 0 Ticket 0 Fare 1 Cabin 327 Embarked 0 dtype: int64)
Veride nümerik değişkenler eksik gözlem barındırdığından bu gözlemler için ortalama değerler atanır.
train["Age"] = np.where(train.Age.isnull(), train.Age.mean(), train.Age) test["Age"] = np.where(test.Age.isnull(), test.Age.mean(), test.Age) test["Fare"] = np.where(test.Fare.isnull(), test.Fare.mean(), test.Fare)
4. Makine Öğrenmesi Giriş
PassengerId ve Name değişkenleri çıkartılır. Name değişkeni daha sonrası için kullanılabilecek bir değişkendir fakat ilk basit modeller kurmak adına çıkartılabilir.
train.drop(["PassengerId", "Name"], axis = 1, inplace = True) test.drop(["PassengerId", "Name"], axis = 1, inplace = True)
4.1. Label Encoder
cat = train.select_dtypes(include=["object"]).columns for col in train[cat].columns: train[col] = train[col].astype(str) test[col] = test[col].astype(str) le = LabelEncoder() le.fit(list(train[col])+list(test[col])) train[col] = le.transform(train[col]) test[col] = le.transform(test[col])
Yazı tipinde olan kategorik verilerin sayısal hale dönüştürülmesi için Label Encoder kullanılır.
4.2. Train Test Split
Zaten titanic verisi train test olarak ayrılmış fakat burada modelin ne kadar iyi olduğunu ölçmek için train veri setini train test diye iki ayrı parçaya bölüyoruz.
X_train, X_test, y_train, y_test = train_test_split(train.drop("Survived", axis = 1), train.Survived, test_size = 0.20, random_state = 41)
4.3. Sınıflandırma Algoritmaları
Bu bölümde etiketli train verisi üzerinden veriyi ikiye parçalayarak ayrıca train test veri setleri oluşturmuştuk. Bunu yapmamızın amacı hangi modellerin daha iyi performans gösterdiğini bulmak.
# Logistic Regression log = LogisticRegression(solver = "liblinear") log.fit(X_train, y_train) y_pred_log = log.predict(X_test) # Naive Bayes nb = GaussianNB() nb.fit(X_train, y_train) y_pred_nb = nb.predict(X_test) # KNN knn = KNeighborsClassifier() # k (n_neighbors) sayısı ön tanımlı değeri 5'tir. knn.fit(X_train, y_train) y_pred_knn = knn.predict(X_test) # SVM - Linear svc = SVC(kernel = "linear", probability=True) svc.fit(X_train, y_train) y_pred_svc = svc.predict(X_test) # SVM - RBF svc_rbf = SVC(kernel = "rbf",probability=True) svc_rbf.fit(X_train, y_train) y_pred_svc_rbf = svc_rbf.predict(X_test) # CART cart = DecisionTreeClassifier() cart.fit(X_train, y_train) y_pred_cart = cart.predict(X_test) # BAGGING bag = BaggingClassifier() bag.fit(X_train, y_train) y_pred_bag = bag.predict(X_test) # VOTING clf1 = LogisticRegression(solver = "liblinear") clf2 = RandomForestClassifier() clf3 = GaussianNB() clf4 = KNeighborsClassifier() vote = VotingClassifier( estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)], voting='hard') vote.fit(X_train, y_train) y_pred_vote = vote.predict(X_test) # RANDOM FOREST rf = RandomForestClassifier() rf.fit(X_train, y_train) y_pred_rf = rf.predict(X_test) # ADABOOST ada = AdaBoostClassifier() ada.fit(X_train, y_train) y_pred_ada = ada.predict(X_test) # GBM gbm = GradientBoostingClassifier() gbm.fit(X_train, y_train) y_pred_gbm = gbm.predict(X_test) # XGBOOST xgb = XGBClassifier() xgb.fit(X_train, y_train) y_pred_xgb = xgb.predict(X_test) # LGBM lgb = LGBMClassifier() lgb.fit(X_train, y_train) y_pred_lgb = lgb.predict(X_test) # CATBOOST cat = CatBoostClassifier() cat.fit(train.drop("Survived",axis = 1), train.Survived, verbose = 0) y_pred_cat = cat.predict(X_test)
Model | Train Accuracy | Test Accuracy | |
---|---|---|---|
0 | Lojistik Regresyon | 0.806180 | 0.810056 |
1 | Naive Bayes | 0.769663 | 0.821229 |
2 | KNN | 0.787921 | 0.692737 |
3 | Lineer SVM | 0.792135 | 0.837989 |
4 | RBF SVM | 0.686798 | 0.675978 |
5 | CART | 0.998596 | 0.810056 |
6 | Bagging | 0.981742 | 0.843575 |
7 | Voting | 0.858146 | 0.849162 |
8 | Random Forest | 0.998596 | 0.882682 |
9 | AdaBoost | 0.846910 | 0.860335 |
10 | GBM | 0.914326 | 0.877095 |
11 | XGBoost | 0.896067 | 0.871508 |
12 | LightGBM | 0.984551 | 0.854749 |
13 | CatBoost | 0.962079 | 0.955307 |
Modellerin accuracy (isabet) oranı değerlerine bakıldığında train ve test ikilisi olarak en iyi sonucu veren algoritma CatBoost olarak karşımıza çıkmaktadır. Fakat çalışma içerisindeki bazı modellerde de denemeler yapılırsa iyi sonuçlar elde edilebilir. Örneğin CART, Bagging, Random Forest, GBM ve LGBM modellerinde train başarı oranı yüksek fakat test başarı oranı düşük.
Yukarıdaki çalışma hangi algoritmaların bu veride daha iyi sonuçlar verebileceğini anlamaya yöneliktir ve train verisi ayrıca train-test diye iki veri setine ayrılmıştır. Şimdi tüm train verisini eğiterek etiketli olmayan test verisindeki tahminler alınıp kaggle’a yüklenecektir ve ardından kaggle’daki başarı skorumuza bakacağız.
Ayrıca tahminlerimizi farklı threshold değerlerine göre yaparsak farklı sonuçlar da elde edebilmemiz mümkün. Burada ilk olarak lojistik regresyonun tahminlerini alacağız ve kaggle’a yükleyeceğiz ardından farklı threshold değerleri ile yeniden tahminler alarak kaggle’a yükleyeceğiz. Başarı oranımızın değişip değişmediğine bakacağız.
4.4. Lojistik Regresyon
log = LogisticRegression(solver = "liblinear") log.fit(X_train, y_train) y_predprob = log.predict_proba(X_test)[:,1] for k in np.arange(0,1.1, 0.1).round(1): y_pred = [1 if i > k else 0 for i in y_predprob] print("Threshold: "+str(k)+ " ", "|", "Accuracy: "+ str(accuracy_score(y_test, y_pred)))
Threshold: 0.0 | Accuracy: 0.4134078212290503 Threshold: 0.1 | Accuracy: 0.48044692737430167 Threshold: 0.2 | Accuracy: 0.7150837988826816 Threshold: 0.3 | Accuracy: 0.7821229050279329 Threshold: 0.4 | Accuracy: 0.8156424581005587 Threshold: 0.5 | Accuracy: 0.8100558659217877 Threshold: 0.6 | Accuracy: 0.8268156424581006 Threshold: 0.7 | Accuracy: 0.776536312849162 Threshold: 0.8 | Accuracy: 0.6983240223463687 Threshold: 0.9 | Accuracy: 0.6312849162011173 Threshold: 1.0 | Accuracy: 0.5865921787709497
Görüldüğü üzere farklı threshold değerlerine göre tahminler ayarlandığında başarı oranlarının yükselebildiği gözlemlenmektedir. En iyi threshold değeri ise 0.6’dır. Kaggle’a tahminlerimizi yollarken farklı threshold değerlerini denemek yarar sağlayabilir.
log = LogisticRegression(solver = "liblinear") log.fit(train.drop("Survived", axis = 1), train.Survived) ypred = log.predict_proba(test)[:,1] # En iyi threshold 0.6 idi ypred = [1 if i > 0.6 else 0 for i in ypred] ts["Survived"] = ypred submissionlog = ts[["PassengerId", "Survived"]] submissionlog.to_csv("submissionlog.csv",columns = ["PassengerId", "Survived"] , index = None)
Ham veri ile olan ilk modelimiz lojistik regresyonun kaggle’daki başarısı 0.78 olarak çıktı. Bu skor ile 16 bin kişi arasından 5 bin kişi olarak gözüküyorum. Şu an için sıralama hiç fena değil, biraz öznitelik mühendisliği (feature engineering) ve hiperparametre ayarlamaları (hyperparameter tuning) yaparak daha iyi modeller elde edebiliriz ve başarı oranı daha yukarılara çıkarılabilir. Kaggle’da Titanic verisinin doğru sonuçları olduğu için çok sayıda 1 skor elde edenler var 5155. sıralamada olmam bu durum göz önüne alındığında gayet iyi.
5. Model Sonuçları
Model | Kaggle Skoru | |
---|---|---|
0 | Bagging | 0.80382 |
1 | Lojistik Regresyon | 0.78468 |
2 | XGBoost | 0.77990 |
3 | Lineer SVM | 0.77511 |
4 | LightGBM | 0.77033 |
5 | GBM | 0.76555 |
6 | Voting | 0.76076 |
7 | CatBoost | 0.76076 |
8 | Random Forest | 0.74641 |
9 | AdaBoost | 0.74162 |
10 | Naive Bayes | 0.73205 |
11 | CART | 0.73205 |
12 | RBF SVM | 0.66985 |
13 | KNN | 0.63636 |
Tüm algoritmalarda varsayılan hiperparametreleri kullandık ve yukarıda 14 tane algoritmanın sonuçları paylaşılmıştır. Titanic veri setine göre en başarılı yöntem Bagging olarak karşımıza çıktı. İlk yaptığımız çalışmalarda hangi model daha başarılı diye baktığımızda CatBoost’un sonuçları daha tatmin edici iken günün sonunda Bagging modeli kaggle’da en yüksek skoru verdi. Model geliştirmelerine devam edilerek kaggle’daki skor daha yukarılara çıkartılabilir.
Bir sonraki yazılarda görüşmek üzere.
Hahaha 🙂
“Bu uygulamada herkesin nefret ettiği Titanic verisi ile sadece algoritmaların varsayılan hiperparametrelerini kullanarak tahmin değerleri üreteceğim ve her bir algoritmanın çıktılarını (submission) Kaggle’a yükleyeceğim ve ardından Kaggle’daki skorlarımı sizler ile paylaşacağım.”