[ad_1]
Hãy tưởng tượng bạn đang lập kế hoạch chiến lược tiếp thị cho công ty taxi của mình hoặc thậm chí xem xét việc gia nhập thị trường như một đối thủ cạnh tranh mới – việc dự đoán số lượng chuyến đi bằng taxi ở các thành phố lớn có thể là một vấn đề kinh doanh thú vị. Hoặc, nếu bạn chỉ là một cư dân tò mò như tôi, thì bài viết này là lựa chọn hoàn hảo để bạn tìm hiểu cách sử dụng mô hình Chuỗi thời gian cấu trúc R Bayesian (BSTS) để dự báo các chuyến đi taxi hàng ngày và khám phá những hiểu biết thú vị.
Trong bài viết này, tôi sẽ hướng dẫn bạn quy trình bao gồm chuẩn bị dữ liệu, phân tích dữ liệu khám phá, lập mô hình chuỗi thời gian, phân tích kết quả dự báo và hiểu biết sâu sắc về doanh nghiệp. Tôi muốn dự đoán số chuyến đi hàng ngày trong nửa cuối năm 2023.
Dữ liệu được thu thập từ Cổng dữ liệu Chicago. (Bạn sẽ thấy nền tảng này có quyền truy cập vào nhiều dữ liệu khác nhau của chính phủ!) Trên trang internet, chỉ cần tìm danh sách thả xuống “Hành động” để truy vấn dữ liệu.
Trong công cụ truy vấn, bạn sẽ tìm thấy các công cụ quản lý bộ lọc, nhóm và cột. Bạn chỉ cần tải xuống tập dữ liệu thô. Tuy nhiên, để tiết kiệm độ phức tạp trong tính toán, tôi đã nhóm dữ liệu theo dấu thời gian lấy hàng để tổng hợp số chuyến đi trong 15 phút.
Với việc khám phá tập dữ liệu, tôi cũng lọc ra bản ghi có 0 chuyến đi và mã khu vực đón khách N/A (có nghĩa là địa điểm đón không nằm trong Chicago). Bạn nên khám phá dữ liệu để quyết định cách bạn muốn truy vấn dữ liệu. Nó nên dựa trên trường hợp sử dụng phân tích của bạn.
Sau đó, xuất dữ liệu đã xử lý. Quá trình tải xuống có thể mất một chút thời gian!
Hiểu dữ liệu là bước quan trọng nhất để tiền xử lý và lập luận lựa chọn mô hình. Trong phần sau, tôi đi sâu vào các đặc điểm khác nhau của tập dữ liệu bao gồm tính thời vụ, xu hướng và kiểm tra thống kê về tính dừng và tự tương quan trong độ trễ.
Tính thời vụ đề cập đến những biến động định kỳ trong dữ liệu xảy ra đều đặn. Những mô hình này lặp lại trong một khoảng thời gian cụ thể, chẳng hạn như ngày, tuần, tháng hoặc quý.
Để hiểu tính thời vụ, trước tiên chúng tôi tổng hợp số chuyến đi theo ngày và tháng để hình dung tác động.
library(lubridate)
library(dplyr)
library(xts)
library(bsts)
library(forecast)
library(tseries)demand_data <- learn.csv("taxi_trip_data.csv")
colnames(demand_data) <- c('trip_cnt','trip_datetime')
demand_data$trip_datetime <- mdy_hms(demand_data$trip_datetime)
demand_data$rounded_day <- floor_date(demand_data$trip_datetime, unit = "day")
demand_data$rounded_month <- floor_date(demand_data$trip_datetime, unit = "month")
monthly_agg <- demand_data %>%
group_by(rounded_month) %>%
summarise(
trip_cnt = sum(trip_cnt, na.rm = TRUE)
)
daily_agg <- demand_data %>%
group_by(rounded_day) %>%
summarise(
trip_cnt = sum(trip_cnt, na.rm = TRUE)
)
Nhu cầu taxi ở Chicago đạt đỉnh điểm vào năm 2014, cho thấy xu hướng giảm theo tính thời vụ hàng năm và bị giảm mạnh do COVID vào năm 2020.
Số lượng hàng ngày trước COVID cho thấy tính thời vụ hàng tuần, với số lượng chuyến đi cao hơn vào Thứ Sáu và Thứ Bảy.
Điều thú vị là tính thời vụ hàng tuần sau COVID đã thay đổi, thứ Năm hiện có nhu cầu cao nhất. Điều này đưa ra giả thuyết về sự can thiệp của COVID.
Xu hướng trong dữ liệu chuỗi thời gian đề cập đến mô hình cơ bản hoặc xu hướng tăng, giảm hoặc duy trì ổn định theo thời gian của dữ liệu. Tôi đã chuyển đổi khung dữ liệu thành dữ liệu chuỗi thời gian để phân tách STL nhằm theo dõi xu hướng.
zoo_data <- zoo(daily_agg$trip_cnt, order.by = daily_agg$rounded_day)
start_time <- as.numeric(format(index(zoo_data)(1), "%Y"))
ts_data <- ts(coredata(zoo_data), begin = start_time, frequency = 365)
stl_decomposition <- stl(ts_data, s.window = "periodic")
plot(stl_decomposition)
Kết quả thành phần STL cho thấy có xu hướng phi tuyến tính. Phần thời vụ cũng thể hiện tính thời vụ hàng năm. Sau khi xem xét kỹ hơn về tính thời vụ hàng năm, tôi thấy rằng Lễ Tạ ơn và Lễ Giáng sinh có nhu cầu thấp nhất hàng năm.
Một chuỗi thời gian được xem xét đứng im nếu các thuộc tính thống kê của nó (ví dụ: giá trị trung bình, phương sai và tự tương quan) không đổi theo thời gian. Từ các biểu đồ trên, chúng ta đã biết dữ liệu này không cố định vì nó thể hiện xu hướng và tính thời vụ. Nếu bạn muốn mạnh mẽ hơn, thử nghiệm ADF và KPSS thường được tận dụng để xác thực giả thuyết khống tương ứng là không cố định và đứng yên.
adf.take a look at(zoo_data)
kpss.take a look at(zoo_data)
Tự tương quan trễ đo lường mối tương quan giữa một chuỗi thời gian và độ trễ của nó trong các khoảng thời gian liên tiếp. Nó giải thích giá trị hiện tại có liên quan như thế nào với các giá trị trong quá khứ của nó. Bằng cách tự tương quan theo độ trễ, chúng tôi có thể xác định các mẫu và giúp chúng tôi chọn mô hình chuỗi thời gian thích hợp (Ví dụ: hiểu cấu trúc tự tương quan giúp xác định thứ tự của các thành phần AR và MA cho mô hình ARIMA). Biểu đồ cho thấy sự tự tương quan đáng kể ở nhiều độ trễ.
acf(zoo_data)
EDA cung cấp những hiểu biết quan trọng về cách chúng ta nên chuyển đổi và xử lý trước dữ liệu để đạt được kết quả dự báo tốt nhất.
COVID đã thay đổi đáng kể chuỗi thời gian. Thật không hợp lý khi đưa vào dữ liệu đã thay đổi quá nhiều. Ở đây tôi điều chỉnh mô hình dựa trên dữ liệu từ tháng 6 năm 2020 đến tháng 6 năm 2023. Đây vẫn là con số dự đoán tỷ lệ thử nghiệm tàu là 6:1 cho nửa cuối năm 2023.
practice <- window(zoo_data, begin = as.Date("2020-07-01"), finish = as.Date("2023-06-30"))
take a look at <- window(zoo_data, begin = as.Date("2023-07-01"), finish = as.Date("2023-12-31"))
Dữ liệu không cố định cho thấy phương sai lớn và xu hướng phi tuyến tính. Ở đây, tôi đã áp dụng phép biến đổi nhật ký và vi sai để giảm thiểu ảnh hưởng của các đặc điểm này đến hiệu suất dự đoán.
train_log <- log(practice + 1)
train_diff <- diff(practice, variations = 1)
Đoạn mã sau hoạt động trên dữ liệu được chuyển đổi nhật ký vì nó mang lại hiệu suất dự báo tốt hơn trong các thử nghiệm sơ bộ.
Hãy tóm tắt nhanh những phát hiện từ EDA:
- Xu hướng đa mùa và phi tuyến tính
- Tác động của các ngày lễ và sự kiện: Các sự kiện quan trọng như ngày lễ ảnh hưởng đến nhu cầu taxi.
- Khoảng thời gian dự đoán dài: Chúng ta cần dự báo trong 180 ngày.
Với những đặc điểm này, mô hình Chuỗi thời gian cấu trúc Bayes (BSTS) là một lựa chọn phù hợp. Mô hình BSTS phân tách chuỗi thời gian thành nhiều thành phần bằng phương pháp Bayesian, nắm bắt các biến tiềm ẩn cơ bản phát triển theo thời gian. Các thành phần chính thường bao gồm:
- Thành phần xu hướng
- Thành phần theo mùa
- Thành phần hồi quy: Kết hợp ảnh hưởng của các biến bên ngoài có thể ảnh hưởng đến chuỗi thời gian.
Đây là mô hình tôi đã sử dụng để dự đoán các chuyến đi bằng taxi:
ss <- AddSemilocalLinearTrend(record(), train_log)
ss <- AddSeasonal(ss, train_log, nseasons = 7)
ss <- AddSeasonal(ss, train_log, nseasons = 365)
ss <- AddMonthlyAnnualCycle(ss, train_log)
ss <- AddRegressionHoliday(ss, train_log, holiday_list)
model_log_opti <- bsts(train_log, state.specification = ss, niter = 5000, verbose = TRUE, seed=1014)
abstract(model_log_opti)
AddSemilocalLinearTrend()
Từ EDA, xu hướng trong dữ liệu của chúng tôi không phải là một bước đi ngẫu nhiên. Do đó, chúng tôi sử dụng xu hướng tuyến tính bán cục bộ, giả sử thành phần cấp độ di chuyển theo bước đi ngẫu nhiên, nhưng thành phần độ dốc tuân theo quy trình AR1 tập trung vào một giá trị có khả năng khác 0. Điều này rất hữu ích cho việc dự báo dài hạn.
Thêm theo mùa()
Mô hình theo mùa có thể được coi là một hồi quy về nseasons
biến giả. Ở đây chúng tôi bao gồm tính thời vụ hàng tuần và hàng năm bằng cách cài đặt nseasons
đến 7 và 365.
AddMonthlyAnnualCycle()
Điều này thể hiện sự đóng góp của mỗi tháng. Ngoài ra, bạn có thể thiết lập nseasons=12
TRONG AddSeasonal()
để giải quyết tính thời vụ hàng tháng.
AddRegressionHoliday()
Trước đây tại EDA, chúng tôi đã biết rằng Lễ tạ ơn và Lễ Giáng sinh có tác động tiêu cực đến việc đi taxi. Hàm này ước tính tác động của từng kỳ nghỉ hoặc sự kiện bằng cách sử dụng hồi quy. Để làm điều này, tôi đã hỏi một người bạn quen thuộc với Chicago (tất nhiên là ChatGPT) về danh sách các ngày lễ và sự kiện lớn ở Chicago. Ví dụ: Chicago Marathon có thể tăng số lượng chuyến đi bằng taxi.
Sau đó tôi thiết lập ngày của những ngày này:
christmas <- NamedHoliday("Christmas")
new_year <- NamedHoliday("NewYear")
thanksgiving <- NamedHoliday("Thanksgiving")
independence_day <- NamedHoliday("IndependenceDay")
labor_day <- NamedHoliday("LaborDay")
memorial_day <- NamedHoliday("MemorialDay")
auto.present <- DateRangeHoliday("Auto_show", begin = as.Date(c("2013-02-09", "2014-02-08", "2015-02-14", "2016-02-13", "2017-02-11"
, "2018-02-10", "2019-02-09", "2020-02-08", "2021-07-15", "2022-02-12"
, "2023-02-11")),
finish = as.Date(c("2013-02-18", "2014-02-17", "2015-02-22", "2016-02-21", "2017-02-20"
, "2018-02-19", "2019-02-18", "2020-02-17"
, "2021-07-19", "2022-02-21", "2023-02-20")))
st.patrick <- DateRangeHoliday("stPatrick", begin = as.Date(c("2013/3/16", "2014/3/15", "2015/3/14", "2016/3/12"
, "2017/3/11", "2018/3/17", "2019/3/16", "2020/3/14"
, "2021/3/13", "2022/3/12", "2023/3/11")),
finish = as.Date(c("2013/3/16", "2014/3/15", "2015/3/14", "2016/3/12"
, "2017/3/11", "2018/3/17", "2019/3/16", "2020/3/14"
, "2021/3/13", "2022/3/12", "2023/3/11")))
air.present <- DateRangeHoliday("air_show", begin = as.Date(c("2013/8/17", "2014/8/16", "2015/8/15", "2016/8/20"
, "2017/8/19", "2018/8/18", "2019/8/17"
, "2021/8/21", "2022/8/20", "2023/8/19")),
finish = as.Date(c("2013/8/18", "2014/8/17", "2015/8/16", "2016/8/21", "2017/8/20"
, "2018/8/19", "2019/8/18", "2021/8/22", "2022/8/21", "2023/8/20")))
lolla <- DateRangeHoliday("lolla", begin = as.Date(c("2013/8/2", "2014/8/1", "2015/7/31", "2016/7/28", "2017/8/3"
, "2018/8/2", "2019/8/1", "2021/7/29", "2022/7/28", "2023/8/3")),
finish = as.Date(c("2013/8/4", "2014/8/3", "2015/8/2", "2016/7/31", "2017/8/6", "2018/8/5"
, "2019/8/4", "2021/8/1", "2022/7/31", "2023/8/6")))
marathon <- DateRangeHoliday("marathon", begin = as.Date(c("2013/10/13", "2014/10/12", "2015/10/11", "2016/10/9", "2017/10/8"
, "2018/10/7", "2019/10/13", "2021/10/10", "2022/10/9", "2023/10/8")),
finish = as.Date(c("2013/10/13", "2014/10/12", "2015/10/11", "2016/10/9", "2017/10/8"
, "2018/10/7", "2019/10/13", "2021/10/10", "2022/10/9", "2023/10/8")))
DateRangeHoliday() cho phép chúng tôi xác định các sự kiện xảy ra vào các ngày khác nhau mỗi năm hoặc kéo dài trong nhiều ngày. TênHoliday() giúp với các ngày lễ liên bang.
Sau đó, xác định danh sách các ngày nghỉ lễ này cho thuộc tính AddRegressionHoliday():
holiday_list <- record(auto.present, st.patrick, air.present, lolla, marathon
, christmas, new_year, thanksgiving, independence_day
, labor_day, memorial_day)
tôi đã tìm thấy Trang web này rất hữu ích trong việc khám phá các thành phần và thông số khác nhau.
Kết quả phù hợp cho thấy mô hình đã nắm bắt tốt thành phần của chuỗi thời gian.
fitted_values <- as.numeric(residuals.bsts(model_log_opti, imply.solely=TRUE)) + as.numeric(train_log)
train_hat <- exp(fitted_values) - 1
plot(as.numeric(practice), kind = "l", col = "blue", ylim=c(500, 30000), fundamental="Fitted consequence")
traces(train_hat, col = "crimson")
legend("topleft", legend = c("Precise worth", "Fitted worth"), col = c("blue", "crimson"), lty = c(1, 1), lwd = c(1, 1))
Trong phân tích phần dư, mặc dù phần dư có giá trị trung bình bằng 0 nhưng vẫn còn một số tính thời vụ. Ngoài ra, phần dư thể hiện hiện tượng tự tương quan ở một vài độ trễ đầu tiên.
Tuy nhiên, khi so sánh những kết quả này với chuỗi thời gian ban đầu, rõ ràng là mô hình đã nắm bắt thành công hầu hết các thành phần tính thời vụ, hiệu ứng kỳ nghỉ và xu hướng. Điều này chỉ ra rằng mô hình BSTS giải quyết một cách hiệu quả các mẫu chính trong dữ liệu, chỉ để lại các cấu trúc còn lại nhỏ cần được kiểm tra thêm.
Bây giờ hãy đánh giá kết quả dự báo của mô hình. Hãy nhớ chuyển đổi các giá trị dự đoán vì mô hình cung cấp các giá trị được ghi lại.
horizon <- size(take a look at)
pred_log_opti <- predict(model_log_opti, horizon = horizon, burn = SuggestBurn(.1, ss))
forecast_values_log_opti <- exp(pred_log_opti$imply) - 1
plot(as.numeric(take a look at), kind = "l", col = "blue", ylim=c(500, 30000), fundamental="Forecast consequence", xlab="Time", ylab="Journey depend")
traces(forecast_values_log_opti, col = "crimson")
legend("topleft", legend = c("Precise worth", "Forecast worth"), col = c("blue", "crimson"), lty = c(1, 1), lwd = c(1, 1))
Mô hình đạt được Sai số phần trăm tuyệt đối trung bình (MAPE) là 9,76%, nắm bắt thành công tính thời vụ và ảnh hưởng của các ngày lễ.
Việc phân tích ảnh hưởng của kỳ nghỉ và sự kiện mang lại những hiểu biết có giá trị cho chiến lược kinh doanh. Các biểu đồ sau minh họa tác động của hồi quy kỳ nghỉ:
PlotHoliday(thanksgiving, model_log_opti)
PlotHoliday(marathon, model_log_opti)
Một ngày trước ngày lễ liên bang có tác động tiêu cực đáng kể đến số lượng chuyến đi. Ví dụ: cả Ngày Lễ Tạ ơn và ngày hôm trước đều cho thấy số chuyến đi bằng taxi giảm đáng kể. Mức giảm này có thể là do nhu cầu thấp hơn hoặc nguồn cung hạn chế. Các công ty có thể điều tra thêm những lý do này và phát triển các chiến lược để giải quyết chúng.
Trái ngược với giả thuyết ban đầu, các sự kiện lớn như Chicago Marathon không cho thấy nhu cầu taxi tăng đáng kể. Điều này cho thấy nhu cầu trong những sự kiện như vậy có thể không cao như mong đợi. Tiến hành nghiên cứu phân khúc khách hàng có thể giúp xác định các nhóm cụ thể có thể bị ảnh hưởng bởi các sự kiện, tiết lộ các cơ hội tiềm năng cho dịch vụ và tiếp thị mục tiêu. Chia nhỏ dữ liệu theo các tiểu khu vực ở Chicago cũng có thể cung cấp thông tin chi tiết tốt hơn. Tác động của các sự kiện có thể khác nhau giữa các vùng lân cận khác nhau và việc hiểu rõ những biến thể này có thể giúp điều chỉnh các chiến lược địa phương hóa.
Vì vậy, đây là cách bạn có thể sử dụng mô hình BSTS để dự đoán số chuyến taxi ở Chicago! Bạn có thể thử nghiệm các thành phần hoặc tham số trạng thái khác nhau để xem mô hình phù hợp với dữ liệu khác nhau như thế nào. Hy vọng bạn thích quá trình này và hãy vỗ tay cho tôi nếu bạn thấy bài viết này hữu ích!
[ad_2]
Source link