LBB Regression Model: Abalone Ring Prediction
Introduction
Background
Linear Regression adalah model statistik yang menguji hubungan linear anatara dua variabel atau lebih. Variabel-variabel tersebut dikenal dengan istilah variabel terikat (dependent variable) dan variabel bebas (independent variable). Dimana:
- Dependent Variable adalah faktor utama yang ingin kita prediksi; target variable (numeric)
- Independent Variable adalah faktor-faktor yang kita hipotesa memiliki pengaruh terhadap target variable; predictor variable (numerical/categorical)
Hubungan linier pada dasarnya berarti bahwa ketika satu (atau lebih) variabel independen meningkat (atau menurun), variabel dependen meningkat (atau menurun) juga.
Linear regression adalah pendekatan untuk memprediksi target variable menggunakan predictor variable. Diasumsikan bahwa kedua variabel tersebut memiliki hubungan linear. Oleh karena itu, dalam linear regression, kita akan mencoba mencari fungsi linear yang memprediksi nilai target variable (y) seakurat mungkin sebagai fungsi dari predictor variable (x)
dimana :
\(m\) = kemiringan garis (slope)
\(c\) = intersep
Jadi pada dasarnya, algoritma linear regression memberi kita nilai paling optimal untuk intersep dan slope (dalam dua dimensi). Variabel y dan x tetap sama, karena merupakan fitur data dan tidak dapat diubah. Nilai yang bisa kita kendalikan adalah intersep (c) dan slope (m). Pada dasarnya apa yang dilakukan oleh algoritma linear regression adalah menyesuaikan beberapa baris pada titik data dan mengembalikan garis yang memiliki kesalahan (error) paling kecil.
Objective
Tujuan dari dibuatnya Learning By Building (LBB) ini adalah :
- Membuat model linear regression pada dataset Abalone melakukan prediksi ukuran ring abolone berdasarkan pengukuran fisiknya.
- Melakukan uji validitas terhadap model yang telah dibuat.
- Melakukan interpretasi dan rekomendasi terhadap hasil prediksi menggunakan model linear regression
Data
Pada kesempatan kali ini saya akan melakukan pembuatan model linear regression menggunakan dataset Abalone. Dimana dataset tersebut berisi informasi dari ukuran fisik pada abalone, dari informasi tersebut kita dapat menentukan umur dari abalone itu sendiri.
Import Library
Pada Learning By Building: Linear Regression kita akan menggunakan beberapa library yang memiliki fungsi masing-masing, library yang digunakan antara lain :
dplyr: Digunakan dalam melakukan proses EDA maupun Data Manipulation.GGally: Digunakan untuk membuat correlation matrix plot setiap variabel.MLmetrics: Digunakan pada tahap evaluasi model.performance: Digunakan ketika ingin membandingkan performa antar model.lmtest: Digunakan saat ingin melakukan uji Breusch-Pagan.car: Digunakan saat melakukan uji Multikolinearitas.stringr: Digunakan saat tahap cleansing
library(dplyr) # Tools EDA/ Data Manipulation
library(GGally) # Tools plot korelasi
library(MLmetrics) # Tools evaluation model
library(performance) # Tools perbandingan performa antar model
library(lmtest) # Tools Uji Breusch-Pagan
library(car) # Tools Uji Multikolinearitas
library(stringr) # Tools cleansingImport Data
Dataset yang digunakan adalah abalone.csv untuk
mengimpor dataset tersebut kita akan menggunakan fungsi
read.csv() dan akan disimpan ke dalam variabel
abalone :
abalone <- read.csv('Data Input/abalone.csv')Selanjutnya untuk langkah awal, kita akan menggunakan fungsi
head() pada variabel caruntuk melihat apakah
file Quikr_car.csv sudah berhasil disimpan di variabel
abalone:
head(abalone)Proses memasukan dataset abalone sudah berhasil dilakukan dan selanjutnya kita akan melakukan proses Exploratory Data Analysis.
Exploratory Data Analysis
Data abalone merupakan data hasil observarsi
pengukuran fisik dari abalone. Untuk mengetahui jumlah baris
dan kolom kita akan menggunakan fungsi dim()
dim(abalone)#> [1] 4177 9
Data abalone memiliki 4177 baris dan 9 kolom, berikut adalah deskripsi kolom pada dataset abalone :
| Name | Data Type | Measurement Unit | Description |
|---|---|---|---|
| Sex | nominal | - | M, F, and I (infant) |
| Length | continuous | mm | Longest shell measurement |
| Diameter | continuous | mm | perpendicular to length |
| Height | continuous | mm | with meat in shell |
| Whole weight | continuous | grams | whole abalone |
| Shucked weight | continuous | grams | weight of meat |
| Viscera weight | continuous | grams | gut weight (after bleeding) |
| Shell weight | continuous | grams | after being dried |
| Rings | integer | – | +1.5 gives the age in years |
Missing Values Check
Selanjutnya kita akan melakukan pengecekan missing
values kita dapat menggunakan kombinasi fungsi
colSums() dan is.na(), sebagai berikut :
colSums(is.na(abalone))#> Sex Length Diameter Height Whole.weight
#> 0 0 0 0 0
#> Shucked.weight Viscera.weight Shell.weight Rings
#> 0 0 0 0
Jika dilihat dari hasil pengecekan di atas, data abalone tidak memiliki missing values. Sehingga kita dapat melanjutkan ke tahap selanjutnya.
Data Types
Pada tahap ini kita akan memastikan bahwa tipe data pada
data abalone sudah sesuai dengan semestinya. Untuk
melakukan pengecekan tersebut kita harus mengetahui tipe data saat ini.
Terdapat beberapa fungsi yang bisa menampilkan informasi tersebut
seperti glimpse(), head(), str(),
dan lainya. Pada kesempatan ini saya akan menggunakan fungsi
glimpse() untuk melihat tipe data abalone.
glimpse(abalone)#> Rows: 4,177
#> Columns: 9
#> $ Sex <chr> "M", "M", "F", "M", "I", "I", "F", "F", "M", "F", "F", …
#> $ Length <dbl> 0.455, 0.350, 0.530, 0.440, 0.330, 0.425, 0.530, 0.545,…
#> $ Diameter <dbl> 0.365, 0.265, 0.420, 0.365, 0.255, 0.300, 0.415, 0.425,…
#> $ Height <dbl> 0.095, 0.090, 0.135, 0.125, 0.080, 0.095, 0.150, 0.125,…
#> $ Whole.weight <dbl> 0.5140, 0.2255, 0.6770, 0.5160, 0.2050, 0.3515, 0.7775,…
#> $ Shucked.weight <dbl> 0.2245, 0.0995, 0.2565, 0.2155, 0.0895, 0.1410, 0.2370,…
#> $ Viscera.weight <dbl> 0.1010, 0.0485, 0.1415, 0.1140, 0.0395, 0.0775, 0.1415,…
#> $ Shell.weight <dbl> 0.150, 0.070, 0.210, 0.155, 0.055, 0.120, 0.330, 0.260,…
#> $ Rings <int> 15, 7, 9, 10, 7, 8, 20, 16, 9, 19, 14, 10, 11, 10, 10, …
Jika dilihat dari hasil pengecekan tipe data menggunakan
glimpse() pada data abalone terdapat
kolom/variabel yang memiliki tipe data yang kurang tepat. Seperti yang
kita ketahui sebelumnya di deskirpsi kolom pada bagian Exploratory Data Analysis.
Terdapat kolom yang nilainya merepresentasikan sebuah kategori. Kolom
tersebut adalah Sex sehingga kita perlu melakukan perubahan
tipe data dari chr menjadi fct.Selanjutnya
kita akan merubah kolom Sex menggunakan fungsi
mutate() dari package dplyr dikombinasikan
dengan fungsi as.factor() dan
as.integer().
abalone <- abalone %>%
mutate(Sex = as.factor(Sex))
glimpse(abalone)#> Rows: 4,177
#> Columns: 9
#> $ Sex <fct> M, M, F, M, I, I, F, F, M, F, F, M, M, F, F, M, I, F, M…
#> $ Length <dbl> 0.455, 0.350, 0.530, 0.440, 0.330, 0.425, 0.530, 0.545,…
#> $ Diameter <dbl> 0.365, 0.265, 0.420, 0.365, 0.255, 0.300, 0.415, 0.425,…
#> $ Height <dbl> 0.095, 0.090, 0.135, 0.125, 0.080, 0.095, 0.150, 0.125,…
#> $ Whole.weight <dbl> 0.5140, 0.2255, 0.6770, 0.5160, 0.2050, 0.3515, 0.7775,…
#> $ Shucked.weight <dbl> 0.2245, 0.0995, 0.2565, 0.2155, 0.0895, 0.1410, 0.2370,…
#> $ Viscera.weight <dbl> 0.1010, 0.0485, 0.1415, 0.1140, 0.0395, 0.0775, 0.1415,…
#> $ Shell.weight <dbl> 0.150, 0.070, 0.210, 0.155, 0.055, 0.120, 0.330, 0.260,…
#> $ Rings <int> 15, 7, 9, 10, 7, 8, 20, 16, 9, 19, 14, 10, 11, 10, 10, …
Setelah tipe data sudah sesuai kita akan melakukan pengecekan Outlier.
Outlier Check
Pada langkah ini, kita akan membuat boxplot pada
setiap kolom yang memiliki tipe data int menggunakan fungsi
boxplot() dan menambahkan $out untuk
menampilkan nilai yang outlier.
boxplot(abalone$Length)$out#> [1] 0.175 0.170 0.075 0.130 0.110 0.160 0.200 0.165 0.190 0.175 0.200 0.175
#> [13] 0.155 0.195 0.165 0.155 0.180 0.150 0.160 0.185 0.195 0.195 0.200 0.185
#> [25] 0.140 0.185 0.135 0.160 0.130 0.180 0.165 0.190 0.170 0.180 0.175 0.155
#> [37] 0.200 0.190 0.180 0.200 0.200 0.165 0.190 0.165 0.175 0.170 0.140 0.160
#> [49] 0.185
boxplot(abalone$Diameter)$out#> [1] 0.150 0.150 0.130 0.130 0.055 0.100 0.090 0.120 0.145 0.120 0.145 0.125
#> [13] 0.150 0.140 0.125 0.110 0.145 0.110 0.105 0.125 0.100 0.110 0.140 0.120
#> [25] 0.130 0.150 0.135 0.105 0.135 0.130 0.110 0.150 0.095 0.130 0.115 0.130
#> [37] 0.150 0.125 0.125 0.135 0.115 0.145 0.150 0.140 0.150 0.135 0.150 0.145
#> [49] 0.125 0.130 0.120 0.150 0.150 0.125 0.130 0.105 0.105 0.120 0.135
boxplot(abalone$Height)$out#> [1] 0.010 0.030 0.030 0.035 0.030 0.020 0.035 0.025 0.025 0.015 0.000 0.515
#> [13] 0.250 0.035 0.250 0.025 1.130 0.035 0.015 0.030 0.030 0.250 0.025 0.030
#> [25] 0.025 0.035 0.035 0.020 0.000
boxplot(abalone$Whole.weight)$out#> [1] 2.5500 2.4990 2.8255 2.5550 2.3020 2.2730 2.2360 2.5050 2.6570 2.2500
#> [11] 2.5085 2.2550 2.2205 2.5155 2.7795 2.2260 2.5260 2.3810 2.3980 2.3305
#> [21] 2.2355 2.3235 2.2305 2.2635 2.2695 2.4925 2.3330 2.5480 2.3810 2.2385
boxplot(abalone$Shucked.weight)$out#> [1] 1.0705 1.1465 1.0120 1.1335 1.0070 1.0950 1.0465 1.0265 1.0260 1.1090
#> [11] 1.1965 1.4880 1.1075 1.0465 1.1565 1.2320 1.0170 1.3510 0.9895 0.9925
#> [21] 1.1455 1.0300 1.0830 1.1155 1.3485 1.0715 1.0815 1.0685 0.9915 1.1280
#> [31] 1.0515 1.0050 1.0615 1.1055 1.2530 1.1705 1.1495 0.9815 0.9955 1.2395
#> [41] 1.0135 1.1455 1.2395 1.2455 1.1945 1.1330 1.0745 0.9840
boxplot(abalone$Viscera.weight)$out#> [1] 0.5410 0.5225 0.5090 0.5500 0.5195 0.5130 0.4985 0.5640 0.5190 0.4925
#> [11] 0.5195 0.5185 0.6415 0.7600 0.5900 0.5005 0.5120 0.5265 0.5235 0.5250
#> [21] 0.5410 0.5115 0.5750 0.5145 0.5745 0.5260
boxplot(abalone$Shell.weight)$out#> [1] 0.6750 0.7800 0.6350 1.0050 0.8150 0.7250 0.8500 0.6500 0.7600 0.6900
#> [11] 0.7100 0.7000 0.8970 0.6380 0.6785 0.7975 0.6300 0.6420 0.6430 0.6460
#> [21] 0.6585 0.8850 0.7250 0.8850 0.6650 0.6850 0.6600 0.7260 0.6855 0.7100
#> [31] 0.7250 0.6650 0.6745 0.6550 0.6570
boxplot(abalone$Rings)$out#> [1] 20 16 19 18 19 16 20 16 21 19 18 17 16 16 18 16 20 20 21 16 22 1 3 3 17
#> [26] 19 22 16 22 18 20 17 17 19 26 3 21 19 23 23 18 16 16 22 16 20 18 17 16 18
#> [51] 20 16 19 17 16 16 19 20 16 20 20 16 18 19 21 18 18 20 18 22 19 16 18 16 16
#> [76] 17 17 21 17 17 21 16 29 17 19 17 19 23 17 16 3 3 20 17 16 20 17 17 19 18
#> [101] 19 16 17 18 18 17 21 19 17 16 18 18 19 17 19 21 23 22 23 16 16 16 2 3 17
#> [126] 18 17 20 17 17 20 20 16 17 17 21 17 17 3 3 3 16 17 19 27 3 16 18 16 17
#> [151] 19 17 20 21 16 21 25 19 18 16 27 18 17 17 17 17 17 17 18 20 19 23 16 16 17
#> [176] 17 23 23 18 17 17 21 17 16 19 18 17 17 20 18 18 19 16 3 16 16 17 17 16 18
#> [201] 18 18 16 16 23 16 20 17 16 20 18 19 3 20 24 21 18 16 20 18 17 17 16 16 18
#> [226] 16 18 19 18 17 17 18 18 24 17 16 16 16 16 17 16 19 16 16 16 17 20 19 17 17
#> [251] 16 19 19 18 16 19 18 18 3 3 3 16 16 18 19 16 16 17 16 16 19 18 20 16 21
#> [276] 17 20 16
Jika kita perhatikan bahwa pada data abalone memilik9
beberapa nilai outliers, tetapi saya akan tetap
menggunakannya dikarenakan agar jumlah data nya akan tetap digunakan
untuk modelling.
Variable Correlation
Sebelum dilakukan pembuatan model linear regression kita
perlu untuk melakukan pengecekan korelasi antara target
variable dengan predictor dengan data
type numerik. Pada kasus ini kita ingin melakukan prediksi terhadap
ukuran Rings suatu abalone berdasarkan dataframe
abalone, maka target variable nya adalah
kolom Rings. Untuk melakukan pengecekan korelasi kita akan
menggunakan fungsi ggcorr() dari package
GGally.
ggcorr(abalone, label = TRUE, label_size = 3, hjust =1)Jika kita lihat pada correlation matrix diatas
secara umum variabel-variabel prediktor memiliki nilai korelasi
positif terhadap target variable. Dimana
sebagai asumsi awal bahwa variabel-variabel prediktor tersebut jika
nilai nya meningkat maka kolom Rings akan
meningkat.
Cross-Validation
Sebelum memasuki tahap modelling, dataframe
abalone akan melalui tahap data
pre-processing terlebih dahulu yaitu
cross-validation. Tujuan dilakukannya
cross-validation adalah membagi dataset kita menjadi
dua bagian, yaitu data train dan test yang
nanti kedepannya kita akan menggunakan data train untuk
pembuatan model, sedangkan untuk data test akan digunakan
untuk evaluasi model. Mengapa perlu dilakukan pembagian tersebut?
dikarenakan agar kita melakukan evaluasi tidak menggunakan informasi
yang sama saat melakukan pemodelan, sehingga hasil evaluasi dapat
dibilang akan lebih ‘nyata’ karena data yang dilakukan evaluasi belum
pernah dimasukan ke dalam model.
Kita akan menggunakan fungsi RNGkind() dan
set.seed() untuk menghasilkan kombinasi angka random yang
akan mengontrol saat dilakukannya splitting data.
RNGkind(sample.kind = 'Rounding')
set.seed(666)Selanjutnya kita akan membagi data kita dengan ratio 80:20, fungsi
yang digunakan adalah sample() yang akan di assign
ke variabel index. Nantinya variabel index
akan digunakan untuk subsetting pada data
abalone.
index <- sample(nrow(abalone), size = nrow(abalone)*0.8)
abalone_train <- abalone[index,]
abalone_test <- abalone[-index,]Setelah dilakukan pemisahan data menjadi abalone_train
dan abalone_test, maka kita dapat melakukan tahap
selanjutnya yaitu modelling menggunakan data
abalone_train.
Create Model
Kita akan membuat model multiple linear regression
menggunakan semua variabel prediktor, dengan target variabel
Rings. Untuk membuat model tersebut kita akan menggunakan
fungsi lm() dengan data abalone_train.
model_abalone_all <- lm(Rings ~ ., abalone_train)Salah satu metric untuk melihat performa atau evaluasi dari suatu
model multiple linear regression menggunakan nilai adj
r-squared yang bisa di dapatkan dari hasil fungsi
summary().
summary(model_abalone_all)#>
#> Call:
#> lm(formula = Rings ~ ., data = abalone_train)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -8.5924 -1.3097 -0.3296 0.8674 13.6010
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 3.92774 0.32958 11.917 < 2e-16 ***
#> SexI -0.80231 0.11582 -6.927 5.13e-12 ***
#> SexM 0.05156 0.09339 0.552 0.581
#> Length -1.13283 1.99866 -0.567 0.571
#> Diameter 12.40536 2.46263 5.037 4.97e-07 ***
#> Height 8.91110 1.61918 5.503 4.01e-08 ***
#> Whole.weight 10.16770 0.81447 12.484 < 2e-16 ***
#> Shucked.weight -20.90954 0.92043 -22.717 < 2e-16 ***
#> Viscera.weight -12.31069 1.45151 -8.481 < 2e-16 ***
#> Shell.weight 7.76846 1.24944 6.218 5.68e-10 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 2.205 on 3331 degrees of freedom
#> Multiple R-squared: 0.545, Adjusted R-squared: 0.5438
#> F-statistic: 443.4 on 9 and 3331 DF, p-value: < 2.2e-16
Jika dilihat dari hasil summary() kita dapat melakukan
beberapa interpretasi terhadap model tersebut :
- Beberapa variabel prediktor memiliki nilai slope
positif yang berarti naiknya 1 nilai pada variabel prediktor
tersebut akan menambahkan nilai sebesar slope variabel dari target
variabel atau
Rings. Variabel tersebut adalahSexM,Diameter,Height,Whole.weightdanShell.weight. - Begitupun sebaliknya variabel prediktor yang memiliki nilai
slope negatif yang berarti naiknya 1 nilai pada
variabel tersebut akan mengurangkan nilai sebesar slope variabel dari
target variabel atau
Rings. Variabel tersebut adalahSexI,Length,Shucked.weightdanViscera.weight. - Jika dilihat dari p-value terdapat variabel yang tidak signifikan di
model tersebut yaitu
SexMdanLength. model_abalone_allmemiliki nilai adjusted R-squared sebesari 54.38%
Tuning Model (Stepwise)
Selanjutnya kita akan mencoba tuning model menggunakan dengan metode
stepwise, fungsi yang digunakan adalah
step(). Kita akan menggunakan
model_abalone_all sebagai object, dengan parameter
direction ‘backward’.
model_abalone_backward <- step(object = model_abalone_all,
direction = 'backward',
trace = 0)kita dapat melihat hasil model_abalone_backward
menggunakan fungsi summary()
summary(model_abalone_backward)#>
#> Call:
#> lm(formula = Rings ~ Sex + Diameter + Height + Whole.weight +
#> Shucked.weight + Viscera.weight + Shell.weight, data = abalone_train)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -8.5698 -1.3077 -0.3312 0.8647 13.6374
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 3.86685 0.31155 12.412 < 2e-16 ***
#> SexI -0.80661 0.11556 -6.980 3.55e-12 ***
#> SexM 0.05085 0.09337 0.545 0.586
#> Diameter 11.15705 1.10170 10.127 < 2e-16 ***
#> Height 8.89560 1.61878 5.495 4.19e-08 ***
#> Whole.weight 10.16941 0.81438 12.487 < 2e-16 ***
#> Shucked.weight -20.94418 0.91831 -22.807 < 2e-16 ***
#> Viscera.weight -12.39125 1.44439 -8.579 < 2e-16 ***
#> Shell.weight 7.79350 1.24853 6.242 4.86e-10 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 2.205 on 3332 degrees of freedom
#> Multiple R-squared: 0.545, Adjusted R-squared: 0.5439
#> F-statistic: 498.9 on 8 and 3332 DF, p-value: < 2.2e-16
Dari hasil tersebut kita dapat menginterpretasikan sebagai berikut:
- Jika dilihat dari variabel prediktor yang digunakan, pada
model_abalone_backwardtidak menggunakan variabelLength. - Nilai adjusted R-squared pada model tersebut sedikit lebih baik
dibandingkan
model_abalone_alldengan nilai 54.39%.
Prediction
Ketika kita sudah memiliki model_abalone_all dan
model_abalone_backward, kita dapat melakukan prediksi
menggunakan data abalone_test sehingga kita bisa
menggunakan hasil predikisi tersebut untuk dilakukannya evaluasi. Untuk
melakukan prediksi sebuah data kita akan menggunakan fungsi
predict().
pred_abalone_all <- predict(
object = model_abalone_all,
newdata = abalone_test,
interval = 'prediction',
level = 0.95
)
head(pred_abalone_all)#> fit lwr upr
#> 1 9.292264 4.964093 13.62043
#> 5 6.781816 2.454521 11.10911
#> 13 10.605720 6.278030 14.93341
#> 15 10.468863 6.139252 14.79847
#> 16 11.122350 6.794977 15.44972
#> 22 7.674684 3.347691 12.00168
pred_abalone_backward <- predict(
object = model_abalone_backward,
newdata = abalone_test,
interval = 'prediction',
level = 0.95
)
head(pred_abalone_backward)#> fit lwr upr
#> 1 9.277729 4.950292 13.60517
#> 5 6.766354 2.439831 11.09288
#> 13 10.613264 6.286094 14.94043
#> 15 10.488872 6.160256 14.81749
#> 16 11.113333 6.786513 15.44015
#> 22 7.690938 3.364751 12.01712
Model Evaluation
Dikarenakan tujuan dari pembuatan model adalah untuk menghasilkan
sebuah prediksi dari sebuah data baru (dalam kasus ini menggunakan data
abalone_test). Maka diperlukan sebuah evaluasi dari model
tersebut untuk melihat apakah model yang sudah kita buat sudah cocok
dengan data yang kita gunakan apa belum. Kita akan melakukan evaluasi
menggunakan MAPE.
Mean Absolute Percentage Error (MAPE)
MAPE menunjukkan seberapa besar penyimpangannya dalam bentuk
persentase. Untuk melakukan perhitungan error tersebut kita akan
menggunakan fungsi MAPE().
\[ MAPE = \frac{1}{n} \sum\frac{|\hat y - y|}{y} \]
MAPE(y_pred = pred_abalone_all, y_true = abalone_test$Rings)#> [1] 0.3879198
MAPE(y_pred = pred_abalone_backward, y_true = abalone_test$Rings)#> [1] 0.3877925
Dapat dilihat bahwa nilai MAPE dari
model_abalone_all dan model_abalone_backward
tidak berbeda jauh. Nilai MAPE model_abalone_all sebesar
38.79%, sedangkan model_abalone_backward
memiliki error sebesar 38.77%.
Assumption Check
Terdapat beberapa asumsi yang diterapkan oleh model. Regresi linear memiliki beberapa asumsi yang perlu dipenuhi agar interpretasi yang didapatkan tidak bersifat bias. Asumsi ini hanya perlu dipenuhi jika tujuan membuat model regresi linear adalah menginginkan interpretasi atau melihat efek dari setiap prediktor terhadap nilai target variabel. Jika hanya ingin menggunakan regresi linear untuk melakukan prediksi, maka asumsi model tidak wajib dipenuhi.
Linearity
Untuk menguji apakah variabel target dan prediktor memiliki hubungan
linear. Dapat dilihat dengan nilai korelasi menggunakan function
ggcorr() atau dapat menggunakan uji statistik
cor.test(). (ingin mendapatkan p-value < alpha agar
tolak \(H_0\))
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.
Linearity hypothesis test:
\[ H_0: korelasi\ tidak\ signifikan\\ H_1: korelasi\ signifikan \]
ggcorr(abalone, label= T, label_size = 3, hjust = 1)Normality of Residual
Harapannya ketika membuat model linear regression, error yang dihasilkan berdistribusi normal. Artinya error banyak berkumpul disekitar angka 0. Untuk menguji asumsi ini dapat dilakukan:
Uji statistik menggunakan shapiro.test(). (harapannya
pvalue > alpha agar keputusan yang diambil adalah gagal tolak H0)
H0: error berdistribusi normal H1: error tidak berdistribusi normal
harapannya p-value > 0.05
Shapiro-Wilk hypothesis test:
hist(model_abalone_all$residuals)shapiro.test(model_abalone_all$residuals)#>
#> Shapiro-Wilk normality test
#>
#> data: model_abalone_all$residuals
#> W = 0.92577, p-value < 2.2e-16
shapiro.test(model_abalone_backward$residuals)#>
#> Shapiro-Wilk normality test
#>
#> data: model_abalone_backward$residuals
#> W = 0.92544, p-value < 2.2e-16
Jika dilhat dari hasil shapiro.tes() nilai
residual/error pada hasil prediksi tidak berdistribusi normal, yang mana
artinya dari hasil prediksi errornya banyak yang mengumpul di titik
0.
Homoscedasticity of Residual
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 yang bias (terlalu sempit atau
terlalu lebar).
Homocesdasticity bisa dicek secara visual dengan melihat apakah ada pola antara hasil prediksi dari data dengan nilai residualnya. Pada plot berikut terlihat bahwa tidak terdapat pola tertentu sehingga kita bisa menyimpulkan bahwa model sudah memiliki error yang konstan.
Berikut adalah beberapa pola yang dapat terbentuk dan menyebabkan
Heteroscesdasticity.
Breusch-Pagan hypothesis test: (harapannya p-value > alpha agar gagal tolak H0)
\[ H_0: Variansi\ error\ menyebar\ konstan\ (Homoscedasticity)\\ H_1: Variansi\ error\ menyebar\ tidak\ konstan\ membentuk\ pola\ (Heteroscedasticity) \]
bptest(model_abalone_all)#>
#> studentized Breusch-Pagan test
#>
#> data: model_abalone_all
#> BP = 345.29, df = 9, p-value < 2.2e-16
bptest(model_abalone_backward)#>
#> studentized Breusch-Pagan test
#>
#> data: model_abalone_backward
#> BP = 338.77, df = 8, p-value < 2.2e-16
Nilai dari hasil bptest() kedua model memiliki p-value
lebih kecil dari 0.05 yang berarti bahwa variansi error menyebar tidak
konstan membentuk pola (Heteroscedasticity).
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):
Ketika nilai VIF lebih dari 10 artinya terjadi multikolinearitas. Harapannya mendapatkan VIF < 10
vif(model_abalone_all)#> GVIF Df GVIF^(1/(2*Df))
#> Sex 1.558553 2 1.117327
#> Length 39.522842 1 6.286719
#> Diameter 40.913532 1 6.396369
#> Height 3.271041 1 1.808602
#> Whole.weight 111.232730 1 10.546693
#> Shucked.weight 28.774969 1 5.364230
#> Viscera.weight 17.627981 1 4.198569
#> Shell.weight 21.154552 1 4.599408
vif(model_abalone_backward)#> GVIF Df GVIF^(1/(2*Df))
#> Sex 1.551196 2 1.116006
#> Diameter 8.190034 1 2.861823
#> Height 3.270109 1 1.808344
#> Whole.weight 111.231196 1 10.546620
#> Shucked.weight 28.648145 1 5.352396
#> Viscera.weight 17.458938 1 4.178389
#> Shell.weight 21.128100 1 4.596531
Dari hasil uji multikolinearitas pada kedua model, masih terdapat
variabel yang memiliki nilai VIF lebih dari 10 yaitu
Whole.weight dikarenakan kolom ini merupakan berat total
dari abalone tersebut.
Conclusion
Dapat disimpulkan dari pembuatan kedua model multiple linear regression sebagai berikut:
- Nilai Adjusted R-squared dari kedua model tersebut tidak berbeda
jauh dengan nilai 54.38% untuk
model_abalone_allsedangkan padamodel_abalone_backwardmemiliki nilai 54.39%. - Nilai MAPE pada
model_abalone_allsebesar 38.79%, sedangkan untukmodel_abalone_backwardsebesar 38.77%. - Dari uji asumsi linearity semua variabel prediktor memiliki hubungan linear dengan target variabel.
- Nilai residual/error pada hasil prediksi tidak berdistribusi normal.
- Variansi error dari kedua model menyebar tidak konstan membentuk pola (Heteroscedasticity).
- Terdapat Multikolinearitas pada variabel
Whole.weight.
A work by Muhammad Yusuf Ibrahim
myusufibrahim@outlook.com