Trong những phần trước, hầu hết tất cả mô hình dự đoán đều ở cấp độ khách hàng (ví dụ: dự đoán churn, ngày mua hàng tiếp theo, v.v.). Sẽ rất hữu ích nếu bạn thu nhỏ và nhìn vào bức tranh rộng hơn. Chúng ta sẽ tác động đến doanh số như thế nào thông qua việc nỗ lực hơn đối với khách hàng?
Dự báo chuỗi thời gian (time series forecasting) là một trong những nền tảng chính của máy học (machine learning).
Có một số phương pháp để thực hiện điều này như Autoregressive Integrated Moving Average (ARIMA), Seasonal Autoregressive Integrated Moving-Average (SARIMA), Vector Autoregression (VAR)...
Trong bài viết này, chúng ta sẽ tập trung vào phương pháp Long Short-term Memory (LSTM), một phương pháp phổ biến nếu bạn sử dụng Deep Learning. Chúng ta sẽ sử dụng Keras trong dự án của mình để triển khai LSTM.
Cuối cùng, dự đoán được doanh số bán hàng trong tương lai sẽ mang lại lợi ích gì đối với việc kinh doanh của chúng ta?
Trước hết, nó là một benchmark. Chúng ta có thể sử dụng nó như công việc kinh doanh sẽ đạt được nếu không thay đổi chiến lược. Hơn nữa, chúng ta có thể tính toán giá trị gia tăng của các hành động mới trên benchmark này.
Tiếp đến, nó có thể được sử dụng để lập kế hoạch. Chúng ta có thể lập kế hoạch hoạt động cung và cầu của mình bằng cách xem các dự báo.
Cuối cùng, nó là một hướng dẫn để chúng ta có thể lập ra kế hoạch ngân sách và mục tiêu.
Bây giờ đã đến lúc bắt tay vào viết code và xây dựng mô hình học sâu đầu tiên. Việc triển khai mô hình gồm 3 bước:
- Sắp xếp dữ liệu (Data Wrangling)
- Chuyển đổi dữ liệu để nó cố định và được giám sát
- Xây dựng mô hình LSTM và đánh giá
Sắp xếp dữ liệu (Data Wrangling)
Trong ví dụ này, chúng ta sử dụng tập dữ liệu từ cuộc thi Kaggle. Nó thể hiện doanh thu hàng ngày của từng cửa hàng và mặt hàng.
Giống như mọi khi, chúng ta bắt đầu với việc nhập các thư viện bắt buộc và nhập dữ liệu của chúng ta từ CSV:
from datetime import datetime, timedelta,date
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from __future__ import division
import warnings
warnings.filterwarnings("ignore")
import plotly.plotly as py
import plotly.offline as pyoff
import plotly.graph_objs as go
#import Keras
import keras
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import Adam
from keras.callbacks import EarlyStopping
from keras.utils import np_utils
from keras.layers import LSTM
from sklearn.model_selection import KFold, cross_val_score, train_test_split
#initiate plotly
pyoff.init_notebook_mode()
#read the data in csv
df_sales = pd.read_csv('sales_data.csv')
#convert date field from string to datetime
df_sales['date'] = pd.to_datetime(df_sales['da
Dữ liệu của chúng ta giống như sau:
Nhiệm vụ của chúng ta là dự đoán tổng doanh số hàng tháng. Chúng ta cần tổng hợp dữ liệu của mình ở cấp độ hàng tháng và tổng hợp cột sales.
#represent month in date field as its first day
df_sales['date'] = df_sales['date'].dt.year.astype('str') + '-' + df_sales['date'].dt.month.astype('str') + '-01'
df_sales['date'] = pd.to_datetime(df_sales['date'])
#groupby date and sum the sales
df_sales = df_sales.groupby('date').sales.sum().reset_index()
Sau khi áp dụng đoạn code trên, df_sales hiển thị tổng doanh số mà chúng ta cần:
Chuyển đổi dữ liệu
Để lập mô hình dự báo dễ dàng và chính xác hơn, chúng ta sẽ thực hiện các chuyển đổi bên dưới:
- Chúng ta sẽ chuyển dữ liệu sang cố định (nếu nó không cố định)
- Chuyển đổi từ chuỗi thời gian sang được giám sát để có bộ tính năng của mô hình LSTM
- Scale dữ liệu
Trước hết, làm cách nào để kiểm tra dữ liệu có cố định hay không? Hãy vẽ biểu đồ và xem xét:
#plot monthly sales
plot_data = [
go.Scatter(
x=df_sales['date'],
y=df_sales['sales'],
)
]
plot_layout = go.Layout(
title='Montly Sales'
)
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Biểu đồ doanh số hàng tháng
Nó rõ ràng không đứng yên mà có xu hướng tăng dần qua các tháng. Một phương pháp là xây dựng mô hình dựa trên sự chênh lệch doanh số bán hàng tháng này so với tháng trước.
#create a new dataframe to model the difference
df_diff = df_sales.copy()
#add previous sales to the next row
df_diff['prev_sales'] = df_diff['sales'].shift(1)
#drop the null values and calculate the difference
df_diff = df_diff.dropna()
df_diff['diff'] = (df_diff['sales'] - df_diff['prev_sales'])
df_diff.head(10)
Bây giờ chúng ta có dataframe cần thiết để lập mô hình cho sự khác biệt:
Hãy vẽ biểu đồ và kiểm tra nó có cố định hay không:
#plot sales diff
plot_data = [
go.Scatter(
x=df_diff['date'],
y=df_diff['diff'],
)
]
plot_layout = go.Layout(
title='Montly Sales Diff'
)
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Bây giờ chúng ta có thể bắt đầu xây dựng bộ tính năng của mình. Chúng ta cần sử dụng dữ liệu bán hàng hằng tháng trước để dự đoán những đợt tiếp theo. Khoảng thời gian nhìn lại có thể khác nhau đối với mọi mô hình. Ví dụ này của chúng ta sẽ là 12.
Vì vậy, những gì chúng ta cần làm là tạo các cột từ lag_1 đến lag_12 và gán giá trị bằng cách sử dụng phương thức shift():
#create dataframe for transformation from time series to supervised
df_supervised = df_diff.drop(['prev_sales'],axis=1)
#adding lags
for inc in range(1,13):
field_name = 'lag_' + str(inc)
df_supervised[field_name] = df_supervised['diff'].shift(inc)
#drop null values
df_supervised = df_supervised.dropna().reset_index(drop=True)
Kiểm tra dataframe mới của chúng ta có tên là df_supervised:
Hiện tại chúng ta có bộ tính năng.
Vậy các tính năng dự đoán của chúng ta có ích như thế nào?
Adjusted R-squared là câu trả lời. Nó cho ta biết các tính năng giải thích sự thay đổi trong nhãn như thế nào.
Hãy xem ví dụ sau:
# Import statsmodels.formula.api
import statsmodels.formula.api as smf
# Define the regression formula
model = smf.ols(formula='diff ~ lag_1', data=df_supervised)
# Fit the regression
model_fit = model.fit()
# Extract the adjusted r-squared
regression_adj_rsq = model_fit.rsquared_adj
print(regression_adj_rsq)
Vậy điều gì đã xảy ra ở trên?
Về cơ bản, chúng ta fit với mô hình hồi quy tuyến tính (OLS — Ordinary Least Squares) và tính toán Adjusted R-squared. Đối với ví dụ ở trên, chúng ta chỉ sử dụng lag_1 để xem nó giải thích mức độ biến thiên/dao động (variation) trong cột diff. Kết quả đầu ra của khối mã này là:
lag_1 giải thích 3% của sự biến thiên/dao động (variation). Hãy kiểm tra những cái khác:
Thêm bốn tính năng nữa đã tăng số điểm từ 3% lên 44%.
Điểm như thế nào nếu chúng ta sử dụng tất cả bộ tính năng:
Kết quả rất ấn tượng với số điểm là 98%. Giờ đây, chúng ta có thể tự tin xây dựng mô hình của mình sau khi scale dữ liệu. Nhưng còn một bước nữa trước khi scale.
Chúng ta nên chia dữ liệu của mình thành những tập dữ liệu kiểm thử (test set) và tập dữ liệu huấn luyện (train set). Đối với tập dữ liệu kiểm thử, chúng ta đã chọn doanh số bán hàng trong 6 tháng qua.
#import MinMaxScaler and create a new dataframe for LSTM model
from sklearn.preprocessing import MinMaxScaler
df_model = df_supervised.drop(['sales','date'],axis=1)
#split train and test set
train_set, test_set = df_model[0:-6].values, df_model[-6:].values
Là scaler, chúng ta sẽ sử dụng MinMaxScaler:
#apply Min Max Scaler
scaler = MinMaxScaler(feature_range=(-1, 1))
scaler = scaler.fit(train_set)
# reshape training set
train_set = train_set.reshape(train_set.shape[0], train_set.shape[1])
train_set_scaled = scaler.transform(train_set)
# reshape test set
test_set = test_set.reshape(test_set.shape[0], test_set.shape[1])
test_set_scaled = scaler.transform(test_set)
Xây dựng mô hình LSTM
Mọi thứ đã sẵn sàng để xây dựng mô hình học sâu đầu tiên. Hãy tạo các bộ nhãn và tính năng từ scaled datasets:
X_train, y_train = train_set_scaled[:, 1:], train_set_scaled[:, 0:1]
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test, y_test = test_set_scaled[:, 1:], test_set_scaled[:, 0:1]
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
Hãy fit với mô hình LSTM:
model = Sequential()
model.add(LSTM(4, batch_input_shape=(1, X_train.shape[1], X_train.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(X_train, y_train, nb_epoch=100, batch_size=1, verbose=1, shuffle=False)
Khối mã ở trên print ra cách mô hình tự cải thiện và giảm lỗi trong mỗi giai đoạn:
Hãy thử dự đoán và xem kết quả như thế nào nhé.
y_pred = model.predict(X_test,batch_size=1)
#for multistep prediction, you need to replace X_test values with the predictions coming from t-1
Các kết quả trông giống nhau nhưng không cho chúng ta biết nhiều vì đây là scaled data cho thấy sự khác biệt. Chúng ta có thể xem dự đoán doanh số bán hàng thực tế như thế nào?
Đầu tiên, chúng ta cần thực hiện phép biến đổi nghịch đảo (inverse transformation) để scale:
#reshape y_pred
y_pred = y_pred.reshape(y_pred.shape[0], 1, y_pred.shape[1])
#rebuild test set for inverse transform
pred_test_set = []
for index in range(0,len(y_pred)):
print np.concatenate([y_pred[index],X_test[index]],axis=1)
pred_test_set.append(np.concatenate([y_pred[index],X_test[index]],axis=1))
#reshape pred_test_set
pred_test_set = np.array(pred_test_set)
pred_test_set = pred_test_set.reshape(pred_test_set.shape[0], pred_test_set.shape[2])
#inverse transform
pred_test_set_inverted = scaler.inverse_transform(pred_test_set)
Thứ hai, chúng ta cần xây dựng dataframe có ngày tháng và các dự đoán. Các dự đoán đã biến đổi đang cho thấy sự khác biệt. Chúng ta nên tính toán doanh số bán hàng dự đoán:
#create dataframe that shows the predicted sales
result_list = []
sales_dates = list(df_sales[-7:].date)
act_sales = list(df_sales[-7:].sales)
for index in range(0,len(pred_test_set_inverted)):
result_dict = {}
result_dict['pred_value'] = int(pred_test_set_inverted[index][0] + act_sales[index])
result_dict['date'] = sales_dates[index+1]
result_list.append(result_dict)
df_result = pd.DataFrame(result_list)
#for multistep prediction, replace act_sales with the predicted sales
Output:
Thật tuyệt! Chúng ta đã dự đoán được doanh số bán hàng trong sáu tháng tới. Hãy kiểm tra mô hình của chúng ta trong sơ đồ nhé.
#merge with actual sales dataframe
df_sales_pred = pd.merge(df_sales,df_result,on='date',how='left')
#plot actual and predicted
plot_data = [
go.Scatter(
x=df_sales_pred['date'],
y=df_sales_pred['sales'],
name='actual'
),
go.Scatter(
x=df_sales_pred['date'],
y=df_sales_pred['pred_value'],
name='predicted'
)
]
plot_layout = go.Layout(
title='Sales Prediction'
)
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
Thực tế so với dự đoán:
Nhìn vào sơ đồ, ta có thể thấy mô hình thực tế so với dự đoán không khác nhau mấy. Ngoài ra, chúng ta có thể cải thiện mô hình bằng cách thêm ngày lễ, thời gian nghỉ ngơi và hiệu ứng theo mùa khác như tính năng mới.
Bài viết được dịch từ đây.
Kieu Hoa
Khi mình yêu cuộc đời, cuộc đời cũng sẽ yêu mình đắm say
Bài viết liên quan
Database (Cơ sở dữ liệu) là gì? Những loại Database phổ biến nhất hiện nay
Sep 01, 2024 • 11 min read
Python là gì? Những đặc điểm nổi bật và Ứng dụng của Python
Aug 28, 2024 • 14 min read
Ứng dụng Hypothesis Testing - Kiểm định giả thuyết trong Y học
Jul 18, 2024 • 8 min read
Google Colab là gì? Hướng dẫn sử dụng Google Colab cho người mới
Jul 02, 2024 • 10 min read
Hướng dẫn cách lấy dữ liệu Facebook Ads Tự động Mỗi ngày Miễn phí - Phần 2
Jun 24, 2024 • 6 min read
Hướng dẫn cách lấy dữ liệu Facebook Ads Tự động Mỗi ngày Miễn phí- Phần 1
Jun 24, 2024 • 11 min read