R Üzerinde Çoklu Regresyon Bölüm 2: Ev Fiyatlarını Tahminleme

Regresyon ile alakalı ilk yazımda, çoklu doğrusal regresyon kullanarak film skorlarını tahminlemiştim. Bu yazıda ise yine çoklu regresyon kullanarak ev fiyatlarını tahminleyeceğim. Yazı boyunca nasıl bir yol izleyeceğimi anlatayım. Öncelikle, bir önceki yazı kadar regresyona dair temel bilgiler aktarmayacağım. Daha çok uygulama ağırlıklı bir yazı olacak ve teorik bilgileri biraz daha azaltmaya çalışacağım. Veri setini ve değişkenlerini tanıttıktan sonra ev fiyatlarını tahminlemek adına birden fazla model kuracağım ve bu modeller arasından en başarılısını seçerek tahminleme işlemini onunla yapacağım. Bir önceki yazıda böyle bir karşılaştırma yapmamıştık. Burada ise farklı modelleri karşılaştırma ve aralarından en başarılısını seçme bu yazının temel konusu olacak.

Yazıda kullanacağım veri setini buradan indirebilirsiniz.

Veri seti, evin ID’sinden başlamak üzere fiyatı, banyo sayısı, yatak odası sayısı, metrekare miktarı, kaç katlı olduğu, yapım yılı ve manzarası olup olmadığı gibi bilgiler içeriyor. Tüm bunları kullanmayacağım için hepsini açıklamıyorum. Zaten model kurdukça bunları göreceğiz. Çoklu regresyon modellerini tam olarak anlamak için, bilinmesi gereken birinci nokta değişken ve özellik arasındaki ilişki ve farklardır. Ben de uygulamaya geçmeden önce burayı teorik olarak anlatmak istiyorum. Basit regresyon modellerinde, bağımlı değişkeni tahmin etmek adına sadece bir bağımsız değişken kullanıldığını söylemiştim. Bir önceki yazımdaki çoklu regresyonda da gördük ki birden fazla değişken işin içine girdiğinde işler biraz daha karışıyor. Değişken derken kastettiğimiz nokta, aslında verisetimizde model içerisinde tahminleme yapmak için kullandığımız kolonlar diyebiliriz. Tabi veri seti doğru şekilde yapılandırılmışsa bu geçerlidir. Örneğin ev fiyatını metrekare büyüklüğünü ve yatak odası sayısını kullanarak tahminlemeye çalıştığımızı düşünelim. Burada metrekare büyüklüğü ve yatak odası bizim değişkenlerimizdir. Fakat ben bu regresyon modeline metrekare büyüklüğünün karesini veya küpünü de dahil edebilirim. İşte bu metrekare değişkeninden türettiğim bir özellik olur. Ya da metrekare büyüklüğü ve yatak odası sayısının karesini toplayarak bir özellik halinde modele dahil edebilirim. Bu da benim bağımsız değişkenlerden türettiğim bir başka özellik olacaktır. Değişken ve özellik arasındaki fark temelde budur. Özellikler, değişkenlerden türetilen ve modele giren farklı tahmincilerdir. Aynı normal değişkenlerde olduğu gibi, bunlar da model içerisinde bir regresyon katsayısına sahip olacak ve bununla ağırlandırılacaklar.

Başka bir senaryo daha düşünelim. Evin fiyatını metrekaresinden, metrekarenin 2 katının küpünden ve direkt karesinden tahminlemeye çalışıyor olalım. Bu noktada aslında elimizde bir değişken var fakat bu değişkenin farklı kombinasyonlarını özellik olarak modele sokuyoruz. Bu tarz regresyonlara da “Polinomik Regresyon” denir. Ben bu yazıda ev fiyatını tahminlemek adına polinomik modeller de dahil olmak üzere birden fazla model deneyeceğim ve aralarından en başarılısını tahminlemede kullanacağım. Yazı ilerledikçe bu aşamalar ile alakalı teorik kısımları anlatmaya da devam edeceğim.

İşe, ilgili kütüphaneleri yükleyerek başlayalım.

#Kütüphaneleri Yükleme
library(visreg)
library(ggplot2)

Daha sonra ise veri setini hazır edelim.

#Verisetini Yükleme
DATA <- read.csv("kc_house_data.csv", stringsAsFactors = FALSE)
head(DATA, 10)

Verisetinin ilk 10 satırı şu şekilde:

1

Üstte de bahsettiğim gibi değişkenler bu şekilde verisetinde yer alıyor. Bu arada veri setinde 21 bin civarı satır var. Modelleri kurmaya polinomik regresyondan başlayalım. Yukarıdaki örnekte olduğu gibi evin metrekaresini alalım ve bu değişkenden türeteceğimiz özellikler ile polinomik modeller kuralım. Daha açık olması adına şöyle anlatayım; metrekare değişkeninin kendisi de dahil olmak üzere yedinci kuvvetine kadar 7 farklı polinomik regresyon modeli kuralım. Bu modellerin en başarılısını, diğer çoklu regresyon modelleriyle yarışmak üzere polinomik model adayı olarak bir üst tura çıkaralım. En son aşamada ise polinomik model ve diğer çoklu modeller dahil olmak üzere tüm modeller arasından en iyisini seçelim.

Bunu yapabilmek adına, aslında bir çeşit döngüye ihtiyacımız var. Bu döngü metrekare değişkeninin kendisinden başlayarak yedinci kuvvetine kadar tüm özellikleri dahil ederek 7 farklı model kuracak. Yani yedinci dereceden polinomik regresyon modeline kadar gidecek. Bunu “poly” fonksiyonunun yardımıyla gerçekleştireceğiz. Bu fonksiyon polinomu üretirken, bildiğimiz lineer model fonksiyonuyla da modelleri kuracağız. En sonunda elimizde birinci dereceden başlamak üzere yedinci dereceye kadar 7 farklı model olacak ve biz bunların hepsinin başarısını test edeceğiz.

Başarı test etmek dendiğinde, akla önce bir başarı ölçütü gelmelidir. Bunun için de birden fazla alternatif bulunmaktadır fakat ben bu yazıda en çok kullanılanlardan biri olan RSS(Residual Sum of Squares) değerini kullanacağım. Bu değer kalıntıların karelerinin toplanmasıyla elde edilir ve bir başarı ölçütüdür. Regresyon modeli kurulurken bu değer minimize edilmeye çalışılır ve bu yönteme de “En Küçük Kareler” yöntemi denir. Bu durumda RSS, aslında gerçek değerler ve modelin tahmin ettiği değerlerin bir fonksiyonudur ve biz bu fonksiyonu minimize etmek istiyoruz. Bir fonksiyon minimize etmek söz konusu olduğunda, ortaya bir optimizasyon problemi çıkmış demektir. Aynı şekilde regresyon modellerinin “fitting” aşaması da bu optimizasyon problemi çözülerek gerçekleştirilir. Minimum RSS değerini bulmak adına elde bulunan çözümlerden biri RSS fonksiyonun türevini sıfıra eşitlemek böylece optimum noktayı bulmaktır. Buna kapalı çözüm de diyebiliriz. Fakat başka ve daha efektif bir çözüm ise “dereceli azalma” algoritmasıdır. Bu algoritma makine öğrenmesinde çok kullanılır ve hesaplama yükü açısından da etkilidir. Bu algoritma içerisinde yine türev kullanılır fakat birden fazla boyut söz konusu olduğunda türev yerine gradyan tercih edilir. Zaten gradyan da modele girecek olan değişkenlerin regresyon katsayılarının(ağırlıklarının) kısmi türevlerinden oluşan bir vektördür. Fonksiyonun minimum noktası bulunmaya çalışılırken keyfi ya da bilinçli olarak seçilmiş olan bir başlangıç noktasından başlanarak her seferinde gradyan’a bakılarak nokta belirlenmiş bir adım büyüklüğü kadar aşağı veya yukarı götürülür. Bu adım çok kez tekrarlanarak en sonunda optimum nokta bulunur. Optimum noktanın bulunduğuna da gradyan büyüklüğü belli bir eşiğin altına düştüğünde karar verilir. Daha fazla bu algoritmanın matematiksel detaylarına girmeden konumuza devam edelim.

Makine öğrenimi uygulamalarında veri genellikle “train” ve “test” kümeleri olmak üzere ikiye, bazen de “validation” kümesinin de eklenmesiyle üçe ayrılır. Model her zaman “train” kümesinin üzerine kurulur. Bu yöntemlerde 3 çeşit hata ve bu hataların da 3 çeşit kaynağı vardır fakat bu kısımlar da çok fazla teoriğe kaçtığı için detaylıca değinmeyeceğim. Şunu bilmeliyiz ki “train” kümesi üzerine RSS minimize edilerek kurulan bir modelin başarısı, “test” kümesi üzerinde denenir. Bunun sebebi ise modelin “test” kümesindeki verileri daha önce hiç görmemiş olması ve daha gerçekçi sonuçlar ortaya koymasıdır. Model zaten “train” kümesi üzerinde kurulduğu için, bu küme üzerinde tahmin yapmak fazla iyimser olacaktır. “Validation” kümesinin ne işe yaradığından da bahsedeyim. Polinomik regresyon modelleri gibi modellerde, polinomun derecesi belirlenirken de bir test aşaması söz konusu olduğundan, model “train” kümesi üzerine kurulduktan sonra “validation” kümesi üzerinde en az RSS değerini üreten polinom derecesi, o modelin en optimum derecesi olarak kabul edilir. Daha sonra bu dereceyi kullanan polinomik regresyon modelinin başarısı da yine “test” kümesi üzerinde denenir. Çok fazla teoriğe kaydık, uygulama da her şey daha net anlaşılacaktır.

İlk aşamada, yukarıda bahsettiğim gibi veri setini bölme işlemini uygulayacağım. Aşağıdaki kod bloğu ile veri setini üçe bölüyorum.


#Train-Test-Validation Ayırması
sample_1 <- sample.int(n = nrow(DATA), size = floor(.7*nrow(DATA)), replace = FALSE)
train_data <- DATA[sample_1, ]
data <- DATA[-sample_1, ]
sample_2 <- sample.int(n = nrow(data), size = floor(.5*nrow(data)), replace = FALSE)
test_data <- data[sample_2, ]
validation_data <- data[-sample_2, ]

Kod bloğunun nasıl çalıştığını açıklayayım. Öncelikle "sample_1" ve "sample_2" olarak tanımladığım nesneler verinin nasıl bölüneceğini belirleyen yöntemler. Elimdeki ham veri setini öncelikle %70 ve %30 oranında bölüyorum ve %70'lik kısma "train_data" diyorum. Bu veri seti benim train setim olacak. %30'luk kısma da "data" adını verdim çünkü burayı da %15 – %15 bölerek test ve validation setlerimi oluşturacağım. Aynı yöntemle onları da bölerek üç farklı veri setini elde ediyorum. Fonksiyondaki "replace = FALSE" argümanı, iadesiz seçme olacağını belirtiyor. Yöntemlerin başına "-" konulduğunda ise, onlar haricinde veriden geriye kalan anlamına geliyor.
Veri setlerine bakacak olursak;

#Satir sayilari
nrow(train_data)
nrow(test_data)
nrow(validation_data)

Sonuç;

4

Evet satır sayıları istediğimiz gibi. Şimdi devam edelim. Bu aşamadan sonra sıra işlem yapmaya geldi.

Üstte bahsettiğimiz döngüyü aşağıda gerçekleştirelim:

#Regresyon Döngüsü
for (i in 1:7) {
  assign(paste0('PolModel_', as.character(i)), lm(price ~ poly(sqft_living, i, raw = TRUE), data = train_data))
}

Bu döngü kod bloğunun neler yaptığını açıklayayım. İlk satırda 1’den 7’ye kadar olmak üzere döngüyü başlatıyoruz. Daha sonra “assign” fonksiyonunu kullanarak döngünün her adımında istediğimiz polinomik modeli kendi adıyla oluşacak olan nesneye atıyoruz. Normal atama işareti değil de “assign” fonksiyonunu kullanmamızın nedeni ise bu tarz bir atamayı direkt olarak atama operatörünün yerine getiremiyor olması. “paste0” fonksiyonu, aralarında boşluk bırakmaksızın iki string ifadeyi birleştireceğinden dolayı her polinomik modelin adı kendi derecesiyle bitecek. “assign” komutu içerisinde virgülün sağında oluşan polinomik model her adımda virgülün sonuna atanacak ve 7.dereceden sonra döngü bitecek. Şunu da belirtelim ki kullandığımız veri train set olacak çünkü model kurma işleminin her zaman train set üzerinde yapılacağını belirtmiştik.

Oluşan modellere şöyle bir bakacak olursak;

#İnceleme
summary(PolModel_2)
summary(PolModel_7)

Kodun sonucuna bakacak olursak;

5

Görüleceği üzere her polinomik model için kaçıncı dereceye kadar ise o kadar bağımsız değişken bulunuyor ve bunların hepsi üstte de bahsettiğim gibi bir eğime(ya da ağırlığa) sahip. Bir sonraki aşamaya geçmeden önce bu polinomik modelleri görselleştirmek ve bu görselleştirmeler esnasında da makine öğrenmesi adına çok önemli olan bir kavrama değinmek istiyorum.

Polinomik modelleri görselleştirelim.

#Birince Derece
f <- function (x, c) {coef(PolModel_1)[1] + coef(PolModel_1)[2]*x}
pl <- ggplot(train_data) + geom_point(aes(x = sqft_living, y = price), size = 2) + xlab('Sqft') + ylab('Price')
pl + stat_function(fun=f, colour = '#339900', size=1)

Önce kod bloğunun nasıl çalıştığına bakalım. Regresyon denkleminden nasıl tahmin yapılıyorsa aynı stratejiyi bir fonksiyona yansıttık. Bu fonksiyon içerisinde de katsayılar ve tahmincileri kullandık tabii ki. Daha sonra "pl" adında bir ggplot2 nesnesi tanımlayarak train setimiz üzerine x ve y değişkenlerini scatter plot'a yansıttık. Sonrasında her x değeri için y'yi hesaplayacak olan fonksiyonu da "stat_function" komutu ile grafiğe entegre ettik. Sonuç:

6

Elimize geçen aslında bir basit doğrusal regresyon doğrusu. Bu da gayet doğal çünkü birinci dereceden polinomik regresyon zaten basit doğrusal regresyona eşit. Şimdi polinomik modelin derecelerini arttırdıkça aslında train set üzerinde RSS değerinin nasıl değiştiğini gözlemleyelim. İkinci dereceye geçelim:

#İkinci Derece
f <- function (x, c) {coef(PolModel_2)[1] + coef(PolModel_2)[2]*x + coef(PolModel_2)[3]*x^2}
pl <- ggplot(train_data) + geom_point(aes(x = sqft_living, y = price), size = 2) + xlab('Sqft') + ylab('Price')
pl + stat_function(fun=f, colour = '#339900', size=1)

Aynı kod bloğu burada da aynı işi yapıyor. Tek değişiklik tabii ki fonksiyonda. Bu kodun sonucuna bakalım:

7

Baktığımızda ikinci derece polinomun RSS değerinin aslında birinci dereceden daha iyi olduğunu görüyoruz. Bunu şu şekilde açıklamak mantıklı olacaktır; ikinci derece polinom eğrisi train setteki siyah noktalara daha iyi oturmuş ve daha iyi açıklıyor. RSS değeri de üstte açıkladığımız gibi siyah noktaların yeşil çizgiye olan uzaklıklarının bir fonksiyonu olduğu için, çizgi veriye ne kadar iyi oturursa RSS o kadar düşük olacaktır. Bunu daha iyi göstermek için bir de 5.derece polinoma bakalım.

#Beşinci Derece
f <- function (x, c) {coef(PolModel_5)[1] + coef(PolModel_5)[2]*x + coef(PolModel_5)[3]*x^2 + coef(PolModel_5)[4]*x^3 + coef(PolModel_5)[5]*x^4 + coef(PolModel_5)[6]*x^5}
pl <- ggplot(train_data) + geom_point(aes(x = sqft_living, y = price), size = 2) + xlab('Sqft') + ylab('Price')
pl + stat_function(fun=f, colour = '#339900', size=1)

Grafik:

8

Grafiğe baktığımızda 5.derece polinomik modelin veriye artık çok daha iyi oturduğunu ve siyah noktaların yeşil çizgiye uzaklığının iyice düştüğünü görüyoruz. Bu da RSS daha da düştü demektir. Son olarak en yüksek dereceli polinomik modele yani 7.dereceye bakalım.

#Yedinci Derece
f <- function (x, c) {coef(PolModel_7)[1] + coef(PolModel_7)[2]*x + coef(PolModel_7)[3]*x^2 + coef(PolModel_7)[4]*x^3 + coef(PolModel_7)[5]*x^4 + coef(PolModel_7)[6]*x^5 + coef(PolModel_7)[7]*x^6 + coef(PolModel_7)[8]*x^7}
pl <- ggplot(train_data) + geom_point(aes(x = sqft_living, y = price), size = 2) + xlab('Sqft') + ylab('Price')
pl + stat_function(fun=f, colour = '#339900', size=1)

Sonuç:

9

Evet, en yüksek dereceli polinom train sete en iyi oturan ve RSS değerini de en düşüğe indirgeyen polinom olarak görülüyor. Bu durumda train setteki RSS değerini en çok minimize eden model bu olduğuna göre, yola bu model ile devam etmeli miyiz? Cevap hayır. Çünkü her ne kadar bu 7.dereceden polinomik model train setin RSS’sini minimize ettiyse de, aslında bu modelin yapacağı tahminlerin ne kadar gerçekçi olacağını tartışmak gerekiyor. Örneğin bu modelle tahmin yapacak olsaydık, daha yüksek metrekareye sahip bir evin, çok daha düşük metrekareye sahip bir evden daha ucuz olacağını görürdük. Çünkü çizginin ucu, veri setindeki en uç noktalara da oturabilmek için baya eğilmiş durumda ve o değere yakın metrekareye sahip evleri tahmin edemeyecek halde. Söylemek istediğim noktayı şöyle toparlayayım, evet yüksek dereceli polinomik modeller train sete çok iyi oturup RSS değerini de çok düşürüyor fakat bu modeller train sete güzel uyabilmek için train seti çok fazla öğreniyor ve artık train set dışındaki gerçek dünyaya genelleştirilemez ve düzgün tahmin edemez oluyor. İşte makine öğrenmesinde buna “overfitting” ya da aşırı öğrenme deniyor. Evet bu önemli kavramdan da bahsettiğime göre devam ediyorum.

Benim amacım en iyi polinom derecesini belirlemek. Bunun için de, üstte bahsettiğim gibi train setin RSS değerine değil, modelin hiç görmemiş olduğu validation setin RSS değerine bakacağım ve validation set üzerinde RSS’yi minimize edebilen polinomik modeli alacağım. O zaman her modelin tek tek validation set üzerindeki RSS değerini hesaplayalım:

#Validation Set RSS Hesaplama
Objects <- as.character(ls()[sapply(mget(ls(), .GlobalEnv), is.object)])
Objects <- as.data.frame(as.character((Objects[substr(Objects, 1, 3) == "Pol"])))
names(Objects)[1] = "Models"
NewData <- validation_data['sqft_living']
for (i in 1:nrow(Objects)) {
  predictions <- predict(get(as.character(Objects[i, ])), NewData)
  residuals <- validation_data['price'] - predictions
  assign(paste0("RSS_", i), sum(residuals * residuals))
}
RSS <- c(RSS_1, RSS_2, RSS_3, RSS_4, RSS_5, RSS_6, RSS_7)
which.min(RSS)

Her şeyden önce, kod bloğunun nasıl çalıştığını açıklayayım. Öncelikle tüm polinomik modeller için validation set üzerinde RSS hesaplamam gerektiğinden, yine bir döngüye ihtiyacım var. Bu yüzden döngü öncesinde ilk satırdaki komutla R ortamındaki tüm var olan nesneleri "Objects" adında yeni bir nesneye atıyorum. Bunu da "sapply" fonksiyonu yardımıyla ortamdaki her nesneye "is.object" komutunu sorarak yapıyorum. Daha sonra bana tüm nesneler arasından sadece regresyon modellerim lazım ki bunları da "substr" fonksiyonu yardımıyla "Pol" ile başlayan nesneleri seçerek yapıyorum ve bunları bir data frame haline getiriyorum. Üçüncü satırda hangi veriyi kullanarak tahmin yapacaklarını modellere söylemek amacıyla validation setteki tüm metrekare değerlerini "NewData" adında yeni bir nesneye atıyorum. "Objects" nesnesinin tüm satırları için birinci satırdan başlamak kaydıyla bir döngü açıyorum ve her satırdaki model için "NewData" nesnesindeki metrekare değerlerini kullanarak fiyatları tahmin ediyorum. Burada "get" komutu,içerisine verilen herhangi bir karakterle aynı isimde olan ortam nesnesini getirir. Bunlar da benim regresyon modellerime karşılık geliyor. Döngünün ikinci satırında kalıntıları hesaplıyorum ve bunu gerçek değerlerden tahminleri çıkararak yapıyorum. Sonrasında ise klasik RSS formülünden yola çıkarak kalıntıların karesini alıyor, bunları topluyor ve en son da kendi indeksleriyle numaralandırılacak olan RSS nesnesine atıyorum. Döngü dışındaki iki satırda da oluşmuş olan tüm RSS değerlerini tek bir vektörde toplayarak bunlardan hangisinin minimum olduğunu soruyorum. Sonuçta bakalım hangisi minimum çıkıyor:

10

Evet, 6.dereceden polinomik regresyon modeli, validation set üzerinde en küçük RSS değerini veren model oldu. Dolayısıyla diğer çoklu regresyon modelleriyle de yarışmak üzere onu bir üst tura çıkarıyorum.

Şimdi, seçtiğimiz polinomik model dışında birkaç aday model daha oluşturalım ve bunların hepsinin performanslarını karşılaştırarak en optimum modeli seçelim. Polinomik modele rakip olarak 4 tane daha ek çoklu model oluşturacağım. Bunlar şu şekilde olacak; birinci model metrekare değerine ek olarak yatak odası ve banyo sayılarını da tahminci olarak kullanacak. İkinci model, ilk modeldeki 3 değişken artı kat sayısı ve manzarası olup olmadığını kullanacak. 4 ve 5. modellerde ise kendim oluşturacağım özellikler ekleyeceğim. 4.model metrekare değerinin logaritması, kat sayısının karesi + banyo ve yatak odası sayılarını kullanacak. Son olarak 5.model ise metrekare değeri, kat sayısı, kaç yıllık bina olduğu(2018 – “yr_built” değişkeni) ve yatak odasıyla banyo sayısının çarpımını alacak. Bu model değişkenlerini keyfi seçiyorum, çünkü amaç farklı modellerin performanslarını karşılaştırmak. Öncelikle gerekli özellikleri oluşturup daha sonra da modelleri kuruyorum:

#Özellikleri oluşturma
train_data['log_sqft_living'] <- log(train_data['sqft_living'])
train_data['floors_squared'] <- train_data['floors'] * train_data['floors']
train_data['years'] <- 2018 - train_data['yr_built']
train_data['rooms'] <- train_data['bedrooms'] * train_data['bathrooms']

test_data['log_sqft_living'] <- log(test_data['sqft_living'])
test_data['floors_squared'] <- test_data['floors'] * test_data['floors']
test_data['years'] <- 2018 - test_data['yr_built']
test_data['rooms'] <- test_data['bedrooms'] * test_data['bathrooms']
#Modelleri kurma
MltModel_1 <- lm(price ~ sqft_living + bedrooms + bathrooms, data = train_data)
MltModel_2 <- lm(price ~ sqft_living + bedrooms + bathrooms + floors + view, data = train_data)
MltModel_3 <- lm(price ~ log_sqft_living + floors_squared + bedrooms + bathrooms, data = train_data)
MltModel_4 <- lm(price ~ sqft_living + floors + years + rooms, data = train_data)

Dikkat edelim ki aynı özellikleri test sette de oluşturduk. Çünkü modeller train set kullanılarak oluşturuluyor fakat tahminleme test set kullanılarak yapılacağı için aynı bağımsız değişkenlerin test sette de yer alması gerekir. Model oluşturma işlemi tamamlandığına göre elimdeki 5 modelin performanslarını karşılaştıracağım. Bu işlemi nasıl yapacağımı üstte anlaştmıştım. Bir kayıp fonksiyonu belirleyerek tüm modellerin tahminlerinin test set üzerinde bu kayıp fonksiyonunu kullanarak nasıl sonuç verdiklerine bakacağım. Kısacası tüm modellerin test setteki hatalarını karşılaştıracak ve en küçük hatayı veren modeli kullanacağım. Bunun için bir kayıp fonksiyonu belirleyelim. Bu noktada bize yardımcı olabilecek bir kayıp ölçüm değeri olan RMSE(Root Mean Squared Error) değerini kullanabiliriz. Bu da aynı şekilde RSS değerinin ortalamaya dönüştürülüp karekökünün alınmasıyla elde edilir. Tüm modellerin test set üzerindeki RMSE'lerini hesaplayarak minimum değeri veren modeli optimum model olarak seçip tahminlemede kullanacağız.

Aşağıdaki kod bloğu ile bu işlemi gerçekleştiriyorum:

#RMSE Hesaplama
Models <- as.data.frame(c('MltModel_1', 'MltModel_2', 'MltModel_3', 'MltModel_4'))
names(Models)[1] = "Regression Models"

PredData_Pol <- data.frame(sqft_living = test_data['sqft_living'])

PredData1 <- data.frame(sqft_living = test_data['sqft_living'], bedrooms = test_data['bedrooms'], bathrooms = test_data['bathrooms'])

PredData2 <- data.frame(sqft_living = test_data['sqft_living'], bedrooms = test_data['bedrooms'], bathrooms = test_data['bathrooms'], floors = test_data['floors'], view = test_data['view'])

PredData3 <- data.frame(log_sqft_living = test_data['log_sqft_living'], floors_squared = test_data['floors_squared'], bedrooms = test_data['bedrooms'], bathrooms = test_data['bathrooms'])

PredData4 <- data.frame(sqft_living = test_data['sqft_living'], floors = test_data['floors'], years = test_data['years'], rooms = test_data['rooms'])

for (i in 1:nrow(Models)) {
  if (i == 1) {predictions <- predict(get(as.character(Models[i, ])), PredData1)}
  if (i == 2) {predictions <- predict(get(as.character(Models[i, ])), PredData2)}
  if (i == 3) {predictions <- predict(get(as.character(Models[i, ])), PredData3)}
  if (i == 4) {predictions <- predict(get(as.character(Models[i, ])), PredData4)}

  residuals <- test_data['price'] - predictions
  RSS <- sum(residuals * residuals)
  mean <- RSS/nrow(test_data)
  assign(paste0('RMSE', i), sqrt(mean))
}

predictions_pol <- predict(lm(price ~ poly(sqft_living, 6, raw = TRUE), data = train_data), newdata = PredData_Pol)
residuals_pol <- test_data['price'] - predictions_pol
RSS_pol <- sum(residuals_pol * residuals_pol)
mean_pol <- RSS_pol/nrow(test_data)
RMSE_pol <- sqrt(mean_pol)

RMSE <- c(RMSE1, RMSE2, RMSE3, RMSE4, RMSE_pol)
which.min(RMSE)

Minimum RMSE değerini veren model aşağıda görünüyor.

11

Vektöre bakacak olursak, ikinci indexe sahip RMSE değeri ikinci çoklu regresyon modelinden geliyor. Yani, metrekare değeri, yatak odası ve banyo sayıları, kat sayısı ve manzara değişkenlerini içeren model. Bu durumda optimum model olarak bunu seçiyoruz ve tahminimizi de bununla yapıyoruz. Şimdi finaldeki modeli kullanarak tahmin işlemini gerçekleştirelim:

#Tahmin işlemi
FinalData <- data.frame(sqft_living = 5002, bedrooms = 5, bathrooms = 6.00, floors = 2, view = 1)
predict(MltModel_2, FinalData)

Sonuca bakalım:

12

Evet, modelimiz üstteki özelliklere sahip bir evin fiyatını 1,388,483 $ olarak tahmin etti. Fakat unutmamak gerekir ki bu özelliklere sahip bir evin fiyatı çok daha fazla veya az olabilir. Çünkü evin lokasyonu, içinde bulunduğu bölgenin suç oranı, içinde eşya olup olmaması gibi bir çok özellik bu fiyatı etkileyebilir. Şuna dikkat çekmek istiyorum, biz modele alacağımız değişkenleri bu yazıda keyfi olarak seçtik. Bu yüzden benim yazıda değinmek istediğim nokta modelin başarısından çok, birden çok aday model arasından en optimum modelin seçilme aşaması oldu. İleriki yazılarımda modele alacağım özellikleri de dikkatle seçtiğimde, hem model başarısı hem de optimum modeli bulma konularına daha ayrıntılı değineceğim.

 

R Üzerinde Çoklu Regresyon Bölüm 2: Ev Fiyatlarını Tahminleme” için 5 yorum

  1. hocam yine harika bir rehber hazırlamışsınız. Udemy’den makine öğrenmesi ile ilgili birçok ders aldım ancak sizin bolğunuzdaki gibi teorik istatistik detaylarına kimse gir(e)miyor. En kalitelisi dahi karadüzen çalışıyor diyebilirim. Tekrar tebrik ederim ülkemiz için çok faydalı işler yapmışsınız.

    benim merak ettiğim konu bu bilgi birikimini nasıl elde ettiğiniz. Okuduğum kadarıyla istatistik mezunusunuz. teorik bilgileriniz okuldan mı geliyor. Yoksa eğitimlerden mi?

    Python ile makine öğrenmesi konusunda iyi seviyedeyim diyebilirim. Sizin R’da yaptığınız bu örnekleri ben de hem R hem de Pythonla yaparak egzersiz yapıyorum. Ama bu tip teorik istatistik alanında zayıfım. Bu konuda hangi kaynakları önerirsiniz?

    Beğen

    1. Yavuz Bey selamlar,

      Okuldan sonra istatistik ve veri bilimi üzerine yaptığım çalışmaların çok faydası oldu. Teorik istatistiğe dair kaynaklar için Coursera’daki eğitimlere başvurabilirsiniz. Ayrıca Edx üzerinde de ücretsiz ve teorik istatistik içeren güzel kurslar bulunuyor bunları da değerlendirmenizi tavsiye ederim. Ayrıca ihtiyaç duymanız halinde ben de size temel istatistik üzerine kaynak teşkil eden bir PDF gönderebilirim.

      İyi çalışmalar.

      Beğen

  2. Selamlar, yine sorularla geldim 🙂

    RSS_pol <- sum(residuals_pol * residuals_pol)
    mean_pol <- RSS/nrow(test_data)
    RMSE_pol <- sqrt(mean_pol)

    Bu kod parcasinda polinomial modelin RSS ortalamasini hesaplarken (mean_pol), RSS yerine RSS_pol'u kullanmak gerekmiyor mu?

    Bir de en iyi polinomial modelin belirlenmesi hususunda; kod her sefer calistirildiginda farkli train, test, validation setleri olusacaktir. Bu da mutlaka her sefer 6. dereceden modelin en dusuk RSS sonucu vermesini gerektirmez. Bu sebeple which.mean(RSS) i bir degiskene atayip, daha sonra ihtiyac oldugunda gereken yere 6 yazmak yerine bu degisken refere edilebilir. Tabii bu programlama pratigi, yazinin huviyetini degistirmiyor ama bir not olarak dusulebilir.

    Iyi calismalar 🙂

    Beğen

    1. Selamlar,

      Kod bloğu konusunda haklısınız, “RSS_pol” ifadesi kullanılmalı. Yazarken gözümden kaçmış, düzelttim.

      İkinci öneriniz de aslında programlama açısından gayet mantıklı ve pratik. Fakat ben orada sonucu göstermek amacıyla direkt olarak kodun çıktısını yansıtmışım. Normalde tabii ki doğru olan değişken yaratılıp buna refere edilmesi.

      Beğen

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s