Yapay Sinir Ağları ile Ev Fiyat Tahmini

Bugünkü yazımızda en son gerçekleştirdiğimiz iris projesine nazaran regresyon problemi üzerinde çalışacağız. Bu yazımıza devam etmeden önce eğer okumadıysanız o yazımızı okumanızı öneririm. Bu projemizde kullanacağımız veri seti Boston’da bulunan evler ile ilgili bilgileri içeriyor. Veri setine https://www.kaggle.com/vikrishnan/boston-house-prices üzerinden erişebilirsiniz.

Veri setimiz hakkında biraz bilgi verecek olursak, veri setimiz Boston’ da bulunan evlerin havadaki nitrik oksit oranı, suç oranları, çevre mahallelerdeki öğrenci öğretmen oranı, vergi değerleri, konut başına ortalama oda sayısı gibi toplamda 13 adet özelliğini içeriyor. Bu özelliklerin sonucunda da evlerin fiyat bilgileri bulunuyor. Bu veri setinin bizim için güzel yanı hiçbir kategorik veri barındırmayıp tamamen sayısal verilerden oluşmasıdır. Bu durum bizim işimizi veri önişleme kısmında oldukça kolaylaştırıyor. Projemizi veri önişleme, modelin yapısını oluşturma, eğitim ve performans ölçümü olacak şekilde dört başlık altında gerçekleştireceğiz.

Veri Önişleme

İşe Kaggle üzerinden indirdiğimiz dosyanın içerisinde bulunan “housing.csv” dosyasını çalışma yapacağımız klasörün içine atmakla başlıyoruz. İlk olarak gerekli kütüphaneleri import ediyoruz. Ardından verilerimizin okuma işlemini gerçekleştiriyoruz. Bu dosyada verilerimizin her bir özelliği boşluk ile ayrıldığı için ona göre bir okuma gerçekleştiriyoruz ve sonrasında bağımsız değişkenlerimizi(X) ve bağımlı değişkenlerimizi(Y) ayırıyoruz.

import pandas as pd
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score

# Verilerimizi okuyoruz.
dataset = pd.read_csv("housing.csv",delim_whitespace=True)

# Bağımlı değişkenleri ve bağımsız değişkenleri ayırıyoruz.
X = dataset.iloc[:,0:13]
Y = dataset.iloc[:,13]

“variable explorer” kısmından veri setimizi inceleyebilirsiniz. Veri setimizde 505 adet örnek bulunmaktadır.

yapay sinir ağları
Veri Seti

Daha sonra öğrenme işlemini daha kolaylaştırmak adına verilerimiz üzerinde ölçeklendirme işlemi gerçekleştiriyoruz. Bunun nedeninin bir önceki “İris Veri Seti Projesi” adlı yazımızda daha detaylı bir şekilde açıklıyoruz. Ardından verilerimizin %80’ini eğitim ve kalan %20’sinin de test için ayırarak veri önişleme kısmını tamamlıyoruz.

# Ölçeklendirme işlemi
scaler = preprocessing.StandardScaler()
X = scaler.fit_transform(X)

# Eğitim ve test kümesi olarak ayırıyoruz.
x_train, x_test, y_train, y_test = train_test_split(X,Y,test_size=0.2,random_state=2)

Yapay Sinir Ağı Modelini Oluşturma

Bağımsız değişken sayımız 13 adet olduğu için girdi katmanımızda 13 tane nöron bulunacak. Girdi katmanımız 8 nöronlu 1. gizli katmana bağlanacak, 1. gizli katmanımız 8 nöronlu 2. gizli katmanına bağlanacak ardından 2. gizli katmanımız 4 nöronlu 3. gizli katmana bağlanacak. Gizli katmanlarımızın her birinde “ReLU” aktivasyon fonksiyonunu kullanacağız. Son olarak 3. gizli katmanımız tek nöronlu çıktı katmanına bağlanacak. Çıktı katmanımızda regresyon problemi ile ilgilendiğimiz için aktivasyon fonksiyonu kullanmayacağız. Modelimiz 3 veya daha fazla gizli katman barındırdığı için modelimizi derin öğrenme algoritması olarak sınıflandırabiliriz. Aşağıdaki görselde oluşturacağımız modelin yapısını inceleyebilirsiniz.

yapay sinir ağları
Model Yapısı

Öncelikle bağımsız değişken sayılarımızı ve çıktı katmanımızın nöron sayılarını belirliyoruz. Daha sonra modelimizin yapısını oluşturuyoruz ve “summary” fonksiyonu ile konsola modelimizin özetini bastırıyoruz.

# Girdi katmanının nöron sayısı
input_num = x_train.shape[1]
# Çıktı katmanının nöron sayısı
output_num = 1

# Modelin yapısını oluşturma
model = Sequential()
    
model.add(Dense(8,input_dim = input_num,activation = 'relu'))
model.add(Dense(8,activation = 'relu'))
model.add(Dense(4,activation = 'relu'))
model.add(Dense(output_num))

model.summary()
yapay sinir ağları
Model Özeti

Modelimizde toplamda 225 adet parametre bulunuyor. Bunlardan 204 tanesi nöronların ağırlık değerleri, kalan 21 tanesi de nöronların eşik değerleridir.

Modelin Eğitimi

Modelimizi eğitirken kullanacağımız optimizasyon tekniği olarak “adam” tekniğini seçiyoruz. Bu optimizasyon tekniği gradyan inişin daha gelişmiş versiyonudur. İlerleyen yazılarımızda daha detaylı bir şekilde adam optimizasyon tekniğine değinebiliriz. Yitim fonksiyonu olarak da regresyon problemlerine uygun olan ortalama kare hatasını seçiyoruz. Modelimizi 500 yineleme boyunca eğitiyoruz ve eğitimi sırasında ise validation_data olarak test verilerimizi veriyoruz ki öğrenme sırasında modelimizin eğitim ve test kümelerindeki performansını karşılaştırıp olası bir aşırı öğrenme(overfitting) veya az öğrenme(underfitting) gibi durumlar ile karşılaşıp karşılaşmadığımızı gözlemleyebilelim.

model.compile(optimizer='adam',loss='mse')
history = model.fit(x_train,y_train,batch_size=16,validation_data=(x_test,y_test),epochs=500)

Modelimizin eğitim ve test kümelerindeki yitim değerlerini grafiğe dökelim.

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])

plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epochs')

plt.legend(['train', 'test'], loc='upper right')
plt.show()

Yukardaki kodu çalıştırdığımızda elde edeceğimiz grafik aşağıdaki gibi olacaktır.

yapay sinir ağları
Yitim Değerleri

Yukarıdaki büyüteç yardımı ile resmi yakınlaştırırsak daha iyi inceleyebiliriz.

yapay sinir ağları
Yakınlaştırılmış Yitim Değerleri

Görüldüğü gibi 150. yineleme civarları modelimizin test verisindeki performansı düşüyor yani test yitim değerleri artışa geçiyor. Bu durum aşırı öğrenmenin göstergesidir. Her ne kadar eğitim yitim değerleri düşmeye devam etse de aşırı öğrenmeye engel olmak için modelimizin eğitimini 150. yinelemede durdurmalıydık. Artık durdurma seçeneğimiz olmadığı için modelimizi baştan 150 yineleme boyunca eğitmek yeterli olacaktır. “fit” fonksiyonundaki epochs parametresini 500 den 150 ye çevirerek model.Sequential()’ dan itibaren kodu baştan çalıştırmalıyız çünkü modelimizin ağırlık değerleri en son haliyle kaldığı için bunu sıfırlamalıyız. Eğer sadece fit fonksiyonunu değiştirip kodu oradan çalıştırırsak modelimiz 500 yinelemenin üstüne 150 yineleme daha eğitilir ve toplamda 650 yineleme eğitilmiş olur. Modelimizi baştan 150 yineleme boyunca eğittikten sonra eğitim ve test kümelerindeki yitim değerleri aşağıdaki gibi olacaktır.

yapay sinir ağları
150 Yineleme Yitim Değerleri

Görüldüğü gibi test yitim değerlerinin artışına izin vermeyip aşırı öğrenmenin önüne geçiyoruz.

Performans Ölçümü

Bu bölümde modelimizin eğitim ve test kümelerindeki performanslarını inceleyeceğiz. Performans metrikleri arasından regresyon problemleri için uygun olan R2 skorunu kullanacağız. Modelimizin “predict” fonksiyonu ile her bir örnek için tahmin değerlerini elde edip R2 skorlarını eğitim ve test için hesaplıyoruz.

train_preds = model.predict(x_train)
print("Eğitim R2 Skoru : ",r2_score(y_train,train_preds))

test_preds = model.predict(x_test)
print("Test R2 Skoru : ",r2_score(y_test,test_preds))

Yukarıdaki kodu çalıştırdığımızda aldığımız değer aşağıdaki gibi olacaktır.

yapay sinir ağları
R2 Skorları

R2 skorlarına baktığımızda modelimizin iyi bir performans gösterdiğini görebiliriz. Aynı zamanda eğitim ve test verilerindeki başarı değerlerinin birbirine yakın olması aşırı öğrenmenin önüne geçtiğimizi de gösteren 2. bir kanıt.

Yazdığımız bütün kodu tek parça halinde aşağıda bulabilirsiniz. Sizin de farklı model yapıları oluşturup daha iyi bir performans elde etmeye çalışmanızı öneririm.

import pandas as pd
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Dense 
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score

dataset = pd.read_csv("housing.csv",delim_whitespace=True)

X = dataset.iloc[:,0:13]
Y = dataset.iloc[:,13]

scaler = preprocessing.StandardScaler()
X = scaler.fit_transform(X)

x_train, x_test, y_train, y_test = train_test_split(X,Y,test_size=0.2,random_state=2)

input_num = x_train.shape[1]
output_num = 1

model = Sequential()
    
model.add(Dense(8,input_dim = input_num,activation = 'relu'))
model.add(Dense(8,activation = 'relu'))
model.add(Dense(4,activation = 'relu'))
model.add(Dense(output_num))

model.summary()


model.compile(optimizer='adam',loss='mse')
history = model.fit(x_train,y_train,batch_size=16,validation_data=(x_test,y_test),epochs=150)


plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])

plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epochs')

plt.legend(['train', 'test'], loc='upper right')
plt.show()


train_preds = model.predict(x_train)
print("Eğitim R2 Skoru : ",r2_score(y_train,train_preds))

test_preds = model.predict(x_test)
print("Test R2 Skoru : ",r2_score(y_test,test_preds))