1. Hello World
Selamat datang di Rmd saya. Rmd ini saya buat untuk meningkatkan pemahaman saya tentang Machine Learning dengan Model Regresi Linier menggunakan bahasa R.
2. Business Goal
Kita diminta untuk memodelkan harga mobil dengan variabel bebas yang tersedia. Ini akan digunakan oleh manajemen untuk memahami bagaimana sebenarnya harga bervariasi dengan variabel independen. Oleh karena itu, mereka dapat memanipulasi desain mobil, strategi bisnis, dll. untuk memenuhi tingkat harga tertentu. Selanjutnya, model tersebut akan menjadi cara yang baik bagi manajemen untuk memahami dinamika harga pasar baru.
3. Brief explanation about the data
Dataset berisi beberapa parameter yang dianggap berpengaruh terhadap harga mobil.
3.1. Import Data
df1 <- read.csv("CarPrice_Assignment.csv")
rmarkdown::paged_table(df1)
3.2. Meta Data
Car_ID : Unique id of each observation (Interger)
Symboling : Its assigned insurance risk rating, A value of +3 indicates that the auto is risky, -3 that it is probably pretty safe.(Categorical)
carCompany : Name of car company (Categorical)
fueltype : Car fuel type i.e gas or diesel (Categorical)
aspiration : Aspiration used in a car (Categorical)
doornumber : Number of doors in a car (Categorical)
carbody : body of car (Categorical)
rivewheel : type of drive wheel (Categorical)
enginelocation : Location of car engine (Categorical)
wheelbase : Weelbase of car (Numeric)
carlength : Length of car (Numeric)
carwidth : Width of car (Numeric)
carheight : height of car (Numeric)
curbweight : The weight of a car without occupants or baggage. (Numeric)
enginetype : Type of engine. (Categorical)
cylindernumber : cylinder placed in the car (Categorical)
enginesize : Size of car (Numeric)
fuelsystem : Fuel system of car (Categorical)
boreratio : Boreratio of car (Numeric)
stroke : Stroke or volume inside the engine (Numeric)
compressionratio : compression ratio of car (Numeric)
horsepower : Horsepower (Numeric)
peakrpm : car peak rpm (Numeric)
citympg : Mileage in city (Numeric)
highwaympg : Mileage on highway (Numeric)
price(Dependent variable) : Price of car (Numeric)
4. Data Wrangling
Di tahapan ini akan dilakukan inspeksi secara mendalam serta perbaikan terhadap data set yang digunakan, agar nanti data ini dapat siap dipakai untuk pemodelan menggunakan machine learning.
4.1. Look deeper into the column with character data type
i = 1
while (i < 27){
s <- df1 %>% select(i)
t <- df1[,i]
if (is.character(t) == TRUE) {
print(colnames(s))
print(unique(t))
print("~~~~~~~**~~~~~~~")
}
else {
print("###")
}
i = i +1
}
## [1] "###"
## [1] "###"
## [1] "CarName"
## [1] "alfa-romero giulia" "alfa-romero stelvio"
## [3] "alfa-romero Quadrifoglio" "audi 100 ls"
## [5] "audi 100ls" "audi fox"
## [7] "audi 5000" "audi 4000"
## [9] "audi 5000s (diesel)" "bmw 320i"
## [11] "bmw x1" "bmw x3"
## [13] "bmw z4" "bmw x4"
## [15] "bmw x5" "chevrolet impala"
## [17] "chevrolet monte carlo" "chevrolet vega 2300"
## [19] "dodge rampage" "dodge challenger se"
## [21] "dodge d200" "dodge monaco (sw)"
## [23] "dodge colt hardtop" "dodge colt (sw)"
## [25] "dodge coronet custom" "dodge dart custom"
## [27] "dodge coronet custom (sw)" "honda civic"
## [29] "honda civic cvcc" "honda accord cvcc"
## [31] "honda accord lx" "honda civic 1500 gl"
## [33] "honda accord" "honda civic 1300"
## [35] "honda prelude" "honda civic (auto)"
## [37] "isuzu MU-X" "isuzu D-Max "
## [39] "isuzu D-Max V-Cross" "jaguar xj"
## [41] "jaguar xf" "jaguar xk"
## [43] "maxda rx3" "maxda glc deluxe"
## [45] "mazda rx2 coupe" "mazda rx-4"
## [47] "mazda glc deluxe" "mazda 626"
## [49] "mazda glc" "mazda rx-7 gs"
## [51] "mazda glc 4" "mazda glc custom l"
## [53] "mazda glc custom" "buick electra 225 custom"
## [55] "buick century luxus (sw)" "buick century"
## [57] "buick skyhawk" "buick opel isuzu deluxe"
## [59] "buick skylark" "buick century special"
## [61] "buick regal sport coupe (turbo)" "mercury cougar"
## [63] "mitsubishi mirage" "mitsubishi lancer"
## [65] "mitsubishi outlander" "mitsubishi g4"
## [67] "mitsubishi mirage g4" "mitsubishi montero"
## [69] "mitsubishi pajero" "Nissan versa"
## [71] "nissan gt-r" "nissan rogue"
## [73] "nissan latio" "nissan titan"
## [75] "nissan leaf" "nissan juke"
## [77] "nissan note" "nissan clipper"
## [79] "nissan nv200" "nissan dayz"
## [81] "nissan fuga" "nissan otti"
## [83] "nissan teana" "nissan kicks"
## [85] "peugeot 504" "peugeot 304"
## [87] "peugeot 504 (sw)" "peugeot 604sl"
## [89] "peugeot 505s turbo diesel" "plymouth fury iii"
## [91] "plymouth cricket" "plymouth satellite custom (sw)"
## [93] "plymouth fury gran sedan" "plymouth valiant"
## [95] "plymouth duster" "porsche macan"
## [97] "porcshce panamera" "porsche cayenne"
## [99] "porsche boxter" "renault 12tl"
## [101] "renault 5 gtl" "saab 99e"
## [103] "saab 99le" "saab 99gle"
## [105] "subaru" "subaru dl"
## [107] "subaru brz" "subaru baja"
## [109] "subaru r1" "subaru r2"
## [111] "subaru trezia" "subaru tribeca"
## [113] "toyota corona mark ii" "toyota corona"
## [115] "toyota corolla 1200" "toyota corona hardtop"
## [117] "toyota corolla 1600 (sw)" "toyota carina"
## [119] "toyota mark ii" "toyota corolla"
## [121] "toyota corolla liftback" "toyota celica gt liftback"
## [123] "toyota corolla tercel" "toyota corona liftback"
## [125] "toyota starlet" "toyota tercel"
## [127] "toyota cressida" "toyota celica gt"
## [129] "toyouta tercel" "vokswagen rabbit"
## [131] "volkswagen 1131 deluxe sedan" "volkswagen model 111"
## [133] "volkswagen type 3" "volkswagen 411 (sw)"
## [135] "volkswagen super beetle" "volkswagen dasher"
## [137] "vw dasher" "vw rabbit"
## [139] "volkswagen rabbit" "volkswagen rabbit custom"
## [141] "volvo 145e (sw)" "volvo 144ea"
## [143] "volvo 244dl" "volvo 245"
## [145] "volvo 264gl" "volvo diesel"
## [147] "volvo 246"
## [1] "~~~~~~~**~~~~~~~"
## [1] "fueltype"
## [1] "gas" "diesel"
## [1] "~~~~~~~**~~~~~~~"
## [1] "aspiration"
## [1] "std" "turbo"
## [1] "~~~~~~~**~~~~~~~"
## [1] "doornumber"
## [1] "two" "four"
## [1] "~~~~~~~**~~~~~~~"
## [1] "carbody"
## [1] "convertible" "hatchback" "sedan" "wagon" "hardtop"
## [1] "~~~~~~~**~~~~~~~"
## [1] "drivewheel"
## [1] "rwd" "fwd" "4wd"
## [1] "~~~~~~~**~~~~~~~"
## [1] "enginelocation"
## [1] "front" "rear"
## [1] "~~~~~~~**~~~~~~~"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "enginetype"
## [1] "dohc" "ohcv" "ohc" "l" "rotor" "ohcf" "dohcv"
## [1] "~~~~~~~**~~~~~~~"
## [1] "cylindernumber"
## [1] "four" "six" "five" "three" "twelve" "two" "eight"
## [1] "~~~~~~~**~~~~~~~"
## [1] "###"
## [1] "fuelsystem"
## [1] "mpfi" "2bbl" "mfi" "1bbl" "spfi" "4bbl" "idi" "spdi"
## [1] "~~~~~~~**~~~~~~~"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
## [1] "###"
Proses ini bertujuan untuk melihat secara lebih detil unique value dari data kategorik didalam dataset.
Selain kolom dengan tipe data character akan dicetak “###” sedangkan untuk kolom dengan tipe data character akan di print unique valuenya
4.2. Clean the words that are still typos
df1$CarName <- gsub("maxda", "mazda", df1$CarName)
df1$CarName <- gsub("Nissan", "nissan", df1$CarName)
df1$CarName <- gsub("toyouta", "toyota", df1$CarName)
df1$CarName <- gsub("vw", "volkswagen", df1$CarName)
df1$CarName <- gsub("vokswagen","volkswagen", df1$CarName)
df1$CarName <- gsub("porcshce", "porsche", df1$CarName)
Setelah diinspeksi setiap unique value dari kolom-kolom tersebut, ternyata beberapa kata masih belum tepat penulisannya sehingga harus diperbaiki. Hal ini dikarenakan kemungkinan adanya kesalahan dalam proses penginputan data.
4.3. Create a new column named cars
df1$cars <- sapply(strsplit(df1$CarName," "), "[", 1)
df1$cars <- sapply(gsub("-","_", df1$cars), "[", 1)
Dibuatlah satu kolom tambahan bernama cars, kolom ini berisi merek dari tiap nama mobil didalam dataset. Proses ini dilakukan dengan mengambil 1 kata pertama dari kolom “CarName” kemudian value tersebut dimasukkan kedalam kolom baru bernama cars. Penambahan kolom ini bertujuan agar nantinya saat proses EDA dapat di ekstrak insight lebih dari dataset yang dipakai.
4.4. Set data type
df1 <- df1 %>% mutate_if(is.character, as.factor)
str(df1)
## 'data.frame': 205 obs. of 27 variables:
## $ car_ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ symboling : int 3 3 1 2 2 2 1 1 1 0 ...
## $ CarName : Factor w/ 142 levels "alfa-romero giulia",..: 1 3 2 4 5 9 5 7 6 8 ...
## $ fueltype : Factor w/ 2 levels "diesel","gas": 2 2 2 2 2 2 2 2 2 2 ...
## $ aspiration : Factor w/ 2 levels "std","turbo": 1 1 1 1 1 1 1 1 2 2 ...
## $ doornumber : Factor w/ 2 levels "four","two": 2 2 2 1 1 2 1 1 1 2 ...
## $ carbody : Factor w/ 5 levels "convertible",..: 1 1 3 4 4 4 4 5 4 3 ...
## $ drivewheel : Factor w/ 3 levels "4wd","fwd","rwd": 3 3 3 2 1 2 2 2 2 1 ...
## $ enginelocation : Factor w/ 2 levels "front","rear": 1 1 1 1 1 1 1 1 1 1 ...
## $ wheelbase : num 88.6 88.6 94.5 99.8 99.4 ...
## $ carlength : num 169 169 171 177 177 ...
## $ carwidth : num 64.1 64.1 65.5 66.2 66.4 66.3 71.4 71.4 71.4 67.9 ...
## $ carheight : num 48.8 48.8 52.4 54.3 54.3 53.1 55.7 55.7 55.9 52 ...
## $ curbweight : int 2548 2548 2823 2337 2824 2507 2844 2954 3086 3053 ...
## $ enginetype : Factor w/ 7 levels "dohc","dohcv",..: 1 1 6 4 4 4 4 4 4 4 ...
## $ cylindernumber : Factor w/ 7 levels "eight","five",..: 3 3 4 3 2 2 2 2 2 2 ...
## $ enginesize : int 130 130 152 109 136 136 136 136 131 131 ...
## $ fuelsystem : Factor w/ 8 levels "1bbl","2bbl",..: 6 6 6 6 6 6 6 6 6 6 ...
## $ boreratio : num 3.47 3.47 2.68 3.19 3.19 3.19 3.19 3.19 3.13 3.13 ...
## $ stroke : num 2.68 2.68 3.47 3.4 3.4 3.4 3.4 3.4 3.4 3.4 ...
## $ compressionratio: num 9 9 9 10 8 8.5 8.5 8.5 8.3 7 ...
## $ horsepower : int 111 111 154 102 115 110 110 110 140 160 ...
## $ peakrpm : int 5000 5000 5000 5500 5500 5500 5500 5500 5500 5500 ...
## $ citympg : int 21 21 19 24 18 19 19 19 17 16 ...
## $ highwaympg : int 27 27 26 30 22 25 25 25 20 22 ...
## $ price : num 13495 16500 16500 13950 17450 ...
## $ cars : Factor w/ 22 levels "alfa_romero",..: 1 1 1 2 2 2 2 2 2 2 ...
Dilakukan penyesuaian tipe data, hal ini menjadi sagat penting karena untuk dapat menganalisisnya tiap kolom harus memiliki tipe data yang tepat sesuai dengan value yang ada didalamnya.
Semua kolom yang bertipe data character diubah menjadi factor, kolom dengan tipe data integer dan numeric sudah tepat
4.5. Cek missing value
colSums(is.na(df1))
## car_ID symboling CarName fueltype
## 0 0 0 0
## aspiration doornumber carbody drivewheel
## 0 0 0 0
## enginelocation wheelbase carlength carwidth
## 0 0 0 0
## carheight curbweight enginetype cylindernumber
## 0 0 0 0
## enginesize fuelsystem boreratio stroke
## 0 0 0 0
## compressionratio horsepower peakrpm citympg
## 0 0 0 0
## highwaympg price cars
## 0 0 0
Tidak ada nilai yang kosong di dalam dataset yang dipakai
4.6. Cek Duplicate
ifelse(sum(duplicated(df1)) == 0, "Tidak ada data yang duplikat", "Ada data yang duplikat")
## [1] "Tidak ada data yang duplikat"
5. Simple EDA
Exploratory Data Analysis (EDA) atau dikenal pula dengan analisis data eksploratif merupakan pendekatan analisis untuk suatu data guna membuat gambaran keseluruhan (summary) data sehingga mudah untuk dipahami. Metode analisis ini menyediakan berbagai alat untuk meringkas dan memperoleh wawasan tentang sekumpulan data dengan cepat menggunakan grafik sebagai bentuk visualisasi data, tanpa menggunakan model statistik, atau formulasi hipotesis.
5.1. Facet Grid
ggplot(df1, aes(drivewheel,price, fill = doornumber)) +
geom_boxplot() + facet_grid(fueltype~carbody) +
theme(legend.title = element_text(size=15),
legend.text = element_text(size = 12),
axis.title.x = element_text(size = 15),
axis.title.y = element_text(size = 15),
axis.text.x = element_text(size = 10),
axis.text.y = element_text(size = 10),
strip.text = element_text(size = 12)) +
scale_y_continuous(label = scales::comma_format()) +
labs(title = "Analyze data distribution using facet grid",
subtitle = "Drivewheel x Price x Doornumber x Fueltype x Carbody") +
theme_dark()
Insight :
Sebagian besar mobil yang ada di dataset ini adalah mobil dengan jenis RWD
Mobil dengan jenis RWD juga rata-rata paling mahal diantara jenis lainnya
Mobil RWD didistribusikan di semua kategori carbody
Jenis bahan bakar didominasi oleh gasoline dan masih sedikit mobil yang menggunakan solar
Mobil convertible dan hardtop kebanyakan adalah mobil bertipe dua pintu
Mobil wagon dan beberapa sedan kebanyakan bertipe dua pintu
5.2. Barplot
harga <- df1 %>%
group_by(cars) %>%
summarise(mean_price = min(price)) %>%
arrange(desc(mean_price))
ggplot(harga, aes(x = mean_price,
y = reorder(cars, mean_price),
fill = mean_price)) +
geom_col() +
scale_fill_gradient(low = "blue", high = "black") +
theme_minimal() +
labs(title = 'What is the most expensive car brand name?' ,
x = 'Price',
y = "Cars",
fill = "Price Rate") +
theme_minimal()
Insight :
Mobil dengan merk Jaguar mempunyai harga rata-rata paling mahal dan Subaru adalah merk mobil dengan harga rata-rata paling murah
6. Building Model
6.1. Prepare data
Sebelum melakukan modeling, terlebih dahulu untuk mempersiapkan data yang akan kita modelkan. Salah satu caranya adalah dengan mengeluarkan outliers yang ada di dalam kolom kategori. Dalam hal ini outliers yang dimaksud adalah kategori yang mengandung frekuensi yang paling sedikit dibandingkan dengan kateogri lainnya didalam satu kolom yang sama.
cylinder <- df1 %>% count(cylindernumber) %>% filter(n > 4)
df1 <- df1 %>%
filter(cylindernumber %in% c("five","four","six","eight"))
df1$cylindernumber <- factor(df1$cylindernumber, unique(df1$cylindernumber))
fuel <- df1 %>% count(fuelsystem) %>% filter(n > 4)
df1 <- df1 %>%
filter(fuelsystem %in% c("1bbl","2bbl","idi","mpfi","spdi"))
df1$fuelsystem <- factor(df1$fuelsystem, unique(df1$fuelsystem))
engine <- df1 %>% count(enginetype) %>% filter(n > 4)
df1 <- df1 %>%
filter(enginetype %in% c("dohc","l","ohc","ohcf","ohcv"))
df1$enginetype <- factor(df1$enginetype, unique(df1$enginetype))
Dalam kasus ini saya mengeluarkan kategori yang frekuensinya kurang dari 3 kali
Mari kita lihat apakah ada pola yang mengindikasi korelasi antar variabel yang akan kita modelkan
df_clean <- df1 %>% select(-c(car_ID,CarName,cars,symboling))
ggcorr(df_clean, label = TRUE, label_size = 2.9, hjust = 1, layout.exp = 2)
Dapat dilihat bahwa terdapat korelasi yang tinggi antar prediktor
didalam data kita, ini dinamakan dengan multicolinearity yang dimana
sebenarnya harus dihindari agar hasil pemodelannya dapat optimal
Dalam proses ini saya juga mengeluarkan kolom-kolom yang tidak diperlukan untuk pemodelan
Agar range antar data numerik sama untuk tiap data numerik, maka dilakukanlah scaling kepada semua data numeric.
# separate numeric and categoric data
df_cat <- df_clean %>% select_if(is.factor)
df_num <- df_clean %>% select_if(is.numeric)
# scaling
df_num_scal <- scale(df_num)
# bind numeric and categoric data
df_clean_scal <-df_cat %>% cbind(df_num_scal)
Metode scaling yang digunaka adalah Z-score Standarization
Tahap akhir persiapa data adalah membuat dummy variabel untuk prediktor kategorik yang akan kita gunakan
library(fastDummies)
df_model_dummy <- dummy_cols(df_clean_scal, remove_first_dummy = T)
#run a function to pinpoint factors(we need to remove them)
isfactor <- sapply(df_model_dummy,is.factor)
#final dataset for modelling
df2 <- df_model_dummy[,!isfactor]
Hal ini menjadi penting karena kalau kita mengeliminasi variabel categorical padahal variabel tersebut cukup berpengaruh, kita akan kehilangan banyak informasi sehingga harus dibuat dummy variabelnya
6.2. Split data set
Sebelum kita membuat model, kita perlu membagi data menjadi data train dan test. Data train akan digunakan untuk melatih model regresi linier. Data test akan digunakan sebagai pembanding dan melihat apakah model mengalami overfit atau model tidak dapat memprediksi data baru yang belum terlihat selama fase traning. Kami membagi datanya sebanyak 70% sebagai data train dan sisanya sebagai data test.
RNGkind(sample.kind = "Rounding")
set.seed(123)
indeks <- sample(nrow(df2), 0.7*nrow(df2))
df_train <- df2[indeks,]
df_test <- df2[-indeks,]
6.3. Modelling
Modelling dengan model Regresi Linear
model_df <- lm(price ~ ., data = df_train)
summary(model_df)
##
## Call:
## lm(formula = price ~ ., data = df_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.6354 -0.1663 -0.0157 0.1312 1.0431
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.727380 1.011197 1.708 0.090601 .
## wheelbase 0.028070 0.082041 0.342 0.732933
## carlength -0.084237 0.106823 -0.789 0.432178
## carwidth 0.263843 0.083681 3.153 0.002118 **
## carheight -0.008327 0.052070 -0.160 0.873254
## curbweight 0.223033 0.168749 1.322 0.189202
## enginesize 0.584534 0.146748 3.983 0.000127 ***
## boreratio 0.019351 0.072457 0.267 0.789944
## stroke -0.192599 0.046099 -4.178 6.18e-05 ***
## compressionratio -0.590647 0.322138 -1.834 0.069613 .
## horsepower -0.069577 0.127866 -0.544 0.587520
## peakrpm 0.181793 0.047087 3.861 0.000198 ***
## citympg -0.009294 0.153962 -0.060 0.951982
## highwaympg 0.054314 0.155111 0.350 0.726930
## fueltype_gas -2.102081 1.064480 -1.975 0.050973 .
## aspiration_turbo 0.194165 0.134593 1.443 0.152165
## doornumber_two 0.038292 0.087696 0.437 0.663285
## carbody_hardtop -0.319818 0.237727 -1.345 0.181478
## carbody_hatchback -0.357537 0.212520 -1.682 0.095527 .
## carbody_sedan -0.191708 0.228986 -0.837 0.404416
## carbody_wagon -0.290100 0.255052 -1.137 0.258003
## drivewheel_fwd -0.116880 0.190127 -0.615 0.540076
## drivewheel_rwd -0.091597 0.222894 -0.411 0.681967
## enginelocation_rear 1.261666 0.422143 2.989 0.003503 **
## enginetype_ohcv -0.877169 0.206757 -4.243 4.84e-05 ***
## enginetype_ohc 0.529266 0.155495 3.404 0.000948 ***
## enginetype_l -0.038821 0.247467 -0.157 0.875651
## enginetype_ohcf 0.028628 0.286687 0.100 0.920652
## cylindernumber_six 0.722539 0.235007 3.075 0.002699 **
## cylindernumber_five -0.149074 0.179452 -0.831 0.408053
## cylindernumber_eight 1.556897 0.456385 3.411 0.000925 ***
## fuelsystem_2bbl 0.014251 0.098283 0.145 0.884993
## fuelsystem_1bbl -0.022114 0.174880 -0.126 0.899619
## fuelsystem_idi NA NA NA NA
## fuelsystem_spdi -0.367933 0.170054 -2.164 0.032805 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2916 on 103 degrees of freedom
## Multiple R-squared: 0.9405, Adjusted R-squared: 0.9214
## F-statistic: 49.32 on 33 and 103 DF, p-value: < 2.2e-16
Meskipun nilai adjusted R-squared yang dihasilkan tergolong baik, model yang terbentuk masih memiliki kesalahan. Ini karena masih ada fitur yang multicolinearity bahkan sampai terjadi singularity, ditandai dengan adanya NA disummary model
Singularitas adalah bentuk ekstrim dari multikolinearitas - ketika ada hubungan linier yang sempurna antara variabel atau, dalam istilah lain, ketika koefisien korelasi sama dengan 1,0 atau -1.0.
Exclude prediktor
model_df2 <- lm(price ~.-fuelsystem_idi,data = df_train)
summary(model_df2)
##
## Call:
## lm(formula = price ~ . - fuelsystem_idi, data = df_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.6354 -0.1663 -0.0157 0.1312 1.0431
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.727380 1.011197 1.708 0.090601 .
## wheelbase 0.028070 0.082041 0.342 0.732933
## carlength -0.084237 0.106823 -0.789 0.432178
## carwidth 0.263843 0.083681 3.153 0.002118 **
## carheight -0.008327 0.052070 -0.160 0.873254
## curbweight 0.223033 0.168749 1.322 0.189202
## enginesize 0.584534 0.146748 3.983 0.000127 ***
## boreratio 0.019351 0.072457 0.267 0.789944
## stroke -0.192599 0.046099 -4.178 6.18e-05 ***
## compressionratio -0.590647 0.322138 -1.834 0.069613 .
## horsepower -0.069577 0.127866 -0.544 0.587520
## peakrpm 0.181793 0.047087 3.861 0.000198 ***
## citympg -0.009294 0.153962 -0.060 0.951982
## highwaympg 0.054314 0.155111 0.350 0.726930
## fueltype_gas -2.102081 1.064480 -1.975 0.050973 .
## aspiration_turbo 0.194165 0.134593 1.443 0.152165
## doornumber_two 0.038292 0.087696 0.437 0.663285
## carbody_hardtop -0.319818 0.237727 -1.345 0.181478
## carbody_hatchback -0.357537 0.212520 -1.682 0.095527 .
## carbody_sedan -0.191708 0.228986 -0.837 0.404416
## carbody_wagon -0.290100 0.255052 -1.137 0.258003
## drivewheel_fwd -0.116880 0.190127 -0.615 0.540076
## drivewheel_rwd -0.091597 0.222894 -0.411 0.681967
## enginelocation_rear 1.261666 0.422143 2.989 0.003503 **
## enginetype_ohcv -0.877169 0.206757 -4.243 4.84e-05 ***
## enginetype_ohc 0.529266 0.155495 3.404 0.000948 ***
## enginetype_l -0.038821 0.247467 -0.157 0.875651
## enginetype_ohcf 0.028628 0.286687 0.100 0.920652
## cylindernumber_six 0.722539 0.235007 3.075 0.002699 **
## cylindernumber_five -0.149074 0.179452 -0.831 0.408053
## cylindernumber_eight 1.556897 0.456385 3.411 0.000925 ***
## fuelsystem_2bbl 0.014251 0.098283 0.145 0.884993
## fuelsystem_1bbl -0.022114 0.174880 -0.126 0.899619
## fuelsystem_spdi -0.367933 0.170054 -2.164 0.032805 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2916 on 103 degrees of freedom
## Multiple R-squared: 0.9405, Adjusted R-squared: 0.9214
## F-statistic: 49.32 on 33 and 103 DF, p-value: < 2.2e-16
Interpretasi Model
Model pertama menghasilkan nilai Adj R-squared 0.9214 artinya model tersebut dapat menjelaskan 92,14% varians pada variabel target (price).
Variabel prediktor yang siginifikan memiliki nilai p-value < 0.05 yaitu yang diberi tanda “*”
Variabel yang berbanding lurus dengan price adalah cylindernumber_eight,cylindernumber_six,enginetype_ohcf,enginetype_ohc,enginelocation_rear,doornumber_two,aspiration_turbo,highwaympg,stroke,boreratio,enginesize,curbweight,carwidth, dan wheelbase
Sedangkan variabel yang berbanding terbalik dengan price variabel yang bertanda “-”
7. Predict
model_df2_pred <- predict(model_df2,newdata = df_test %>% select(-price))
Hasil prediksi di assign ke objek baru bernama model_df2_pred
8. Evaluation
Tujuan melakukan pemodelan yang bersifat prediktif adalah memprediksi data yang belum dimiliki. Untuk mengetahui model machine learning yang telah dibuat sudah bagus atau tidak dapat melihat dari error yang dihasilkan, diharapkan error yang dihasilkan sekecil mungkin.
# Train
RMSE(model_df2$fitted.values * sd(df_num$price) + mean(df_num$price), df_train$price * sd(df_num$price) + mean(df_num$price))
## [1] 1990.793
# Test
RMSE(model_df2_pred * sd(df_num$price) + mean(df_num$price), df_test$price * sd(df_num$price) + mean(df_num$price))
## [1] 2423.668
RMSE adalah bentuk akar kuadrat dari MSE. Karena sudah diakarkan, maka interpretasinya kurang lebih sama dengan MAE. RMSE dapat digunakan jika kita lebih concern dengan error yang sangat besar.
Pada kedua hasil train dan test, nilai RMSE untuk data train lebih rendah daripada data set, menunjukkan bahwa model yang dihasilkan mungkin overfit.
9. Assumptions
9.1. Linearity
linear <- data.frame(residual = model_df2$residuals, fitted = model_df2$fitted.values)
linear %>%
ggplot(aes(fitted, residual)) + geom_point() + geom_smooth() +
geom_hline(aes(yintercept = 0)) +
theme(panel.grid = element_blank(), panel.background = element_blank())
Berdasarkan pola yang ditampilkan menunjukkan bahwa model mungkin belum
cukup linier.
9.2. Normality
shapiro.test(x = model_df2$residuals)
##
## Shapiro-Wilk normality test
##
## data: model_df2$residuals
## W = 0.95053, p-value = 8.023e-05
Karena nilai p-value < 0.05 maka asumsi normalitas tidak terpenuhi, maka hasil uji signifikansi dan nilai standar error intercept dan slop masing-masing prediktor yang dihasilkan bias atau tidak mencerminkan nilai sebenarnya.
9.3. Homoscedasticity
library(lmtest)
bptest(model_df2)
##
## studentized Breusch-Pagan test
##
## data: model_df2
## BP = 44.501, df = 33, p-value = 0.08719
Karena p-value > 0.05 itu berarti eror varians tersebar secara acak atau konstan
9.4. Multicolinearity
library(car)
vif(model_df2)
## wheelbase carlength carwidth
## 11.617964 19.596824 11.818125
## carheight curbweight enginesize
## 4.057035 47.844451 40.169246
## boreratio stroke compressionratio
## 8.108016 3.618340 146.048414
## horsepower peakrpm citympg
## 27.579552 3.380173 40.824701
## highwaympg fueltype_gas aspiration_turbo
## 41.523585 145.869348 4.353111
## doornumber_two carbody_hardtop carbody_hatchback
## 3.037412 3.201098 15.465764
## carbody_sedan carbody_wagon drivewheel_fwd
## 21.087203 10.216570 13.904571
## drivewheel_rwd enginelocation_rear enginetype_ohcv
## 18.547338 4.129335 5.084875
## enginetype_ohc enginetype_l enginetype_ohcf
## 7.806349 6.674764 8.125780
## cylindernumber_six cylindernumber_five cylindernumber_eight
## 10.152588 2.514978 9.509804
## fuelsystem_2bbl fuelsystem_1bbl fuelsystem_spdi
## 3.262970 2.388473 2.258455
Masih banyak prediktor yang berkolerasi tinggi dengan prediktor lainnya, ditandai dengan nilai VIF > 10. Sehingga dilakukan pemodelan lanjutan dengan mengubah prediktor agar tidak terjadi multicolinearity
10. Tunning
10.1. Modelling
model_df3 <- lm(price ~.-fuelsystem_idi-fueltype_gas-carwidth-drivewheel_rwd-carbody_sedan-enginesize-cylindernumber_six-drivewheel_rwd-horsepower-highwaympg-curbweight-carlength,data = df_train)
summary(model_df3)
##
## Call:
## lm(formula = price ~ . - fuelsystem_idi - fueltype_gas - carwidth -
## drivewheel_rwd - carbody_sedan - enginesize - cylindernumber_six -
## drivewheel_rwd - horsepower - highwaympg - curbweight - carlength,
## data = df_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.7508 -0.2490 -0.0344 0.1987 2.4595
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.18765 0.20140 0.932 0.35347
## wheelbase 0.47003 0.08785 5.350 4.65e-07 ***
## carheight -0.14662 0.06911 -2.122 0.03606 *
## boreratio 0.04214 0.07759 0.543 0.58810
## stroke 0.01878 0.05698 0.330 0.74237
## compressionratio 0.08859 0.07399 1.197 0.23370
## peakrpm -0.02820 0.05961 -0.473 0.63708
## citympg -0.31409 0.09347 -3.360 0.00106 **
## aspiration_turbo 0.06333 0.13352 0.474 0.63620
## doornumber_two 0.18234 0.12614 1.446 0.15106
## carbody_hardtop -0.39821 0.24391 -1.633 0.10533
## carbody_hatchback -0.23647 0.13038 -1.814 0.07238 .
## carbody_wagon -0.17694 0.14345 -1.234 0.21995
## drivewheel_fwd -0.21591 0.13154 -1.641 0.10350
## enginelocation_rear 3.11031 0.45024 6.908 3.06e-10 ***
## enginetype_ohcv 0.01717 0.25172 0.068 0.94573
## enginetype_ohc -0.07627 0.19857 -0.384 0.70162
## enginetype_l -0.77577 0.25730 -3.015 0.00317 **
## enginetype_ohcf -0.25401 0.34325 -0.740 0.46083
## cylindernumber_five 0.11882 0.21707 0.547 0.58520
## cylindernumber_eight 1.62910 0.33653 4.841 4.13e-06 ***
## fuelsystem_2bbl -0.03307 0.13602 -0.243 0.80834
## fuelsystem_1bbl 0.28732 0.24861 1.156 0.25025
## fuelsystem_spdi -0.29573 0.23764 -1.244 0.21589
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4541 on 113 degrees of freedom
## Multiple R-squared: 0.8417, Adjusted R-squared: 0.8095
## F-statistic: 26.12 on 23 and 113 DF, p-value: < 2.2e-16
10.2. Predict
model_df3_pred <- predict(model_df3,newdata = df_test %>% select(-price))
10.3. Evaluation
# Train
RMSE(model_df3$fitted.values * sd(df_num$price) + mean(df_num$price), df_train$price * sd(df_num$price) + mean(df_num$price))
## [1] 3246.904
# Test
RMSE(model_df3_pred * sd(df_num$price) + mean(df_num$price), df_test$price * sd(df_num$price) + mean(df_num$price))
## [1] 2939.855
Berdasarkan hasil RMSE didapat bahwa tidak terjadi over fitting karena nilai RMSE data test lebih kecil dibandingkan RMSE data train
10.4. Assumption
Linearity
linear2 <- data.frame(residual = model_df3$residuals, fitted = model_df3$fitted.values)
linear2 %>%
ggplot(aes(fitted, residual)) + geom_point() + geom_smooth() +
geom_hline(aes(yintercept = 0)) +
theme(panel.grid = element_blank(), panel.background = element_blank())
Berdasarkan pola yang ditampilkan menunjukkan bahwa model mungkin belum linier.
Normality
shapiro.test(x = model_df3$residuals)
##
## Shapiro-Wilk normality test
##
## data: model_df3$residuals
## W = 0.85817, p-value = 3.857e-10
Karena nilai p-value < 0.05 maka asumsi normalitas tidak terpenuhi, maka hasil uji signifikansi dan nilai standar error intercept dan slop masing-masing prediktor yang dihasilkan bias atau tidak mencerminkan nilai sebenarnya.
Homoscedasticity
bptest(model_df3)
##
## studentized Breusch-Pagan test
##
## data: model_df3
## BP = 25.377, df = 23, p-value = 0.3311
Karena p-value > 0.05 itu berarti eror varians tersebar secara acak atau konstan
Multicolinearity
vif(model_df3)
## wheelbase carheight boreratio
## 5.494894 2.947375 3.834740
## stroke compressionratio peakrpm
## 2.280374 3.177617 2.234081
## citympg aspiration_turbo doornumber_two
## 6.205558 1.766769 2.591686
## carbody_hardtop carbody_hatchback carbody_wagon
## 1.389837 2.400871 1.332890
## drivewheel_fwd enginelocation_rear enginetype_ohcv
## 2.745154 1.937326 3.108549
## enginetype_ohc enginetype_l enginetype_ohcf
## 5.250234 2.975992 4.804175
## cylindernumber_five cylindernumber_eight fuelsystem_2bbl
## 1.517782 2.132650 2.577629
## fuelsystem_1bbl fuelsystem_spdi
## 1.990854 1.818927
Tidak ada multicolinearity
11. Conclusion
Untuk melakukan evaluasi pada regression model dapat dilakukan dengan beberapa cara yaitu:
- menggunakan nilai R-Squared dan Adj R-Squared
- untuk menentukan seberapa baik model dalam menjelaskan variansi dari target variabel
- menggunakan nilai error
- untuk melihat apakah prediksi yang dibuat menghasilkan nilai error terkecil
Pada kasus ini dipilih model dengan pertama karena nilai RMSE yang lebih kecil dibandingkan dengan model hasi tunning. Pada model pertama prediktor yang paling berpengaruh terhadap target (price) adalah carheigh, enginesize, stroke, peakrpm, enginelocation_rear, enginetype_ohcv, enginetype_ohc, cylindernumber_six, cylindernumber_eight, dan fuelsystem_spdi
Nilai adjusted R-squared juga tinggi yang dimana 92.14% prediktor dapat menjelaskan varians harga mobil. Akurasi model untuk memprediksi diukur dengan nilai RMSE yang dihasilkan pada data test yaitu sebesar 2423.668.