Ekonomi ve Veri Bilimi
- Murat Özel
- 4 gün önce
- 4 dakikada okunur
Makine öğrenmesi artık sağlıktan finansa, mühendislikten ekonomiye kadar epey geniş bir alana yayılmış durumda; geçmiş verilerden yola çıkarak geleceğe dair tahminler üretmek neredeyse standart bir yaklaşım haline geldi. Aslında mantık çok karmaşık değil: elimizde yeterince veri varsa ve bu veri geçmişte gerçekleşmiş olayları yansıtıyorsa, benzer koşullar altında ileride ne olabileceğini kestirmek istatistiksel olarak mümkün. Regresyon problemleri de bu işin en yaygın örneklerinden biri sonuç değişkeni kategorik değil de sürekli olduğunda (fiyat, sıcaklık, gelir gibi) devreye giren yaklaşım bu.
Konut fiyatı tahmini ise bunun belki de en klasik uygulamalarından. Hem anlaşılması kolay hem de gerçek hayatta işe yarayan bir problem olduğu için literatürde de sık sık karşımıza çikiyor. Emlak sektöründeki fiyatlandırma kararlarından bankacılıktaki kredi risk analizlerine, hatta şehir planlamasına kadar birçok yerde bu tarz modeller kullanılıyor. Ben de bu çalışmada klasik ama öğretici bir problem üzerinden hem veri ön işleme hem de güncel optimizasyon tekniklerini bir arada denemek istedim.
Çalışmada California Housing veri setini kullandım. 1990 ABD nüfus sayımından derlenmiş bu veri seti, California eyaletindeki farklı bölgelerin konut özelliklerini içeriyor: bölgenin medyan geliri, toplam oda sayısı, yatak odası sayısı, nüfus, hane sayısı, coğrafi konum (enlem- boylam) ve okyanusa yakınlık gibi değişkenler mevcut. Amacım bu değişkenlerden yola çıkarak evlerin medyan satış fiyatını olabildiğince az hatayla tahmin edebilmekti.
Veriyi ilk incelediğimde dikkatimi çeken birkaç şey oldu. Örneğin toplam oda ve yatak odası sayıları bölge bazında toplu verilmis, yanı tek başlarına pek bir şey ifade etmiyorlar. Bir bölgede s000 oda olması, orası kalabalıksa gayet normal ama az hane varsa dikkat çekici bir durum. Bu yüzden ham değişkenleri olduğu gibi modele vermek yerine aralarındakı oranları çıkarmanın daha mantıklı olacağını düşündüm; bu konuya birazdan feature engineering kısmında tekrar döneceğim.
Model olarak XGBoost Regressor'ı seçtim. Mantığı aslında oldukça sezgisel: birçok karar ağacını art arda ekleyip her yeni ağacın bir öncekinin hatasını azaltmaya çalışması üzerine kurulu. Model, iterasyon ilerledikçe kendi hatalarından öğrenerek gelişiyor diyebiliriz. Bu yaklaşıma “gradient boosting” deniyor, ismini de her adımda kayıp fonksiyonunun gradyanı yönünde ilerlenmesinden alıyor.
Matematiksel olarak nihai tahmini şöyle özetleyebiliriz: y_tahmin = f1(X) + f2(x) + £3(x) +... + f(x) = 2(k=1 to K) fk(x)
Burada her fk(x) modele eklenen bir karar ağacını temsil ediyor, K ise toplam ağaç sayısını (n_estimators parametresi) ifade ediyor. Model ağaçları teker teker ekliyor; her yeni ağaç, o ana kadarki tahminlerin gerçek değerlerden ne kadar saptığını, yanı kalıntı hatayı (residual) azaltmaya çalışıyor.
XGBoost'u diğer gradient boosting yöntemlerinden ayıran önemli noktalardan biri, optimize ettiği amaç fonksiyonuna bir regularizasyon terimi eklemiş olması. Amaç fonksiyonu genel olarak şöyle yazılabılır: Obj = 2(i=1 to n) L(y_i, Yi) + >(ks1 to K) O(fk)
L burada tahmin ile gerçek değer arasındaki kaybı ölçen fonksiyon (regresyonda genelde kare hata), (fk) ise her ağacın karmaşıklığını cezalandıran regularizasyon terimi. Bu terim kabaca şöyle tanımlanıyor: O(f) = yT + (1/2)A2w_j*
T agactaki yaprak sayısı, w_j her yaprağın verdiği tahmin değeri, y ve A ise sırasıyla yaprak sayısını ve yaprak ağırlıklarını cezalandıran katsayılar. Bu regularizasyon sayesinde model gereksiz yere karmaşık ağaçlar kurup eğitim verisini ezberlemek yerıne, daha sade ve genellenebilir yapılar öğrenmeye yöneliyor — pratikte bunun karşılığı genelde overfitting’in azalması oluyor.
Sadece elimdeki değişkenlerle yetinmedim, biraz feature engineering de denedim; çünkü ham değişkenlerin çoğu tek başına pek anlamlı bilgi taşımıyordu. Şu yeni değişkenleri türettim:
Toplam oda sayısını hane sayısına bölerek ”Rooms Per Household” (hane başına oda sayısı)
Yatak odası sayısını toplam oda sayısına bölerek ” Bedrooms Per Room” (odaların ne kadarının yatak odası olduğu) Nüfusu hane sayısına bölerek ”Population Per Household” (hane başına düşen kişi sayısı, kalabalıklık göstergesi)
Bunun yanında medyan gelirin karesini alarak (income”) gelir ile ev fiyatı arasındakı doğrusal olmayan ılişkiyi modele biraz daha iyi yansıtmayı hedefledim. Nitekim gerçek hayatta da gelir arttıkça ev fiyatlarındaki artış doğrusal ilerlemiyor, belli bir noktadan sonra hızlanan bir eğilim var; yüksek gelirli bölgelerde fiyat farkları orantısız biçimde büyüyor. Karesini almak, ağaç tabanlı bir modelde bile bu ılışkiyi biraz daha belirgin hale getiriyor, çünkü model bölünme noktalarını ararken bu dönüştürülmüş değişken üzerinden daha net ayrımlar yapabiliyor.
Kod üzerinde yaptığım denemelerde bu ek değişkenlerin modelin veri içindeki örüntüleri yakalamasına gerçekten katkı sağladığını gördüm. Değişkenleri çıkarıp geri eklediğimde RMSE’de gözle görülür bir fark oluştuğunu fark ettim.
XGBoost'un performansı hiperparametrelere epey duyarlı olduğu icin parametreleri elle deneme yanilmayla ayarlamak yerıne Optuna kullandım. Optuna, belirlediğiniz aralıklar içinde farklı kombinasyonları deneyip en düşük hatayı veren ayarı bulan bir optimizasyon kütüphanesi. Grid search gibi kaba kuvvetle her kombinasyonu denemek yerine, Optuna varsayılan olarak [ree-structured Parzen Estimator (TPE) adı verilen Bayesyen bir yaklaşım kullanıyor.
TPE’nin mantığını kabaca şöyle özetleyebilirim: algoritma denenen her hiperparametre kombinasyonunu ve elde edilen sonucu (bu çalışmada RMSE) bir eşik değere göre “iyi” ve “kötü” olarak ikiye ayırıyor, sonra bu iki grubun olasılık dağılımlarını ayrı ayrı modelliyor:
I(x) = p(x | y < y*) > iyı sonuç veren kombinasyonların dağılımı g(x) = p(x | y > y*) > kötü sonuç veren kombinasyonlarin dağılımı Bir sonrakı denemede 1(x)/g(x) oranını maksımıze eden bölgeden yeni parametreler örnekleniyor. Bir başka ifadeyle algoritma, Iyı sonuç veren bölgelere benzeyen ama kötü sonuç veren bölgelerden uzak noktaları tercih ederek arama uzayını akıllıca daraltıyor. Bu sayede rastgele aramaya kıyasla çok daha az denemeyle iyı sonuçlara ulaşmak mümkün oluyor.
200 deneme çalıştırdım ve her denemeyı cross validation ile değerlendirdim; böylece modelin sadece eğitim verisini ezberlemediginden, görmediği verilerde de tutarlı sonuç verdiğinden emin olmaya çalıştım. Optimize ettiğim parametreler arasında max_depth, learning_rate, n_estimators, subsample, colsample_bytree, min_child_weight ve gamma gibi modelin öğrenme sürecin ve ağaç yapısını etkileyen hiperparametreler yer alıyordu.
Performans metrigi olarak RMSE (Root Mean Squared Error) kullandım:
RMSE - / ((1/n): XÇizi to n) (y_gercek,i — y_tahmin,i)*)
n toplam örnek sayısı, y. gerçek gerçek fiyat, y_tahmin ise modelin tahmin ettiği fiyat. RMSE ne kadar düşükse model o kadar Iyı tahmin yapıyor demek. RMSE’yi tercih etmemin bir nedeni de hataları kare alarak hesaplaması; büyük hatalar bu sayede orantısız şekilde cezalandırılıyor, ki fiyat tahmini gibi büyük sapmaların özellikle istenmediği bir problemde bu mantıklı bir tercih.
Tum bu adımların ardından test setinde 2.01 RMSE değerine ulaştım. Bu sonuç beni oldukça memnun etti, çünkü hem feature engineering hem de Optuna ile yapılan hiperparametre optimizasyonunun modele ciddi katkı sağladığını gösteriyor. İlk denemelerde dikkatımı çeken nokta, özellikle gelirin karesini eklemenin ve oda/hane oranlarını türetmenin RMSE’yi belirgin şekilde düşürmesiydi. Optuna'nın bulduğu en iyi parametre setiyle varsayılan parametreleri kıyasladığımda da aradakı farkın küçümsenmeyecek boyutta olduğunu söyleyebilirim.
Sonuç olarak, doğru veri ön işleme, akıllı feature engineering ve sistematik hiperparametre optimizasyonu bir araya geldiğinde XGBoost gibi güçlü bir algoritmanın regresyon problemlerinde ne kadar iyi çalışabıldığını bir kez daha görmüş oldum. 2.01’lik RMSE değerinin bu veri seti için gayet makul bir sonuç olduğunu düşünüyorum; elbette farklı özellik kombinasyonları veya farklı modellerle daha da iyi sonuçlar elde edilebilir, bu çalışmayı kesin bir son nokta olarak değil, deneme sürecinde ulaştığım bir aşama olarak görüyorum.



Yorumlar