มาทำนายผลราคาบ้านด้วยขั้นตอนการทำ machine learning จาก house-price-india dataset ด้วย R กันเถอะ

บทความนี้เป็นการใช้ภาษา R ในการทำ Machine Learning เพื่อทำนายผลราคาบ้านของ Dataset house price india ด้วยการใช้ Linear Regression และ KNN ทำมาเพื่อเปรียบเทียบประสิทธิภาพในการทำนายผล ซึ่งเป็นการฝึกทำขั้นตอนการทำ machine learning ที่เรียนมาจาก data rockie bootcamp โดยข้อสรุปของผลที่ได้นั้น อ่านต่อด้านล่างนี้ได้เลย
ก่อนจะเริ่มทำ Machine Learning จริงๆแล้ว เราควรจะทำการ EDA หรือใช้ความรู้ทางสถิติเพื่อ สำรวจข้อมูลก่อนเพื่อที่จะจัดการข้อมูลหรือที่เรียกว่า Preparation Data เสียก่อน
โดยเริ่มจากการตั้งคำถามก่อน โดยตั้งเอาไว้ 2 ข้อดังนี้
- อยากรู้ว่าราคาทั้งหมดของ Data set มีการกระจายตัวอย่างไรบ้าง
- model ระหว่าง linear regression กับ knn แบบไหนดีกว่ากัน
จากนั้นก็ load library ที่จำเป็นแล้วเริ่มทำการ explore data
library("tidyverse")
## EDA
library("readxl")
library("tidyverse")
library("caret")
library("httr")
GET("<https://query.data.world/s/abvtdvuruklmcomk4h7y2hbjtru63m>", write_disk(tf <- tempfile(fileext = ".xlsx")))
df_hp_india <- read_excel(tf)
View(df_hp_india)
mean(df_hp_india$Price)
median(df_hp_india$Price)
max(df_hp_india$Price)
min(df_hp_india$Price)
จากนั้นก็ทำการ sampling data
## Split Data
set.seed(50)
n <- nrow(df_hp_india)
id <- sample(1:n, size=0.7*n)
train_data <- df_hp_india[id, ]
test_data <- df_hp_india[-id, ]
## Visualization
hist(df_hp_india$Price)
boxplot(df_hp_india$Price)
จะพบว่ามีค่าที่สูงจนไม่สามารถดูได้ และ เบ้ขวา
ข้อมูลมีลักษณะของเบ้ขวา จะต้องทำการ sampling เพื่อ ทำ normal distribution ก่อนที่จะเข้า machine learning
ซึ่งถ้าสังเกต histogram จะมีค่าที่สูงมากๆ แม้ว่าจะ sampling ค่ามา จะต้องทำการใส่ค่า log เพื่อเปลี่ยนค่าให้เล็กลง
log_price <- log(train_data$Price)
log_price
hist(log_price)
แล้วทำการ Explore ดูอีกครั้งหลังจากใส่ค่า Log
> mean(log_price)
[1] 13.04824
> median(log_price)
[1] 13.01701
> max(log_price)
[1] 15.85673
> min(log_price)
[1] 11.26448
หลังจากที่ใส่ค่า log แล้ว สามารถที่จะ exp() เพื่อคืนค่าเดิมได้ จะมีตัวอย่างให้ดูด้านล่างนี้
ถ้ามาลองคิดดูแล้ว น่าจะต้องเอาค่า feature ทุกตัวที่ต้องการเป็น input มา predict จะต้องทำการ log ค่าเช่นเดียวกัน
ซึ่งจะมีค่าดังนี้
number of bedrooms
number of bathrooms
living area
number of views
lot area
ทำการแปลงค่าโดยสร้าง dataframe ขึ้นมาใหม่ โดยใช้ความรู้ data transform หรือ library ชื่อ dplyr
ทำการ select data มาทำเป็น dataframe
## select data feature
df_prepare_data <- df_hp_india %>% select(Price,
`number of bedrooms`,
`number of bathrooms`,
`living area`,
`number of views`,
`lot area`)
ทำการเพิ่ม column
df_prepare_data %>% mutate(log_Price = log(Price + 1),
log_num_bedroom = (log(`number of bedrooms`) + 1),
log_num_bathrooms = (log(`number of bathrooms`) + 1),
log_living_area = (log(`living area`) + 1),
log_num_views = (log(`number of views`) + 1),
log_lot_area = (log(`lot area`) + 1)
)
View(df_prepare_data)
เดี๋ยวจะใส่กลับเข้าไปใน object เดิม คราวนี้เราก็จะได้ column ที่เป็นค่า log ของแต่ละ feature
ทำการ split ใหม่อีกครั้ง จาก new dataset
## Split Data Again with new dataset
set.seed(42)
n <- nrow(df_prepare_data)
id <- sample(1:n, size=0.7*n)
new_train_data <- df_prepare_data[id, ]
new_test_data <- df_prepare_data[-id, ]
จากนั้นก็เอามาเข้า ml เพื่อ train model เริ่มจาก linear regression ก่อน
## Train Model
ctrl <- trainControl(method = 'cv', number=10)
linear_regression_model <- train(log_Price ~
log_num_bedroom +
log_num_bathrooms +
log_living_area +
log_num_views +
log_lot_area,
data = new_train_data,
method = 'lm',
trControl = ctrl)
เมื่อลอง run พบว่า เกิด error บางอย่าง ก็คือ เจอค่า null ใน column log_num_view อาจจะเป็นเพราะ บวก 1 ไม่ถูก ในที่นี้ขอตัดค่า log_num_view ออกไปก่อน
## Train Model
ctrl <- trainControl(method = 'cv', number=10)
linear_regression_model <- train(log_Price ~
log_num_bedroom +
log_num_bathrooms +
log_living_area +
log_lot_area,
data = new_train_data,
method = 'lm',
trControl = ctrl)
###### Result ######
> linear_regression_model
Linear Regression
10234 samples
4 predictor
No pre-processing
Resampling: Cross-Validated (10 fold)
Summary of sample sizes: 9210, 9210, 9211, 9211, 9211, 9210, ...
Resampling results:
RMSE Rsquared MAE
0.3751279 0.4943142 0.3012616
Tuning parameter 'intercept' was held constant at a value of TRUE
จากนั้นลอง เอามา model มา predict กับ new data หรือ test dataset
## Score Model
log_price_pred <- predict(linear_regression_model, newdata = new_test_data)
log_price_pred
ลองหาค่า error ที่ได้จากการ ทดสอบ โดยใช้ function Root Mean Square Error ตาม code ด้านล่าง
## Evaluate Model
rmse_metric <- function(actual, prediction){
sq_error <- (actual - prediction)**2
sqrt(mean(sq_error))
}
ทำการประเมิน
rmse_metric(newtest_data$log_Price, log_price_pred)
[1] 0.3705133
เอาค่าที่ได้จาก predict และ test มาเทียบกัน
train : 0.3751279
test : 0.3705133
มีค่าใกล้เคียงกัน
ลองสร้าง data ใหม่ที่สมมติขึ้นมา
(new_data <- data.frame(
log_price_pred = c(13.25164),
log_num_bedroom = c(2.586294),
log_num_bathrooms =c(1.910930),
log_living_area = c(8.918685),
log_lot_area = c(11.937969)
))
ทดสอบอีกครั้ง ได้ผลว่า price เดิม ใกล้เคียงกับ price ที่ลองสมมติขึ้นมา
log_price_pred <- predict(linear_regression_model, newdata = new_data)
log_price_pred
## price
13.17152
ลอง convert ค่า 13.17152 ด้วย exponential
exp(13.17152)
###
525192.4
คราวนี้มาลองทดสอบ ด้วย knn model เพื่อเปรียบเทียบ model
ctrl <- trainControl(method = 'cv', number=10)
knn_model <- train(log_Price ~
log_num_bedroom +
log_num_bathrooms +
log_living_area +
log_lot_area,
data = new_train_data,
method = 'knn',
trControl = ctrl)
knn_model
##### Result #####
k-Nearest Neighbors
10234 samples
4 predictor
No pre-processing
Resampling: Cross-Validated (10 fold)
Summary of sample sizes: 9209, 9210, 9210, 9211, 9211, 9211, ...
Resampling results across tuning parameters:
k RMSE Rsquared MAE
5 0.3780176 0.4942525 0.2994490
7 0.3689344 0.5137424 0.2926094
9 0.3650446 0.5224657 0.2900262
RMSE was used to select the optimal model using the smallest value.
The final value used for the model was k = 9.
## Score Model
log_price_pred <- predict(linear_regression_model, newdata = new_test_data)
log_price_pred
## Evaluate Model
rmse_metric <- function(actual, prediction){
sq_error <- (actual - prediction)**2
sqrt(mean(sq_error))
}
###
> rmse_metric(new_test_data$log_Price, log_price_pred)
[1] 0.3372817
เปรียบเทียบ Model
Linear Regression
train : 0.3751279
test : 0.3705133
Knn
train :
k RMSE
5 0.3780176
7 0.3689344
9 0.3650446
test : 0.3372817
ได้ข้อสรุปว่า เมื่อเปรียบเทียบระหว่าง model linear regression กับ knn
knn มีค่า error ที่ต่ำกว่า
code ทั้งหมด
library("readxl")
library("tidyverse")
library("caret")
library("httr")
GET("<https://query.data.world/s/abvtdvuruklmcomk4h7y2hbjtru63m>", write_disk(tf <- tempfile(fileext = ".xlsx")))
df_hp_india <- read_excel(tf)
View(df_hp_india)
mean(df_hp_india$Price)
median(df_hp_india$Price)
max(df_hp_india$Price)
min(df_hp_india$Price)
hist(df_hp_india$Price)
boxplot(df_hp_india$Price)
## Split Data
set.seed(50)
n <- nrow(df_hp_india)
id <- sample(1:n, size=0.7*n)
train_data <- df_hp_india[id, ]
test_data <- df_hp_india[-id, ]
hist(train_data$Price)
boxplot(train_data$Price)
log_price <- log(train_data$Price + 1)
log_price
hist(log_price)
boxplot(log_price)
mean(log_price)
median(log_price)
max(log_price)
min(log_price)
## select data feature
df_prepare_data <- df_hp_india %>% select(Price,
`number of bedrooms`,
`number of bathrooms`,
`living area`,
`number of views`,
`lot area`) %>% mutate(log_Price = log(Price + 1),
log_num_bedroom = (log(`number of bedrooms`) + 1),
log_num_bathrooms = (log(`number of bathrooms`) + 1),
log_living_area = (log(`living area`) + 1),
log_num_views = (log(`number of views`) + 1),
log_lot_area = (log(`lot area`) + 1))
View(df_prepare_data)
## Split Data Again with new dataset
set.seed(42)
n <- nrow(df_prepare_data)
id <- sample(1:n, size=0.7*n)
new_train_data <- df_prepare_data[id, ]
new_test_data <- df_prepare_data[-id, ]
new_train_data
## Train Model
ctrl <- trainControl(method = 'cv', number=10)
linear_regression_model <- train(log_Price ~
log_num_bedroom +
log_num_bathrooms +
log_living_area +
log_lot_area,
data = new_train_data,
method = 'lm',
trControl = ctrl)
linear_regression_model
## Score Model
log_price_pred <- predict(linear_regression_model, newdata = new_test_data)
log_price_pred
## Evaluate Model
rmse_metric <- function(actual, prediction){
sq_error <- (actual - prediction)**2
sqrt(mean(sq_error))
}
rmse_metric(new_test_data$log_Price, log_price_pred)
(new_data <- data.frame(
log_price_pred = c(13.25164),
log_num_bedroom = c(2.586294),
log_num_bathrooms =c(1.910930),
log_living_area = c(8.918685),
log_lot_area = c(11.937969)
))
log_price_pred <- predict(linear_regression_model, newdata = new_data)
log_price_pred
exp(13.17152)
knn_model <- train(log_Price ~
log_num_bedroom +
log_num_bathrooms +
log_living_area +
log_lot_area,
data = new_train_data,
method = 'knn',
trControl = ctrl)
knn_model
## Score Model
log_price_pred <- predict(knn_model, newdata = new_test_data)
log_price_pred
## Evaluate Model
rmse_metric <- function(actual, prediction){
sq_error <- (actual - prediction)**2
sqrt(mean(sq_error))
}
rmse_metric(new_test_data$log_Price, log_price_pred)
เป็นอย่างไรบ้างครับ หวังว่าจะมีประโยชน์ ฝากกดแชร์บทความนี้ให้กับเพื่อนๆที่สนใจ ขั้นตอนการทำ machine learning กันด้วยนะครับ
