Trong lĩnh vực bán lẻ, việc dự báo chính xác doanh thu mang ý nghĩa sống còn. Dựa trên dữ liệu thực tế từ bộ dữ liệu Walmart Sales Dataset (download tại đây), chúng ta sẽ xây dựng mô hình Cây quyết định hồi quy để dự đoán doanh thu bán hàng hằng tuần (Weekly_Sales) của các cửa hàng dựa trên các biến số về kinh tế vĩ mô, thời vụ và đặc điểm cửa hàng.
Biến thời gian: Cột Date trong dữ liệu gốc là chuỗi văn bản (ví dụ: "05-02-2010"), chúng ta bắt buộc phải dùng lệnh pd.to_datetime để bóc tách thành Năm, Tháng, Tuần.
Kỷ luật xử lý: Mô hình Cây quyết định không tính toán dựa trên khoảng cách hình học, do đó các biến số định lượng không cần phải chuẩn hóa (passthrough). Tuy nhiên, biến phân loại như mã cửa hàng (Store) bắt buộc phải được mã hóa bằng kỹ thuật One-Hot Encoding để tránh việc thuật toán hiểu nhầm mã cửa hàng là các con số có tính thứ bậc lớn bé.
Bạn có thể sao chép và chạy trực tiếp đoạn mã dưới đây (bảo đảm tệp walmart-sales-dataset-of-45stores.csv đã được tải lên):
Khai báo thư viện
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
# =====================================================================
# BƯỚC 1: ĐỌC DỮ LIỆU VÀ XỬ LÝ BIẾN THỜI GIAN
# =====================================================================
# Đọc file CSV (Lưu ý đường dẫn file)
df = pd.read_csv('https://drive.google.com/uc?export=download&id=1WZCmMcIJGM0MNjn5CUo-ZSg8hiprG2wN')
# Chuyển đổi 'CPI' bằng cách loại bỏ dấu phân cách hàng nghìn ('.') và sau đó sang kiểu số thực.
df['CPI'] = pd.to_numeric(df['CPI'].astype(str).str.replace('.', '', regex=False), errors='coerce')
# Chuyển đổi 'Unemployment' sang kiểu số thực (giả sử '.' là dấu thập phân).
df['Unemployment'] = pd.to_numeric(df['Unemployment'], errors='coerce')
# Chuyển đổi cột Date sang định dạng datetime (Lưu ý dữ liệu gốc dùng dayfirst=True)
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
# Trích xuất các đặc trưng thời gian để đưa vào mô hình
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Week'] = df['Date'].dt.isocalendar().week
# =====================================================================
# BƯỚC 2: PHÂN TÁCH BIẾN ĐẦU VÀO VÀ BIẾN MỤC TIÊU
# =====================================================================
X = df[['Store', 'Holiday_Flag', 'Temperature', 'Fuel_Price', 'CPI', 'Unemployment', 'Year', 'Month', 'Week']]
y = df['Weekly_Sales']
# Tách biến thành 2 nhóm: Danh mục (Categorical) và Định lượng (Numeric)
categorical_features = ['Store']
numeric_features = ['Holiday_Flag', 'Temperature', 'Fuel_Price', 'CPI', 'Unemployment', 'Year', 'Month', 'Week']
# =====================================================================
# BƯỚC 3: THIẾT LẬP QUY TRÌNH TIỀN XỬ LÝ (PREPROCESSING)
# =====================================================================
# Chú ý: Cây quyết định KHÔNG yêu cầu StandardScaler cho biến định lượng (dùng 'passthrough')
preprocess_tree = ColumnTransformer(
transformers=[
('num', 'passthrough', numeric_features),
('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
]
)
# =====================================================================
# BƯỚC 4: CHIA TẬP DỮ LIỆU VÀ HUẤN LUYỆN MÔ HÌNH
# =====================================================================
# Chia tập huấn luyện (80%) và tập kiểm tra (20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Khởi tạo Pipeline nối dòng chảy từ Tiền xử lý đến Mô hình Decision Tree
dt_pipeline = Pipeline(steps=[
('preprocess', preprocess_tree),
('model', DecisionTreeRegressor(random_state=42))
])
# Kích hoạt quá trình huấn luyện
dt_pipeline.fit(X_train, y_train)
# =====================================================================
# BƯỚC 5: DỰ ĐOÁN VÀ ĐÁNH GIÁ TRÊN TẬP TEST
# =====================================================================
y_pred_dt = dt_pipeline.predict(X_test)
print("--- KẾT QUẢ ĐÁNH GIÁ MÔ HÌNH DECISION TREE ---")
print(f"MAE : {mean_absolute_error(y_test, y_pred_dt):,.2f}")
print(f"RMSE : {np.sqrt(mean_squared_error(y_test, y_pred_dt)):,.2f}")
print(f"R2 : {r2_score(y_test, y_pred_dt):.4f}")
Khi thực thi, mô hình Cây quyết định hồi quy này có thể đạt được các chỉ số cực kỳ ấn tượng với Hệ số xác định R^2 xấp xỉ 0.92. Điều này chứng tỏ rằng các quy tắc rẽ nhánh "Nếu - Thì" của Cây quyết định đã nắm bắt và giải thích được tới ~92% sự biến thiên của doanh thu hằng tuần, chứng minh khả năng học các mối quan hệ phi tuyến tính phức tạp (như tác động của ngày lễ hay sự biến động nhiệt độ) rất xuất sắc.
Việc ứng dụng mô hình Decision Tree Regressor mang lại giá trị chiến lược to lớn cho các nhà bán lẻ:
Tối ưu hóa quản lý tồn kho (Inventory Management): Nếu mô hình thông qua các nhánh cây dự báo doanh thu tuần tới sẽ tăng mạnh (nhờ rơi vào các nút nhánh có Holiday_Flag = 1), doanh nghiệp có thể chủ động chuẩn bị nguồn hàng, tránh tình trạng "cháy kệ" (stockout) làm mất cơ hội doanh thu.
Hoạch định Nhân sự và Logistics: Tại các nút lá (Leaf nodes) cho ra dự báo doanh số đỉnh điểm, siêu thị có thể thiết lập hệ thống cảnh báo để chủ động điều phối tăng ca cho nhân viên tại cửa hàng, đồng thời tối ưu hóa lịch trình vận chuyển của đội xe logistics.
Bạn có thể copy đoạn mã này thả vào Colab để chạy thử ngay! Cấu trúc dùng ColumnTransformer kết hợp Pipeline trong đoạn code trên chính là chuẩn mực thực chiến cao nhất hiện nay, giúp code gọn gàng và ngăn chặn tuyệt đối rủi ro rò rỉ dữ liệu (Data Leakage).
xem tiếp