top of page

Xây dựng mô hình Marchine learning dự báo giá xe hơi

Trong bài viết này, tôi sẽ giới thiệu một thuật toán cơ bản của Machine Learning - Linear Regression (Hồi quy Tuyến tính) thuộc nhóm học có giám sát (Supervised learning). Hồi quy Tuyến tính là một phương pháp đơn giản nhưng đã được chứng minh rằng nó rất hữu ích trong nhiều tình huống khác nhau. Trên thực tế, Hồi quy Tuyến tính làm việc như thế nào sẽ được trình bày chi tiết trong bài viết này.

Khi nghiên cứu về phân tích dữ liệu, chúng ta thường gặp thuật ngữ "Hồi quy" (Regression) thường xuyên. Trước khi đi sâu vào Hồi quy Tuyến tính, hãy hiểu khái niệm cơ bản của Hồi quy. Hồi quy là một phương pháp thống kê dùng để xác định mối quan hệ giữa một biến phụ thuộc và một nhóm các biến độc lập.

Đặt vấn đề

Mô hình dự báo giá xe hơi giúp chúng ta ước lượng giá trị của một chiếc xe hơi dựa trên các thông tin và đặc điểm quan trọng.

Trong quá trình xây dựng mô hình, chúng ta sẽ sử dụng các kỹ thuật và thuật toán để tìm mối quan hệ giữa các yếu tố như năm sản xuất, dung tích động cơ, số dặm đã đi, và nhiều yếu tố khác đến giá trị của xe hơi.

Việc xây dựng mô hình dự báo giá xe hơi không chỉ giúp chúng ta hiểu sâu hơn về quy luật và yếu tố ảnh hưởng đến giá trị xe, mà còn có thể hỗ trợ trong việc đưa ra quyết định mua bán, định giá và dự báo xu hướng thị trường xe hơi.

Thông tin dự án

Sau đây là thông tin các file đã được đính kèm trong dự án xây dựng mô hình Marchine learning để dự báo giá xe có chứa trong github:

  • app.py: File Python chứa mã nguồn cho ứng dụng web. Nó sử dụng mô hình hồi quy để đưa ra dự báo giá xe hơi và hiển thị trên trang web giả lập chạy trên localhost.

  • build_model.ipynb: File Jupyter Notebook chứa quá trình xây dựng mô hình và phân tích dữ liệu.

  • index.html: File HTML để người dùng nhập các biến đầu vào.

  • result.html: File HTML để hiển thị kết quả dự báo khi người dùng đã nhập đầy đủ các thuộc tính.

  • /data: Thư mục chứa dữ liệu về xe hơi, bao gồm các trường như năm sản xuất, dung tích động cơ, số dặm đã đi và giá là biến phụ thuộc.

  • /templates: Thư mục chứa các file HTML templates.

  • /static/images: Thư mục chứa các hình ảnh sử dụng trong trang web.

  • report.pdf: File PDF chứa báo cáo chi tiết về dự án.

Sau đây, chúng ta sẽ tìm hiểu cụ thể cách xây dựng mô hình ML và đưa ra các kết quả dự báo.

Chuẩn bị dữ liệu

  1. Import các thư viện cần thiết

  2. Đọc dữ liệu

  3. Khám phá dữ liệu (EDA)

Thêm các thư viện cần thiết

#Import thư viện

import pandas as pd

import numpy as np

import math

import os

from os import listdir

from datetime import date

from sklearn.compose import ColumnTransformer

from sklearn.pipeline import Pipeline

from sklearn.preprocessing import OneHotEncoder, StandardScaler

import statsmodels.api as sm

from flask import Flask, render_template, request

Đọc dữ liệu

basic = 'data/'

df = pd.DataFrame(data = None)

for file in dirs:

url = basic + file

new_df = pd.read_csv(url) #đọc từng file trong folder

new_df['automaker'] = file.split(".")[0] #tạo cột hãng xe

if file == 'hyundi.csv':

new_df.rename(columns = {'tax(£)': 'tax'}, inplace =True) #đổi tên cột thuế

df = pd.concat([df,new_df]) #gộp file

Sau khi check các cột dữ liệu của các tệp, ta phát hiện có file csv của dòng xe Huyndi bị sai tên cột. Cụ thể, thay vì có tên là ‘tax’ như các file khác thì lại có tên là 'tax(£)'. Vì thế, tại phải đổi tên cột trong file này trước khi gộp các file dữ liệu lại với nhau.

Khám phá dữ liệu (EDA)

Dữ liệu có 104641 dòng với 10 cột và tại cột tax, mpg có dữ liệu bị thiếu.

Mô tả các biến định lượng

Phần trăm giá trị riêng biệt trong các cột định lượng

# Đếm số giá trị riêng biệt trong biến định lượng

distincts = []

percents = []

for numerical_col in numerical_cols:

distinct = df[numerical_col].nunique()

percent = distinct*100/df.shape[0]

print(numerical_col, 'column has',distinct,'distinct values')

print('It takes', format(percent,'.2f'),'%')

print('---')

distincts.append(distinct)

percents.append(format(percent,'.2f')+'%')

data = {'Count Distinct': distincts,'Take Percent':percents}

Phần trăm giá trị riêng biệt trong các cột định lượng

Những cột định lượng có ít giá trị riêng biệt thì có thể nhóm các giá trị lại theo tứ phân vị. Chuyển đổi thành những cột mang tính định tính.

Độ tương quan giữa giá xe và tổng số dặm đã đi (mileage)

Tương quan giá với mileage

Vì chưa thấy tương quan nhiền nên ta thử logarit biến mileage

Tương quan giá với logarit mileage

Tương quan trung bình giá với các biến category

Tương quan giá xe trung bình với các biến category

Tiền xử lý dữ liệu

Xử lý dữ liệu thiếu - Missing value

Kiểm tra

columns = df.columns

for i,column in enumerate(columns):

missing = df[column].isnull().sum()

percent = missing*100/(df.shape[0])

if missing > 0:

print('Column', column, 'contains', missing, 'missing value')

print('take', format(percent, ".2f"), "%")

print("--")

Dữ liệu cột tax và mpg bị thiếu. Ta giải quyết bằng cách thay những giá trị bị null bằng giá trị trung bình của toàn dữ liệu.

Chuyển đổi dữ liệu

Nhóm cụm dữ liệu

Với hình ảnh trực quan về automaker với giá xe ta có thể gom cụm các automaker lại và chia thành ba mục chính (Luxury, Mid-range, Affordable).

def fill_class(x):

if x in ('merc','audi','bmw'):

return "Luxury"

if x in ('vw','skoda','focus'):

return "Mid-range"

else:

return "Affordable"


df['Class'] = df['automaker'].apply(lambda x: fill_class(x))

Vì cột year, engineSize có rất ít dữ liệu riêng biệt nên ta có thể xem nó như những dữ liệu định tính. Ta phân nhóm những trường dữ liệu này theo tứ phân vị.

df['year'] = pd.cut(df['year'],

bins = [0, 2015.9, 2016.9, 2018.9, 2061],

labels =['hơn 5 năm','4-5 năm','2-4 năm','dưới 2 năm'])


df['engineSize'] = pd.cut(df['engineSize'],

bins = [-1, df['engineSize'].quantile(0.25)-0.01, df['engineSize'].quantile(0.5)-0.01, df['engineSize'].quantile(0.75)-0.01, df['engineSize'].max()+0.01],

labels =['Small','Medium','Large','Very Large'])

Xử lý outlier

Những dữ liệu định lượng trong bộ dữ liệu có hiện tượng bị outlier khá nhiều, Hướng giải quyết cho điều này là thay thể các giá trị outlier về ngưỡng cho phép.

# Xử lý Outlier

cols = ['ln_mileage','tax','ln_mpg','price']

for col in cols:

# Tính IQR của biến

Q1 = df[col].quantile(0.25)

Q3 = df[col].quantile(0.75)

IQR = Q3 - Q1


# Xác định ngưỡng trên và ngưỡng dưới

upper_threshold = Q3 + (1.5 * IQR)

lower_threshold = Q1 - (1.5 * IQR)


# Thay thế các giá trị outlier

df[col] = df[col].apply(lambda x: upper_threshold if x >= upper_threshold else (lower_threshold if x <= lower_threshold else x))

Chia tập dữ liệu thành X và y

cat_features = ['year','transmission','fuelType','engineSize','Class']

num_features = ['ln_mileage','tax','ln_mpg']

features = cat_features + num_features

X = df[features].reset_index(drop=True)

y = df['price'].reset_index(drop=True)

Chuẩn hóa và đưa về dạng sẵn sàng để huấn luyện mô hình

Ở bước này, ta tiến hành mã hóa các biến category về dạng (0,1,..). Scale các biến định lượng. Cụ thể, tạo một Pipeline bằng thư viện sklearn và fit vào bộ dữ liệu X.

from sklearn.compose import ColumnTransformer

from sklearn.pipeline import Pipeline

from sklearn.preprocessing import OneHotEncoder, StandardScaler

num_transformer = Pipeline(steps = [

('scaler', StandardScaler())

])

cat_transformer = Pipeline([

('encoder',OneHotEncoder())

])

#Khai báo quá trình xử lý

preprocessor = ColumnTransformer([

('num',num_transformer,num_features),

('cat',cat_transformer,cat_features),

])

#Fit và transform vào bộ dữ liệu

X_transformed = preprocessor.fit_transform(X)

Chia training set và test set

Để tránh tình trạng bị bias khi huấn luyện mô hình, ta sẽ chia bộ dữ liệu thành 2 bộ nhỏ hơn với bộ trainning dùng để train mô hình máy học. Bộ test dùng để kiểm tra lại khi đã huấn luyện xong.

#Chia bộ dữ liệu

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_transformed,y, train_size = 0.8)

Tỷ lệ chia là 8 - 2.

Chạy mô hình

from sklearn import linear_model

from sklearn.metrics import mean_squared_error

from sklearn.metrics import r2_score

#Khai báo mô hình

linear_regression = linear_model.LinearRegression()


#Huấn luyện mô hình

linear_regression.fit(X_train, y_train)

Kiểm tra các thông số kỹ thuật

y_pred = linear_regression.predict(X_test)

r2 = r2_score(y_test, y_pred)

print('R2 Score:',r2)

mse = mean_squared_error(y_test, y_pred)

rmse = np.sqrt(mse)

print('MSE:',mse)

print('RMSE:',rmse)

Hệ số xác định (coefficient of determination) ký hiệu là R2, một con số thống kê tổng hợp khả năng giải thích của một phương trình. R2 = 82% thể hiện tổng mức biến thiên của các biến độc lập giải thích được 82% sự biến thiên của biến phụ thuộc. RMSE = 3325 là sai số bình quân khi dự đoán.

Tương quan giữa sai số và dự đoán


Mô hình hồi quy OLS

Mô hình hồi quy OLS (Ordinary Least Squares) là một phương pháp ước lượng tham số trong mô hình hồi quy tuyến tính. Đây là phương pháp phổ biến và cơ bản nhất trong hồi quy tuyến tính.

Trong mô hình hồi quy OLS, chúng ta cố gắng tìm ra các tham số ước lượng sao cho tổng bình phương sai số (sum of squared residuals) là nhỏ nhất. Cụ thể, ta tính toán sai số giữa giá trị dự báo và giá trị thực tế cho từng điểm dữ liệu, sau đó bình phương và tổng hợp chúng lại.

Chuẩn bị dữ liệu

Mã hóa các cột category

#Mã hóa các cột category

# Thực hiện encode cho các cột categorical

X['price'] = y

cat_cols = ['year', 'transmission','fuelType','engineSize','Class']

for cat_col in cat_cols:

min_value = X.groupby(cat_col)['price'].sum().sort_values().index[0]

values = X[cat_col].unique()

for value in values:

X[value] = X[cat_col].apply(lambda x: 0 if x == min_value else (1 if x == value else 0))

del X['price']

remove_cols = cat_cols

X = X.drop(columns = remove_cols,axis =1)

Thay vì mã hóa bằng thư viện sklearn thì chúng ta mã hóa thủ công.

Scale các cột định lượng

# Thực hiện scaler cho các cột numerical

from sklearn.preprocessing import StandardScaler

num_cols = ['ln_mileage','tax','ln_mpg']

scaler = StandardScaler()

X[num_cols] = pd.DataFrame(data = scaler.fit_transform(X[num_cols]), columns= num_cols)

Chia bộ dữ liệu

#Chia bộ dữ liệu

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X,y, train_size = 0.8)

Huấn luyện mô hình

#Huấn luyện mô hình

model = sm.OLS(y_train, X_train)

X = sm.add_constant(X)

results = model.fit()

Thông số kỹ thuật

results.summary()

R2 = 82.7%. F<0.05 ⇒ Mô hình có ý nghĩa thống kê.

p-value của những biến như Manual, Automatic, Semi-Auto, Hybrid cao hơn 0.05

⇒ Với mức ý nghĩa 5% thì những biến này không có ý nghĩa thống kê.

⇒ Có thể nói fuelType không ảnh hưởng đến giá của xe.

Dự báo

Tương quan giữa sai số dự báo với giá dự báo. Sai số thấp hơn so với mô hình dùng trong sklearn.

Ứng dụng demo dự án dự báo giá xe hơn

Sau khi đã hoàn thành xong mô hình, chúng ta tạo một file python cho phép đọc dữ liệu và huấn luyện mô hình trong file. File python sẽ chạy một website với hosting là localhost. Cho phép chúng ta nhập dữ liệu trên web. Sau đó, từ dữ liệu người dùng nhập chúng ta sẽ dự báo giá xe theo mô hình đã huấn luyện từ đầu. Kết quả trả ra sẽ là giá xe được dự báo.


Comments


JOIN MY MAILING LIST

Thanks for submitting!

© 2035 by Lovely Little Things. Powered and secured by Wix

  • Instagram
  • YouTube
  • Facebook
  • Pinterest
bottom of page