LightGBM ile Merhaba Dünya
Karar ağacı tabanlı makine öğrenmesi algoritmalarının Kaggle yarışmalarını domine ettiği bir gerçek. Kazanan çözümlerin yarısından fazlası XGBoost algoritmasını benimsemiş durumda. Microsoft da kendi gradient boosting altyapısı olan LightGBM‘in duyurusunu geçtiğimiz yıl yapmıştı. LightGBM’ şu günlerde tüm ilgiyi üzerine çekmiş durumda. Kaggle yarışmacıları LightGBM’i XGBoost’tan daha fazla kullanmaya başlaması bunun bir göstergesi. Araştırmalar XGBoost ile (biraz) daha iyi sonuçlar üretildiğini gösterse de LightGBM kısa bir süre öncesine kadar 10 kat, şu an ise 6 kat daha hızlı çalışmakta. Kaggle türevi yarışmalarda da nitelik mühendisliği ve yüzlerce model ile deneme yapma ihtiyacı hızı başarıdan daha önemli kılmakta. Şimdiden onlarca LightGBM ile oluşturulmuş model kaggle yarışmalarında podyuma çıkmış durumda.
pip install lightgbm komutunu çalıştırarak paketi yükledikten sonra altyapıyı kullanabiliyorsunuz. Sonrasında python kodunuzda ilgili kütüphaneyi şu şekilde referans göstermeniz gerekiyor.
1 2 3 4 5 |
import lightgbm as lgb |
Veri seti
Veri madenciliği derslerinden sıklıkla alışkın olduğunuz hava durumu, sıcaklık, nem ve rüzgar niteliklerine istinaden golf oynama kararlarının verildiği veri seti üzerinde çalışacağız. Veri setine buradan erişebilirsiniz. Bu veri setini seçtim çünkü hem nümerik hem de metin niteliklerini içeriyor. Karar sütunu niteliklere göre kurallarını çıkarmak istediğim hedef sütunu. Veri setini pandas ile yüklemem ileriki adımlarda kolon bazlı işlemleri daha kolay yapmamı sağlayacak.
1 2 3 4 5 6 7 |
import pandas as pd dataset = pd.read_csv('golf2.txt') dataset.head() |
Veri setim pandas’ın data frame formatında saklanacak. Data frame’in head fonksiyonu ile veri setinin ilk 5 satırını görüntüleyebilirim.
Outlook | Temp. | Humidity | Wind | Decision | |
0 | Sunny | 85 | 85 | Weak | No |
1 | Sunny | 80 | 90 | Strong | No |
2 | Overcast | 83 | 78 | Weak | Yes |
3 | Rain | 70 | 96 | Weak | Yes |
4 | Rain | 68 | 80 | Weak | Yes |
Etiketlerin kodlanması
LightGBM, kategorik yani metinsel niteliklerin tam sayıya dönüştürülmesini beklemekte. Burada sıcaklık ve nem sütunları zaten sayı halindeler. Fakat hava durumu ve rüzgar sütunları kategorik halde, bu sütunları dönüştürmeliyiz. Dönüşüm için scikit-learn kütüphanesinin dönüştürücüsünü kullanacağım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from sklearn import preprocessing le = preprocessing.LabelEncoder() features = []; categorical_features = [] num_of_columns = dataset.shape[1] for i in range(0, num_of_columns): column_name = dataset.columns[i] column_type = dataset[column_name].dtypes if i != num_of_columns - 1: #skip target features.append(column_name) if column_type == 'object': le.fit(dataset[column_name]) feature_classes = list(le.classes_) encoded_feature = le.transform(dataset[column_name]) dataset[column_name] = pd.DataFrame(encoded_feature) if i != num_of_columns - 1: #skip target categorical_features.append(column_name) if is_regression == False and i == num_of_columns - 1: num_of_classes = len(feature_classes) |
Her ne kadar kategorik nitelikler tam sayıya dönüştürülse de kategorik olanları belirtmemiz gerekecek. Bu sebeple yukarıdaki kod bloğunda nitelikleri (features) ve kategorik nitelikleri (categorical_features) ayrı değişkenlerde tuttum.
Veri setini tekrar görüntüleyelim.
1 2 3 4 5 |
dataset.head() |
Outlook | Temp. | Humidity | Wind | Decision | |
0 | 2 | 85 | 85 | 1 | 0 |
1 | 2 | 80 | 90 | 0 | 0 |
2 | 0 | 83 | 78 | 1 | 1 |
3 | 1 | 70 | 96 | 1 | 1 |
4 | 1 | 68 | 80 | 1 | 1 |
Böylelikle veri seti son formuna dönüştürülmüş oldu. Şimdi de LightGBM’e beslemek için girdi niteliklerini ve çıktı etiketlerini ayırmamız gerekiyor. Son durumda bunları aşağıdaki değişkenlerde numpy dizisi olarak saklıyorum.
1 2 3 4 5 6 |
y_train = dataset['Decision'].values x_train = dataset.drop(columns=['Decision']).values |
Kategorik niteklerin belirtilmesi
String niteliklerin integer’a dönüşümünü önceki adımlarda yaptığımızı hatırlarsınız. Şimdi bu niteliklerin kategorik olduklarını ayrıca belirteceğiz. Her ne kadar belirtilmediği durumda da çalışsa da, komplikasyonlara neden olabilmekte. Sayısal nitelikler için karar ağaçları bir eşik değerden büyük ya da küçük olduğu kontrolünü uygulamakta. Örneğin cinsiyet bilgisini ele alalım. Bilinmeyen cinsiyetler için 0, erkekler için 1, kadınlar için de 2 değerini atadığımızı varsayalım. Karar ağacı bir noktada cinsiyet sıfırdan büyük mü değil mi şeklinde bir kontrol uygulayabilir. Bu da anlamlı cinsiyet bilgisini kaybetmemiz anlamına gelmektedir. Niteliğin kategorik olduğunun belirtilmesi 0, 1 ve 2 için ayrı dallar oluşturulmasını sağlayacağından bu handikaptan kurtulmuş oluyoruz.
1 2 3 4 5 6 7 8 |
lgb_train = lgb.Dataset(x_train, y_train ,feature_name = features , categorical_feature = categorical_features ) |
Eğitim
Problemi hem regresyon hem de sınıflandırma olarak modelleyebiliriz. Temelde objektif ve metrik parametrelerinde değişiklik yapmak yetecektir. Parametre seti ve LightGBM için oluşturduğum eğitim setinin geçilmesi eğitimi başlatacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
params = { 'task': 'train' , 'boosting_type': 'gbdt' , 'objective': 'regression' if is_regression == True else 'multiclass' , 'num_class': num_of_classes , 'metric': 'rmsle' if is_regression == True else 'multi_logloss' , 'min_data': 1 , 'verbose': -1 } gbm = lgb.train(params, lgb_train, num_boost_round=50) |
Tahminleme
Bir önceki adımda makine öğrenmesi modelimizin eğitimini gerçekleştirmiş ve gbm değişkeninde saklamıştık. Yeni bir örnekleme ait kararı bu değişkene artık sorabiliriz. Kısıtlı bir veri kümesi üzerinde çalıştığımız için eğitim setinin kararlarını doğrudan sormayı tercih ediyorum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
predictions = gbm.predict(x_train) for index, instance in dataset.iterrows(): actual = instance[target_name] if is_regression == True: prediction = round(predictions[index]) else: #classification prediction = np.argmax(predictions[index]) print((index+1),". actual= ",actual,", prediction= ",prediction) |
Bu kod bloğu eğitim setimiz için aşağıdaki tahminleri yapıyor. Görüldüğü gibi tüm örneklemler doğrulukla tahmin edilebilmiş.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
actual= 0 , prediction= 0 actual= 0 , prediction= 0 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 0 , prediction= 0 actual= 1 , prediction= 1 actual= 0 , prediction= 0 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 1 , prediction= 1 actual= 0 , prediction= 0 |
Görselleştirme
Sinir ağları gibi algoritmaların aksine karar ağacı algoritmaları okuyabildiğimiz ve anlayabildiğimiz kural setlerinden oluşmakta. LightGBM ile oluşturulan karar ağacını ve niteliklerin önemini kolaylıkla görselleştirebiliyoruz.
Bunun için öncelikle Graph Visualization Software’in kurulumunu gerçekleştirmemiz gerekmekte. İlk olarak pip install graphviz komutunu çalıştırarak python paketinin kurulumunu gerçekleştireceğiz. Sonrasında bu linkten işletim sisteminiz ile ilişkili programın kurulumunu da yapmanız gerekiyor. Kodumuzda kurulumu yaptığımız dizini aşağıdaki gibi gösterebiliyoruz.
1 2 3 4 5 6 7 |
import matplotlib.pyplot as plt import os os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin' |
Sonrasında ağacı kolayca çiziyoruz.
1 2 3 4 5 6 7 8 9 |
ax = lgb.plot_importance(gbm, max_num_features=10) plt.show() ax = lgb.plot_tree(gbm) plt.show() |
Karar kuralları aşağıdaki ağaçtan kolaylıkla okunabilir.
Ayrıca veri setindeki niteliklerin önemine de artık hakimiz.
Bu yazımızda Microsoft’un bir çok makine öğrenmesi araştırmacısının benimsediği LightGBM altyapısını inceledik. Alternatifleri ile kıyaslandığında artılarını ve eksilerine de değinmiş olduk. Bunlarla birlikte bir “Merhaba Dünya” modelini LightGBM ile geliştirdik. Son olarak, yazı sırasında paylaştığım kod bloklarının tamamını içeren not defterini GitHub’ta paylaştım.
Bu yazı A Gentle Introduction to LightGBM for Applied Machine Learning yazısından Türkçe’ye çevrilmiştir.