Prediksi Harga Properti dengan menggunakan Machine Learning

Pasar properti merupakan salah satu sektor yang menarik perhatian banyak orang, baik sebagai tempat tinggal atau sebagai investasi. Bertambahnya jumlah penduduk membuat kebutuhan akan properti semaki meningkat, yang mana hal ini merupakan salah satu faktor yang membuat harga properti terus meningkat setiap tahunnya. Namun, kita tidak bisa berasumsi bahwa semua harga properti akan selalu naik tiap tahunnya, ada banyak faktor lain yang perlu dipertimbangkan seperti lokasi, ukuran, fasilitas, kondisi, dan faktor sosial-ekonomi lainnya yang mungkin bisa berdampak pada harga properti.

Dalam artikel ini, kita akan belajar bagaimana cara memprediksi harga properti yang paling umum dan populer, yaitu rumah. Memprediksi harga rumah termasuk kedalam supervised learning, yaitu regresi dimana dalam pembuatan model regresi memerlukan data historis untuk digunakan dalam melatih model yang akan digunakan untuk memprediksi harga rumah yang belum diketahui harganya.

Disini penulis menggunakan Anaconda-Navigator untuk membuat model hingga melakukan deployment, jadi pastikan kalian sudah menginstall Anaconda-Navigator jika ingin mengikuti sampai ke tahap deployment. Namun jika kalian hanya ingin membuat model saja, google colab sudah lebih dari cukup karena tidak perlu melakukan instalasi apapun. Selain anaconda-navigator kalian juga bisa menggunakan miniconda dan visual studio code / pycharm atau bahkan cukup dengan IDE dari python, terserah mana yang lebih familiar.

Persiapan

Disini penulis menggunakan data Perth Metropolitan Area House Prices. silahkan untuk data tersebut dan install library berikut apabila belum:

pip install pandas
pip install -U scikit-learn

Karena disini kita hanya membahas modelling maka kita hanya me-load librari yang kita perlukan untuk modelling, apabila kebingungan mengenai feature yang dipilih pada artikel ini, dapat melihat explorasi data pada dataset ini pada artikel ini.

#load libraries
import pandas as pd

#load data
data = pd.read_csv('https://docs.google.com/spreadsheets/d/e/2PACX-1vSJme7k4plKxdpiGs3Yn9nyGYRlPdeDZp7qhviZ5NFQMxsvD25GPoBfcDVAHBMMbvjt-ezvA0f-a0jF/pub?gid=2011056954&single=true&output=csv')
data.head(5)

kode data = pd.read_csv('link file csv') berfungsi untuk memanggil dataset Perth Housing dan kode data.head(5) berfungsi untuk menampilkan 5 data teratas dari dataset tadi. Selanjutnya kita perlu melihat missing value dataset untuk menentukan langkah selanjutnya. Untuk melihat jumlah missing value pada dataset secara keseluruhan dapat menggunakan perintah data.isnull().sum() untuk menampilkan semua data yang memiliki missing value.

data.isnull().sum() 

###### OUTPUT #######
ADDRESS                 0
SUBURB                  0
PRICE                   0
BEDROOMS                0
BATHROOMS               0
GARAGE               2478
LAND_AREA               0
FLOOR_AREA              0
BUILD_YEAR           3155
CBD_DIST                0
NEAREST_STN             0
NEAREST_STN_DIST        0
DATE_SOLD               0
POSTCODE                0
LATITUDE                0
LONGITUDE               0
NEAREST_SCH             0
NEAREST_SCH_DIST        0
NEAREST_SCH_RANK    10952

dapat kita lihat bahwa terdapat 3 kolom yang memiliki missing value, untuk kolom NEAREST_SCH_RANK dapat kita drop karena jumlah missing valuenya >30%, untuk kolom GARAGE dan BUILD_YEAR dapat kita isi nilai yang kosong dengan mode. Selain itu, untuk kolom ADDRESS dapat kita drop karena memiliki kardinalitas yang tinggi.

#drop misisng value >30% dan kolom yang tidak diperlukan
data.drop(['ADDRESS', 'NEAREST_SCH_RANK'], axis=1, inplace=True)
#isi dengan mode
data['GARAGE'] = data['GARAGE'].fillna(data['GARAGE'].mode()[0])
data['BUILD_YEAR'] = data['BUILD_YEAR'].fillna(data['BUILD_YEAR'].mode()[0])

Kemudian, kita pisahkan tahun dan bulan pada DATE_SOLD, dan hapus kolom DATE_SOLD

#pisah tanggal terjual menjadi bulan dan tahun
data['DATE_SOLD'] = pd.to_datetime(data['DATE_SOLD'])
data['DATE_SOLD_YEAR'] = data['DATE_SOLD'].dt.year
data['DATE_SOLD_MONTH'] = data['DATE_SOLD'].dt.month
#hapus kolom tanggal terjual
data.drop(['DATE_SOLD'], axis=1, inplace=True)

karena kolom SUBURB, NEAREST_STN, NEAREST_SCH masih berupa string, maka perlu kita ubah terlebih dahulu, disini penulis menggunakan dummy encoding .

data_final = data.copy()
obj_col = data_final.select_dtypes(include = "object").columns
for i in obj_col.to_list():
    dummies = pd.get_dummies(data_final[i])
    data_final = pd.concat([data_final, dummies], axis=1)
    data_final = data_final.drop(i, axis=1)

kode diatas, penulis menduplikasi dataset ‘data’ ke ‘data_final’ kemudian membuat daftar kolom yang bertipe object / string dan menyimpannya kedalam variabel obj_col, kemudian membuat iterasi dengan menggunakan fungsi for untuk menerapkan dummy encoding pada masing-masing kolom dan menghapus kolom awal yang telah diubah dengan menggunakan dummy encoding. Setelah proses persiapan data selesai, selanjutnya adalah modelling.

Modelling

Dalam membuat model machine learning, kita perlu memisah dataset awal menjadi data latih dan data uji, dimana besarannya biasanya 70-80% untuk data latih dan sisanya sebagai data uji. Pemisahan ini sangat penting karena data uji tadi akan digunakan untuk mengukur kinerja dari model yang telah kita buat.

from sklearn.model_selection import train_test_split
X=data_final.drop(['PRICE',],axis=1)
y=data_final['PRICE']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=25, shuffle=True)

pada kode diatas penulis memisahkan dataset menjadi 80% data untuk data latih dan 20% data untuk data uji dengan menggunakan library bawaan dari sklearn. Selanjutnya kita bisa langsung menggunakan data yang telah dipisah tadi ke dalam beberapa algorithma machine learning untuk kemudian dibandingkan model mana yang memiliki kinerja yang paling baik.

Linear Regression

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_test)

Elastic Net

from sklearn.linear_model import ElasticNet
en = ElasticNet()
en.fit(X_train, y_train)
y_pred_en = en.predict(X_test)

Random Forest

from sklearn.ensemble import RandomForestRegressor
random_forest = RandomForestRegressor(random_state=25)
random_forest.fit(X_train, y_train)
y_pred_rf = random_forest.predict(X_test)

XGBoost

from xgboost import XGBRegressor
xgb = XGBRegressor(random_state=25)
xgb = xgb.fit(X_train, y_train)
y_pred_xgb = xgb.predict(X_test)

Kita menggunakan 4 algorithma machine learning yang berbeda, secara garis besar, cara penggunan dari algorithma diatas sama sama, yaitu pertama kita load algoritmanya terlebih dahulu, lalu kita buat model dengan perintah fit pada data train kemudian model tersebut kita suruh untuk melakukan prediksi pada data data uji (X_test). output dari prediksi tersebut kita simpan kedalam variabel y_pred_[nama] untuk kemudian kita bandingkan dengan kunci jawaban guna mendapatkan skor evaluation metrics yang kita tentukan.

Evaluasi

Untuk mengukur model mana yang memiliki kinerja paling baik, kita dapat melihat dari evaluation metrics barupa R2, MAE dan RMSE. Setelah sebelumnya kita membuat model dan melakukan prediksi pada data uji, sekarang kita perlu membandingkan hasil dari prediksi tersebut.

from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error

# LR
LR_r2 = r2_score(y_test, y_pred_lr)
LR_mae = mean_absolute_error(y_test, y_pred_lr)
LR_rmse = np.sqrt(mean_squared_error(y_test, y_pred_lr))
# EN
EN_r2 = r2_score(y_test, y_pred_en)
EN_mae = mean_absolute_error(y_test, y_pred_en)
EN_rmse = np.sqrt(mean_squared_error(y_test, y_pred_en))
# RF
RF_r2 = r2_score(y_test, y_pred_rf)
RF_mae = mean_absolute_error(y_test, y_pred_rf)
RF_rmse = np.sqrt(mean_squared_error(y_test, y_pred_rf))
# XGB
XGB_r2 = r2_score(y_test, y_pred_xgb)
XGB_mae = mean_absolute_error(y_test, y_pred_xgb)
XGB_rmse = np.sqrt(mean_squared_error(y_test, y_pred_xgb))

models = pd.DataFrame({
    'Model': ['Linear Regression', 'Elastic Net', 'Random Forest', 'XGBoost'],
    'R2 Score': [LR_r2, EN_r2, RF_r2, XGB_r2],
    'MAE': [LR_mae, EN_mae, RF_mae, XGB_mae],
    'RMSE': [LR_rmse, EN_rmse, RF_rmse, XGB_rmse]
                    })

models.sort_values(by='RMSE', ascending=True)

Dengan kode diatas, kita mengukur nilai R2, MAE, dan RMSE pada masing-masing model. Kemudian kita membuat dataframe baru dengan nilai dari hasil pengukuran tadi dan mengurutkannya berdasarkan nilai RMSE terendah. Output dari kode diatas adalah sebagai berikut:

Model	                R2 Score	MAE	        RMSE
XGBoost                 0.846536	84985.052987	137913.103529
Random Forest	        0.843228	83132.820524	139391.403056
Linear Regression	0.766210	109785.511653	170221.720814
Elastic Net	        0.517930	166664.965149	244431.277732

Perlu diketahui jika kita menggunakan R2 sebagai acuan pengukuran kinerja, maka R2 dengan nilai tertinggi adalah yang paling baik, sebaliknya jika kita menggunakan Mean Absolute Error (MAE) maupun Root Mean Square Error (RMSE) maka nilai terkecilah yang paling baik.

Kemudian untuk melihat importance dari model XGBoost dapat menggunakan kode dibawah ini, dimana kode tersebut akan menampilkan 5 feature importance teratas.

# feature importance
fi = pd.DataFrame({'nama fitur' : xgb.feature_names_in_, 
                    'importances' : xgb.feature_importances_})
fi = fi.sort_values(by='importances', ascending=False)
fi = fi.reset_index(drop=True)
print(fi.head(5))



###################### OUTPUT ########################
                        nama fitur  importances
0                         POSTCODE     0.230457
1  JOHN CURTIN COLLEGE OF THE ARTS     0.072959
2                Fremantle Station     0.044550
3                         CBD_DIST     0.024791
4                            Trigg     0.023533
Referensi:
  1. Dataset: https://www.kaggle.com/code/lucasgsalves/perth-house-prices

Leave a Reply

Your email address will not be published. Required fields are marked *