-- Genel, Yapay Sinir Ağları

Yapay Sinir Ağları Kullanılarak Boston Housing Dataseti Üzerinde Fiyat Tahmini

Merhabalar (uzun bir aradan sonra yeniden),

Bugün R üzerinde Neural Network (Sinir Ağları) kullanarak Boston Housing veri seti üzerinde fiyat tahminlerinde bulunacağız. Öncelikle “Yapay Sinir Ağları Nedir” hakkında daha önce yazmış yazılara göz atmanızda fayda var. Linkleri aşağıda paylaşıyorum.

Yapay Sinir Ağları (YSA) Nedir – Bölüm 1 ?

Yapay Sinir Ağları (YSA) Nedir – Bölüm 2 ?

Yapay Sinir Ağları (YSA) Nedir – Bölüm 3 ?

Neler Yapacağız?

  1. Kullanılacak Olan Kütüphaneleri İndirme ve Yükleme (Install & Load Use Library)
  2. Dataset Hakkında, İndirme ve Yükleme (Loading the dataset)
  3. Dataseti Özetleme (Summarizing the dataset)
  4. Dataseti Görselleştirme (Visualizing the dataset)
  5. Dataseti Normalleştirme (Normalization of Data)
  6. Model Kurma ve Tahmin (Making Model & Predictions)
  7. Değerlendirme (Conclusion)
R Ön Hazırlık
rm(list=ls()) # Sistemdeki değişkenleri temizler.

cat("\014") # Konsolu temizler.

set.seed(123) # Rasgele sayılar üretilirken kullanılan başlangıç değelerinin aynı olmasını sağlar.

  1. Kullanılacak olan Kütüphaneleri İndirme ve Yükleme
    # Install & Use Library ---------------------------------------------------
    
    if (require("MASS")==FALSE){
      install.packages("MASS")
      library(MASS)
    }
    
    if (require("neuralnet")==FALSE){
      install.packages("neuralnet")
      library(neuralnet)
    }
    
  2. Dataset Hakkında, İndirme ve Yükleme (Loading the dataset)

    Dataset Adı: Housing Values in Suburbs of Boston

    Dataset Linki: https://archive.ics.uci.edu/ml/machine-learning-databases/housing/ ve https://www.kaggle.com/c/boston-housing

    Yukarıda paylaştığım birinci linkte aşağıda açıklamalarını bahsettiğim dosyalar yer almaktadır. İkinci linkte ise dataset hakkında açıklayıcı bilgiler yer almaktadır.

    housing.data: Ham datanın bulunduğu dosyadır

    housing.names: Dataya ait metadata bilgisinin yer aldığı dosyadır.

    Metadata Nedir: “Verinin verisi” ya da “Veri hakkında veri/bilgi” olarak ifade edilebilir. Kaynak: https://tr.wikipedia.org/wiki/Metadata

    Not: Biz bu çalışmada dataseti R içerisinde MASS paketi içerisinde yer aldığı için indirmeye gerek kalmadan kullanacağız.

    DataSet <- MASS::Boston # Mass library içerisindeki ‘Housing Values in Suburbs of Boston’
    
    help(Boston) # Daha fazlası için
    
    str(DataSet) #Structure of Dataset
    
    'data.frame':	506 obs. of  14 variables:
     $ crim   : num  0.00632 0.02731 0.02729 0.03237 0.06905 ...
     $ zn     : num  18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
     $ indus  : num  2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
     $ chas   : int  0 0 0 0 0 0 0 0 0 0 ...
     $ nox    : num  0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
     $ rm     : num  6.58 6.42 7.18 7 7.15 ...
     $ age    : num  65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
     $ dis    : num  4.09 4.97 4.97 6.06 6.06 ...
     $ rad    : int  1 2 2 3 3 3 5 5 5 5 ...
     $ tax    : num  296 242 242 222 222 222 311 311 311 311 ...
     $ ptratio: num  15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
     $ black  : num  397 397 393 395 397 ...
     $ lstat  : num  4.98 9.14 4.03 2.94 5.33 ...
     $ medv   : num  24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
  3. Dataseti Özetleme (Summarizing the dataset)

    Dataseti incelediğimizde;

    summary(DataSet) #Datasete ait descriptive bilgileri gösterir.
    
          crim                 zn                indus               chas                 nox           
     Min.   : 0.006320   Min.   :  0.00000   Min.   : 0.46000   Min.   :0.00000000   Min.   :0.3850000  
     1st Qu.: 0.082045   1st Qu.:  0.00000   1st Qu.: 5.19000   1st Qu.:0.00000000   1st Qu.:0.4490000  
     Median : 0.256510   Median :  0.00000   Median : 9.69000   Median :0.00000000   Median :0.5380000  
     Mean   : 3.613524   Mean   : 11.36364   Mean   :11.13678   Mean   :0.06916996   Mean   :0.5546951  
     3rd Qu.: 3.677083   3rd Qu.: 12.50000   3rd Qu.:18.10000   3rd Qu.:0.00000000   3rd Qu.:0.6240000  
     Max.   :88.976200   Max.   :100.00000   Max.   :27.74000   Max.   :1.00000000   Max.   :0.8710000  
           rm                age                dis                 rad                 tax          
     Min.   :3.561000   Min.   :  2.9000   Min.   : 1.129600   Min.   : 1.000000   Min.   :187.0000  
     1st Qu.:5.885500   1st Qu.: 45.0250   1st Qu.: 2.100175   1st Qu.: 4.000000   1st Qu.:279.0000  
     Median :6.208500   Median : 77.5000   Median : 3.207450   Median : 5.000000   Median :330.0000  
     Mean   :6.284634   Mean   : 68.5749   Mean   : 3.795043   Mean   : 9.549407   Mean   :408.2372  
     3rd Qu.:6.623500   3rd Qu.: 94.0750   3rd Qu.: 5.188425   3rd Qu.:24.000000   3rd Qu.:666.0000  
     Max.   :8.780000   Max.   :100.0000   Max.   :12.126500   Max.   :24.000000   Max.   :711.0000  
        ptratio             black              lstat               medv         
     Min.   :12.60000   Min.   :  0.3200   Min.   : 1.73000   Min.   : 5.00000  
     1st Qu.:17.40000   1st Qu.:375.3775   1st Qu.: 6.95000   1st Qu.:17.02500  
     Median :19.05000   Median :391.4400   Median :11.36000   Median :21.20000  
     Mean   :18.45553   Mean   :356.6740   Mean   :12.65306   Mean   :22.53281  
     3rd Qu.:20.20000   3rd Qu.:396.2250   3rd Qu.:16.95500   3rd Qu.:25.00000  
     Max.   :22.00000   Max.   :396.9000   Max.   :37.97000   Max.   :50.00000 
    
    dim(DataSet) #Datasete ait boyut bilgisini verir. Burada 506 satır, 14 sütun
    [1] 506  14
    
    head(DataSet, 5) # Datasete ait ilk 5 satırı gösterir.
    
         crim zn indus chas   nox    rm  age    dis rad tax ptratio  black lstat medv
    1 0.00632 18  2.31    0 0.538 6.575 65.2 4.0900   1 296    15.3 396.90  4.98 24.0
    2 0.02731  0  7.07    0 0.469 6.421 78.9 4.9671   2 242    17.8 396.90  9.14 21.6
    3 0.02729  0  7.07    0 0.469 7.185 61.1 4.9671   2 242    17.8 392.83  4.03 34.7
    4 0.03237  0  2.18    0 0.458 6.998 45.8 6.0622   3 222    18.7 394.63  2.94 33.4
    5 0.06905  0  2.18    0 0.458 7.147 54.2 6.0622   3 222    18.7 396.90  5.33 36.2
    
    tail(DataSet, 5) # Datasete ait son 5 satırı gösterir.
           crim zn indus chas   nox    rm  age    dis rad tax ptratio  black lstat medv
    502 0.06263  0 11.93    0 0.573 6.593 69.1 2.4786   1 273      21 391.99  9.67 22.4
    503 0.04527  0 11.93    0 0.573 6.120 76.7 2.2875   1 273      21 396.90  9.08 20.6
    504 0.06076  0 11.93    0 0.573 6.976 91.0 2.1675   1 273      21 396.90  5.64 23.9
    505 0.10959  0 11.93    0 0.573 6.794 89.3 2.3889   1 273      21 393.45  6.48 22.0
    506 0.04741  0 11.93    0 0.573 6.030 80.8 2.5050   1 273      21 396.90  7.88 11.9
  4. Dataset Görselleştirme (Visualizing the dataset)
    hist(DataSet$medv)

  5. Dataseti Normalleştirme (Normalization of Data)
    Değişkenlerin(feature) ortalama ve varyansları birbirinden önemli ölçüde farklı olduğu takdirde ortalama ve varyansı büyük olan değişkenlerin diğer değişkenler üzerinde etkisi fazla olacağından diğerlerinin etkisini azaltacaktır. Bu neden ile bir data üzerinde normalleştirme(standartlaştırma) bu problemin önüne geçecektir. En çok kullanılan normalleştirmeler: Min-Max Normalleştirmesi ve Z-Score Normalleştirmesi’dir. Bu bu çalışmada Min-Max Normalleştirmesi kullanarak dataset üzerinden standartlaştırma yapacağız. Min-Max normalleştirmesi değerleri 0-1 aralığa dönüştürecektir.X* = (Xi – XMİN) / (XMAX – XMİN)
    X*: Dönüştürülmüş değerleri,
    Xi: Gözlem değelerini,
    XMİN: En küçük gözlem değerini,
    XMAX: En büyük gözlem değerini belirtir.Normalleştirme işlemi yapabilmemiz için oldukça kullanışlı olan apply() ve türevleri olan fonksiyonun kullanacağız. Veriseti içerisinde satır bazında veya sütun bazında bilgiler elde etmek istediğimizde kullandığımız fonksiyonlardır. Örnek verecek olusak; her satın/her sütun için min, max, mean, range vb. descriptive değerleri ile özel tanımlanan fonksiyonları kullanarak bu fonksiyon içerisinde değerleri elde edilebiliriz. Birbirine çok benzeyen bu 3 fonksiyonun kullanımı oldukça basittir. Aralarındaki fark çıktılarının veri tiplerinin farklı olmasından gelir.

    apply(): Matris içerisinde satır ve sütun bazında işlemler yapmamızı sağlar.

    sapply ve lappy(): Vektör ve Listeler tipleriyle çalışırlar.

    sapply() ‘ın çıktısı vektör, lapply() ‘ın çıktısı liste’dir.

    Kullanımı:

    apply(dataset, 2, mean) # Sütunları[2] ortalamasını verir. 1 parametresi satırları, 2 parametresi sürunları belirtir.

    apply(dataset, 2, range) # Sütunları[2] ortalamasını verir. 1 parametresi satırları, 2 parametresi sürunları belirtir.

    apply(DataSet, 2, mean) # Dataset içerisindeki sütunlara ait ortalama değerlerini verir.
               crim              zn           indus            chas             nox              rm             age 
      3.61352355731  11.36363636364  11.13677865613   0.06916996047   0.55469505929   6.28463438735  68.57490118577 
                dis             rad             tax         ptratio           black           lstat            medv 
      3.79504268775   9.54940711462 408.23715415020  18.45553359684 356.67403162055  12.65306324111  22.53280632411 
    
    apply(DataSet, 2, range) # Dataset içerisindeki sütunlara ait range(aralık) değerlerini verir.
             crim  zn indus chas   nox    rm   age     dis rad tax ptratio  black lstat medv
    [1,]  0.00632   0  0.46    0 0.385 3.561   2.9  1.1296   1 187    12.6   0.32  1.73    5
    [2,] 88.97620 100 27.74    1 0.871 8.780 100.0 12.1265  24 711    22.0 396.90 37.97   50

    Çalışmaya dönecek olursak;

    MaxValue <- apply(DataSet, 2, max) # Dataset içerisindeki sütunlara ait max değerlerini verir.
    > MaxValue
        crim       zn    indus     chas      nox       rm      age      dis      rad      tax  ptratio    black 
     88.9762 100.0000  27.7400   1.0000   0.8710   8.7800 100.0000  12.1265  24.0000 711.0000  22.0000 396.9000 
       lstat     medv 
     37.9700  50.0000 
    
    MinValue <- apply(DataSet, 2, min) # Dataset içerisindeki sütunlara ait min değerlerini verir.
    MinValue
         crim        zn     indus      chas       nox        rm       age       dis       rad       tax   ptratio 
      0.00632   0.00000   0.46000   0.00000   0.38500   3.56100   2.90000   1.12960   1.00000 187.00000  12.60000 
        black     lstat      medv 
      0.32000   1.73000   5.00000 
    
    DataSetN <- as.data.frame(scale(DataSet, center = MinValue, scale = MaxValue-MinValue ))
    #DataSet verisini Min-Max Normalleştirmesi uyguluyoruz.
    
  6. Model Kurma ve Tahmin (Making Model & Predictions)

    Bu çalışmada Supervised(öğreticili/danışmalı/eğiticili) bir model (Neural Network) kullanacağımız için önce dataseti Train ve Test olarak iki ayrı parçaya ayırmamız gerekiyor. Burada Train verisi için 400 gözlem, Test verisi için 106 gözlem rastgele alınarak oluşturulacaktır. Literatürde %90 – %10 yada %80 – %20 oldukça yaygın olarak kullanılmaktadır.

    ind <- sample(1:nrow(DataSet),400) # 1 ile 506 gözlem içerisinden rastgele 400 gözlem seçilir.
    
    TrainDF <- DataSetN[ind,] #Train datası için Dataset içerisindeki rastgele 400 gözlem seçilir.
    TestDF  <- DataSetN[-ind,] #Test datası için Dataset içerisindeki rastgele 106 gözlem seçilir.
    
    

    Dataset içerisinde 14 adet değişkenimiz (feature) bulunmaktadır. Burada bağımsız değişkenler ile bağımlı değişkeni tahmin etmeye çalışıyoruz. Bu sebeble

    AllVars <- colnames(DataSet)
    
    PredictVars <- allVars[!allVars%in%"medv"]
    #PredictVars içerisinde yer alan bağımlı "medv" olan değişkeni çıkarıyoruz.
    
    PredictVars
     [1] "crim"    "zn"      "indus"   "chas"    "nox"     "rm"      "age"     "dis"     "rad"     "tax"    
    [11] "ptratio" "black"   "lstat"  
    
    PredictVars <- paste(PredictVars, collapse = "+")
    #Bağımsız değişkenler ile Bağımsız Değişkenleri Tahmin edeceğimiz üzere modeli formüle ediyoruz.
    
    PredictVars
    [1] "crim+zn+indus+chas+nox+rm+age+dis+rad+tax+ptratio+black+lstat"
    
    ModelFormula <-as.formula(paste("medv~", PredictVars, collapse = "+"))
    ModelFormula
    medv ~ crim + zn + indus + chas + nox + rm + age + dis + rad + 
        tax + ptratio + black + lstat
    

    NeuralNetwork modelimini kurmadan önce hatırlamamız gereken Temel Bileşenler var. Bunların belirlenmesi modelin başarısında oldukça belirleyici olduğunu hatırlatmakta fayda var. Eğer yukarıda paylaştığım yazımı okumadıysanız hala geç değil 🙂

    Yapay Sinir Ağlarının Temel Bileşenleri

    1. Mimari Yapı
    2. Öğrenme Algoritması
    3. Aktivasyon Fonksiyonu

    Modeli oluşturuyoruz ve grafiksel olarak çizdiriyoruz:

    NNModel <- neuralnet(formula=ModelFormula, hidden=c(4,2), linear.output=T, data=TrainDF)
    #Neural Network Modelini GirdiKatmanı, GizliKatman1, GizliKatman2 ve ÇıktıKatmanı olarak oluşturuyoruz.
    
    plot(NNModel) #Neural Network Modelini çizdiriyoruz.

    Mimari Yapı: Girdi, 1.GizliKatman, 2.GizliKatman ve Çıktı katmanı olmak üzere 4 katmandan oluşmaktadır. 1. Gizli Katmanda 4 nöron, 2. Gizli Katmanda 2 nöron bulunmaktadır.

    Öğrenme Algoritması: Backpropagation Algorithm

    Aktivasyon Fonksiyonu: Logistic (varsayılan)

    PredictValues <- compute(NNModel, TestDF[,1:13]) #NNModel ile TestDF datasını
    
    PredictValues <- PredictValues$net.result
    
    ActualValues <- (TestDF$medv)
    
    Result <- data.frame(Actual=ActualValues, Predict=PredictValues, Diff=ActualValues-PredictValues)
    
    head(Result)
             Actual      Predict           Diff
    6  0.5266666667 0.4434082115  0.08325845513
    8  0.4911111111 0.2917075865  0.19940352464
    9  0.2555555556 0.2435206581  0.01203489749
    10 0.3088888889 0.2910989204  0.01778996848
    18 0.2777777778 0.2933875774 -0.01560979964
    26 0.1977777778 0.2684711768 -0.07069339904
    
    tail(Result)
               Actual      Predict           Diff
    486 0.36000000000 0.3995228085 -0.03952280853
    490 0.04444444444 0.2208018159 -0.17635737148
    495 0.43333333333 0.3165751666  0.11675816677
    496 0.40222222222 0.2845141144  0.11770810779
    497 0.32666666667 0.2549447216  0.07172194509
    505 0.37777777778 0.4250194089 -0.04724163108
    
    

    Result data frame’inde Actual yani TestDF değerleri(106 Gözlem), Predict yani Neural Network Modeli kurularak elde edilen değerler, ve Actual-Predict arasındaki fark olan Diffrence kolonundan oluşmaktadır. Burada head ve tail ile ilk 6 satır karşılaştırılması gözükmektedir.

    ColMean <- apply(Result, 2, mean) #Actual, Predic ve Diff değişkenlerine ait ortalamalar
    
    ColMean
           Actual       Predict          Diff 
     0.3866037736  0.4006694639 -0.0140656903

     

    Actual ile Predict kolonlarına ait ortalama değerlerinin (0.386 – 0.400) birbirine oldukça yakın olduğu görülmüştür. Şimdi Mean Square Error (MSE) değerlerini hesaplayıp görelim.

    MSE <- sum((PredictValues - ActualValues)^2)/nrow(TestDF) #Mean Square Error
    
    MSE
    [1] 0.009414517716

    MSE değeri 0.009 olduğu görülmüştür. Bir başka mimariye sahip Neural Network modeli ile ya da Regresyon gibi başka bir model ile karşılaştırarak model tercihinde bulunabilir. Son olarak

    plot(ActualValues, PredictValues, col='blue', 
    main='Actual vs Predicted', pch=1, cex=0.9, type = "p", xlab ="Frequency", ylab="Actual")
    abline(0,1,col="black")

    Orjinden 45 derecelik açı ile geçen kırmızı çizgiye bitişik bir şekilde değerlerin yer aldığı görülmüştür.

  7. Değerlendirme (Conclusion)

Bu çalışmada Boston Housing dataseti üzerinde Neural Network modeli kurularak fiyat tahmininde bunulmuştur. Dataset içerisinde 13 bağımsız değişken(feature) ile model kurularak 1 bağımlı(medv) değişken tahmini yapıldı. Neural Network mimari yapısında Girdi Katmanında 13 nöron, 1. Gizli Katmanda 4, 2. Gizli Katmanda 2 ve Çıktı Katmanında 1 nöron bulunmak üzere 13x4x2x1 modeli kurulmuştur. Modelin Mean Square Error (MSE) değerinin 0.009 olduğu görülmüştür.

Peki bundan sonra; Gizli Katman Sayısı ve bu katmanlardaki Nöron Sayısını nasıl belirleyeceğiz? Ben burada tamamen kendi isteğime göre mimari yapıyı oluşturdum. Daha fazla yada daha az da olabilirdi. Mimari yapının modelin başarısını etkileyen 3. önemli temel bileşenden biridir. Bu yazının 2 versiyonunda Gizli Katman Sayısı(1 ile 3 arasında) ve Gizli Katmandaki Nöron Sayısını(1 ile 3) parametrik yapıp en iyi mimari yapısını modelin performans ölçütü olan MSE değeri ile tespit edeceğiz.

Çok kısa süre içerisinde yukarıdaki kodları github üzerinde paylaşıyor olacağım. Konu hakkındaki görüş, öneri ve yorumlarınızı buradan ya da  uslumetin@gmail.com üzerinden belirtebilirsiniz.  Yeniden görüşmek üzere, selamlar. 🙂