Day 4 Algorit.ma : Regression Model

32 minute read

Day 4, here I will share my notes of Inclass notebook. For further example you can check out on https://github.com/Saltfarmer/Algoritma-BFLP-DS-Audit/tree/main

Inclass: Regression Model

  • Durasi: 7 hours
  • Last Updated: Desember 2023

import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from helper import linearity_test

Introduction

Machine learning bertujuan untuk membuat mesin yang belajar berdasarkan data. Machine learning terbagi dua:

Supervised Learning:

  • memiliki target variable.
  • untuk pembuatan model prediksi (y ~ x)
  • ada ground truth (label aktual) sehingga ada evaluasi model

Unsupervised Learning:

  • tidak memiliki target variable.
  • untuk mencari pola dalam data sehingga menghasilkan informasi yang berguna/dapat diolah lebih lanjut. umumnya dipakai untuk tahap explanatory data analysis (EDA)/data pre-processing.
  • tidak ada ground truth sehingga tidak ada evaluasi model

Regression Model

Regression model merupakan Supervised Learning karena data yang dibutuhkan harus memiliki target variabel (y). Target variabel dari Regression Model harus bertipe numerik, namun untuk prediktornya (x) boleh numerik/kategorik

📝Business Problem

Pemilihan variabel target biasanya dikaitkan dengan masalah bisnis yang ingin diselesaikan:

  1. Sebuah dealer mobil berusaha membangun sebuah model untuk memprediksi harga mobil untuk digunakan sebagai patokan ketika membuka harga transaksi. Untuk itu mereka mengembangkan sebuah model dengan:

    • Variabel target:
    • Variabel prediktor:
  2. Seorang mahasiswa pertanian diminta untuk melakukan analisis regresi untuk memprediksi produktivitas padi dari berbagai lahan di Pulau Jawa. Untuk itu ia mengembangkan sebuah model dengan:

    • Variabel target:
    • Variabel prediktor:

Regression Modeling Workflow - Predicting Property Sales Price: in Jakarta, Tangsel, and Depok Area

Sebagai Tim Data di sebuah institusi perbankan, kita diminta untuk melakukan analisis untuk mengetahui prediksi harga properti untuk acuan dasar data credit KPR.

Keinginan untuk memiliki properti sendiri merupakan impian banyak orang. Selain bisa dijadikan tempat tinggal, memiliki properti di Jakarta dan Depok adalah salah satu aset investasi yang menguntungkan karena harganya yang cenderung naik setiap tahunnya.

Dalam proses pencarian tempat tinggal idaman ini, beberapa orang mungkin saja mengalami hambatan, yaitu kesulitan dalam mencari tempat tinggal yang sesuai dengan spesifikasi yang diinginkan dan budget yang dimiliki. Banyak orang menemukan tempat tinggal dengan harga yang cukup mahal namun tidak sesuai dengan spesifikasi yang ditawarkan.

Apakah terdapat sistem yang dapat memberikan referensi harga properti?” menjadi tujuan analisis pada pembahasan analisis kita.

Simple Linear Regression

Pada Simple Linear Regression, kita akan membuat model regresi dengan satu buah variabel prediktor. Formula untuk simple linear regression adalah

Formula model simple linear regression:

\[\hat{y}=\beta_0+\beta_1.x_1\]

dimana:

  • $\hat{y}$ : nilai prediksi target variabel
  • $\beta_0$ : nilai intercept (nilai target variabel ketika kita tidak memiliki prediktor sama sekali)
  • $\beta_1$ : nilai slope (nilai kemiringan garis regresi / nilai kontribusi prediktor dalam menentukan target variabel)

Bagaimanakah kita mendapatkan garis yang paling representatif terhadap data kita?

Regresi bekerja berdasarkan konsep Ordinary Least Square yang mencari persamaan garis linear dengan nilai error terkecil. Error adalah selisih nilai prediksi/nilai pada garis dengan nilai aktual.

1. Import data

Kita akan gunakan data properti.csv yang tersimpan di folder data_input. Data yang diambil adalah data hasil scrapping dari website https://www.rumah123.com/

# code ini untuk mengatur pemisah angka ribuan
pd.options.display.float_format = '{:,.3f}'.format
# Data
properti = pd.read_csv("data_input/properti_jual.csv")
properti.head()
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota Price
0 3 4 294 SHM - Sertifikat Hak Milik Rumah Jakarta Utara 3500000000
1 3 3 78 SHM - Sertifikat Hak Milik Apartemen Jakarta Selatan 2500000000
2 1 1 33 HGB - Hak Guna Bangunan Apartemen Jakarta Timur 265000000
3 2 2 120 SHM - Sertifikat Hak Milik Rumah Jakarta Pusat 2600000000
4 3 3 130 SHM - Sertifikat Hak Milik Rumah Depok 1300000000

Berikut deskripsi variabel dari data tersebut:

  • K..Mandi: Jumlah kamar mandi pada suatu properti

  • K..Tidur: Jumlah kamar tidur pada suatu properti

  • L..Bangunan: Luas bangunan properti (m2)

  • Sertifikat: Jenis sertifikat atas properti yang di jual
    • Sertifikat Hak Pakai
    • Sertifikat Hak Sewa
    • Sertifikat lainnya (PPJB, Girik, Adat, dll)
    • Sertifikat PPJB
    • Sertifikat Hak Milik
  • Tipe.Properti: Jenis properti yang dijual
    • Rumah: Untuk tipe properti rumah
    • Apartemen: Untuk tipe properti apartemen
  • Kota: Lokasi kota tempat properti di jual
    • Depok
    • Jakarta Selatan
    • Jakarta Timur
    • Jakarta Utara
    • Jakarta Barat
    • Jakarta Pusat
    • Tangerang Selatan
  • Price: Nominal harga properti yang dijual

2. Inspect data berdasarkan tipe datanya

## code here
properti.dtypes
K..Mandi          int64
K..Tidur          int64
L..Bangunan       int64
Sertifikat       object
Tipe.Properti    object
Kota             object
Price             int64
dtype: object

Tipe data yang belum sesuai adalah :

  • ‘Sertifikat’, ‘Tipe.Properti’, ‘Kota’
# Object nama kolom kategori
cat_var = ['Sertifikat', 'Tipe.Properti', 'Kota']

# Mengubah tipe data dari beberapa kolom
properti[cat_var] = properti[cat_var].astype('category')
# Cek kembali hasil proses perubahan tipe data
properti.dtypes
K..Mandi            int64
K..Tidur            int64
L..Bangunan         int64
Sertifikat       category
Tipe.Properti    category
Kota             category
Price               int64
dtype: object

3. Cek missing value

Sangat penting untuk mengidentifikasi apakah terdapat missing value di dataset kita sebelum dilakukan pemodelan machine learning.

❓ Karena missing value dapat mempengaruhi performa model secara signifikan

Missing value ada disebabkan karena:

  1. Kesalahan koleksi data
  2. Permasalahan pada saat preprocessing
  3. Sesimple karena data tidak terkumpul oleh sebagian observasi

Metode yang dapat dilakukan untuk mengetahui apakah pada data yang diolah memiliki nilai missing dengan menggunakan fungsi isnull().sum().

## melihat nilai missing
properti.isnull().sum()
K..Mandi         0
K..Tidur         0
L..Bangunan      0
Sertifikat       0
Tipe.Properti    0
Kota             0
Price            0
dtype: int64

4. 🎯 Mendefinisikan Business Problem

Dari pernyataan bisnis yang diajukan, kita ingin melakukan prediksi harga properti berdasarkan Luas Bangunan

❓ Berdasarkan kolom-kolom data, mari kita coba tentukan kolom apa yang akan menjadi target dan prediktor?

  • Variabel target:
  • Variabel prediktor:

5. Exploratory Data Analysis (EDA)

  • **Descriptive Statistics**

Analisis statistik deskriptif digunakan untuk memberikan gambaran awal mengenai distribusi dan perilaku data dengan melihat nilai minimum, nilai maximum, rata – rata (mean), dan standar deviasi dari masing-masing variabel independen dan variabel dependen.

Method describe() menampilkan 8 ringkasan statistika deskriptif. Secara default menampilkan ringkasan untuk kolom numerik.

properti.describe()
K..Mandi K..Tidur L..Bangunan Price
count 6,287.000 6,287.000 6,287.000 6,287.000
mean 1.909 2.410 92.866 1,705,079,211.070
std 0.948 0.975 66.115 1,254,170,884.604
min 1.000 1.000 1.000 205,000,000.000
25% 1.000 2.000 41.000 740,000,000.000
50% 2.000 2.000 75.000 1,350,000,000.000
75% 3.000 3.000 130.000 2,350,000,000.000
max 5.000 4.000 600.000 5,970,000,000.000
properti[properti['L..Bangunan'] < 19]
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota Price
177 1 1 18 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Timur 250000000
282 1 1 17 HP - Hak Pakai Apartemen Depok 360000000
557 1 1 14 HGB - Hak Guna Bangunan Apartemen Jakarta Utara 290000000
663 4 3 4 Lainnya (PPJB,Girik,Adat,dll) Rumah Jakarta Pusat 3700000000
1074 1 1 16 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 260000000
1128 1 2 12 Lainnya (PPJB,Girik,Adat,dll) Apartemen Tangerang Selatan 1500000000
1363 1 1 17 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 270000000
1436 1 2 12 Lainnya (PPJB,Girik,Adat,dll) Apartemen Tangerang Selatan 1500000000
1740 1 1 17 SHM - Sertifikat Hak Milik Apartemen Depok 235000000
1787 1 1 18 SHM - Sertifikat Hak Milik Apartemen Tangerang Selatan 250000000
2078 2 3 2 SHM - Sertifikat Hak Milik Rumah Jakarta Pusat 2000000000
2197 1 1 17 HGB - Hak Guna Bangunan Apartemen Depok 260000000
2686 1 1 14 SHM - Sertifikat Hak Milik Apartemen Jakarta Utara 290000000
2768 1 1 14 HGB - Hak Guna Bangunan Apartemen Jakarta Utara 290000000
2775 1 1 17 SHM - Sertifikat Hak Milik Apartemen Tangerang Selatan 450000000
2881 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 250000000
2944 1 1 18 SHM - Sertifikat Hak Milik Apartemen Jakarta Barat 400000000
3041 1 1 17 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 250000000
3214 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 350000000
3253 1 1 16 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 350000000
3342 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 325000000
3361 1 1 18 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Timur 350000000
3673 1 1 17 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 280000000
3720 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 300000000
3755 1 1 17 HGB - Hak Guna Bangunan Apartemen Depok 255000000
3848 1 1 17 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 300000000
3965 1 1 16 Lainnya (PPJB,Girik,Adat,dll) Apartemen Tangerang Selatan 590000000
4048 1 1 18 Lainnya (PPJB,Girik,Adat,dll) Apartemen Tangerang Selatan 380000000
4109 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
4191 1 2 1 Lainnya (PPJB,Girik,Adat,dll) Rumah Tangerang Selatan 1350000000
4225 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
4255 1 1 16 HGB - Hak Guna Bangunan Apartemen Depok 450000000
4282 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
4346 1 1 17 HGB - Hak Guna Bangunan Apartemen Tangerang Selatan 310000000
4369 1 2 3 SHM - Sertifikat Hak Milik Apartemen Jakarta Pusat 3750000000
4658 1 2 10 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 550000000
4675 1 1 18 SHM - Sertifikat Hak Milik Apartemen Tangerang Selatan 350000000
4778 1 1 18 SHM - Sertifikat Hak Milik Apartemen Jakarta Barat 525000000
4898 1 1 18 Lainnya (PPJB,Girik,Adat,dll) Apartemen Depok 230000000
5467 2 4 3 SHM - Sertifikat Hak Milik Rumah Jakarta Barat 4500000000
5529 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
5569 1 1 18 SHM - Sertifikat Hak Milik Apartemen Jakarta Barat 580000000
5579 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
5595 1 1 18 HGB - Hak Guna Bangunan Apartemen Jakarta Utara 375000000
5641 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
5775 1 1 18 HGB - Hak Guna Bangunan Apartemen Depok 565000000
5844 1 1 14 HGB - Hak Guna Bangunan Apartemen Jakarta Utara 290000000
6019 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
6057 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 290000000
6120 1 2 1 Lainnya (PPJB,Girik,Adat,dll) Rumah Tangerang Selatan 1000000000
6130 2 4 3 SHM - Sertifikat Hak Milik Rumah Jakarta Barat 4500000000
6216 1 1 18 SHM - Sertifikat Hak Milik Apartemen Depok 550000000
6222 1 1 14 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 350000000
6225 1 1 16 HGB - Hak Guna Bangunan Apartemen Jakarta Utara 350000000

Luas bangunan dibawah 14 $m^2$ kemungkinan besar tidak tepat atau salah ukur

properti.info()
<class 'pandas.core.frame.DataFrame'>
Index: 6287 entries, 0 to 6286
Data columns (total 7 columns):
 #   Column         Non-Null Count  Dtype   
---  ------         --------------  -----   
 0   K..Mandi       6287 non-null   int64   
 1   K..Tidur       6287 non-null   int64   
 2   L..Bangunan    6287 non-null   int64   
 3   Sertifikat     6287 non-null   category
 4   Tipe.Properti  6287 non-null   category
 5   Kota           6287 non-null   category
 6   Price          6287 non-null   int64   
dtypes: category(3), int64(4)
memory usage: 264.7 KB

❓ Apakah ada hal yang menarik dari hasil describe di atas?

  • **Cek korelasi antar variabel target dan prediktor**

Biasanya uji korelasi ini akan sangat berhubungan dengan uji regresi yang menunjukkan apakah masing-masing variabel saling berhubungan erat. Meskipun variabel tersebut saling berhubungan erat atau berkorelasi, belum tentu variabel tersebut saling mempengaruhi.

Dalam analisis korelasi ini, output yang dihasilkan hanya dalam rentang -1 sampai 1

  • Bila korelasi dua variabel numerik mendekati -1 artinya korelasi negatif kuat
  • Bila korelasi dua variabel numerik mendekati 1 artinya korelasi positif kuat
  • Bila korelasi dua variabel numerik mendekati 0 artinya tidak berkorelasi

korelasi

  • Menggunakan nilai korelasi
properti['Price'].corr(properti['L..Bangunan'])
0.7856264787666598
properti[properti['L..Bangunan'] >= 14][['Price', 'L..Bangunan']].corr()
Price L..Bangunan
Price 1.000 0.789
L..Bangunan 0.789 1.000
  • Menggunakan visualisasi
properti.plot.scatter(x = 'L..Bangunan', y = 'Price')
plt.show()

png

properti[(properti['Price'] < 1e9) & (properti['L..Bangunan'] > 450)]
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota Price
6206 2 2 478 HGB - Hak Guna Bangunan Apartemen Jakarta Barat 480000000
properti = properti[(properti['L..Bangunan'] >= 14) & (properti['L..Bangunan'].index != 6206)]
properti.plot.scatter(x = 'L..Bangunan', y = 'Price')
plt.show()

png

  • Kesimpulan dari plot:

Berdasarkan kesimpulan dan analisis yang sudah dilakukan, adakah yang perlu kita lakukan pada data kita?

L.Bangunan berkorelasi positif dengan price meskipun masih terdapat beberapa outlier

  • **Identifikasi Outlier**

Dari hasil analisa statistik deskriptif belum diketahui apakah pada data yang kita miliki memiliki outlier atau tidak, maka dari itu mari coba kita lihat dengan menggunakan visualisasi Box Plot.

Visualisasi Box Plot dapat dibuat dengan menggunakan fungsi boxplot() dari library matplotlib.

# Melihat nilai outlier
properti.boxplot(column = 'L..Bangunan')
<Axes: >

png

Masih ada outlier

from matplotlib.cbook import boxplot_stats

bp_stats = boxplot_stats(properti['L..Bangunan'].values)

bp_stats[0]['fliers'].min()
263

6. Membuat Model Simple Linear Regression

6.1 Model dengan outlier

Dari tahapan EDA (checking outlier) dengan boxplot, diketahui bahwa variabel L..Bangunan memiliki nilai outlier.

Selanjutnya jika kita ingin menjawab business problem yang kita miliki, yaitu kita ingin melakukan prediksi harga Price properti berdasarkan besaran Luas Bangunan. Kita akan memakai seluruh observasi yang ada terlebih dahulu.

**Tahapan 1 - Menentukan Target dan Prediktor**

  • Y : df['target']
  • X : sm.add_constant(df['prediktor']). Supaya intercept tidak dianggap 0
# membuat objek untuk prediktor (pilih kolom yang akan digunakan)
X_data = properti['L..Bangunan']

# menambahkan intercept/add_constant
X_data = sm.add_constant(X_data)

# membuat objek target
Y_data = properti['Price']

**Tahapan 2 - Membuat model Prediksi**

Untuk membuat model regresi linier di Python kita akan menggunakan fungsi OLS() dari package statsmodels.

Syntax: sm.OLS(target, prediktor).fit()

# sm.OLS(properti['Price'], properti['L..Bangunan']).fit().summary()
# Nggak work kare di sm.OLS tidak ada constantnya
# https://stackoverflow.com/questions/30286095/do-i-need-to-add-a-constant-when-using-sm-ols
# Membuat model
lm_outlier = sm.OLS(Y_data, X_data).fit()

**Tahapan 3 - Melihat hasil / menginterpretasikan model**

  • intercept dan slope: model.params
  • summary model : model.summary()
# Summary model
print(lm_outlier.params, lm_outlier.summary())
const         303,614,296.475
L..Bangunan    15,068,066.597
dtype: float64                             OLS Regression Results                            
==============================================================================
Dep. Variable:                  Price   R-squared:                       0.628
Model:                            OLS   Adj. R-squared:                  0.627
Method:                 Least Squares   F-statistic:                 1.057e+04
Date:                Mon, 08 Jan 2024   Prob (F-statistic):               0.00
Time:                        10:15:37   Log-Likelihood:            -1.3728e+05
No. Observations:                6276   AIC:                         2.746e+05
Df Residuals:                    6274   BIC:                         2.746e+05
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
===============================================================================
                  coef    std err          t      P>|t|      [0.025      0.975]
-------------------------------------------------------------------------------
const        3.036e+08   1.67e+07     18.182      0.000    2.71e+08    3.36e+08
L..Bangunan  1.507e+07   1.47e+05    102.809      0.000    1.48e+07    1.54e+07
==============================================================================
Omnibus:                     1807.386   Durbin-Watson:                   2.034
Prob(Omnibus):                  0.000   Jarque-Bera (JB):             6246.081
Skew:                           1.431   Prob(JB):                         0.00
Kurtosis:                       6.962   Cond. No.                         197.
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

📝 Interpretasi model :

  1. Model linier regresi untuk kasus prediksi harga properti di daerah Jakarta, Depok, dan Tangsel adalah:

Price = b0 + b1*L..Bangunan

Price = ... + ...*L..Bangunan

  • slope : 1.507e+07
  • intercept: 3.036e+08
  1. Signifikansi prediktor (bandingkan nilai p-value dengan alpha)
    • H0: Luas Bangunan tidak mempengaruhi Harga Properti
    • H1: Luas Bangunan mempengaruhi Harga Properti

    Note: Ketika p-value < 0.05 (alpha) maka kesimpulannya adalah menolak H0 yang berarti Luas Bangunan signifikan berpengaruh terhadap Harga properti

    p-value : 0.00

    Kesimpulan : Tolak $H_0$

  2. Goodness of fit (melihat nilai R-squared, dimana 0 ≤ $R^2$ ≤ 1)

    Nilai R-Squared merepresentasikan % variasi dari data yang berhasil dijelaskan oleh model.

    • Semakin mendekati 1, mengindikasikan model semakin fit
    • Semakin mendekati 0, mengindikasikan model tidak fit

    R-Squared: 0.617

    Kesimpulan : Cukup fit

[Optional] Other Information in Summary

  1. Tabel 1, sisi kiri menyimpan informasi dasar dari model
    • Dep. Variable : Target variabel (Y)
    • Model : Model regresi linier
    • Method : Metode yang digunakan untuk membuat model regresi linier
    • No. Observations: Jumlah observasi yang digunakan ketika membuat model regresi linier
    • DF Residuals : Degrees of freedom error/residual (No. Observations - parameter)
    • DF Model : Degrees of freedom model (jumlah prediktor)
  2. Tabel 1, sisi kanan menyimpan informasi kebaikan model
    • R-squared : Goodness of fit
    • Adj. R-squared : Goodneess of fit untuk multiple linear regression
    • F-statistic : Statistik hitung dari F-test (uji simultan)
    • Prob (F-statistic): p-value dari F-test

      a. H0 –> Tidak ada prediktor yang berpengaruh signifikan terhadap target

      b. H1 –> Min terdapat 1 prediktor yang berpengaruh signifikan terhadap target

    • Log-likelihood : Log dari nilai likelihood.
    • AIC : Akaike Information Criterion (information loss)
    • BIC : Bayesian Information Criterion (serupa dengan AIC, namun perhitungan nilainya berbeda)
  3. Tabel 2 menyimpan informasi dari koefisien regresi
    • coef : Estimasi koefisien
    • std err : Estimasi selisih nilai sampel terhadap populasi
    • t : Statistik hitung dari t-test (uji parsial)
    • **P > t ** : P-value dari t-test
  4. Tabel 3 menyimpan hasil uji statistik error/residual
    • Omnibus D’Angostino’s test: Statistik hitung untuk pengujian Skewness dan Kurtosis
    • Prob(Omnibus): p-value dari Omnibus D’Angostino’s test
    • Skewness: Mengukur kecondongan distribusi error
    • Kurtosis: Mengukur keruncingan distribusi error
    • Durbin-Watson: Statistik hitung pengujian autokorelasi
    • Jarque-Bera: Serupa dengan Omnibus D’Angostino’s test, namun memiliki perhitungan yang berbeda
    • Prob (JB): p-value dari Jarque-Bera
    • Cond. No: Pengujian multicolinearity

**Tahapan 4 - Hasil Visualisasi 2 Dimensi**

  • hanya bisa untuk 1 variabel prediktor
# Plot scatter
properti.plot.scatter(x='L..Bangunan', y='Price')

# Plot garis linear model
plt.plot(properti['L..Bangunan'], lm_outlier.fittedvalues, c='red')
plt.show()

png

**Tahapan 5 - Melakukan Prediksi Model**

❓🏠 Business Question: Terdapat properti A dengan Luas Bangunan 90m2. Kita diminta untuk memprediksi harga properti A, berapakah harga prediksinya?

## code here (manual)
intercept = 3.036e+08
slope = 1.507e+07

house_price_new = intercept + slope*90
house_price_new
1659900000.0

Untuk melakukan prediksi terhadap beberapa Luas bangunan, dapat menggunakan model.predict()

Eg : Data properti dengan Luas Bangunan terbaru

new_house = pd.DataFrame({'L.B': (75, 320, 188, 60, 90)})
new_house
L.B
0 75
1 320
2 188
3 60
4 90
## code here
# predict copiers datasest
X_new = sm.add_constant(new_house)

lm_outlier.predict(X_new)
0   1,433,719,291.236
1   5,125,395,607.458
2   3,136,410,816.677
3   1,207,698,292.284
4   1,659,740,290.189
dtype: float64

6.2 Model tanpa outlier

Untuk membuat model tanpa outlier, langkah pertama yang harus dilakukan adalah melakukan filtering pada data.

❓ Coba tinjau lagi nilai outlier pada data properti kita, kira-kira berapa threshold batas outlier yang dimiliki?

# melihat nilai outlier kembali dengan boxplot
properti.boxplot('L..Bangunan')
<Axes: >

png

Dalam kasus ini dikarenakan outlier L..Bangunan di atas 280 m2, maka data yang digunakan adalah data dengan L..Bangunan < 280 m2.

# remove outlier (membuang nilai outlier dengan L.B < 280m2)
properti_new = properti[(properti['L..Bangunan'] <= 263)]
properti_new
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota Price
1 3 3 78 SHM - Sertifikat Hak Milik Apartemen Jakarta Selatan 2500000000
2 1 1 33 HGB - Hak Guna Bangunan Apartemen Jakarta Timur 265000000
3 2 2 120 SHM - Sertifikat Hak Milik Rumah Jakarta Pusat 2600000000
4 3 3 130 SHM - Sertifikat Hak Milik Rumah Depok 1300000000
5 1 1 97 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Barat 3200000000
... ... ... ... ... ... ... ...
6282 2 3 80 SHM - Sertifikat Hak Milik Rumah Jakarta Timur 960000000
6283 2 3 84 SHM - Sertifikat Hak Milik Rumah Depok 1070000000
6284 2 2 132 Lainnya (PPJB,Girik,Adat,dll) Apartemen Jakarta Utara 1900000000
6285 3 3 83 SHM - Sertifikat Hak Milik Rumah Depok 1260000000
6286 4 3 200 SHM - Sertifikat Hak Milik Rumah Jakarta Selatan 2900000000

6160 rows × 7 columns

# melakukan modeling dengan data baru 
# define predictor variable
# X_data_no = properti_new['L..Bangunan']
X_data_no = sm.add_constant(properti_new['L..Bangunan'])

#define target variable
Y_data_no = properti_new['Price']

# build model with outlier
lm_no_outlier = sm.OLS(Y_data_no, X_data_no).fit()

lm_no_outlier.summary()
OLS Regression Results
Dep. Variable: Price R-squared: 0.615
Model: OLS Adj. R-squared: 0.615
Method: Least Squares F-statistic: 9838.
Date: Mon, 08 Jan 2024 Prob (F-statistic): 0.00
Time: 10:49:42 Log-Likelihood: -1.3459e+05
No. Observations: 6160 AIC: 2.692e+05
Df Residuals: 6158 BIC: 2.692e+05
Df Model: 1
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 2.044e+08 1.74e+07 11.730 0.000 1.7e+08 2.39e+08
L..Bangunan 1.636e+07 1.65e+05 99.185 0.000 1.6e+07 1.67e+07
Omnibus: 1802.302 Durbin-Watson: 2.036
Prob(Omnibus): 0.000 Jarque-Bera (JB): 5875.961
Skew: 1.479 Prob(JB): 0.00
Kurtosis: 6.762 Cond. No. 194.



Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

📝 Interpretasi model:

  1. Model linier regresi untuk kasus prediksi harga properti di daerah Jakarta, Depok, dan Tangsel adalah:

    Price = b0 + b1*L..Bangunan

    Price = ... + ...*L..Bangunan

    • slope : 1.636e+07
    • intercept: 2.044e+08
  2. Signifikansi prediktor (bandingkan nilai p-value dengan alpha)
    • H0: Luas Bangunan tidak mempengaruhi Harga Properti
    • H1: Luas Bangunan mempengaruhi Harga Properti

    Note: Ketika p-value < 0.05 (alpha) maka kesimpulannya adalah menolak H0

    p-value : 0.00

    Kesimpulan : $H_0$ ditolak

  3. Goodness of fit (melihat nilai R-squared, dimana 0 ≤ $R^2$ ≤ 1)

    Nilai R-Squared merepresentasikan % variasi dari data yang berhasil dijelaskan oleh model. Formula:

    $R^2=1- \frac {∑ \limits_{i=1}^n (Y_i−\hat Y)^2}{∑ \limits_{i=1}^n(Y_i−\bar Y)^2}$

    • Semakin mendekati 1, mengindikasikan model semakin fit
    • Semakin mendekati 0, mengindikasikan model tidak fit

    R-Squared: 0.615

    Kesimpulan : Cukup fit

# visualize the result
fig1, ax1 = plt.subplots()
properti.plot.scatter(x='L..Bangunan', y='Price', c='yellow', ax=ax1, ylim=[0,6.5e9])
properti_new.plot.scatter(x='L..Bangunan', y='Price', c='blue',ax=ax1)
# visualisasi model no_outlier
plt.plot(properti_new['L..Bangunan'], lm_no_outlier.fittedvalues, c='black')
# visualisasi model dengan outlier
plt.plot(properti['L..Bangunan'], lm_outlier.fittedvalues, c='red')
plt.show()

png

Leverage vs. Influence

Leverage adalah nilai yang letaknya jauh dari letak observasi lainnya, sering disebut sebagai outlier. Nilai leverage dapat mempengaruhi model linier regresi atau pun tidak.

  • Ketika leverage mempengaruhi (menurunkan R-Squared) model linier regresi: high influence, sebaiknya di-exclude -> membuat model menjadi lebih jelek
  • Ketika leverage tidak mempengaruhi (meningkatkan R-Squared) model linier regresi: low influence, sebaiknya di-include -> membuat model menjadi lebih baik
print("R-Squared model dengan outlier :", (lm_outlier.rsquared).round(2))
print("R-Squared model tanpa outlier :", (lm_no_outlier.rsquared).round(2))
R-Squared model dengan outlier : 0.63
R-Squared model tanpa outlier : 0.62

Kesimpulan: high influence -> membuat model menjadi lebih jelek

Multiple Linear Regression

Linear regression dengan lebih dari satu prediktor bisa meningkatkan performa model karena lebih banyak informasi yang dapat menjelaskan target.

Formula multiple linear regression:

\[\hat{y}=\beta_0+\beta_1.x_1+...+\beta_n.x_n\]

dimana $\hat{y}$ merupakan prediksi target variabel dan $x_1,…,x_n$ prediktor lainnya.

Workflow pada simple linear regression dan multiple linear regression adalah sama. Berikut merupakan worklownya:

1. Preparation Data

Kita akan membuat multiple linear regression menggunakan data properti untuk memprediksi Price berdasarkan keseluruhan variabel.

  • y: Price
  • x: K..Mandi, K..Tidur, L..Bangunan, Sertifikat, Tipe.Properti, dan Kota

💡 Categorical Predictor: Dummy Variable Encoding

Di Python, data input dan output untuk model machine learning harus berbentuk numeric. Ini berarti, ketika data kita mempunyai nilai kategorikal, harus di-encode menjadi numerik terlebih dahulu.

Sebelum melakukan fitting model, kita harus mengubah prediktor kategorik menjadi dummy variable, dengan cara:

  • Dilakukan dengan menggunakan fungsi pd.get_dummies()
  • One hot encoding = mengubah kolom kategorik menjadi kolom-kolom baru dari setiap kategori yang berisi nilai 0 dan 1
  • Dummy variable = mengubah kolom kategorik menjadi kolom-kolom baru yang terdiri dari k-1 kategori, berisi nilai 0 dan 1. Kategori yang tidak menjadi kolom, akan menjadi kondisi basis. Untuk membuat dummy variable, tambahkan parameter drop_first=True

📌 Dalam kasus regresi wajib memakai dummy variabel.

💡 NOTES: Salah satu kolom di-drop karena bersifat redundan (berulang). Untuk kolom yang hanya memiliki 2 kategori, tidak ada perbedaan hasil/efek baik ketika memilih ordinal ataupun dummy, akan tetapi best practicenya menggunakan dummy variabel.

Mari kita coba menerapkan Dummy Variable Encoding untuk kolom-kolom kategorikal.

properti.head()
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota Price
0 3 4 294 SHM - Sertifikat Hak Milik Rumah Jakarta Utara 3500000000
1 3 3 78 SHM - Sertifikat Hak Milik Apartemen Jakarta Selatan 2500000000
2 1 1 33 HGB - Hak Guna Bangunan Apartemen Jakarta Timur 265000000
3 2 2 120 SHM - Sertifikat Hak Milik Rumah Jakarta Pusat 2600000000
4 3 3 130 SHM - Sertifikat Hak Milik Rumah Depok 1300000000
# Object nama kolom kategori
cat_dummy = properti.select_dtypes('category').columns

# dummy encoding
properti_enc = pd.get_dummies(data = properti,
                             columns = cat_dummy,
                             drop_first = True,
                             dtype = 'int64')

# melihat hasil encoding
properti_enc
K..Mandi K..Tidur L..Bangunan Price Sertifikat_HP - Hak Pakai Sertifikat_HS - Hak Sewa Sertifikat_Lainnya (PPJB,Girik,Adat,dll) Sertifikat_PPJB Sertifikat_SHM - Sertifikat Hak Milik Tipe.Properti_Rumah Kota_Jakarta Barat Kota_Jakarta Pusat Kota_Jakarta Selatan Kota_Jakarta Timur Kota_Jakarta Utara Kota_Tangerang Selatan
0 3 4 294 3500000000 0 0 0 0 1 1 0 0 0 0 1 0
1 3 3 78 2500000000 0 0 0 0 1 0 0 0 1 0 0 0
2 1 1 33 265000000 0 0 0 0 0 0 0 0 0 1 0 0
3 2 2 120 2600000000 0 0 0 0 1 1 0 1 0 0 0 0
4 3 3 130 1300000000 0 0 0 0 1 1 0 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6282 2 3 80 960000000 0 0 0 0 1 1 0 0 0 1 0 0
6283 2 3 84 1070000000 0 0 0 0 1 1 0 0 0 0 0 0
6284 2 2 132 1900000000 0 0 1 0 0 0 0 0 0 0 1 0
6285 3 3 83 1260000000 0 0 0 0 1 1 0 0 0 0 0 0
6286 4 3 200 2900000000 0 0 0 0 1 1 0 0 1 0 0 0

6276 rows × 16 columns

2. Membuat Model Multiple Linear Regression

# membuat objek prediktor dan target
Y = properti_enc['Price']
X = sm.add_constant(properti_enc.drop(columns='Price'))

# Membuat model
lm_multiple = sm.OLS(Y, X).fit()

# Melihat summary
lm_multiple.summary()
OLS Regression Results
Dep. Variable: Price R-squared: 0.691
Model: OLS Adj. R-squared: 0.690
Method: Least Squares F-statistic: 934.1
Date: Mon, 08 Jan 2024 Prob (F-statistic): 0.00
Time: 11:24:54 Log-Likelihood: -1.3669e+05
No. Observations: 6276 AIC: 2.734e+05
Df Residuals: 6260 BIC: 2.735e+05
Df Model: 15
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const -6.805e+07 4.05e+07 -1.680 0.093 -1.47e+08 1.14e+07
K..Mandi 8.037e+07 1.8e+07 4.457 0.000 4.5e+07 1.16e+08
K..Tidur 8.87e+07 1.67e+07 5.313 0.000 5.6e+07 1.21e+08
L..Bangunan 1.417e+07 2.28e+05 62.107 0.000 1.37e+07 1.46e+07
Sertifikat_HP - Hak Pakai -1.917e+08 1.23e+08 -1.564 0.118 -4.32e+08 4.86e+07
Sertifikat_HS - Hak Sewa -2.992e+08 3.13e+08 -0.956 0.339 -9.13e+08 3.15e+08
Sertifikat_Lainnya (PPJB,Girik,Adat,dll) 2.888e+07 3.11e+07 0.929 0.353 -3.2e+07 8.98e+07
Sertifikat_PPJB -1.797e+08 4.94e+08 -0.364 0.716 -1.15e+09 7.89e+08
Sertifikat_SHM - Sertifikat Hak Milik -7.895e+07 3.02e+07 -2.616 0.009 -1.38e+08 -1.98e+07
Tipe.Properti_Rumah -3.403e+08 3.01e+07 -11.307 0.000 -3.99e+08 -2.81e+08
Kota_Jakarta Barat 3.911e+08 3.24e+07 12.072 0.000 3.28e+08 4.55e+08
Kota_Jakarta Pusat 5.054e+08 3.78e+07 13.385 0.000 4.31e+08 5.79e+08
Kota_Jakarta Selatan 7.807e+08 3.74e+07 20.891 0.000 7.07e+08 8.54e+08
Kota_Jakarta Timur -8.513e+06 3.05e+07 -0.279 0.780 -6.83e+07 5.13e+07
Kota_Jakarta Utara 3.45e+08 3.72e+07 9.287 0.000 2.72e+08 4.18e+08
Kota_Tangerang Selatan 2.589e+08 3.21e+07 8.061 0.000 1.96e+08 3.22e+08
Omnibus: 1458.887 Durbin-Watson: 2.052
Prob(Omnibus): 0.000 Jarque-Bera (JB): 5120.034
Skew: 1.143 Prob(JB): 0.00
Kurtosis: 6.789 Cond. No. 6.40e+03



Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 6.4e+03. This might indicate that there are
strong multicollinearity or other numerical problems.

3. Interpretasi Model Multiple Linear Regression

[Contoh Interpretasi Variabel Kategorik]

  • Terdapat category golongan darah A, AB, B, dan O
  • Cara menginterpretasikan model apabila memiliki lebih dari 2 kategori :

y = b0 + 1.96* gol.darahAB + 0.97* gol.darahB + 1.39* gol.darahO

 - slope gol.darahAB = 1.96, nilai y ketika golongan darah nya adalah AB sebesar **b0 + 1.96**
 - slope gol.darahB = 0.97, nilai y ketika golongan darah nya adalah B sebesar **b0 + 0.97**
 - slope gol.darahO = 1.39, nilai y ketika golongan darah nya adalah O sebesar **b0 + 1.39**
 - nilai y ketika golongan darah nya adalah A sebesar **b0 saja** (b0 + est. gol.darahAB * 0 + est. gol.darahB * 0 + est. gol.darahO * 0)
 - Golongan darah AB meningkatkan nilai y sebesar 1.96 poin dibandingkan golongan darah A (Basis)
lm_multiple.params
const                                       -68,046,193.387
K..Mandi                                     80,369,440.910
K..Tidur                                     88,704,257.583
L..Bangunan                                  14,172,990.715
Sertifikat_HP - Hak Pakai                  -191,668,410.368
Sertifikat_HS - Hak Sewa                   -299,168,643.727
Sertifikat_Lainnya (PPJB,Girik,Adat,dll)     28,879,971.583
Sertifikat_PPJB                            -179,723,373.918
Sertifikat_SHM - Sertifikat Hak Milik       -78,951,929.200
Tipe.Properti_Rumah                        -340,252,862.068
Kota_Jakarta Barat                          391,095,409.104
Kota_Jakarta Pusat                          505,410,922.104
Kota_Jakarta Selatan                        780,736,333.606
Kota_Jakarta Timur                           -8,512,539.802
Kota_Jakarta Utara                          345,049,019.597
Kota_Tangerang Selatan                      258,934,983.035
dtype: float64
lm_multiple.pvalues[lm_multiple.pvalues > 0.05].index
Index(['const', 'Sertifikat_HP - Hak Pakai', 'Sertifikat_HS - Hak Sewa',
       'Sertifikat_Lainnya (PPJB,Girik,Adat,dll)', 'Sertifikat_PPJB',
       'Kota_Jakarta Timur'],
      dtype='object')

📝 Interpretasi model:

1. Interpretasi masing-masing variabel

contoh:

  • K..Tidur: Setiap 1 Kamar Tidur, meningkatkan harga properti sebesar 88,704,257.583
  • L..Bangunan: Setiap 1 $m^2$ meningkatkan harga 14,172,990.715
  • Sertifikat_HS - Hak Milik: Jika sertifikatnya SHM, maka properti berkurang sebesar 78,951,929.200
  • Kota_Jakarta Selatan:

2. Signifikansi prediktor

  • variabel signifikan (p-value < 0.05) : ‘K..Mandi’, ‘K..Tidur’, ‘L..Bangunan’, ‘Sertifikat_SHM - Sertifikat Hak Milik’, ‘Tipe.Properti_Rumah’, ‘Kota_Jakarta Barat’, ‘Kota_Jakarta Pusat’, ‘Kota_Jakarta Selatan’, ‘Kota_Jakarta Utara’, ‘Kota_Tangerang Selatan’
  • variabel tidak signifikan (p-val>e < 0.05)’const’, ‘Sertifikat_HP - Hak Pakai’, ‘Sertifikat_HS - Hak Sewa’, ‘Sertifikat_Lainnya (PPJB,Girik,Adat,dll)’, ‘Sertifikat_PPJB’, ‘Kota_Jakarta Timur’ :

note: untuk prediktor kategorik, dianggap signifikan mempengaruhi target jika salah satu kategori signifikan

4. Prediksi

Setelah model terbentuk, model tidak dapat langsung digunakan sebelum melewati tahap evaluasi.

Tahapan evaluasi dapat dilakukan dengan melakukan prediksi terhadap data yang ada. Prediksi model dapat dilakukan dengan memanfaatkan fungsi predict(), berikut syntax yang dapat digunakan:

nama_model.predict(data_prediktor)

X_predict = pd.DataFrame({"K..Mandi": [1, 2, 3],
                         "K..Tidur": [2, 4, 5],
                         "L..Bangunan": [123, 321, 531],
                         "Sertifikat": ["SHM - Sertifikat Hak Milik", "PPJB", "HGB - Hak Guna Bangunan"],
                         "Tipe.Properti": ["Apartemen", "Rumah", "Rumah"],
                         "Kota": ["Depok", "Jakarta Selatan", "Jakarta Pusat"]})

X_predict.head()
K..Mandi K..Tidur L..Bangunan Sertifikat Tipe.Properti Kota
0 1 2 123 SHM - Sertifikat Hak Milik Apartemen Depok
1 2 4 321 PPJB Rumah Jakarta Selatan
2 3 5 531 HGB - Hak Guna Bangunan Rumah Jakarta Pusat
X_predict_enc = pd.get_dummies(data = X_predict,
                             columns = cat_dummy,
                             drop_first = True,
                             dtype = 'int64')

X_predict_enc = X_predict_enc.reindex(columns = X.columns, fill_value=0)
X_predict_enc.shape
(3, 16)
res = lm_multiple.predict(X_predict_enc)
res
0   1,922,103,884.819
1   5,325,846,029.281
2   8,375,645,740.335
dtype: float64
# membuat kolom prediksi yang berisi hasil dari prediksi model
properti_enc['Prediksi'] = lm_multiple.predict(X)
properti_enc.head()
K..Mandi K..Tidur L..Bangunan Price Sertifikat_HGB - Hak Guna Bangunan Sertifikat_HP - Hak Pakai Sertifikat_HS - Hak Sewa Sertifikat_Lainnya (PPJB,Girik,Adat,dll) Sertifikat_PPJB Sertifikat_SHM - Sertifikat Hak Milik Tipe.Properti_Apartemen Tipe.Properti_Rumah Kota_Depok Kota_Jakarta Barat Kota_Jakarta Pusat Kota_Jakarta Selatan Kota_Jakarta Timur Kota_Jakarta Utara Kota_Tangerang Selatan Prediksi
0 3 4 294 3500000000 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 4,620,582,658.209
1 3 3 78 2500000000 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 2,246,452,582.268
2 1 1 33 265000000 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 560,223,658.899
3 2 2 120 2600000000 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 2,057,066,220.233
4 3 3 130 1300000000 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1,862,458,903.773

5. Goodness of Fit: R-Squared vs. Adj. R-Squared

Perbedaan R-Squared dan Adj. R-Squared:

  • R-Squared: Seberapa baik model menjelaskan data, dengan mengukur seberapa besar informasi (variansi) dari target dapat dijelaskan oleh prediktor. Sehingga, jelas ketika prediktor bertambah, informasi (variansi) yang dirangkum semakin banyak atau dengan kata lain jelas nilai R-Squared akan meningkat.

    Syntax: nama_model.rsquared

  • Adj. R- Squared: tidak demikian pada adj. r-squred, karena disesuaikan dengan jumlah prediktor yang digunakan. Adj. r-squared akan meningkat hanya jika prediktor baru yang ditambahkan mengarah pada hasil prediksi yang lebih baik (prediktor signifikan mempengaruhi target)

    Syntax: nama_model.rsquared_adj

Mari kita bandingan nilai R-Squared dan Adj. R-Squared antara lm_outlier dengan lm_multiple!

# R-Squared
print('R-Squared Simple Linear Regression :', (lm_outlier.rsquared))
print('R-Squared Simple Linear Regression :', (lm_multiple.rsquared))
R-Squared Simple Linear Regression : 0.6275163087637301
R-Squared Simple Linear Regression : 0.6911833941775697
# Adj R-Squared
print('Adj R-Squared Simple Linear Regression :', (lm_outlier.rsquared_adj))
print('Adj R-Squared Simple Linear Regression :', (lm_multiple.rsquared_adj))
Adj R-Squared Simple Linear Regression : 0.6274569393516746
Adj R-Squared Simple Linear Regression : 0.6904434182850239

📝 Kesimpulan: Berdasarkan nilai R-Squared dan Adj R-Squared, maka model yang terbaik adalah model lm_multiple

Model Evaluation : Nilai Error

Untuk melihat apakah prediksi yang dibuat menghasilkan nilai error terkecil

Error/residual adalah selisih antara hasil prediksi dengan nilai aktual.

\[Error/residual = actual - prediction = y - \hat y\]

Terdapat beberapa nilai error yang ada :

  1. MAE (Mean Absolute Error): Memperlakukan error dengan lebih ringan. Formula: \(MAE = \frac{1}{N} \sum_{i=1}^{N} \left | y_{i} - \hat{y} \right |\)

  2. RMSE (Root Mean Square Error): Memperlakukan error dengan lebih sensitif. Ketika nilai error besar, maka nilai RMSE akan semakin besar dan sebaliknya. Formula: \(RMSE = \sqrt{\frac{1}{N} \sum_{i=1}^{N} (y_{i} - \hat{y})^{2}}\)

  3. MAPE (Mean Absolute Percentage Error): Menunjukan seberapa besar penyimpangan error dalam bentuk persentase \(MAPE = \frac{1}{N} \sum_{i=1}^{N} \frac {\left | y_{i} - \hat{y} \right |} {y_{i}}\)

RMSE digunakan ketika model yang dibuat memuat observasi outlier. Sedangkan, MAE digunakan ketika model yang dibuat tidak memuat observasi outlier. MAPE adalah metrik yang baik untuk interpretasi karena mudah dipahami.

MAE

Fungsi meanabs(kolom_target, kolom_prediksi)

# code here
from statsmodels.tools.eval_measures import meanabs
meanabs(properti_enc['Price'], properti_enc['Prediksi'])
481478265.53622854

RMSE

Fungsi rmse(kolom_target, kolom_prediksi)

# code here
from statsmodels.tools.eval_measures import rmse
rmse(properti_enc['Price'], properti_enc['Prediksi'])
696545892.4274079

MAPE

Fungsi mean_absolute_percentage_error()

Pada fungsi tersebut nantinya akan kita isi dengan parameter yaitu

  • y_true = Parameter ini akan diisi dengan kolom target
  • y_pred = Parameter ini akan diisi dengan kolom hasil prediksi
# code here
from sklearn.metrics import mean_absolute_percentage_error
mean_absolute_percentage_error(properti_enc['Price'], properti_enc['Prediksi'])
0.3754900268095911

Assumption Checking

Limitasi dari pemodelan linear regresi adalah terdapat beberapa asumsi yang perlu dipenuhi agar model linear regresi dikatakan model yang baik. Pendekatan Ordinary Least Square/Linear Regression dikatakan BLUE (Best Linear Unbiased Estimator) ketika memenuhi beberapa uji asumsi berikut:

  1. Linearity: antara x dan y nya ada hubungan linear
    • Bisa dilihat dari R-squared model, jika R-squared kecil, maka kemungkinan antara prediktor dan target, tidak ada hubungan linear
  2. Normality of Residual: Residual nya berdistribusi normal
    • Saat berdistribusi normal, error berada di sekitar 0
  3. No-Heteroscedasticity: Variansi residual konstan (tidak membentuk sebuah pola)
  4. Little to No-Multicollinearity: antar variabel prediktor nya harus independence (tidak mempunyai hubungan)

Linearity

Untuk menguji apakah variabel target dan prediktor memiliki hubungan linear. Dapat dilihat dengan nilai korelasi.

Linearity artinya target variabel dengan prediktornya memiliki hubungan yang linear atau hubungannya bersifat garis lurus. Selain itu, efek atau nilai koefisien antar variabel bersifat additive. Jika linearity ini tidak terpenuhi, maka otomatis semua nilai koefisien yang kita dapatkan tidak valid karena model berasumsi bahwa pola yang akan kita buat adalah linear.

# Residual vs fitted values
linearity_test(lm_multiple)

png

Bagaimana apabila ada yang tidak linear?

  • Exclude variable tersebut dari model
  • Apabila mayoritas variable prediktor tidak linear, maka bisa ganti model

Normality of Residual

Harapannya ketika membuat model linear regression, error yang dihasilkan berdistribusi normal. Artinya error banyak berkumpul disekitar angka 0. Untuk mengecek residual menyebar normal, pengujian yang paling sering dilakukan adalah Shapiro test:

  • $H_0$: Residual berdistribusi normal
  • $H_1$: Residual tidak berdistribusi normal

Dalam melakukan pengujiannya kita akan dibantu library scipy dan memanfaatkan fungsi shapiro(). Untuk memanfaatkan fungsi tersebut, kita akan mengeluarkan nilai residu dari model yang sudah dibuat dengan menambahkan .resid pada objek model yang dibuat.

📌 Note: Jika asumsi normalitas tidak terpenuhi, maka hasil uji signifikansi serta nilai standard error dari intercept dan slope setiap prediktor yang dihasilkan bersifat bias atau tidak mencerminkan nilai sebenarnya. Jika residual memiliki distribusi yang tidak normal, bisa lakukan transformasi/scaling data pada target variabel atau menambahkan sample data.

pd.DataFrame({
    'Prediction': lm_multiple.fittedvalues,
    'Actual': properti_enc['Price'],
    'Residual': lm_multiple.resid
}).head()
Prediction Actual Residual
0 4,620,582,658.209 3500000000 -1,120,582,658.209
1 2,246,452,582.268 2500000000 253,547,417.732
2 560,223,658.899 265000000 -295,223,658.899
3 2,057,066,220.233 2600000000 542,933,779.767
4 1,862,458,903.773 1300000000 -562,458,903.773

Untuk melakukan pengujian asumsi normality of residual bisa menggunakan visualisasi histogram.

lm_multiple.resid.hist()
<Axes: >

png

Selain itu bisa juga menggunakan pengujian statistik yaitu Shapiro Test. Dalam melakukan pengujiannya kita akan dibantu library scipy dan memanfaatkan fungsi shapiro(). Untuk memanfaatkan fungsi tersebut, kita akan mengeluarkan nilai residu dari model yang sudah dibuat dengan menambahkan .resid pada objek model yang dibuat.

from scipy.stats import shapiro
shapiro(lm_multiple.resid)
C:\Users\SaltFarmer\miniconda3\envs\algoritma\lib\site-packages\scipy\stats\_morestats.py:1816: UserWarning: p-value may not be accurate for N > 5000.
  warnings.warn("p-value may not be accurate for N > 5000.")





ShapiroResult(statistic=0.9078583717346191, pvalue=0.0)

Nilai p-value yang kita harapkan pada uji shapiro test yaitu p-value > alpha.

Handling asumsi yang tidak terpenuhi untuk normality of residuals yaitu dengan cara:

  • menambahkan data
  • transformasi pada target varibel (y)

No Heteroscedasticity (Homoscedasticity)

Homocesdasticity menunjukkan bahwa residual atau error bersifat konstan atau tidak membentuk pola tertentu. Jika error membentuk pola tertentu seperti garis linear atau mengerucut, maka kita sebut dengan Heterocesdasticity dan akan berpengaruh pada nilai standard error pada estimate/koefisien prediktor yan bias (terlalu sempit atau terlalu lebar).

Untuk mengecek terjadinya heteroscedasticity kita dapat menggunakan Breusch-Pagan test:

  • $H_0$: residual homogen(tidak membentuk sebuah pola/acak)
  • $H_1$: residual heteros (membentuk sebuah pola)

Kita bisa menggunakan method het_breuschpagan() dari library statsmodels.

Pada lm_multiple_new yang kita miliki, kita bisa memvisualisasikan sebaran dari residual yang ada dengan menggunakan scatter plot.

plt.scatter(y = lm_multiple.resid, x = lm_multiple.fittedvalues)
plt.axhline(y = 0, color = 'r')
<matplotlib.lines.Line2D at 0x1fefc3bc8e0>

png

from statsmodels.compat import lzip
import statsmodels.stats.api as sms

name = ['Lagrange multiplier statistics', 'p-value', 'f-value', 'f p-value']

test = sms.het_breuschpagan(lm_multiple.resid, lm_multiple.model.exog)
lzip(name, test)
[('Lagrange multiplier statistics', 985.8090677322887),
 ('p-value', 1.4820389736444784e-200),
 ('f-value', 77.76864569434078),
 ('f p-value', 8.904001347049246e-219)]

No Multicolinearity

Harapannya pada model linear regression, tidak terjadi multikolinearitas. Multikolinearitas terjadi ketika antar variabel prediktor yang digunakan pada model memiliki hubungan yang kuat. Ada atau tidak multikolinearitas dapat dilihat dari nilai VIF(Variance Inflation Factor).

VIF dibagi menjadi beberapa nilai berikut:

  • 1 = tidak berkorelasi antar prediktornya
  • antara 1 dan 5 = korelasinya moderate
  • Lebih besar 5 = paling kuat berkorelasi antar prediktornya
  • Biasanya VIF lebih besar 10 adalah yang menunjukkan variabel prediktor sangat berkorelasi kuat.

Ketika nilai VIF > 10 maka ada hubungan yang kuat antar prediktor. Yang diingkan ketika membuat model, nilai VIF < 10 agar tidak ada hubungan antar prediktor.

from statsmodels.stats.outliers_influence import variance_inflation_factor
import statsmodels.api as sm

vif = [variance_inflation_factor(X[['K..Mandi', 'K..Tidur', 'L..Bangunan']].values, i) for i in range(len(X[['K..Mandi', 'K..Tidur', 'L..Bangunan']].columns))]
pd.Series(data=vif, index = X[['K..Mandi', 'K..Tidur', 'L..Bangunan']].columns).sort_values(ascending=False)
K..Mandi      16.904
K..Tidur      14.499
L..Bangunan    7.280
dtype: float64

Jika terjadi multicollinearity, yang bisa dilakukan adalah:

  • Membuang salah satu variabel
  • Membuat variabel baru, dari rata-rata nilai kedua variabel

Leave a comment