TowardsDataScience 博客中文翻译 2016~2018(二百八十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

英国 A&E 就诊和急诊入院的时间序列分析和预测

原文:https://towardsdatascience.com/time-series-analysis-and-forecasting-for-a-e-attendances-and-emergency-admission-in-england-53e41a93be35?source=collection_archive---------6-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简介:

这个项目的目标是分析和预测实时序列数据。这些报告和数据集来自 NHS 英格兰网站,该网站报告了英格兰国家医疗服务机构和独立部门组织的事故和急诊人数。

数据周期从 2010 年 8 月开始,到 2018 年 7 月结束。正如你所注意到的,我已经将注意力集中在“总出席人数”这一主要栏目上,并计划将其扩展到其他栏目,如果有人对该分析感兴趣的话。以下是数据集的屏幕截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

关于时间序列分析:

时间序列分析是数据科学的重要课题之一。在这种类型的分析中,数据科学家尽可能准确地预测未来,这就是所谓的预测。我们可以想到大量的应用和想法,其中时间序列分析和预测可以有利于决策。在我之前的文章(点击这里)中,我讨论了医疗保健领域的一个应用。然而,让我们想一想不同领域的更多应用。

1)您可以使用时间序列分析,通过分析历史事件来预测或预报您的网站在未来的点击量和点击数。

2)预测或预测股票或黄金的价格和走势。

3)制造商预测生产和消耗率的另一个应用程序。…等等

价值主张:

我认为,对于数据科学家来说,思考项目的潜在价值以及它如何为决策者带来好处是非常重要的。这是我个人在一个项目开始时所做的。

对于这个项目,我相信通过预测和预测每月的 A&E(事故和紧急情况)出勤,许多重要的决定可以很容易地做出。无论是关于医疗和非医疗的股票购买或员工招聘和他们的工作时间表。此外还要为招待与会者做一些后勤准备。因此,将有助于提高服务质量和减少病人的等待时间。

该项目:

我将使用 R 中的时间序列包来分析和预测 Total A & E 英国 NHS 的出勤情况。以下是主要步骤的总结:

1.加载库和数据集

2.时间序列绘图和分析

3.探测

4.分解

5.均值和朴素方法预测

6.线性回归预测

7.ARIMA 模型预测

8.参考

注意:我是通过 Jupyter 笔记本环境使用 R 的。

加载库和数据集

在本节中,我将加载所需的库、数据集,然后进行一些数据辩论:

library(dplyr)library(urca)library(forecast)library(dygraphs)require(ggplot2)

正在加载数据集:

df <- read.csv ( file= ".. A&E admissions.csv", header = TRUE, sep = "\t")

更改标题名称,使其对 r 更友好。现在“总出席人数”列将表示为“TA”:

setnames ( df, old= c("Period","Total.Attendances), new=c("dateTime", "TA")

检查 ta 列中缺失的数据:

summary(is.na(df$TA))*> Mode   FALSE**> logical      96*

看来没有丢失数据,太好了!现在,我将使用 POSIX 函数将“dateTime”列转换为带有时区说明的日期时间对象:

to.POSIXct <- function(col) {*## Function to create a POSIXct time series*

  *## Create a character vector from the numeric input*dateStr <- paste(as.character(col))*## Return the POSIXct time series object*as.POSIXct( strptime(dateStr, "%d/%m/%Y"))}df$dateTime <- to.POSIXct(df$dateTime)class(df$dateTime)>'POSIXct' 'POSIXt'

时间序列绘图与分析

现在,将 TA 转换为时间序列类:

TA.ts <- ts ( df[,'TA'] , frequency = 12,  start=c(2010,8), end= c(2018,7) )class(TA.ts)> 'ts'

时间序列摘要:

summary(TA.ts)*> Min. 1st Qu.  Median    Mean 3rd Qu.    Max.**> 1599364 1784570 1871972 1875892 1950438 2176022*

绘制英国每月 A&E 总出勤率

plot.ts(TA.ts, main = "Monthly Total A&E Attendance in England",  
         xlab = "Year", ylab = "TA")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制 A&E 在英国的季度和年度总出勤率:

TA.ts.qtr <- aggregate (TA.ts, nfrequency = 4)
TA.ts.yr <- aggregate (TA.ts, nfrequency = 1)plot.ts(TA.ts.qtr, main = "Quarterly Total A&E Attendance in England", xlab = "Year", ylab = "TA")
plot.ts(TA.ts.yr, main = " Yearly Total A&E Attendance in England", xlab = "Year", ylab = "TA")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制直方图和箱线图,以检查 TA 分布:

hist (TA.ts, breaks = 20, main = paste('Distribution of Total A&E Attendance in England'), xlab = "TA")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

boxplot(TA.ts ~ cycle(TA.ts), xlab = "Month", ylab = "TA", main = "Monthly Total A&E Attendance in England - Boxplot")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以注意到 TA 在同一个月和其他月份之间的分布和变化。5 月、7 月和 3 月分别是过去 8 年中最繁忙的月份。

探测

现在,仔细看看过去 8 年的与会者总数。这可以通过应用移动平均技术来实现,以便平滑趋势信号。我们将计算 6、12、24 和 36 个月的平均值,以控制趋势平滑度。

par(mfrow = c(2,2))plot(TA.ts, col="gray", main = "Half Year Moving Average Smoothing")
lines(ma(TA.ts, order = 6), col = "red", lwd=3)plot(TA.ts, col="gray", main = "1 Year Moving Average Smoothing")
lines(ma(TA.ts, order = 12), col = "blue", lwd=3)plot(TA.ts, col="gray", main = "2 Year Moving Average Smoothing")
lines(ma(TA.ts, order = 24), col = "green", lwd=3)plot(TA.ts, col="gray", main = "3 Year Moving Average Smoothing")
lines(ma(TA.ts, order = 36), col = "yellow4", lwd=3)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,在过去的几年中,A&E 与会者的人数几乎呈线性增长。

接下来,让我们检查从 2010 年到 2017 年英国人口对 A&E 出席人数的影响。首先,我必须收集英格兰人口的时间序列数据。幸运的是,我在英国国家统计网站找到了想要的数据。

Eng.Pop <- read.csv(file= ".. /England Pop.csv", header = TRUE,  sep = ",")head(Eng.Pop)*> Year Population**> 2010 52642500**> 2011 53107200**> 2012 53493700**> 2013 53865800**> 2014 54316600**> 2015 54786300*

创建带有刻度(1000)的时间序列人口数据

pop.ts <- ts((Eng.Pop$Population)/1000, frequency = 1, start= 2010, end= 2017)

地块人口时间序列:

plot(pop.ts, main = "England Popuation", xlab = "Year", ylab = "Number of People in 1,000")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,让我们从每年的 A&E 总出勤数据中去除英国人口上升的影响,然后比较两条曲线:

par(mfrow = c(1,2))
plot.ts((TA.ts.yr/pop.ts), lwd=2,col = "red", main = "Yearly Total A&E Attendance in England Adjusted by Population", xlab = "Year", ylab = "TA")
plot.ts(TA.ts.yr, col = "blue", lwd=2, main = " Yearly Total A&E Attendance in England", xlab = "Year", ylab = "TA")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以明显地注意到,在 2010 年至 2017 年期间,英国人口数量的增加对 A&E 每年的总出席人数影响甚微。从 2011 年年中到 2014 年年中,与会者人数几乎保持不变。然后曲线从 2014 年年中开始跳跃到 2015 年底。需要额外的调查和数据来研究为什么英格兰在 2014 年底开始收到突然大量的事故和紧急情况。

分解

在这一步中,我们将把时间序列数据分解成三个部分:趋势、季节和剩余部分。剩余分量必须是稳定的(随机噪声)。换句话说,均值和方差必须是常数。另外,自协方差函数不依赖于时间。

我将对 TA 的记录时间序列使用 STL(使用黄土的季节和趋势分解)分解:

autoplot( stl(log(TA.ts), s.window="periodic", robust=TRUE))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们必须检查和测试剩余的数据,以确保它是稳定的。首先,我们将绘制自相关函数和偏自相关函数:

par(mfrow = c(1,2))
Acf(TA_rem, main ="ACF for Remainder")
Pacf(TA_rem, main ="PACF for Remainder")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ACF 没有明显的滞后,也没有季节效应,这意味着自协方差不依赖于时间。让我们通过绘制剩余部分的箱线图来检查常数均值和方差:

boxplot(TA.ts_rem ~ cycle(TA.ts), xlab = "Month", ylab = "TA", main = "Boxplot of Total Attendance Remainder")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

平均值和方差是常数(无显著变化)。此外,我将应用单位根检验(KPSS 检验)来检查信号。KPSS 检验的零假设表明数据是稳定的,我们将寻找任何证据来拒绝零假设。

TA.ts_rem %>% ur.kpss()  %>% summary()*####################### 
# KPSS Unit Root Test # 
#######################*> Test is of type: mu with 3 lags.> Value of test-statistic is: 0.0287 

> Critical value for a significance level of: 
                10pct  5pct 2.5pct  1pct
> critical values 0.347 0.463  0.574 0.739

检验统计值小于 10%临界值,表明通过了零假设,数据是稳定的。

意味着&天真的方法预测

在这里,我们将应用一些基本模型来预测 12 个月(从 2018 年 8 月至 2019 年 7 月)的 A&E 出席总人数。平均法就是取所有样本点的平均值。而天真和天真的季节性预测使用上一期进行下一期预测。

TA.fit.sa <- meanf(TA.ts, h = 12)
TA.fit.na <- naive(TA.ts, h = 12)
TA.fit.sna <- snaive(TA.ts, h = 12)
plot.ts(TA.ts, main = "Monthly Total Attendance NHS in England", xlab = "Year", ylab = "TA", xlim = c(2010, 2019))
lines(TA.fit.sa$mean, col = "blue")
lines(TA.fit.na$mean, col = "green")
lines(TA.fit.sna$mean, col = "red")
legend("topleft",lty=1,col=c("blue","green", "red"), cex = 0.75, legend=c("Mean method","Naive method", "Seasonal naive method"))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线性回归预测

首先,将拟合时间序列线性回归模型,然后使用“预测”包以 80%和 95%的置信区间预测 12 个月的值(从 2018 年 8 月到 2019 年 7 月):

fit.lm_TA.ts <- tslm(TA.ts ~ trend+season)frcst.lm <- forecast(fit.lm_TA.ts, h = 12, level = c(80,95))plot.ts(TA.ts, main = "Monthly Total A&E Attendance in England", xlab = "Year", ylab = "TA", xlim = c(2010,2019))lis(frcst.lm$fitted, col = "b

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线性回归模型表现相当好,因为我们将拟合数据(蓝色)与实际数据(黑色)进行了对比。接下来,让我们通过检查残差来评估模型。残差均值和方差必须随时间保持不变,如下所示:

boxplot(residuals(fit.lm_TA.ts) ~ cycle(TA.ts), xlab = "Month", ylab = "TA", main = "Boxplot of Residuals")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拟合值和实际值之间的散点图:

df[,"TA.fitted"] <- as.numeric(fit.lm_TA.ts$fitted.values)plot(df$TA, df$TA.fitted, main = "Scatterplot between fitted & actual values", xlab = "Fitted Value", ylab = "Actual")
abline(0, 1, col="blue")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制并列出 2018 年 8 月至 2018 年 7 月的一年预测:

plot.ts(TA.ts, main = "Monthly Total Attendance NHS in England", xlab = "Year", ylab = "TA", xlim = c(2010,2019))
lines(frcst.lm$mean, col = "blue")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

frcst.lm*> Point          Forecast   Lo 80   Hi 80   Lo 95   Hi 95*
*> Aug 2018        1990708 1932450 2048965 1901013 2080402*
*> Sep 2018        1984479 1926222 2042736 1894784 2074174*
*> Oct 2018        2045357 1987100 2103614 1955662 2135051*
*> Nov 2018        1957509 1899252 2015766 1867814 2047204*
*> Dec 2018        1997633 1939376 2055890 1907939 2087328*
*> Jan 2019        1957718 1899461 2015975 1868023 2047413*
*> Feb 2019        1860605 1802347 1918862 1770910 1950299*
*> Mar 2019        2113073 2054816 2171330 2023378 2202768*
*> Apr 2019        2022652 1964395 2080909 1932957 2112347*
*> May 2019        2137346 2079089 2195603 2047651 2227040*
*> Jun 2019        2073922 2015664 2132179 1984227 2163616*
*> Jul 2019        2153840 2095583 2212097 2064145 2243535*

ARIMA 模型预测

ARIMA 代表自回归综合移动平均线。这是时间序列预测的另一种方法。事实上,这是时间序列预测中最广泛使用的方法。

在本节中,我们将对季节性调整数据进行差分变换,以获得平稳信号。然后通过实验得出非季节性 ARIMA 模型的 p,d,q 参数。然后,为季节性 ARIMA 模型设置 P,D,Q 值。最后,将季节性 ARIMA 和自动 ARIMA 模型的结果进行比较。这是《预测原理和实践》一书中的图表摘要,介绍了使用 ARIMA 模型进行预测的一般过程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

记住 ARIMA(p,D,q)(P,D,Q)模型:

p =非季节性部分的自回归部分的阶

d =非季节性部分涉及的一阶差异度

q =非季节性部分的移动平均部分的顺序

P =季节部分的自回归部分的阶

D =季节部分涉及的一阶差异度

Q =季节性部分的移动平均部分的阶数

首先,我们将分解数据,然后在没有季节成分的情况下重新构建— seasadj()函数:返回经季节调整的数据:

TA.ts %>% stl(s.window='periodic') %>% seasadj() -> TA.ts_seasadj
autoplot(TA.ts_seasadj, main= " Seasonal Adjusted Monthly A&E Attendance", lwt= 3)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ggtsdisplay(TA.ts_seasadj, main="Seasonal Adjusted Data with ACF and PACF plots")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

显而易见,我们可以看到季节性调整数据并不是稳定的。让我们用 KPSS 单位根检验来复查一下:

TA.ts_seasadj %>% ur.kpss() %>% summary()*####################### 
# KPSS Unit Root Test # 
#######################* 

> Test is of type: mu with 3 lags. 

> Value of test-statistic is: 2.2591 

> Critical value for a significance level of: 
                10pct  5pct 2.5pct  1pct
> critical values 0.347 0.463  0.574 0.739

测试统计值远高于临界值的 1%。这意味着信号不是稳定的。为了做到这一点,我们将应用一种叫做差分的有用的变换。差异可以通过消除时间序列水平的变化,从而消除(或减少)趋势和季节性,帮助稳定时间序列的平均值。

TA.ts_seasadj %>% diff() -> TA.ts_diff
ggtsdisplay(TA.ts_diff, main="Differencing Seasonal Adjusted Data with ACF and PACF plots")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ACF 图和 PACF 中的一些显著滞后将帮助我们确定 AR 和 MA 的 p 和 q 值。但总的来说,信号看起来是平稳的,让我们用 KPSS 单位根检验再次确认:

TA.ts_diff %>% ur.kpss() %>% summary()*####################### 
# KPSS Unit Root Test # 
#######################*> Test is of type: mu with 3 lags.> Value of test-statistic is: 0.0547> Critical value for a significance level of: 
                10pct  5pct 2.5pct  1pct
> critical values 0.347 0.463  0.574 0.739

测试统计值小于 10%临界值,这意味着数据是稳定的。这意味着一个差分变换足以获得静态数据。让我们评价和比较几个 ARIMA 模型——ARIMA(0,1,2)、ARIMA(1,1,2)和 ARIMA(1,1,1):

*# ARIMA(0,1,2)*summary(Arima (TA.ts_seasadj, order= c(0,1,2)))*> Series: TA.ts_seasadj* 
*> ARIMA(0,1,2)**> Coefficients:*
*>          ma1      ma2*
*>       -0.4453  -0.2117*
*> s.e.   0.0999   0.0937**> sigma^2 estimated as 1.459e+09:  log likelihood=-1136.32*
*> AIC=2278.64   AICc=2278.9   BIC=2286.3**> Training set error measures:*
*>                 ME     RMSE      MAE       MPE     MAPE      MASE        ACF1*
*> Training set 8044.3 37593.57 29865.46 0.3906696 1.586877 0.5389833 -0.05881525*

# ARIMA(1,1,2)
summary(Arima (TA.ts_seasadj, order= c(1,1,2)))*> Series: TA.ts_seasadj* 
*> ARIMA(1,1,2)* 

*> Coefficients:*
*>          ar1      ma1      ma2*
*>      -0.0782  -0.3745  -0.2516*
*> s.e.   0.3092   0.2901   0.1742*

*> sigma^2 estimated as 1.474e+09:  log likelihood=-1136.29*
*> AIC=2280.58   AICc=2281.02   BIC=2290.8*

*> Training set error measures:*
*>                   ME     RMSE      MAE      MPE     MAPE      MASE       ACF1*
*> Training set 7978.19 37581.15 29927.57 0.387108 1.589947 0.5401043 -0.0523739*

# ARIMA(1,1,1)
summary(Arima (TA.ts_seasadj, order= c(1,1,1)))*> Series: TA.ts_seasadj* 
*> ARIMA(1,1,1)**> Coefficients:*
*>         ar1      ma1*
*>       0.2644  -0.7487*
*> s.e.  0.1427   0.0907**> sigma^2 estimated as 1.477e+09:  log likelihood=-1136.91*
*> AIC=2279.82   AICc=2280.08   BIC=2287.48**> Training set error measures:*
*>                    ME     RMSE      MAE       MPE     MAPE      MASE       ACF1*
*> Training set 8057.644 37831.55 29899.12 0.3908637 1.589457 0.5395909 -0.019330*

ARIMA(0,1,2)是最好的,因为平方误差比系数值低得多。此外,它还具有最低的 AIC、BIC 和误差测量值,如 RMSE。让我们拟合选择的模型,检查残差,最后预测 12 个月:

fit*_TA.ts <- Arima (TA.ts_*seasadj, order= c(0,1,2))
checkresiduals(fit_TA.ts, lag = 10)*> Ljung-Box test*

*> data:  Residuals from ARIMA(0,1,2)*
*> Q* = 7.0949, df = 8, p-value = 0.5264*

*> Model df: 2\.   Total lags used: 10*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

残差几乎呈正态分布,略有偏斜。除了在第 12 个阶段,ACF 没有显示出显著的数值。具有显著 p 值的 Ljung-Box 检验得出结论,残差是随机的(白噪声)。

从 2018 年 8 月到 2019 年 7 月的 12 个月预测:

frcst_TA.ts = forecast (fit_TA.ts, h=12)plot(frcst_TA.ts)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

经过多次迭代后,我将季节部分(P,D,Q)的值估计为(1,1,1)。接下来,将拟合、评估和预测季节性 ARIMA 模型:

fit.seas_TA.ts <- Arima (TA.ts, order= c(0,1,2), seasonal=c(1,1,1))summary(fit.seas_TA.ts)*> Series: TA.ts* 
*> ARIMA(0,1,2)(1,1,1)[12]* 

*> Coefficients:*
*>           ma1      ma2     sar1     sma1*
*>       -0.5537  -0.2862  -0.3102  -0.6428*
*> s.e.   0.1050   0.1036   0.1416   0.1891*

*> sigma^2 estimated as 1.741e+09:  log likelihood=-1005.48*
*> AIC=2020.96   AICc=2021.74   BIC=2033.06*

*> Training set error measures:*
*>                    ME     RMSE      MAE       MPE     MAPE      MASE*
*> Training set 3386.278 37856.27 28465.13 0.1337672 1.513877 0.5137116*
*>                      ACF1*
*> Training set -0.009264586*

所有平方误差都远低于系数的绝对值。AIC 和 BIC 的表现优于非季节性 ARIMA 模型(0,1,2)。同样,我们需要确保残差是随机的,并且是非结构化的:

checkresiduals(fit.seas_TA.ts)*> Ljung-Box test*

*> data:  Residuals from ARIMA(0,1,2)(1,1,1)[12]*
*> Q* = 23.202, df = 20, p-value = 0.279*

*> Model df: 4\.   Total lags used: 24*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直方图分布有点偏斜,但模型仍然通过了永盒测试。p 值显著,ACF 图中没有显著的滞后。因此,我们现在有了一个季节性 ARIMA 模型,它通过了检查,可以进行预测了。该模型对未来一年的预测如下所示:

frcs.seas*_TA.ts <- forecast (fit.seas_*TA.ts, h=12)
summary(frcs.seas_TA.ts)*> Forecast method: ARIMA(0,1,2)(1,1,1)[12]*

*> Model Information:*
*> Series: TA.ts* 
*> ARIMA(0,1,2)(1,1,1)[12]* 

*> Coefficients:*
*>           ma1      ma2     sar1     sma1*
*>       -0.5537  -0.2862  -0.3102  -0.6428*
*> s.e.   0.1050   0.1036   0.1416   0.1891*

*> sigma^2 estimated as 1.741e+09:  log likelihood=-1005.48*
*> AIC=2020.96   AICc=2021.74   BIC=2033.06*

*> Error measures:*
*>                    ME     RMSE      MAE       MPE     MAPE      MASE*
*> Training set 3386.278 37856.27 28465.13 0.1337672 1.513877 0.5137116*
*>                      ACF1*
*> Training set -0.009264586*

*> Forecasts:*
*>          Point Forecast   Lo 80   Hi 80   Lo 95   Hi 95*
*> Aug 2018        2021727 1968205 2075248 1939872 2103581*
*> Sep 2018        2014485 1955875 2073094 1924849 2104121*
*> Oct 2018        2070211 2010979 2129444 1979623 2160800*
*> Nov 2018        1990520 1930671 2050369 1898988 2082052*
*> Dec 2018        2024607 1964148 2085067 1932142 2117072*
*> Jan 2019        1981844 1920780 2042907 1888455 2075233*
*> Feb 2019        1880516 1818854 1942178 1786212 1974820*
*> Mar 2019        2139569 2077315 2201824 2044359 2234780*
*> Apr 2019        2036234 1973392 2099076 1940126 2132342*
*> May 2019        2161701 2098278 2225124 2064703 2258698*
*> Jun 2019        2092552 2028553 2156552 1994674 2190431*
*> Jul 2019        2175445 2110872 2240018 2076689 2274200*

ARIMA 12 个月预测图(0,1,2) (1,1,1) [12]:

plot(frcs.seas_TA.ts)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一方面,我们可以使用 auto.arima()来完成大部分工作。它将给出以下结果:

fit_TA = auto.arima(TA.ts, max.p=5, max.q=5,
                   max.P=2 , max.Q=2, max.order=5, max.d=2, max.D=2, 
                   start.p=0, start.q=0, start.P=0, start.Q=0)
frcst*_TA = forecast(fit_*TA, h=12)
summary(frcst_TA)*> Forecast method: ARIMA(1,0,0)(1,1,1)[12] with drift**> Model Information:*
*> Series: TA.ts* 
*> ARIMA(1,0,0)(1,1,1)[12] with drift**> Coefficients:*
*>          ar1     sar1     sma1      drift*
*>       0.4134  -0.2152  -0.7774  2753.7605*
*> s.e.  0.1001   0.1514   0.2567   225.8097**> sigma^2 estimated as 1.667e+09:  log likelihood=-1016.63*
*> AIC=2043.26   AICc=2044.03   BIC=2055.41**> Error measures:*
*>                     ME     RMSE      MAE        MPE     MAPE      MASE*
*> Training set -1930.433 37268.02 28165.95 -0.1540752 1.507049 0.5083123*
*>                    ACF1*
*> Training set 0.01430932**> Forecasts:*
*>          Point Forecast   Lo 80   Hi 80   Lo 95   Hi 95*
*> Aug 2018        2015362 1962792 2067932 1934963 2095761*
*> Sep 2018        1997133 1940272 2053995 1910171 2084096*
*> Oct 2018        2044986 1987423 2102549 1956951 2133021*
*> Nov 2018        1958307 1900624 2015989 1870089 2046524*
*> Dec 2018        1994969 1937266 2052671 1906720 2083217*
*> Jan 2019        1949321 1891615 2007027 1861067 2037575*
*> Feb 2019        1857882 1800176 1915589 1769627 1946137*
*> Mar 2019        2115227 2057520 2172934 2026972 2203482*
*> Apr 2019        2015541 1957834 2073247 1927286 2103795*
*> May 2019        2131158 2073452 2188864 2042904 2219412*
*> Jun 2019        2066159 2008456 2123863 1977909 2154410*
*> Jul 2019        2147445 2089755 2205135 2059215 2235674*

绘制 ARIMA 12 个月的预测(1,0,0) (1,1,1) [12]:

plot(frcst_TA)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测摘要

最后,让我们将季节性朴素线性回归、ARIMA(0,1,2)(1,1,1)和自动 ARIMA(1,0,0)(1,1,1)的所有预测结果合并到一个名为 summary.ts 的数据框架中,然后绘制线图:

summary.ts*>    Seas.Naive	Linear.Reg	ARIMA	Auto.ARIMA*
*> Aug-18	1924663	1990708	2021727	2015362*
*> Sep-18	1925961	1984479	2014485	1997133*
*> Oct-18	2044137	2045357	2070211	2044986*
*> Nov-18	1976971	1957509	1990520	1958307*
*> Dec-18	2003954	1997633	2024607	1994969*
*> Jan-19	2000086	1957718	1981844	1949321*
*> Feb-19	1820012	1860605	1880516	1857882*
*> Mar-19	2049785	2113073	2139569	2115227*
*> Apr-19	1978084	2022652	2036234	2015541*
*> May-19	2161779	2137346	2161701	2131158*
*> Jun-19	2091318	2073922	2092552	2066159*
*> Jul-19	2176022	2153840	2175445	2147445*

— — -

summary(summary.ts)>       Seas.Naive        Linear.Reg          ARIMA           Auto.ARIMA     
> Min.   :1820012   Min.   :1860605   Min.   :1880516   Min.   :1857882  
> 1st Qu.:1964219   1st Qu.:1977789   1st Qu.:2008494   1st Qu.:1985803  
> Median :2002020   Median :2010143   Median :2030421   Median :2015451  
> Mean   :2012731   Mean   :2024570   Mean   :2049118   Mean   :2024458  
> 3rd Qu.:2060168   3rd Qu.:2083709   3rd Qu.:2104307   3rd Qu.:2078426  
> Max.   :2176022   Max.   :2153840   Max.   :2175445   Max.   :2147445

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参考文献

其实我看过很多文章练习时间序列分析。毕竟,最有用的一本是《预测:原理与实践》,作者是罗布·J·海曼,乔治·阿萨纳索普洛斯

此外,我从微软获得的课程和证书(应用机器学习)也非常有益。除了关于时间序列分析的有价值的信息之外,还有动手实验。

Python 中的时间序列分析:简介

原文:https://towardsdatascience.com/time-series-analysis-in-python-an-introduction-70d5a5b1d52a?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用于时间序列建模的可加模型

时间序列是日常生活中最常见的数据类型之一。金融价格、天气、家庭能源使用量甚至体重都是可以定期收集的数据示例。几乎每个数据科学家都会在日常工作中遇到时间序列,学习如何对它们建模是数据科学工具箱中的一项重要技能。分析和预测周期性数据的一个强大而简单的方法是加法模型。这个想法很简单:将时间序列表示为不同尺度的模式组合,比如每天、每周、每季度和每年,以及总体趋势。你的能源消耗可能在夏天上升,在冬天下降,但是随着你提高你家的能源效率,总的趋势是下降的。加法模型可以向我们展示两种模式/趋势,并根据这些观察结果做出预测。

下图显示了将时间序列分解为总体趋势、年度趋势和周趋势的加法模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of Additive Model Decomposition

本文将介绍一个使用 Python 和脸书开发的 Prophet 预测包为金融时间序列数据创建附加模型的示例。在这个过程中,我们将介绍使用 pandas 的一些数据操作,使用 Quandl 库和访问财务数据,以及使用 matplotlib 进行绘图。我在有指导意义的地方加入了代码,我鼓励任何人查看 GitHub 上的 Jupyter 笔记本以获得完整的分析。这个介绍将向你展示你自己开始建模时间序列所需的所有步骤!

免责声明:现在到了令人厌烦的部分,我不得不提到,当谈到财务数据时,过去的表现不是未来表现的指标,你不能用这里的方法致富。我选择使用股票数据,因为它很容易在每天的频率上获得,而且玩起来很有趣。如果你真的想变得富有,学数据科学是比玩股市更好的选择!

检索财务数据

通常,花费在数据科学项目上的大约 80%的时间是获取和清理数据。多亏了 quandl 金融库,这个项目的这个比例降低到了 5%。Quandl 可以从命令行与 pip 一起安装,让您用一行 Python 就可以访问数千个财务指标,并且每天允许多达 50 个请求,无需注册。如果你注册了一个免费账户,你会得到一个允许无限请求的 api 密匙。

首先,我们导入所需的库并获取一些数据。Quandl 自动将我们的数据放入 pandas dataframe,这是数据科学的首选数据结构。(对于其他公司,只需用股票代码替换“TSLA”或“通用汽车”即可。您也可以指定日期范围)。

# quandl for financial data
import quandl
# pandas for data manipulation
import pandas as pdquandl.ApiConfig.api_key = 'getyourownkey!'# Retrieve TSLA data from Quandl
tesla = quandl.get('WIKI/TSLA')# Retrieve the GM data from Quandl
gm = quandl.get('WIKI/GM')
gm.head(5)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Snapshot of GM data from quandl

关于 quandl 的数据几乎是无限的,但我想重点比较同一行业的两家公司,即特斯拉和通用汽车。特斯拉是一家令人着迷的公司,不仅因为它是 111 年来第一家成功的美国汽车初创公司,还因为在 2017 年的中,尽管只销售了 4 种不同的汽车,但它仍是美国最有价值的汽车公司。最有价值汽车公司头衔的另一个竞争者是通用汽车公司,该公司最近显示出拥抱汽车未来的迹象,制造了一些非常酷(但看起来不酷)的全电动汽车。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Not a very hard choice

我们可以轻松地花费数小时来搜索这些数据,并将其下载为 csv 电子表格文件,但是,多亏了 quandl,我们在几秒钟内就获得了所有需要的数据!

数据探索

在我们开始建模之前,最好通过绘制一些探索图来了解一下结构和范围。这也将允许我们寻找需要纠正的异常值或缺失值。

熊猫数据帧可以很容易地用 matplotlib 绘制。如果任何图形代码看起来吓人,不要担心。我还发现 matplotlib 不直观,经常从堆栈溢出或文档中复制并粘贴示例来获得我想要的图形。编程的规则之一是不要重新发明一个已经存在的解决方案!

# The adjusted close accounts for stock splits, so that is what we should graph
plt.plot(gm.index, gm['Adj. Close'])
plt.title('GM Stock Price')
plt.ylabel('Price ($)');
plt.show()plt.plot(tesla.index, tesla['Adj. Close'], 'r')
plt.title('Tesla Stock Price')
plt.ylabel('Price ($)');
plt.show();

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Raw Stock Prices

仅从股价上比较两家公司并不能说明哪家更有价值,因为公司的总价值(市值)还取决于股票数量(市值=股价*股票数量)。Quandl 没有股票数量的数据,但我可以通过快速的谷歌搜索找到两家公司的平均年度股票。虽然不精确,但对我们的分析来说足够精确了。有时候我们不得不用不完美的数据来凑合!

为了在我们的数据框架中创建一列市值,我们使用了一些 pandas 的技巧,比如将索引移动到一列(reset_index ),同时使用 ix 索引和修改数据框架中的值。

# Yearly average number of shares outstanding for Tesla and GM
tesla_shares = {2018: 168e6, 2017: 162e6, 2016: 144e6, 2015: 128e6, 2014: 125e6, 2013: 119e6, 2012: 107e6, 2011: 100e6, 2010: 51e6}gm_shares = {2018: 1.42e9, 2017: 1.50e9, 2016: 1.54e9, 2015: 1.59e9, 2014: 1.61e9, 2013: 1.39e9, 2012: 1.57e9, 2011: 1.54e9, 2010:1.50e9}# Create a year column 
tesla['Year'] = tesla.index.year# Take Dates from index and move to Date column 
tesla.reset_index(level=0, inplace = True)
tesla['cap'] = 0# Calculate market cap for all years
for i, year in enumerate(tesla['Year']):
    # Retrieve the shares for the year
    shares = tesla_shares.get(year)

    # Update the cap column to shares times the price
    tesla.ix[i, 'cap'] = shares * tesla.ix[i, 'Adj. Close']

这为特斯拉创造了一个“上限”栏。我们对 GM 数据做同样的处理,然后合并两者。合并是数据科学工作流的重要组成部分,因为它允许我们在共享列上连接数据集。在这种情况下,我们有两个不同公司在相同日期的股票价格,因此我们希望连接日期列上的数据。我们执行“内部”合并,只保存同时出现在两个数据帧中的日期条目。合并后,我们重命名这些列,这样我们就知道哪一列对应哪一家汽车公司。

# Merge the two datasets and rename the columns
cars = gm.merge(tesla, how='inner', on='Date')cars.rename(columns={'cap_x': 'gm_cap', 'cap_y': 'tesla_cap'}, inplace=True)# Select only the relevant columns
cars = cars.ix[:, ['Date', 'gm_cap', 'tesla_cap']]# Divide to get market cap in billions of dollars
cars['gm_cap'] = cars['gm_cap'] / 1e9
cars['tesla_cap'] = cars['tesla_cap'] / 1e9cars.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Merged Market Capitalization Dataframe

市值以十亿美元计。我们可以看到,在我们的分析期开始时,通用汽车的市值大约是特斯拉的 30 倍!事情会在整个时间线上保持不变吗?

plt.figure(figsize=(10, 8))
plt.plot(cars['Date'], cars['gm_cap'], 'b-', label = 'GM')
plt.plot(cars['Date'], cars['tesla_cap'], 'r-', label = 'TESLA')
plt.xlabel('Date'); plt.ylabel('Market Cap (Billions $)'); plt.title('Market Cap of GM and Tesla')
plt.legend();

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Market Capitalization Historical Data

在数据过程中,我们观察到特斯拉的快速增长和通用汽车的小幅增长。2017 年期间,特斯拉的价值甚至超过了通用汽车!

import numpy as np# Find the first and last time Tesla was valued higher than GM
first_date = cars.ix[np.min(list(np.where(cars['tesla_cap'] > cars['gm_cap'])[0])), 'Date']
last_date = cars.ix[np.max(list(np.where(cars['tesla_cap'] > cars['gm_cap'])[0])), 'Date']print("Tesla was valued higher than GM from {} to {}.".format(first_date.date(), last_date.date()))**Tesla was valued higher than GM from 2017-04-10 to 2017-09-21.**

在此期间,特斯拉卖了大约 48,000 辆,而通用卖了 1,500,000 辆。在一段时间内,通用汽车的销量是特斯拉的 30 倍,但其价值却低于特斯拉!这无疑展示了一个有说服力的高管和一个高质量(尽管数量非常少)产品的力量。虽然特斯拉的价值现在低于通用汽车,但一个好问题可能是,我们能期待特斯拉再次超过通用汽车吗?什么时候会这样?为此,我们求助于加法模型进行预测,或者换句话说,预测未来。

用先知建模

2017 年 Python 和 R 发布了脸书先知包,全世界的数据科学家都欢欣鼓舞。Prophet 设计用于分析具有日常观察的时间序列,这些观察显示不同时间尺度上的模式。它还具有高级功能,可以对假日对时间序列的影响进行建模,并实现自定义的变点,但我们将坚持使用基本功能来启动和运行模型。Prophet 和 quandl 一样,可以从命令行安装 pip。

我们首先导入 prophet,并将数据中的列重命名为正确的格式。日期列必须称为’ ds ‘,而我们要预测的值列必须称为’ y '。然后,我们创建 prophet 模型并使其符合数据,就像 Scikit-Learn 机器学习模型一样:

import fbprophet# Prophet requires columns ds (Date) and y (value)
gm = gm.rename(columns={'Date': 'ds', 'cap': 'y'})# Put market cap in billions
gm['y'] = gm['y'] / 1e9# Make the prophet model and fit on the data
gm_prophet = fbprophet.Prophet(changepoint_prior_scale=0.15)
gm_prophet.fit(gm)

当创建 prophet 模型时,我将 changepoint 设置在 0.15 之前,高于默认值 0.05。该超参数用于控制趋势对变化的敏感程度,数值越高越敏感,数值越低越不敏感。这个值用于对抗机器学习中最基本的权衡之一:偏差与方差

如果我们太接近我们的训练数据,称为过拟合,我们有太多的方差,我们的模型将不能很好地推广到新数据。另一方面,如果我们的模型没有捕捉到训练数据中的趋势,那么它就不合适,并且有太多的偏差。当模型拟合不足时,增加变点先验允许模型更灵活地拟合数据,如果模型拟合过度,减少先验会限制灵活性。变点先验比例的影响可以通过用一系列值做出的图形预测来说明:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

变点先验比例越高,模型就越灵活,越符合训练数据。这可能看起来正是我们想要的,但是学习训练数据太好可能会导致过度拟合,并且无法准确地对新数据进行预测。因此,我们需要在拟合训练数据和能够推广到新数据之间找到恰当的平衡。由于股票每天都在变化,我们希望我们的模型能够捕捉到这一点,所以在尝试了一系列值后,我增加了灵活性。

在创建 prophet 模型的调用中,我们还可以指定变点,当时间序列从增加到减少,或从缓慢增加到快速增加时,会出现这些变点(它们位于时间序列中速率变化最大的位置)。转折点可能对应于重大事件,如产品发布或市场中的宏观经济波动。如果我们不指定变点,prophet 将为我们计算它们。

为了进行预测,我们需要创建一个所谓的未来数据框架。我们指定要预测的未来周期数(两年)和预测频率(每天)。然后,我们用我们创建的先知模型和未来数据框架进行预测:

# Make a future dataframe for 2 years
gm_forecast = gm_prophet.make_future_dataframe(periods=365 * 2, freq='D')# Make predictions
gm_forecast = gm_prophet.predict(gm_forecast)

我们未来的数据框架包含特斯拉和通用汽车未来两年的估计市值。我们可以用 prophet plot 函数可视化预测。

gm_prophet.plot(gm_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
plt.title('Market Cap of GM');

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

黑点代表实际值(注意它们如何在 2018 年初停止),蓝线表示预测值,浅蓝色阴影区域是不确定性(始终是任何预测的关键部分)。由于初始不确定性会随着时间的推移而传播和增长,因此预测的不确定性区域会越来越大。这可以在的天气预报中观察到,天气预报的时间越长越不准确

我们还可以检查由模型识别的变更点。同样,变点表示时间序列增长率显著变化的时间(例如,从增加到减少)。

tesla_prophet.changepoints[:10]**61    2010-09-24
122   2010-12-21
182   2011-03-18
243   2011-06-15
304   2011-09-12
365   2011-12-07
425   2012-03-06
486   2012-06-01
547   2012-08-28
608   2012-11-27**

为了比较,我们可以看看这段时间内谷歌对特斯拉的搜索趋势,看看变化是否一致。我们在同一张图上绘制了变化点(垂直线)和搜索趋势:

# Load in the data 
tesla_search = pd.read_csv('data/tesla_search_terms.csv')# Convert month to a datetime
tesla_search['Month'] = pd.to_datetime(tesla_search['Month'])
tesla_changepoints = [str(date) for date in tesla_prophet.changepoints]# Plot the search frequency
plt.plot(tesla_search['Month'], tesla_search['Search'], label = 'Searches')# Plot the changepoints
plt.vlines(tesla_changepoints, ymin = 0, ymax= 100, colors = 'r', linewidth=0.6, linestyles = 'dashed', label = 'Changepoints')# Formatting of plot
plt.grid('off'); plt.ylabel('Relative Search Freq'); plt.legend()
plt.title('Tesla Search Terms and Changepoints');

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tesla Search Frequency and Stock Changepoints

特斯拉市值的一些变化点与特斯拉搜索频率的变化一致,但不是全部。由此,我会说相对谷歌搜索频率并不是一个很好的股票变化指标。

我们仍然需要弄清楚特斯拉的市值何时会超过通用汽车。由于我们对未来两年都有预测,合并数据框架后,我们可以在同一张图上绘制两家公司。在合并之前,我们重命名列以跟踪数据。

gm_names = ['gm_%s' % column for column in gm_forecast.columns]
tesla_names = ['tesla_%s' % column for column in tesla_forecast.columns]# Dataframes to merge
merge_gm_forecast = gm_forecast.copy()
merge_tesla_forecast = tesla_forecast.copy()# Rename the columns
merge_gm_forecast.columns = gm_names
merge_tesla_forecast.columns = tesla_names# Merge the two datasets
forecast = pd.merge(merge_gm_forecast, merge_tesla_forecast, how = 'inner', left_on = 'gm_ds', right_on = 'tesla_ds')# Rename date column
forecast = forecast.rename(columns={'gm_ds': 'Date'}).drop('tesla_ds', axis=1)

首先,我们将只绘制估计值。估计值(在 prophet 软件包中称为“yhat ”)消除了数据中的一些噪声,因此它看起来与原始图略有不同。平滑程度将取决于变点先验比例-更高的先验意味着更灵活的模型和更多的起伏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GM and Tesla Predicted Market Capitalization

我们的模型认为,特斯拉在 2017 年短暂超越通用汽车只是一个噪音,直到 2018 年初,特斯拉才在预测中永远击败通用汽车。确切的日期是 2018 年 1 月 27 日,所以如果这种情况发生,我会很高兴地因为预测未来而受到表扬!

制作上图时,我们忽略了预测中最重要的部分:不确定性!我们可以使用 matplotlib(参见笔记本)来显示有疑问的区域:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是预测的一个更好的表示。这表明两家公司的价值都有望增加,但特斯拉的增长将比通用汽车更快。同样,不确定性随着时间的推移而增加,正如预测所预期的那样,特斯拉的下限低于通用汽车在 2020 年的上限,这意味着通用汽车可能会保持领先地位。

趋势和模式

市值分析的最后一步是查看整体趋势和模式。Prophet 使我们能够轻松地可视化整体趋势和组件模式:

# Plot the trends and patterns
gm_prophet.plot_components(gm_forecast)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

General Motors Time Series Decomposition

趋势非常明显:通用汽车的股票正在上涨,并将继续上涨。每年的模式很有趣,因为它似乎表明通用汽车的价值在年底增加,并在夏季缓慢下降。我们可以尝试确定在一段时间内通用汽车的年度市值和平均月销售额之间是否存在相关性。我首先从谷歌收集每月的汽车销量,然后用 groupby 计算几个月的平均值。这是另一个关键的数据科学操作,因为我们经常想要比较不同类别的统计数据,例如特定年龄组的用户,或者来自一个制造商的车辆。在这种情况下,我们希望计算每个月的平均销售额,因此我们将这些月份组合在一起,然后计算销售额的平均值。

gm_sales_grouped = gm_sales.groupby('Month').mean()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看起来月销售额与市值并不相关。8 月单月销量第二高,正好在市值最低点!

查看每周趋势,似乎没有任何有意义的信号(周末没有记录股票价格,所以我们查看一周内的变化)。这是意料之中的,因为经济学中的随机游走理论指出,股票价格每天都没有可预测的模式。正如我们的分析所证明的,从长期来看,股票往往会增加,但在日常尺度上,即使有最好的模型,我们也几乎没有可以利用的模式。

简单看一下道琼斯工业平均指数(股票交易所 30 家最大公司的市场指数)就能很好地说明这一点:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Dow Jones Industrial Average (Source)

很明显,这个信息是回到 1900 年,投资你的钱!或者在现实中,当市场下跌时,不要退出,因为根据历史,它会重新上涨。总的来说,每天的波动太小,甚至看不到,如果我们像数据科学家一样思考,我们会意识到,与投资整个市场并长期持有相比,每天玩股票是愚蠢的。

Prophet 还可以应用于更大规模的数据测量,如国内生产总值,这是一个国家经济总体规模的衡量指标。我根据美国和中国的历史 GDP 建立了先知模型,做出了以下预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

中国 GDP 超过美国的确切日期是 2036 年!由于观察频率低(GDP 每季度测量一次,但 prophet 使用每日数据效果最佳),该模型存在局限性,但它提供了一个基本预测,不需要宏观经济知识。

有许多方法可以对时间序列建模,从简单的线性回归带有 LSTM 细胞的递归神经网络。加法模型是有用的,因为它们开发快,训练快,提供可解释的模式,并做出具有不确定性的预测。Prophet 的能力令人印象深刻,我们在这里只是触及了皮毛。我鼓励你利用这篇文章和笔记本来探索 Quandl 提供的一些数据或者你自己的时间序列。请继续关注时间序列分析的未来工作,以及 prophet 在我日常生活中的应用,参见我在上的帖子,使用这些技术来建模和预测体重变化。作为探索时间序列的第一步,Python 中的附加模型是必由之路!

一如既往,我欢迎反馈和建设性的批评。可以在 wjk68@case.edu 找到我。

时序日历热图

原文:https://towardsdatascience.com/time-series-calendar-heatmaps-9f576578fcfe?source=collection_archive---------12-----------------------

一种可视化时间序列数据的新方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

介绍

时间序列是按时间顺序编制索引的一系列数据。时间顺序可以用天、周、月或年来表示。可视化时间序列数据的最常见方法是使用简单的折线图,其中横轴绘制时间增量,纵轴绘制所测量的变量。可以使用ggplot2中的geom_line()或简单使用Base R中的plot()功能来实现可视化。

在本教程中,我将介绍一个名为时序日历热图的新工具来可视化时序数据。我们将看看如何使用ggplot2绘制时间序列日历热图。我们还将探索由 Paul Bleicher 编写的calendarHeat()函数(在 GPL 许可下作为开源发布),它提供了一种创建可视化的简单方法。

动机

如果你曾经去过 GitHub,你肯定会偶然发现下面的图表,它显示了一个用户在过去一年中所做的贡献。瓷砖的颜色代表贡献的数量(如图表右下角的图例所述)。在这里,日历热图提供了一种直观的方式,在类似日历的视图中直观地显示用户一年中所做的提交数量,从而很容易识别日常模式或异常情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Heatmap from Github

另一个很好的例子可以在下面这篇由《华尔街日报》发表的文章中找到,这篇文章显示了 70 年来美国所有 50 个州的感染人数。

http://graphics.wsj.com/infectious-diseases-and-vaccines/

在这里,日历热图可以很容易地识别各种疾病感染人数的年度模式。

个案研究

为了说明日历热图的使用,我们将可视化亚马逊过去 5 年的股票价格(NASDAQ: AMZN)。我们将关注调整后的收盘价,该收盘价将通过tidyquant包获得。

包装

我们将安装并导入tidyquant包来获取亚马逊的股票价格。我们还将安装并导入ggplot2来执行可视化。calendarHeat()的 R 代码可以通过 Paul Bleicher 的 Github 页面下载。

*# install tidyquant* install.packages('tidyquant', repos = "http://cran.us.r-project.org")
library(tidyquant) *#install ggplot2* install.packages("ggplot2", repos = "http://cran.us.r-project.org") library(ggplot2) *#Load the function to the local through Paul Bleicher's GitHub page* source("https://raw.githubusercontent.com/iascchen/VisHealth/master/R/calendarHeat.R")

加载数据

amznStock = as.data.frame(tidyquant::tq_get(c("AMZN"),get="stock.prices")) *# get data using tidyquant* 
amznStock = amznStock[year(amznStock$date) > 2012, ] *# Using data only after 2012*Using ggplot2

使用

使用ggplot2创建日历热图的过程有些麻烦。在制作热图之前,我们需要将数据整理成正确的形状。下面的代码列出了如何使用ggplot2管理创建日历热图的数据的步骤。

library(plyr)
library(plotly)amznStock$weekday = as.POSIXlt(amznStock$date)$wday *#finding the day no. of the week*amznStock$weekdayf<-factor(amznStock$weekday,levels=rev(1:7),labels=rev(c("Mon","Tue","Wed","Thu","Fri","Sat","Sun")),ordered=TRUE) *#converting the day no. to factor* amznStock$monthf<-factor(month(amznStock$date),levels=as.character(1:12),labels=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),ordered=TRUE) *# finding the month* amznStock$yearmonth<- factor(as.yearmon(amznStock$date)) *#finding the year and the month from the date. Eg: Nov 2018* amznStock$week <- as.numeric(format(amznStock$date,"%W")) #finding the week of the year for each date amznStock<-ddply(amznStock,.(yearmonth),transform,monthweek=1+week-min(week)) *#normalizing the week to start at 1 for every month* p <- ggplot(amznStock, aes(monthweek, weekdayf, fill = amznStock$adjusted)) + geom_tile(colour = "white") + facet_grid(year(amznStock$date)~monthf) + scale_fill_gradient(low="red", high="green") + xlab("Week of Month") + ylab("") + ggtitle("Time-Series Calendar Heatmap: AMZN Stock Prices") + labs(fill = "Price") p

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Calendar Heatmap using ggplot2

使用 calendarHeat()

calendarHeat()使流程变得更加简单。我们只需要调用函数并指定以下五个参数。

  • date:需要绘制数据的日期。
  • values:与这些日期相关联的值。
  • color:调色板。默认为 r2g(红转绿)。其他预定义选项有 r2b(红到蓝)和 w2b(白到蓝)。您可以通过定义如下所示的向量来创建自己的调色板。
  • ncolors:热图的颜色数量
  • varname:图表标题
r2g <- c("#D61818", "#FFAE63", "#FFFFBD", "#B5E384") calendarHeat(amznStock$date, amznStock$adjusted, ncolors = 99, color = "r2g", varname="AMZN Adjusted Close")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Calendar Heatmap using calendarHeat()

何时使用ggplot2?中的calendarHeat() v/s geom_tile

calendarHeat()是一个预定义的函数,因此它在如何修改图形方面提供的灵活性较小。为了用除了在calendarHeat()函数中指定的五个参数之外的其他方式更新数字,我们需要修改底层代码。ggplot2另一方面提供了灵活性,因为我们从头开始构建可视化。

此外,ggplotly可以与ggplot2图表集成,使其更具交互性。例如,通过使用ggplotly我们将能够计算每天的价格。calendarHeat()另一方面,不能与ggplotly集成(不确定是否有现有的包可以帮助实现相同的功能)。

说到方便,calendarHeat()提供了一种更简单的方法来构建图表。我们只需要调用一个函数,一个相对标准的数据集就可以很容易地可视化,而不需要做太多的数据筛选。

什么时候应该使用日历热图?

当“每日值”或“星期几”值很重要时,日历热图很有用。如果我们想查看全年的每日数值,那么日历热图特别有用。

另一方面,如果我们想看到一个趋势(例如:季节性、形状、平稳性等。),日历热图帮助不大。这些也不能描绘月度或年度趋势。如果我们希望看到数据的总体趋势,那么简单的折线图是更好的方法。

参考

https://www.r-bloggers.com/ggplot2-time-series-heatmapshttps://www . rdocumentation . org/packages/iClick/versions/1.4/topics/calendar heathttps://github . com/iascchen/vis health/blob/master/R/calendar heat。Rhttps://www . tableau . com/about/blog/2017/2/viz-variety-show-heat maps-66330

假人的时间序列——三步过程

原文:https://towardsdatascience.com/time-series-for-dummies-the-3-step-process-447fb642a6f1?source=collection_archive---------13-----------------------

克里斯·圣·杰尔&肖恩·安肯布鲁克,Zencos

在一顿令人满意的中餐外卖后,你心不在焉地打开了免费的幸运饼干。瞥了一眼里面的财富,你读到,“你的一个梦想将会实现。”你一边嗤之以鼻,一边扔掉小纸片,把饼干放进嘴里。作为一个聪明、理性的人,你知道财富是微不足道的——没有人能预测未来。然而,这种想法可能是不完整的。有一种方法可以非常准确地预测未来:时间序列建模。

时间序列建模可能无法告诉你什么时候会遇到你一生的挚爱,或者你应该穿蓝色还是红色的领带去上班,但它非常擅长使用历史数据来识别现有的模式,并用它们来预测未来会发生什么。与大多数高级分析解决方案不同,时间序列建模是一种低成本的解决方案,可以提供强大的洞察力。

本文将介绍构建高质量时间序列模型的三个基本步骤:使数据稳定、选择正确的模型以及评估模型的准确性。本文中的例子使用了一家大型汽车营销公司的历史页面浏览量数据。

步骤 1:使数据稳定

时间序列涉及到数据的使用,这些数据是由等间距的时间增量(分钟、小时、天、周等)索引的。).由于时间序列数据的离散性,许多时间序列数据集在数据中内置了季节和/或趋势元素。时间序列建模的第一步是考虑现有的季节(一段固定时间内重复出现的模式)和/或趋势(数据向上或向下移动)。考虑到这些嵌入模式,我们称之为使数据稳定。趋势和季节性数据的例子可以在下面的图 1 和图 2 中看到。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Example of Upward Trending Data

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Example of Seasonal Data

什么是平稳性?

正如我们之前提到的,时间序列建模的第一步是消除数据中存在的趋势或季节的影响,使其保持平稳。我们一直在讨论术语平稳性,但是它到底是什么意思呢?

平稳序列是指序列的平均值不再是时间的函数。对于趋势数据,随着时间的增加,序列的均值会随着时间的推移而增加或减少(想想房价随着时间的推移而稳步上升)。对于季节性数据,序列的平均值随着季节而波动(想想每 24 小时温度的上升和下降)。

我们如何实现平稳性?

有两种方法可以应用于实现平稳性,差分数据或线性回归。要计算差值,需要计算连续观察值之间的差值。要使用线性回归,您需要在模型中包含季节性组件的二进制指示变量。在我们决定应用这些方法中的哪一种之前,让我们来研究一下我们的数据。我们使用 SAS 视觉分析绘制了历史每日页面浏览量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: Time Series Plot of Raw Page Views

最初的模式似乎每七天重复一次,表示一周一季。随着时间的推移,页面浏览量持续增加,这表明有略微上升的趋势。对数据有了大致的了解后,我们应用了平稳性的统计检验,即扩展的 Dickey-Fuller (ADF)检验。ADF 检验是平稳性的单位根检验。我们不会在这里进入细节,但是一个单位根表示序列是否是非平稳的,所以我们使用这个测试来确定处理趋势或季节的适当方法(差异或回归)。基于上述数据的 ADF 测试,我们通过对一周中某一天的虚拟变量进行回归来去除七天季节,并通过对数据进行差分来去除趋势。由此产生的静态数据可以在下图中看到。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: Stationary Data After Removing Season and Trend

步骤 2:构建时间序列模型

既然数据是稳定的,时间序列建模的第二步是建立一个基本水平的预测。我们还应该注意到,大多数基本水平的预测不需要第一步使你的数据稳定。只有更高级的模型才需要这样做,比如我们马上要讨论的 ARIMA 模型。

建立基础水平预测

时间序列模型有几种类型。要构建一个可以准确预测未来页面浏览量(或任何您感兴趣的预测)的模型,有必要确定适合您的数据的模型类型。

最简单的选择是假设 y 的未来值(您有兴趣预测的变量)等于 y 的最新值。这被认为是最基本的,或“天真模型”,其中最近的观察是明天最可能的结果。

第二种模型是平均模型。在这个模型中,数据集中的所有观察值被赋予相同的权重。y 的未来预测值计算为观测数据的平均值。如果数据是水平的,生成的预测可能相当准确,但如果数据是趋势性的或具有季节性成分,则提供的预测会非常差。使用平均模型对页面浏览量数据的预测值如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 5: Average (Mean) Model Forecast

如果数据具有季节性或趋势性元素,那么基准水平模型的更好选择是实施指数平滑模型(ESM)。ESM 在上述简单模型和平均模型之间找到了一个合适的中间点,最近的观察值被赋予最大的权重,而所有以前的观察值的权重随着时间的推移呈指数递减。ESM 还允许将季节性和/或趋势性组件纳入模型。下表提供了 0.7 的初始权重以 0.3 的速率指数下降的示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Table 1: Example of the exponentially decreasing effect of past observations of Y.

在时间序列预测中,可以实施各种类型的 ESM。要使用的理想模型将取决于您拥有的数据类型。下表根据数据中的趋势和季节组合,提供了使用哪种 ESM 的快速指南。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Table 2: Model Selection Table

由于强七天季节和数据的上升趋势,我们选择了一个附加的冬季 ESM 作为新的基准水平模型。生成的预测很好地延续了轻微的上升趋势,并捕捉到了七天的季节。但是,数据中仍有更多模式可以删除。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 6: Additive Winters ESM Forecast

ARIMA 造型

在确定了最能解释数据中的趋势和季节的模型后,您最终有了足够的信息来生成一个像样的预测,如上图所示。然而,这些模型仍然是有限的,因为它们没有考虑到感兴趣的变量在以前的时间段内与其自身的相关性。我们将这种相关性称为自相关,这在时间序列数据中很常见。如果数据具有自相关性,就像我们的一样,那么就可以进行额外的建模来进一步改进基线预测。

为了捕捉时间序列模型中的自相关效应,有必要实施自回归综合移动平均(或 ARIMA)模型。ARIMA 模型包括说明季节和趋势的参数(如使用虚拟变量表示一周中的天数和差异),但也允许包含自回归和/或移动平均项来处理数据中嵌入的自相关。通过使用适当的 ARIMA 模型,我们可以进一步提高页面浏览量预测的准确性,如下图 3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 7: Seasonal ARIMA Model Forecast

步骤 3:评估模型准确性

虽然您可以看到所展示的每个模型的准确性都有所提高,但是直观地确定哪个模型的准确性最好并不总是可靠的。计算 MAPE(平均绝对百分比误差)是比较建议模型的整体预测精度的一种快速简便的方法-MAPE 越低,预测精度越好。比较前面讨论的每个模型的 MAPE,很容易看出季节性 ARIMA 模型提供了最佳的预测精度。请注意,有几种其他类型的比较统计数据可用于模型比较。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Table 3: Model Error Rate Comparison

摘要

总之,建立一个强大的时间序列预测模型的诀窍是尽可能多地去除噪声(趋势、季节和自相关),这样数据中唯一剩下的未解释的运动就是纯粹的随机性。对于我们的数据,我们发现带有回归变量的季节性 ARIMA 模型提供了最准确的预测。与上面提到的简单模型、平均模型和 ESM 模型相比,ARIMA 模型的预测更加准确。

虽然没有时间序列模型能够帮助你的爱情生活,但有许多类型的时间序列模型可以帮助你预测从页面浏览量到能源销售的任何事情。准确预测您感兴趣的变量的关键是,首先,理解您的数据,其次,应用最符合您的数据需求的模型。

最初发表于【www.kdnuggets.com】

时间序列预测— ARIMA 模型

原文:https://towardsdatascience.com/time-series-forecasting-arima-models-7f221e9eee06?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ARIMA 代表自回归综合移动平均线。有季节性和非季节性 ARIMA 模型可用于预测

非季节性 ARIMA 模型:

这种方法需要考虑三个变量

P =滞后时段,例如:(如果 P= 3,则我们将在计算的自回归部分使用时间序列的前三个时段)P 有助于调整预测序列的拟合线

纯自回归模型类似于线性回归,其中预测变量是 P 个前期

a 在 ARIMA 模型中,我们使用差分将时间序列转换为平稳序列(没有趋势或季节性的序列)。d 指时间序列达到稳定状态所需的差分变换次数。

平稳时间序列是指**均值和方差在一段时间内保持不变。**当数列平稳时更容易预测。

差分是一种将非平稳时间序列转化为平稳时间序列的方法。这是为 ARIMA 模型准备数据的重要一步。

第一差值是当前时间段和先前时间段之间的差值。如果这些值不能围绕恒定的平均值和方差旋转,那么我们使用第一个差分的值找到第二个差分。我们重复这个过程,直到得到一个平稳序列

确定序列是否充分差分的最佳方法是绘制差分序列,并检查是否有恒定的均值和方差。

Q =该变量表示误差分量的滞后,其中误差分量是时间序列的一部分,不能用趋势或季节性来解释

自相关函数图(ACF):

自相关是指时间序列与其过去值的相关程度,而 ACF 是用于查看点之间相关性的图,直到并包括滞后单位。在 ACF 中,相关系数在 x 轴上,而滞后数在 y 轴上显示。

自相关函数图将让您了解给定的时间序列如何与其自身相关

通常在 ARIMA 模型中,我们使用 AR 项或 MA 项。我们只是在极少数情况下才使用这两个术语。我们使用 ACF 图来决定在我们的时间序列中使用哪一项

如果在滞后 1 处有一个正自相关,那么我们使用 AR 模型

如果在滞后 1 处有一个负自相关,那么我们使用 MA 模型

在绘制 ACF 图之后,我们转向部分自相关函数图(PACF)。偏相关是时间序列中的观测值与先前时间步的观测值之间关系的总结,其中插入观测值的关系已被移除。

滞后 k 处的部分自相关是在去除了由较短滞后处的项引起的任何相关的影响之后得到的相关。

如果 PACF 曲线在滞后 n 处下降,那么使用 AR(n)模型,如果 PACF 曲线的下降更加平缓,那么我们使用 MA 项

自回归成分:纯粹的 ar 模型仅使用过去值的组合进行预测,类似于线性回归,其中使用的 AR 项的数量与预测中考虑的以前期间的数量成正比。

在模型中使用 AR 术语

  • ACF 图显示自相关向零衰减
  • PACF 曲线很快接近零
  • 平稳序列的 ACF 在滞后-1 时为正

移动平均线:时间序列图中的随机跳跃,其影响在两个或多个连续的时间段内都能感觉到。这些跳跃代表在我们的 ARIMA 模型中计算的误差,并代表 MA 分量将滞后的情况。一个纯粹的 MA 模型会像指数平滑法一样平滑这些突然的跳跃。

当模型符合以下条件时,在模型中使用 MA 术语

  • 滞后-1 时负自相关
  • 几个滞后之后急剧下降的 ACF
  • PACF 逐渐减少

综合成分:当时间序列不稳定时,该成分开始起作用。我们必须对级数求差以使其稳定的次数就是积分分量的参数(I 项)

我们可以用 ARIMA(ar-term,ma-term,i-term)表示我们的模型

找到正确的模型是一个迭代过程。

季节性 ARIMA (SARIMA)款:

顾名思义,当时间序列表现出季节性时,就使用这种模型。这个模型类似于 ARIMA 模型,我们只需要添加一些参数来解释季节

我们把萨里玛写成

ARIMA(p,D,Q)

  • p —自回归的次数
  • d——差异程度
  • q —移动平均项的数量
  • m —指每个季节的周期数
  • (P,D,Q)-表示时间序列季节性部分的(P,D,Q)

季节性差异考虑了季节和当前值与上一季度值的差异,例如:月份差异可能是 2018 年 5 月的值-2017 年 5 月的值。

  • 在纯季节性 AR 模型中,ACF 衰减缓慢,而 PACF 截止到零
  • 当季节性自相关为正时,使用 AR 模型
  • 在纯季节性 MA 模型中,ACF 截止到零,反之亦然
  • 当季节性自相关为负时,使用 MA 模型

最后的步骤

  • **第一步——检查平稳性:**如果一个时间序列有趋势或季节性成分,在我们可以使用 ARIMA 预测之前,它必须是平稳的。。
  • **第二步—差分:**如果时间序列不是平稳的,需要通过差分来平稳化。取第一个差值,然后检查平稳性。尽可能多地接受差异。一定要检查季节差异。
  • **第三步——过滤出一个验证样本:**这将用于验证我们的模型有多准确。使用列车测试验证分割来实现这一点
  • **步骤 4 —选择 AR 和 MA 术语:**使用 ACF 和 PACF 来决定是否包括 AR 术语、MA 术语或两者都包括。
  • **步骤 5 —建立模型:**建立模型,并将预测的周期数设置为 N(取决于您的需求)。
  • **步骤 6 —验证模型:**将预测值与验证样本中的实际值进行比较。

我也附上我的回购代码:))))))

[## sangarshanan/时间序列预测

了解时间序列预测。为 Sangarshanan/时间序列预测的发展作出贡献

github.com](https://github.com/Sangarshanan/Time-Series-Forecasting)

时间序列预测流程

原文:https://towardsdatascience.com/time-series-forecasting-flow-2e49740664de?source=collection_archive---------14-----------------------

需求预测的关键步骤简介

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

C 收集

这里的关键是数据存储的格式。

直观上,我们认为时间序列数据的格式如下,也称为格式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,宽格式对于基于 SQL 的存储是不利的,因为当我们添加新日期时,我们需要向表中添加另一列,因此,最佳实践是以 long 格式存储数据,如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里值得一提的另一件事是,由于我们很可能在这里预测多个产品,一种方便的方法是使用 Python 字典,其中键是产品 ID,值是长数据格式(基本上是一个数据帧)。所以我们最终得到了一个数据框架的字典。

清洗

这里的清洁很标准。基本上我们寻找异常值。通常的做法是,如果我们有奇怪的值,比如需求的固定负数(通常大于或等于 0),我们就丢弃它们。这里我们需要寻找的另一件事是丢失的值。我们可以使用 pandas fillna 函数,在该函数中,我们指定是否要用 0 来替换它们,或者用诸如 last demand(回填)这样的方法来替换它们。

测试

也称为回溯测试。基本上最常见的两种开窗方式,一种是滑动(训练和预测时间固定),一种是扩展(训练数据长度一次增加 x)。优步做了一项伟大的工作,将以下两种方法形象化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

常见的评估指标包括 MAPE、wMAPE、sMAPE,以及 RMSE 和 RMLSE(如果数据分布是偏斜的)。

M 造型

这里最重要的一点是,通常简单的方法(如所有数据点的平均值)优于更复杂的 ARIMA。FB 的 prophet 包(用 R 和 Python 两种语言)也可以是一个首选算法。

E 估价

在评估性能时,我们可以尝试不同的训练和预测长度,以更好地理解我们的数据以及所使用的算法。例如,当训练数据为 1 周,预测数据为下一周时,Naive 方法表现极佳;在训练和预测方面,当我们拥有更长的数据长度时,ARIMA 会大放异彩。换句话说,我们需要首先确定我们的业务用例,无论是短期预测还是长期预测,这样我们才能更好地评估来自不同算法的结果。

问问题?

jchen6912@gmail.com

最佳气体补充的时间序列预测

原文:https://towardsdatascience.com/time-series-forecasting-for-optimal-gas-refill-88650b1cf029?source=collection_archive---------4-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Aral petrol station in the mountainous region of Bamberg — Reinhold Möller

你有没有遇到过这样的情况,当你开车经过一个加油站,当你昨天支付的价格比现在高很多时,你变得沮丧?别担心!我们可以用数据科学来克服这个问题!我们可以把这个问题变成一个预测问题。在这篇文章中,我们将建立一个模型来预测你应该今天还是明天补充。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The idea of the data science solution. We want to forecast if the price increases by looking at the past.

数据

2013 年,德国联邦政府决定建立一个中央组织,收集德国所有加油站的油价数据。所有加油站都被迫提供气价变化。数据是公开的,有很多应用程序可以让你看到这些数据。我们将使用这些数据来解决我们的预测问题。数据可以从https://creativecommons.tankerkoenig.de/下载。数据存储为 PostgreSQL 转储。包含了 2015 年 5 月以来的所有气价。解压缩数据后,您可以使用以下命令将它们放入本地 PostgreSQL 数据库:

C:\Program Files\PostgreSQL\10\bin>psql.exe -U postgres -f “C:\…\history.dump”

RapidMiner 中实现这一点很容易:你需要将 PostgreSQL 数据库连接到你的工作室,并使用 Read Database 操作符。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RapidMiner process to get the data into it. The Read Database operator contains the SQL-script which is posted below.

在我的特例中,我想为一个加油站这样做:位于多特蒙德 Westfalendamm 的 ARAL 加油站。这是德国 RapidMiner 办公室正前方的加油站。因此,我们使用一个快速 SQL 查询来获取这个加油站的所有数据:

SELECT * FROM gas_station_information_history
JOIN gas_station
ON gas_station.id = gas_station_information_history.stid
WHERE gas_station.street = ‘Westfalendamm’ AND brand = ‘ARAL’

存储后,我们可以看看数据。

数据准备

两个基本属性是“日期”和“e10”,其中 e10 表示含 10%乙醇的标准气体。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A view of the data. E10 is premium gasoline. The original data set also contains the prices for diesel as well as additional data on the station.

这里的问题是数据没有等距的时间戳。它只记录数据的每次变化。我们想要生成什么样的数据集:

Aug 26, 2016, 4PM — 1269Aug 26, 2016, 5PM — 1269Aug 26, 2016, 6PM — 1269….

这将使我们的数据每小时均衡一次。为此,我们首先创建一个示例集,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Data set after equalization

我们将它附加到原始集合中,对其进行排序,得到下表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The original data set and the equalized data set combined. We can fill the missing data using the previous values to get the price at a given time.

我们用最后一个存在的前一个值来填充缺失的值,并通过过滤“isEqualized”来过滤掉原始数据。RapidMiner 流程如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RapidMiner process for the preprocessing.

数据集现在是干净的,我们可以继续进行特征生成和建模。

特征生成

首先,我们生成一个标签。请记住,我们想要解决这个问题:*我是今天还是明天再加注?*因此,我们的标签是当前价格和 24 小时内价格之间的差异。由此我们可以生成一个表示价格上涨的二项式标签。

下一步是特征生成。首先,我们对数据进行窗口处理。窗口意味着我们在当前行中包含过去 48 小时的所有价格。结果数据集如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Windowed data set in RapidMiner. e10–47 indicates the price 47 hours before, e10–46 the price 46h ago and so.

因为我早上 8 点到达办公室,所以我想预测现在或明天早上 8 点补充是否有意义。因此,我只查看上午 8 点的数据,并过滤掉其余的数据。特征准备的完整 RapidMiner 过程如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们为每个数据点生成一个特征向量。这已经足够训练一个模特了。

系统模型化

我们现在有了一个可以学习的完美数据集。我用一个广义线性模型来预测我们的标签。对于这样的第一次尝试,结果是好的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Confusion Matrix for the GLM. The confusion matrix is estimated using a 10-fold Cross Validation.

该模型的 AUC 为 0.7。虽然这并不完美,但仍然比默认模型要好!

基于 LSTMs 和 Prophet 的时间序列预测

原文:https://towardsdatascience.com/time-series-forecasting-with-lstms-and-prophet-predict-your-email-workload-48bf9cdb1580?source=collection_archive---------6-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image via photodune.net under license to mtstrauss

预测您的电子邮件工作量

ime 系列预测为测试数据科学算法提供了一个绝佳的平台。毕竟,如果一个人能够预测未来,那该有多好?用于演示预测算法的典型数据集是股票图表、销售和气象数据。在这里,我们将尝试一些与每个在线用户更相关的东西,即你将收到的电子邮件的数量。根据一份电子邮件统计报告,2014 年,上班族平均每天收到 85 封电子邮件。让我们试着根据你的历史收件箱数据做一个准确的预测。为此,我们将探讨使用 LSTMs 和脸书的先知。这里的目标是如何为不同的算法准备数据,并提供一个定性的概述,而不是微调。可以说,结果会因你通常收到的电子邮件数量以及你用于训练的数据而有很大差异。

收集数据

我们首先在imapclient包的帮助下用我们自己的收件箱创建一个数据集。一个很好的介绍可以在自动化枯燥的东西上找到,第 16 章。我们将加载过去三年(从 2016 年 1 月 1 日开始)的所有电子邮件,并获取主题和日期。我们使用pandas将它转换成数据帧。

A total of 12738 e-mails loaded.

在我的例子中,我们现在有 12738 封电子邮件用于培训。请注意,上面的代码是针对装满电子邮件的收件箱的。如果你已经将你的电子邮件分类在不同的文件夹中,相应地调整代码。有些人,包括我自己,会立即删除不重要的电子邮件。然后,模型的输出是重要消息的数量,而不是实际的电子邮件。另请注意,一些电子邮件提供商(如谷歌)会阻止连接,称他们不允许从“不太安全”的应用程序连接到他们的服务。这可以在他们的设置中启用。原则上,你也可以查看本地邮箱。查看mailbox套餐可能是一个好的开始。

数据探索

现在,让我们先做一些可视化数据探索,并绘制每小时和每天的电子邮件数量。为此,我们将使用pandas及其重采样和groubpy功能。通过使用sum()count()参数,我们可以对每个时间间隔进行标准化。此外,我们使用seaborn进行可视化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Exploring the data

从数据中,我们可以看到一个独特的模式,即分布遵循典型的周一至周五 9-5 时间表,上午 10 点收到的电子邮件最多。由于每小时电子邮件的峰值数量仅略高于一封电子邮件,因此尝试对此数据集进行每小时预测没有什么意义。因此,我们将尝试预测每天的电子邮件工作量。

初步考虑:预测不可预测的事情

在我们深入研究我们的模型之前,有必要考虑一下我们问题的一些主要限制。可以说,接收电子邮件的时间点在某种程度上是随机的,因此无法预测。在大多数情况下,发送者并不知道对方是谁;因此,我们可以假设它们在统计上是独立的。作为估计,我们可以将我们的过程近似为泊松过程,其标准偏差等于其平均值的平方根。对于大约 12 封电子邮件,我们预计 RMSE 至少为 3.5,这完全是由于我们分布的随机性(sqrt(11.95) ~ 3.461)。
为了进一步阅读,我推荐阅读关于二郎分布的文章,该分布被开发用于检查在某个时间段内打电话的次数。

计算基线

为了创建基线模型,我们可以使用来自历史数据的查找表。在过去的某一天,我收到了多少封电子邮件?为了对模型进行基准测试,我使用一个移动窗口来创建我的查找表,并计算第二天的预测差异。

RMSE for BASELINE 7.39

对于基线模型,我们得到 7.39 的 RMSE,我认为,相对于至少 3.5 的预期 RMSE,这是一个不错的值。

与 LSTM 的电子邮件预测

作为更高级的模型,我们将使用长短期记忆(LSTM)神经网络。关于 LSTMs 的精彩介绍可以在这里找到。对于我们的模型,我们将使用 6 天的窗口大小,并让模型预测第七天。

RMSE for LSTM 7.90

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Training the LSTM

通过观察损失,我们可以看到 LSTM 网络正在学习,并且在预测未来价值方面变得越来越好。我们还可以看到,RMSE 比基线模型差一点。虽然名义上的差异并不大,但它与基线模型的接近程度确实令人瞩目。这表明网络能够学习一周的工作结构,在周末你会收到较少的电子邮件。

另一件值得一提的事情是,我们不能直接比较基线的 RMSE 和 LSTM。这是因为我们为基线的滚动预测转移了训练数据,而 LSTM 只看到了 80%的训练数据。你也可以这样做来训练 LSTM;然而,这在计算上将更加昂贵。

先知的电子邮件预测

接下来,我们将使用脸书的先知库创建一个模型。这是一个加法模型,我们可以用每年、每周和每天的季节性来拟合非线性趋势。同样,为了对模型进行基准测试,我们将把数据分成训练集和测试集,并计算 RMSE。与基线模型类似,我们将增加拟合数据的数量,并计算 RMSE。

RMSE for PROPHET 6.96

从 RMSE 基准测试来看,Prophet 模型是数据集性能最好的模型。现在让我们试着理解这是为什么。为此,我们绘制了模型的组成部分,以更好地理解模型正在做什么。这可以通过在我们的模型上使用performance_metrics函数来完成。

from fbprophet.diagnostics import performance_metrics
prophet_model.plot_components(prophet_forecast)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: Components of the Prophet model

通过检查 Prophet 模型的组件,我们可以看到它可以识别数据中的关键趋势。总的趋势是电子邮件的总体增长。每周季节性准确地描述了工作日/周末时间表。一年中的季节性表现在重大节日,即新年期间电子邮件很少,但圣诞节前会增加。9 月份也是低点,9 月份是数据集所在国家的重要节假日。因此,可以理解为什么性能相当好。

综合起来:电子邮件预测

最后,我们将部署 Prophet 模型作为预测工具。为此,我们再次登录 IMAP 服务器,并使用自 2016 年 1 月 1 日以来的所有历史数据来训练我们的预测模型。在训练模型之后,我们绘制前一周的历史数据和下一周的预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: E-mail forecast for the upcoming week

讨论

LSTMs 和脸书的 prophet 提供了一种直接的方法,可以相当准确地预测电子邮件数据。当考虑到模型的基本机制时,我认为这是可以理解的。LSTM 预测是基于一组最后的值,因此我们不太容易因季节性变化,并已经考虑了当前的趋势。与此形成对比的是,prophet 模型作为一个附加系统在建模方面做得很好,它发现并展示了季节性。当谈到规划未来的工作量或人员配备时,我发现这是您正在寻找的信息。现在可以对模型进行微调。这类问题的一个关键挑战是,如果你只有零星的事件,内在的随机性将是不可预测的。
最后,我们不要忘记,我们已经有了一个很好的基线模型,它强调预测模型不一定总是需要复杂的 ML 算法。

基于递归神经网络的时间序列预测

原文:https://towardsdatascience.com/time-series-forecasting-with-rnns-ff22683bbbb0?source=collection_archive---------8-----------------------

在这篇文章中,我想给你一个我建立的预测时间序列数据的 RNN 模型的概述。这项工作的主要目标是设计一个模型,该模型不仅可以预测下一个时间步,还可以生成一系列预测,并利用多个行驶时间序列以及一组静态(标量)特征作为其输入。

模型架构

在高层次上,该模型利用了非常标准的序列到序列递归神经网络架构。其输入是预测时间序列的过去值,与其他驱动时间序列值(可选)和时间戳嵌入(可选)连接在一起。如果静态特征可用,模型也可以利用它们来调节预测。

编码器

编码器用于将时间序列输入及其各自的时间戳嵌入[ x ]编码为固定大小的向量表示[ S ]。它还为单独的时间步长[ h ]产生潜在向量,这些潜在向量稍后用于解码器关注。为此,我利用了一个多层单向递归神经网络,其中除了第一层之外的所有层都是残差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 1. — Example 2-layer encoder

在某些情况下,您可能有太长的输入序列,可能会导致训练失败,因为 GPU 内存问题或大大降低它的速度。为了处理这个问题,该模型将输入序列与具有相同内核大小和步长的 1D 卷积进行卷积,然后将其馈送到 RNN 编码器。这将 RNN 输入减少了 n 倍,其中 n 是卷积核的大小。

语境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2. — Context layer

上下文层位于输入编码器和解码器层之间。它将编码器最终状态[ S ]与静态特征和静态嵌入连接起来,并产生一个固定大小的向量[ C ,该向量随后被用作解码器的初始状态。

解码器

解码器层被实现为具有注意力自回归递归神经网络。每一步输入都是先前序列值和为该步骤嵌入的时间戳的串联。向解码器提供时间戳嵌入有助于模型学习季节性数据中的模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 3. — Decoder layer

在第一步,编码器将上下文[ C ]作为初始单元值,并将初始序列值[ v 和第一时间戳嵌入[ E ]的串联作为单元输入。然后,第一层发出注意查询[ q ],该查询被馈送到注意模块,该模块输出状态[ s ],该状态然后被用作下一步骤中的单元状态。解码器的较低层不使用注意力。解码器[ o ]的输出是原始预测值,这些预测值随后与为该步骤嵌入的时间戳一起被馈送到下一步骤。

注意

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 4. — Attention

注意允许解码器在解码期间选择性地访问编码器信息。这是通过学习加权函数来实现的,该加权函数将先前的单元状态[ q ]和编码器输出列表[ h ]作为输入,并输出每个编码器输出的标量权重。然后,它取编码器输出的加权和,将其与查询连接,并取非线性投影作为下一个单元状态。从数学上讲,这可以表述如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 1. — Attention function

数据准备

在本文中,我不会一步一步地指导如何为序列对序列学习问题准备数据,但我会尝试向您概述让模型工作所需的步骤。

首先,您需要确保时间序列要素的范围不与目标的范围重叠,并且最新的要素时间戳正好在第一个目标时间戳之前。此外,如果您有任何静态特性(例如聚合统计),它们需要聚合到最后一个特性时间戳。我知道这听起来是显而易见的,但有时真的很容易忽略,并为您的模型表现如此之好而兴奋,只是发现您将未来的信息泄露到了您的训练数据集中。

数据,包括特征和目标,需要被标准化为神经网络模型的合适范围。这通常意味着在 -11 之间的某处。我决定采用的标准化方案是首先采用一个对数来消除任何潜在的偏差,然后计算一个平均值标准偏差。然后,网络的输入是日志的 z 分数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2. — Features normalization

对于目标值,有多个标准化选项。例如,可以使用我在上面描述的类似方法预测最新输入值(如果输入值为 0,这可能是一个问题)或归一化绝对值的相对变化。

结果

作为本文的一个例子,我使用上面描述的模型来预测 Shopify 股票未来五个交易日的收盘价,给定过去六十个交易日的数据。内核/步距= 5 的输入序列卷积层用于将编码器 RNN 输入大小从 60 步减少到 12 步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chart 1. — Shopify closing price

有人可能会说,在不考虑新闻等其他因素的情况下,股价是不可预测的(即使这样也很难)。这就是为什么我决定使用另外六个报价器(苹果、亚马逊、谷歌、脸书、微软和 IBM)作为模型的输入,以便它可以学习它们之间可能的相关性。使用的特征是每日开盘价、最高价、最低价、收盘价(OHLC)和成交量。我用“spread”(abs(high-low))和每个特征的过去 60 天平均值作为静态输入来扩充时间序列特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chart 2. — MAE by day

*图表 2。*显示每天的平均绝对误差。我们可以看到,我们对未来的预测越深入,就越糟糕。从直觉上来说,这是有意义的,因为该模型对下一个交易日的预测比五天后的预测更好。

正如每一个机器学习模型一样,有模型做出非常好的预测的成功,也有预测不太好的失败。以下是这种情况的一些例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chart 3. — Successes

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chart 4. — Failures

结论

递归神经网络是对序列数据建模的有力工具。本文中描述的模型可以应用于从销售预测到能源消耗预测的许多问题。它可以根据多元输入序列和标量输入来调整其预测,这使得它足够灵活,可以合并多个数据源。Tensorflow 实现的模型可以在这里找到。

如果你喜欢这篇文章,请推荐给其他人。另外,如果你有任何建议,请在下面留下你的评论。

使用 Splunk 进行时间序列预测。第一部分介绍&卡尔曼滤波器。

原文:https://towardsdatascience.com/time-series-forecasting-with-splunk-part-i-intro-kalman-filter-46e4bff1abff?source=collection_archive---------3-----------------------

让我们考虑一个比调整仪表板上的输入字段更实际的任务。

时间序列预测是数据分析中一项非常典型的任务。Splunk ML Toolkit 为此任务提供了两种众所周知的方法:卡尔曼滤波和 ARIMA。不幸的是,当遇到实际问题时,这些方法有时会失败。因此,让我们仔细研究一下它们,然后考虑 Splunk 中时间序列预测的一些其他技术。

工作

好了,我们来定义一个目标。让我们使用 Splunk 来监控一些指标,例如登录系统的次数、数据库中的事务数等。我们希望分析我们业务的增长(例如,为了容量规划和资源管理)。作为分析的一部分,我们希望根据过去几年的数据预测一年的登录次数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Number of logins (max hour per day) from 2015 to 2017

如你所见,这是一个很普通的任务。但是让我们用灵活性的要求使它变得更复杂。因为监控不是唯一的指标,我们的方法或算法必须非常通用,以预测几乎任何指标,而无需用户进行大量调整。毕竟,我们需要构建一个具有这种功能的仪表板:用户选择一个指标,指定几个调优参数,并获得所选指标一年的适当预测。

趋势、季节性和平稳性

我们来刷新一下关于时间序列的一些基本概念。一般来说,时间序列可以分解成几个部分:趋势部分、季节部分和残差部分。趋势是时间序列值变化的一个大致方向。例如,上升趋势意味着时间序列的值平均比以前的值大。季节性成分代表数据中的一些周期性波动。例如,夜间的登录次数总是比白天少,工作日的登录次数总是比周末多。残差分量是时间序列值和确定性分量(趋势、季节性)之间的差值,通常代表某种噪声。

有两种主要的模型来处理这些组件。在加法模型中,初始时间序列表示为分量之和,在乘法模型中表示为它们的乘积。有时候,选择哪种模式可能是一个艰难的选择。一般来说,如果季节性波动的幅度随着时间的推移而增加,则乘法模型更为可取。

对于每个时间序列,我们可以计算均值、方差和自相关。如果这些参数随时间保持不变,则时间序列是稳定的。在下图中,您可以找到一些平稳(蓝色)和非平稳(黄色、红色、紫色)时间序列的示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Examples of stationary and non-stationary time series

‘蓝色’系列的均值和方差分别等于 0 和 1,所以这个系列是平稳的。“黄色”系列显示出增加的趋势,即平均值不是常数。“红色”序列表现出明显的日季节性,即自相关函数在滞后 24、48……小时时有一个局部最大值,而且它也不是常数。“紫罗兰”系列表现出增加的趋势和扰动,即均值和方差也不是常数。

真实世界的时间序列很少是平稳的。但是有很多技术和变换可以把它们变成静态的。

让我们打开 ML Toolkit 并尝试预测我们的系列。

卡尔曼滤波器

卡尔曼滤波是一种产生未知变量估计值的算法,这种估计值往往比基于单一测量值的估计值更准确(抱歉,我复制了来自维基文章的定义)。换句话说,卡尔曼滤波器将时间序列作为输入,并执行某种平滑和去噪。在此之后,可以预测平滑的序列。但是应该考虑到卡尔曼滤波首先是去噪,而不是预测。这就是为什么预测的结果可能有点不合适。

进入助手>预测时间序列,选择卡尔曼滤波器作为算法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Let’s get it started

ML 工具包提供了几种预测方法:

  • LL(地方水平)仅预测时间序列的地方水平(没有任何趋势或季节性);
  • LLT(本地级别趋势)仅预测趋势;
  • LLP(季节性当地水平)仅预测季节性成分;
  • LLP5(结合了 LLT 和 LLP)考虑了趋势和季节性。

玩具示例

首先,让我们尝试将卡尔曼滤波器应用于上述示例中的一个非平稳时间序列,以检查平滑能力。让我们选择“黄色”系列—它只是恒定趋势和正态分布噪声的总和。我是通过这个 SPL 查询得到它的(normal是一个定制的外部命令,它从分别在locscale参数中指定的字段返回一个具有均值和方差的正态分布值):

| gentimes start=”01/01/2018" increment=1h
| eval _time=starttime, loc=0, scale=20
| normal loc=loc scale=scale 
| streamstats count as cnt
| eval gen_normal = gen_normal + cnt
| table _time, gen_normal
| rename gen_normal as “Non-stationary time series (trend)”

好的,让我们用“LLT”算法应用卡尔曼滤波器,未来时间跨度= 200,置信区间= 95。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kalman filtering with LLT forecasting

看起来不错。滤波器真正去除正态分布的噪声,并预测实际趋势。

真实的谈话

现在让我们尝试预测我们的登录次数。我们的时间序列显然包括趋势和季节成分,所以让我们选择预测算法= LLP5,未来时间跨度= 365(预测一年),周期= 365(因为我们预计这个季节周期是最长的)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kalman filter with LLP5 forecasting of number of logins

嗯……很明显,结果有点出乎意料。似乎过滤器认为我们的数据波动是一种噪音。因此,滤波器消除了这种噪声,只保留了趋势分量。但有点令人困惑的是,算法中负责季节性成分的“LLP”部分根本不起作用。反正这个预测是不能接受的。

然而,也有一线希望。首先,置信区间的上下界对于离群点检测非常有用。第二,不可否认,趋势成分的预测相当不错。所以,让我们试着过滤掉所有的异常值,从初始数据中去除趋势成分。请注意,初始时间序列的方差随着时间的推移而增加。这就是为什么乘法模型似乎更适合我们的情况。所以,让我们用初始值除以趋势分量的值。

| inputlookup daylogins.csv
| timechart span=1d fixedrange=f max(daylogins) as daylogins
| predict “daylogins” as prediction algorithm=”LLT” future_timespan=365 period=365 lower”95"=lower”95" upper”95"=upper”95"
| eval daylogins = case(daylogins < ‘lower95(prediction)’, ‘lower95(prediction)’, daylogins > ‘upper95(prediction)’, ‘upper95(prediction)’, 1=1, daylogins)
| eval season = daylogins / prediction
| table _time, season
| where _time<strptime(“2018–01–01”, “%F”)

这里我在 SPL 使用了一个predict命令。这是一个卡尔曼滤波的命令,你可以通过点击“预测时间序列”仪表板上的“显示 SPL”按钮来检查它。

将方法更改为 LLP,然后单击“预测”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Forecast of seasonal component

嗯,还不错。主要的季节性特征(比如新年后的大衰退)几乎被完美地捕捉和预测。

俄罗斯有一个延长的新年假期。它开始于 1 月 1 日,持续约 8-10 天(实际持续时间每年不同)。它指出,在那些日子里,许多地区的用户活动比其他日子少得多。

但是,一如既往,细节决定成败。看看新年假期后预测的峰值。好像和一年前一样。实际上,它们看起来太相似了。请注意,在 2015 年和 2016 年,没有任何类似的峰值。如果关闭异常值移除,相似性会变得更加明显。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Forecast seems to be just a copy of the last period of data

预测中会重复 2017 年 2 月的异常值,但不会重复 2016 年 5 月的异常值。因此,似乎卡尔曼滤波器与 LLP 算法高估了最后一段时间的价值(在我们的情况下是最后 365 天),而不理会相应的前一段时间的价值。

同样的情况也发生在除夕夜的旺季。

然而,卡尔曼滤波的这种特性并没有使这种预测完全不充分。如果我们真的只想依赖最近一段时间的数据,这可能会有用。例如,我们将根据前几周的数据预测一周的登录次数,以便实时检测关键问题。如果登录次数显著减少,这可能意味着认证服务器的可用性或类似的一些问题。对于这种监控,我们可以创建一个简单明了的预测,只需将新数据与置信区间的界限进行比较。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Week forecast for the data completeness check

好吧,让我们回到最初的一年预测。尽管有明显的缺点,我们的时间序列的季节成分的预测是相当合理的。因此,让我们将预测的趋势分量乘以预测的季节分量,以恢复到所需的登录次数。

| inputlookup daylogins.csv 
| timechart span=1d fixedrange=f max(daylogins) as daylogins 
| predict "daylogins" as prediction algorithm="LLT" future_timespan=365 lower"95"=lower"95" upper"95"=upper"95" 
| eval daylogins = case(daylogins < 'lower95(prediction)', 'lower95(prediction)', daylogins > 'upper95(prediction)', 'upper95(prediction)', 1=1, daylogins) 
| eval season = daylogins / prediction 
| predict "season" as season_prediction algorithm="LLP" future_timespan=365 period=365 lower"0"=lower"0" upper"0"=upper"0"
| eval prediction = prediction * season_prediction
| table _time, daylogins, prediction
| eval prediction = if(isnull(daylogins), prediction, null)
| where _time<strptime("2019-01-01", "%F")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Forecast of number of logins using Kalman filtering

看起来很不错。注意,我最终在没有 ML Toolkit Assistant GUI 的情况下在纯 SPL 实现了这个预测。因此,我可以将该搜索插入到任何应用程序的任何仪表板中(只需考虑知识对象的权限)。我需要指定的唯一参数是季节成分的周期(即多重季节性情况下的最大季节周期)。您可以允许用户通过简单的输入文本框在仪表板上指定此参数,默认值为 365。还可以使用傅立叶变换或分析自相关函数来自动计算最大季节周期(我想我们稍后会谈到这一点)。

未完待续…

下面我们简单回顾一下 Splunk 中的卡尔曼滤波器。

  • 这是一个简单而有用的时间序列预测工具。
  • 人们只需一个 SPL 命令就可以轻松创建预测,而无需调整大量参数。
  • 滤波器(顾名思义)在平滑噪声时间序列方面表现良好。

但是这种简单意味着缺乏灵活性。

  • 你根本无法控制季节周期。在多重季节性的情况下,你只能依靠过滤器的内部算法。
  • 季节性预测很少考虑最后一段时间以外的值。
  • 没有任何类似“平滑系数”的参数用于“去噪灵敏度”的调节。因此,滤波器有时会执行非常激进的平滑,并且会导致有价值信息的丢失。

好吧,今晚到此为止。在下一部分,让我们更仔细地看看 Splunk 中的 ARIMA 。敬请期待!

时序嵌套交叉验证

原文:https://towardsdatascience.com/time-series-nested-cross-validation-76adba623eb9?source=collection_archive---------0-----------------------

这篇博文讨论了对时间序列数据使用传统交叉验证的缺陷。具体来说,我们解决了 1)在不导致数据泄漏的情况下分割时间序列,2)使用嵌套交叉验证来获得独立测试集的无偏误差估计,以及 3)使用包含多个时间序列的数据集进行交叉验证。

用例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这篇文章是对缺乏关于如何对包含多个时间序列的数据使用交叉验证的在线信息的回应。

这篇文章将帮助任何有时间序列数据的人,特别是多个独立的时间序列。这些方法是为医学研究中多个参与者的时间序列医学数据而设计的。

交叉验证

交叉验证(CV)是一种用于调整超参数和产生模型性能的稳健测量的流行技术。两种最常见的交叉验证是k-折叠交叉验证和保留交叉验证。

由于文献中术语的差异,我们明确定义了我们的 CV 程序。首先,我们将数据集分成一个称为训练集的子集和另一个称为测试集的子集。如果需要调整任何参数,我们将训练集分成一个训练子集和一个验证集。在训练子集上训练模型,并且选择最小化验证集上的误差的参数。最后,使用选择的参数在完整的训练集上训练模型,并记录测试集上的误差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Example of hold-out cross-validation. The data is split into a training set and a testing set. Then the training set is split again to tune hyperparameters- one part is used to train the model (training subset) and the other part (validation set) is used to validate the model.

为什么时间序列的交叉验证不同?

在处理时间序列数据时,传统的交叉验证(如 k -fold)不应使用,原因有二:

  1. 时间依赖性

对于时间序列数据,在分割数据时必须特别小心,以防止数据泄漏。为了准确地模拟“真实世界的预测环境,我们站在现在并预测未来”(Tashman 2000),预测者必须保留在用于拟合模型的事件之后按时间顺序发生的事件的所有数据。因此,对于时间序列数据,我们使用保留交叉验证,而不是使用 k 折叠交叉验证,其中数据的子集(暂时分割)被保留用于验证模型性能。例如,参见图 1,其中测试集数据按时间顺序排在训练集之后。类似地,验证集按时间顺序排在训练子集之后。

2.任意选择测试集

您可能会注意到,图 1 中测试集的选择是相当随意的,这种选择可能意味着我们的测试集误差是对独立测试集误差的糟糕估计。为了解决这个问题,我们使用了一种叫做嵌套交叉验证的方法。嵌套 CV 包含一个用于误差估计的外环和一个用于参数调整的内环(见图 2)。内部循环的工作方式与前面讨论的完全一样:将训练集分为训练子集和验证集,在训练子集上训练模型,并选择使验证集上的误差最小化的参数。然而,现在我们添加了一个外部循环,它将数据集分成多个不同的训练和测试集,并且对每次分割的误差进行平均,以便计算模型误差的稳健估计。这是有利的,因为:

嵌套的交叉验证过程提供了真实误差的几乎无偏的估计。(瓦尔马和西蒙,2006 年)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Nested CV Example

时间序列的嵌套 CV 方法

我们建议用两种方法对单一时间序列的数据进行嵌套 CV。我们将处理这样一个场景,其中我们有来自一个医疗患者/参与者的多天数据:

  1. 预测下半年
  2. 日正向链接

预测下半年

第一种类型,预测后半部分,是嵌套 CV 的“基本情况”,只有一个训练/测试分割。这样做的好处是这种方法易于实现;然而,它仍然受到任意选择的测试集的限制。数据的前半部分(在时间上分开)被分配给训练集,后半部分成为测试集。验证集的大小可以根据给定的问题而变化(例如,在图 3 的示例中是 1 天的数据),但是确保验证集在时间上在训练子集之后是很重要的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: Predict Second Half Nested Cross-Validation

日前向连锁

预测后半部分嵌套交叉验证方法的一个缺点是,任意选择保留测试集会对独立测试集产生预测误差的有偏估计。为了更好地估计模型预测误差,通常的方法是创建许多训练/测试分割,并对所有分割的误差进行平均。我们使用的技术称为日前向链,基于一种称为前向链的方法(在文献中也称为滚动原点评估(Tashman 2000 年)和滚动原点重新校准评估(Bergmeir 和 bentez 2012 年))。使用这种方法,我们连续地将每一天作为测试集,并将所有以前的数据分配到训练集中。例如,如果我们的数据集有五天,那么我们将产生三个不同的训练和测试分割,如图 4 所示。请注意,在本例中,我们有三次拆分,而不是五次,因为我们需要确保至少有一天的培训和验证数据可用。该方法产生许多不同的训练/测试分割,并且对每个分割的误差进行平均,以便计算模型误差的稳健估计。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: Day Forward-Chaining Nested Cross-Validation

请注意,在我们的示例中,我们使用“Day”正向链接;然而,一次也可以迭代每个数据点(但这将意味着更多的分割),而不是迭代跨越天*。*

多个时间序列的嵌套交叉验证

既然我们有两种分割单个时间序列的方法,我们讨论如何处理具有多个不同时间序列的数据集。同样,我们使用两种类型:

常规

对于“常规”嵌套交叉验证,如何进行训练/验证/测试分割的基本思想与之前相同。唯一的变化是拆分现在包含了来自我们数据集中每个参与者的数据。例如,如果有两个参与者,参与者 A 和 B,则训练集将包含来自参与者 A 的前半天的数据和来自参与者 B 的前半天的数据。同样,测试集将包含每个参与者的后半天的数据。

人口知情

对于“群体知情嵌套交叉验证”,我们利用不同参与者数据之间的独立性。这使得我们可以打破严格的时间顺序,至少在个体的数据之间(在个体的数据内部仍然是必要的)。由于这种独立性,我们可以稍微修改常规的嵌套交叉验证算法。现在,测试和验证集只包含来自一个参与者的数据,比如说参与者 A,并且来自数据集中所有其他参与者的所有数据都允许出现在训练集中。请参见图 5,了解这对于群体通知日正向链接嵌套交叉验证是如何工作的。该图显示,参与者 A 的第 18 是测试集(红色),之前的三天是验证集(黄色),训练集(绿色)包含来自参与者 A 之前的所有数据,以及来自其余参与者的 all 数据(本例中为 BCDE )。需要强调的重要一点是,正是由于这些参与者的时间序列的独立性,使用其他参与者的“未来”观察结果不会造成数据泄漏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 5: Population-Informed Day Forward-Chaining, where, in addition to Day Forward-Chaining method (left subfigure) for Participant A, we also allow all other participants’ data to be in the training set (right subfigure). Note that the grey bars indicate when the participant was sleeping.

其他重要的嵌套交叉验证注意事项

最后,我们总结了不同嵌套交叉验证方法的优缺点,特别是在计算时间和独立测试集误差估计的偏差方面。分割数量假设数据集包含 p 名参与者和 d 名参与者的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总结:

我们首先回顾了交叉验证,列举了使用嵌套交叉验证背后的基本原理。我们讨论了如何分割时间序列数据而不导致数据泄漏,特别建议了两种方法:1)预测下半年和 2)日前向链接。然后,我们讨论了如何使用两种方法处理多个独立的时间序列:1)常规方法和 2)群体通知方法。

引文:

C.伯格梅尔和 J. M .贝尼特斯。时间序列预测器评估的交叉验证的使用我 *nf。Sci。,*2012 年 5 月 191:192–213。ISSN 0020–0255。doi:10.1016/j . ins . 2011 . 12 . 028 . URL hTTP://dx . doi . org/10.1016/j . ins . 2011 . 12 . 028 .

长度 j .塔什曼。预测准确性的样本外检验:分析与评述。国际预测杂志,16(4):437–450,2000 年。URL https://ideas . repec . org/a/eee/int for/v16y 2000 i4p 437-450 . html

南瓦尔玛和西蒙。使用交叉验证进行模型选择时误差估计的偏差。BMC 生物信息学,7(1):91,2006 年 2 月。ISSN 1471–2105。doi:10.1186/1471–2105-7–91。

时机很重要:社交网络中预定的影响力最大化

原文:https://towardsdatascience.com/timing-matters-scheduled-influence-maximization-in-social-networks-2736543fffed?source=collection_archive---------12-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Influence spread

社交网络领域中的一个高度研究的主题是搜索有影响力的节点,当这些节点被播种(即被有意激活)时,可以通过病毒传染过程进一步激活网络的大部分。实际上,文献中提出了各种数学模型来描述这种扩散过程的动态特性,并提出了不同的解决方案来最大化这种模型的影响。
然而,这些解决方案中的大多数集中在选择一组在扩散过程的初始阶段被播种的节点。

我们最近的出版物( PDF ) 发表在 IEEE 计算社会系统汇刊(D. Goldenberg,A. Sela 和 E. Shmueli) 上,该出版物是特拉维夫大学大数据实验室研究的一部分,提出了一种预定播种方法,该方法不仅旨在找到要播种的最佳节点集,还旨在找到执行这些播种的正确时机。
更具体地说,我们确定了现有传染模型的三个不同属性,可通过预定方法利用这些属性来提高激活节点的总数:

  1. 随机动力学
  2. 社会效应递减
  3. 状态依赖播种

通过分别分析这些属性,我们通过理论和经验评估证明了调度播种方法相对于传统初始播种方法的优势。
我们的分析显示,当使用计划播种方法时,感染节点的最终数量提高了 10%-70%。

随机动力学

在图 1 中,我们展示了随机动力学中调度方法的优势,其中延迟播种可以在激活节点数量方面获得高达 30%的改善:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 1: Comparing Scheduling seeding approaches in stochastic diffusion models.

因为延迟播种决策可以避免播种预算的不必要花费,所以通过最大化对网络的总影响,这些预算单元可以用于新的目标。

社会效应递减

通过分析具有复杂传染特性和随时间递减效应的扩散模型,我们发现预定播种方法可以通过“及时”利用播种预算来改善总影响。图 2 展示了在社会效应递减的线性阈值模型下,初始播种策略和预定播种策略的最佳可能结果的比较:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 2: Dynamics of the diffusion process for Initial and Scheduled seeding approaches on the Dolphins network

正如我们所看到的,通过为第三时间步节省单个播种预算单位,调度方法成功地激活了 49 个节点,而不是传统初始播种方法中的仅 43 个。

状态依赖播种

在播种动作本身的结果取决于邻居节点的激活状态的设置中,播种的定时可以起到至关重要的作用。在图 3 中,我们展示了一个例子,在这个例子中,为了被激活,一个种子节点需要有至少一半的邻居已经被激活。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: An example of scheduling advantage in state-dependent seeding dynamics.

通过逐步实施播种行动,我们可以利用累积激活过程并在播种结束时获得更大的总影响力。

总结

我们的发现有可能开辟一个新的研究领域,专注于寻找播种行动的正确时机,从而有助于提高我们对信息传播动力学的理解,并设计更好的影响最大化策略。对于每个提出的属性,我们考虑了一个简化的传染模型,允许我们隔离特定属性对预定播种方法的成功的贡献。然后,我们展示了一个极简的玩具示例,展示了通过预定播种方法获得的好处。我们还进行了理论分析,以比较调度播种方法和传统初始播种方法的性能。最后,我们展示了一组经验模拟实验,这些实验比较了调度和初始播种方法在许多真实世界社交网络拓扑上的性能。在整个工作中,我们尽量保持分析的简单性。
例如,在展示有利于计划播种方法的三个属性时,我们将每个属性与其他属性隔离开来。
未来的工作可能会进一步分析这些属性的不同组合,这可能会呈现它们之间的非平凡的相互作用。例如,虽然随机性的存在被证明是支持延迟播种行为的有力论据,但是社会效应递减的存在可能需要尽快播种节点。对这种情况的初步探索可以在我们以前的工作中找到(主动病毒营销:将持续的主动播种努力纳入扩散模型),其中分析了状态依赖播种的动态以及随机性和社会效应递减的存在。

我们的评估主要基于利用真实网络拓扑的理论分析和模拟。在未来,用额外的真实世界数据(如用户的购买历史)来丰富我们的模拟会很有趣。此外,进行现场实验来比较通过预定播种方法和初始播种方法获得的采用率将是有见地的。总之,我们相信我们的发现有潜力打开一个全新的研究领域,专注于寻找播种行动的正确时机,从而帮助我们提高对扩散动力学的理解,并设计更好的策略来塑造社会行为。

数据可视化技巧

原文:https://towardsdatascience.com/tips-for-data-visualization-c00d505db7cf?source=collection_archive---------7-----------------------

您的数据取决于您理解和交流数据的能力,这就是为什么选择正确的可视化/图表至关重要。如果您不能有效地展示数据,关键的见解可能会丢失。信息可以用几种不同的方式可视化,每种方式都更能提供特定的洞察力。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

处理数据时,首先要理解你想要讲述的故事或你试图强调的关系。这将有助于选择正确的形象来传达你的信息。

在开始可视化数据之前,您应该了解常见的数据类型:

  1. 定量——可以计数或测量;数字的
  2. 分类—可以根据组或类别进行排序
  3. 离散-具有有限数量的可能值
  4. 连续-测量,其值在一个范围内

理解数据关系对于数据可视化过程非常重要。下面列出了常见的数据关系:

👉时间序列—跟踪一段时间内指标值的变化

👉名义比较-比较子类别的数量值

👉相关性—包含两个或更多变量的数据,这些变量之间可能存在正相关性或负相关性

👉部分到整体的关系——与整体相比的数据子集

👉分布—显示围绕中心值的数据分布

👉偏差-显示数据点之间的相互关系,以查看任意给定点与平均值的差距

👉排名-显示两个或多个值在相对大小上的相互比较

其他提示:

使用图标增强理解,减少额外的标签/图例

使用逻辑层次对数据集进行排序

以一种让受众能够简单比较数值的方式来可视化数据

使用注释或标注突出显示重要信息

用一种颜色代表每个类别,在整个演示文稿/仪表盘中保持一致

不要使用三维图表——它可能会扭曲对信息的理解

避免在一个视图中使用超过 5 种颜色

不要使用分散注意力的背景色或有渐变的颜色

有效的数据科学讲座技巧

原文:https://towardsdatascience.com/tips-for-effective-data-science-talks-b50961262c26?source=collection_archive---------9-----------------------

在研究生院,我学会了在做演讲前练习。授课进一步强化了沟通的重要性,这让我在行业中受益匪浅。

最近,我不得不为实习生在全公司范围内展示他们的项目提供建议。我意识到我没有一个向导来指引他们…所以现在我正在制作它。

这并不意味着是真理,它们只是我在过去 15 年左右的时间里通过非正式测试学到的一些技巧。

让我们从最重要的部分开始:你必须努力工作。但是通过练习会变得更容易。

把它想象成编写软件:在对任何用户进行测试之前,你曾经编写过完美的软件吗?为什么你会期望发表一个伟大的演讲而不在人们身上进行测试呢?迭代开发的类比更深入:你可以尝试聪明地预测你的受众,或者你可以只是去找一个小的随机样本受众并尝试一下。

诚实地考虑他们的反馈,不要觉得自己受到了批评。大约一半的反馈不应该只看表面。当有人向你建议解决方案时,首先确定他们正在解决的问题。解决同一个问题往往有更简单的方法。

我建议在演讲中只回答澄清性的问题,而把所有讨论性的问题留到最后。最好提前说:如果有人在第二张幻灯片上迷失了方向,觉得自己不被允许大声说出来,这种缺乏理解的情况通常会加剧,他们将很难理解接下来的几张幻灯片(有时甚至是整个演讲!)你允许提问。但是你不想和 1%的听众进行 10 分钟的讨论。之后进行讨论。

管理您的技术

买一个遥控器,让幻灯片播放时不会分心。在会议上,这很正常,但在公司会谈中,这甚至很有帮助。你可以更专注于吸引观众,减少开销。

如果您使用的是 Mac,请设定“请勿打扰”模式。最糟糕的是在谈话中得到一个松弛/Hangouts 通知。同样,关闭谷歌日历或禁用中断通知。或者完全关闭 Wifi。

当我们谈到技术的时候,早点到那里,仔细检查投影仪/电视。如果你在连接器和设置上笨手笨脚,观众可能会开始互相交谈,很难重新获得他们的注意力。

如果你有麦克风,最好说大声点,让麦克风离嘴远一点。这样就不会放大你的呼吸声。它还能防止许多廉价麦克风拾取的尖锐声音。你也会显得更加自信。

在大房间里,迅速确认后面的观众能听到你。这可能看起来很傻,但 10 秒钟是值得的。

尊重观众

不熟悉的术语往往会失去你的听众。你的观众并不愚蠢,但他们可能不知道什么是雅各宾派,或者被教了一个不同的词,或者不习惯英语。吴恩达的机器学习课程就是一个好技术的例子;他经常会多花几秒钟来确保术语的定义,以及所有不同背景的人都有平等的机会。

用具体的例子描述你的问题可以减少术语和抽象概念的复杂性。在许多情况下,依靠一个例子来解释将决定留住和失去一个人。

尽可能让房间里的每个人都有机会阅读您的幻灯片。增加默认字体大小。

有些人视力不好或者没有视力。所以当你展示图表时,用文字描述你所看到的。

当简单的单词可以使用时,不要使用难懂的单词

抓住观众的注意力

吸引你的观众很重要。人们相互镜像;如果你对他们感兴趣,他们也会对你感兴趣。至少试着和大多数观众进行一次眼神交流。

动画文本,以便一次显示一个项目符号。对于一个复杂的话题,这有助于你的听众将注意力集中到当前最重要的事情上*,这通常是最后一个要点。*

幻灯片不是用来传递信息的;文本只是提供备份。

优先考虑

抄袭最好的,但要给予表扬。这是你在准备时间用完时,从制作讲座幻灯片中学到的东西。例如,如果你试图解释监督学习和非监督学习之间的区别,网上可能有一个很好的图表。

计算机科学中的一个常见错误是使内容过于技术化(即使是在会议上)。会议演讲的目的是让人们阅读你的论文。在一个简短的演讲结束时,听众应该都知道这篇论文是否与他们相关。在行业讲座上,你可能会向其他领域的同行解释新技术。你应该积极地优先考虑你认为 90%的观众需要知道的内容,永远不要为了炫耀你的技术实力而牺牲掉那 90%的内容。

论记忆与练习

我不会一字不差地记住我的演讲。但我确实记得那次谈话的感觉。对我来说,练习就是学习如何从一张幻灯片流到另一张幻灯片。然后当我在台上演讲时,我自然会跟着感觉正确的流程走。这导致了受控但没有死记硬背的谈话。

一般来说,我通过一次看一张幻灯片并假装说话来练习一次。我动了动嘴,没有发出声音。这有助于我更准确地估计时间。

然后在同龄人之前练习。特别是,我试图包括一些不熟悉这个话题的人和一些熟悉的人。来自非技术人员的反馈通常是最重要的。你甚至可以用它来建立关系网,大多数人会很乐意帮忙的。

对于重要的会谈,在会谈的那天,我会自己练习一遍。如果我有一个酒店房间,我大声说话。

这是我的方法,但是你可能会发现记忆对你有用。或者你可能会复制吴恩达和记录自己

结束想法

糟糕的演讲的一个标志是观众不会提问。

好的展示的一个标志是他们会问你问题。

一场精彩演讲的标志是,他们会问你一些聪明的问题,并相互辩论。你教会了他们一些有价值的东西,他们的好奇心会推动你学习更多。

在 pandas 中使用日期时间索引

原文:https://towardsdatascience.com/tips-on-working-with-datetime-index-in-pandas-2bcedf956d70?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Jordan Benton from Pexels

对一个人有用的东西可能对另一个人有用

正如您从标题中所理解的,它并不是 Python 中时间序列或日期时间数据类型的完整指南。因此,如果你期望从 A 到 Z 得到深入的解释,那就错了。说真的。关于这个话题有一篇精彩的文章,解释得很好,很详细,也很直白。不要在这个上浪费你的时间。

对于已经读到这一部分的人,我会告诉他们,你肯定会在这里找到有用的东西。再说一次,说真的。我找到了我关于时间序列的笔记,并决定把它整理成一篇小文章,里面有一些通用的提示,我想这些提示在你处理日期的 80%到 90%的情况下都是适用的。所以很值得分享不是吗?

我有一个数据集,其中包含自 2016 年以来马德里每小时的空气污染物测量值,因此我将以它为例。

导入数据

默认情况下,当使用read_csv()导入 csv 文件时,pandas 将使用第一列作为索引,因此如果您的日期时间列不是第一列,您将需要显式指定它index_col='date'.

pandas 的美妙之处在于它可以在导入过程中预处理您的 datetime 数据。通过指定parse_dates=True,pandas 将尝试解析索引,如果我们传递整数或名称的列表,例如 if [1,2,3]–它将尝试将第 1、2、3 列分别解析为单独的日期列,列表列表,例如 if [[1,3]]–将第 1 和第 3 列合并,解析为单个日期列,dict,例如{‘foo’ : [1,3]}–将第 1、3 列解析为日期,并调用结果“foo”。如果您使用其他方法导入数据,您可以在其后使用pd.to_datetime

我使用以下代码导入了我的数据:

import pandas as pd
import globpattern = 'data/madrid*.csv'
csv_files = glob.glob(pattern)
frames = []for csv in csv_files: 
    df = pd.read_csv(csv, index_col='date', parse_dates=True)     frames.append(df)
df = pd.concat(frames)
df.head()Out[4]: 
                     BEN  CH4   CO  EBE  NMHC     NO   NO_2  NOx  
date                                                                          
2016-11-01 01:00:00  NaN  NaN  0.7  NaN   NaN  153.0   77.0  NaN  
2016-11-01 01:00:00  3.1  NaN  1.1  2.0  0.53  260.0  144.0  NaN  
2016-11-01 01:00:00  5.9  NaN  NaN  7.5   NaN  297.0  139.0  NaN  
2016-11-01 01:00:00  NaN  NaN  1.0  NaN   NaN  154.0  113.0  NaN   
2016-11-01 01:00:00  NaN  NaN  NaN  NaN   NaN  275.0  127.0  NaN

这些数据是从 24 个不同的站点收集的,涉及 14 种不同的污染物。我们不打算分析这些数据,为了简单一点,我们将只选择一个站,两种污染物,并删除所有 NaN 值(危险!请不要在不了解后果的情况下在家里重复)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

df_time = df[['O_3', 'PM10']][df['station'] == 28079008].dropna() df_time.head() Out[9]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0
2016-11-01 05:00:00  6.0  27.0

现在,当我们准备好数据后,我们就可以玩日期时间索引了。

选择值

尽管默认的 pandas datetime 格式是 ISO8601(“yyyy-mm-DD hh:mm:ss”),但当使用部分字符串索引选择数据时,它可以理解许多其他不同的格式。例如:

**df_time.loc['2016-11-01'].head()** Out[17]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0
2016-11-01 05:00:00  6.0  27.0**df_time.loc['November 1, 2016'].head()** Out[18]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0
2016-11-01 05:00:00  6.0  27.0**df_time.loc['2016-Nov-1'].head()** Out[19]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0

都产生相同的输出。所以我们可以自由使用任何对我们来说更舒适的东西。我们还可以选择整个月的数据:

**df_time.loc['2016-11'].head()** Out[20]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0
2016-11-01 05:00:00  6.0  27.0**df_time.loc['2016-11'].count()** Out[24]: 
O_3     715
PM10    715
dtype: int64

如果我们想选择整年,情况也是如此:

**df_time.loc['2016'].head()** Out[31]: 
                     O_3  PM10
date                          
2016-11-01 01:00:00  4.0  46.0
2016-11-01 02:00:00  4.0  37.0
2016-11-01 03:00:00  4.0  31.0
2016-11-01 04:00:00  5.0  31.0
2016-11-01 05:00:00  6.0  27.0**df_time.loc['2016'].count()** Out[32]: 
O_3     8720
PM10    8720
dtype: int64

如果我们想对数据进行切片并找到某个特定时间段的记录,我们继续使用loc访问器,所有规则与常规索引相同:

**df_time.loc['2017-11-02 23:00' : '2017-12-01'].head()** Out[34]: 
                     O_3  PM10
date                          
2017-11-02 23:00:00  5.0  30.0
2017-11-03 00:00:00  5.0  25.0
2017-11-03 01:00:00  5.0  12.0
2017-11-03 02:00:00  6.0   8.0
2017-11-03 03:00:00  7.0  14.0**df_time.loc['2017-11-02 23:00' : '2017-12-01'].count()** Out[35]: 
O_3     690
PM10    690
dtype: int64

重采样

Pandas 具有简单、强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将秒数据转换为 5 分钟数据)。这在金融应用中极为常见,但不限于此。

resample()是一个基于时间的 groupby,其后是对其每个组的归约方法。

resample功能非常灵活,允许我们指定许多不同的参数来控制频率转换和重采样操作。summeanstdsemmaxminmedianfirstlastohlc
resample()返回对象的方法

# Converting hourly data into monthly data
**df_time.resample('M').mean().head()** Out[46]: 
                  O_3       PM10
date                            
2016-01-31  21.871622  19.990541
2016-02-29  32.241679  25.853835
2016-03-31  44.234014  16.952381
2016-04-30  46.845938  12.189076
2016-05-31  53.136671  14.671177

对于向上采样,我们可以指定一种向上采样的方法,以便在创建的间隙上进行插值:

# Converting hourly data into 10-minutely data
**df_time.resample('10Min').mean().head()** Out[47]: 
                     O_3  PM10
date                          
2016-01-01 01:00:00  8.0  17.0
2016-01-01 01:10:00  NaN   NaN
2016-01-01 01:20:00  NaN   NaN
2016-01-01 01:30:00  NaN   NaN
2016-01-01 01:40:00  NaN   NaN**df_time.resample('10Min').mean().ffill().head()** Out[48]: 
                     O_3  PM10
date                          
2016-01-01 01:00:00  8.0  17.0
2016-01-01 01:10:00  8.0  17.0
2016-01-01 01:20:00  8.0  17.0
2016-01-01 01:30:00  8.0  17.0
2016-01-01 01:40:00  8.0  17.0

我们可以使用以下方法来填充 NaN 值:*‘填充’,‘回填’,’ ffill ‘,’ bfill ‘,‘最近的’。文档中可以找到更多相关细节。或者我们可以通过以下方法使用插值来实现:‘线性’,‘时间’,‘索引’,‘值’,‘最近’,‘零’,‘线性’,‘二次’,‘三次’,‘重心’,’ krogh ‘,‘多项式’,‘样条’,‘分段 _ 多项式’,’ from _ 导数’,’ pchip ‘,’ akima '。*同样,关于这一点的更深入的解释可以在熊猫文档中找到。

和重采样频率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

形象化

Datetime Index 的另一个令人惊叹的特性是绘图简单,因为 matplotlib 会自动将其视为 x 轴,所以我们不需要显式指定任何内容。

import seaborn as sns
sns.set()
df_plot = df_time.resample('M').mean()
**plt.plot(df_plot)** plt.title('Air polution by O3 and PM10')
plt.ylabel('micrograms per cubic meter (mg/m3)')
plt.xticks(rotation=45)
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如在开始时所承诺的——一些小技巧,在大多数情况下,在处理日期时间数据时会有所帮助。对我来说——又一个将思想转化为知识的更新者和组织者。都赢了。有人会觉得它有用,有人可能不会(我在第一段就警告过:D),所以实际上我希望每个阅读这篇文章的人都会觉得它有用。

这是知识最令人兴奋的特点——当你分享它时,你不会失去任何东西,你只会有所收获。要写一篇文章,需要一些研究,一些验证,一些学习——基本上你最终会获得更多的知识。

知识只是一种工具。应用与否是你的责任。归根结底,你知道多少并不重要,重要的是你如何运用这些知识。但那已经是另一个故事了…

感谢您的阅读,度过不可思议的一周,学习,传播知识,明智地使用它,并将其用于行善🙂

最初发表于【sergilehkyi.com】

数据科学家,你需要知道的一个图算法

原文:https://towardsdatascience.com/to-all-data-scientists-the-one-graph-algorithm-you-need-to-know-59178dbb1ec2?source=collection_archive---------4-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Alina Grubnyak on Unsplash

图表为我们提供了一种非常有用的数据结构。它们可以帮助我们找到数据中的结构。随着机器学习和大数据的出现,我们需要获得尽可能多的关于我们数据的信息。学习一点图论当然可以帮助我们。

这里有一个由 UCSanDiego 在 Coursera 上开设的大数据图形分析课程,我强烈推荐学习图论的基础知识。

我在这篇文章中要关注的算法之一叫做连通域。为什么它很重要。我们都知道聚类。

你可以用非常通俗的术语把连通分量看作是一种硬聚类算法,它在相关/连通的数据中寻找聚类/孤岛。举一个具体的例子:假设您有关于连接世界上任何两个城市的道路的数据。你需要找出世界上所有的大洲以及它们包含的城市。

你将如何实现这一目标?来吧,考虑一下。

从零售角度来看**:比方说,我们有很多客户使用很多账户。使用连通分量算法的一种方法是在数据集中找出不同的族。我们可以基于相同的信用卡使用、相同的地址或相同的手机号码等假设客户之间的边界(道路)。一旦我们有了这些连接,我们就可以在相同的上运行连接组件算法来创建单独的聚类,然后我们可以为这些聚类分配一个家族 ID。我们可以使用这些家庭 id 根据家庭需求提供个性化建议。我们还可以使用这个家族 ID,通过创建基于家族的分组特征来推动我们的分类算法。**

财务视角中:另一个用例是使用这些家庭 id 来捕获欺诈。如果一个帐户过去曾有过欺诈行为,那么关联的帐户也很有可能容易受到欺诈。

足够多的用例。让我们从一个用 Python 编写的简单的 graph 类开始,用代码开始我们的开发。

从现在开始,这篇文章将更多地围绕代码展开。

您当然可以使用我们的新图形类。在这里,我们试图建立一些图表。

Output:
Vertices of graph:
['a', 'c', 'b']
Edges of graph:
[['a', 'd', 2], ['c', 'b', 5], ['c', 'e', 5], ['c', 'd', 3], ['b', 'c', 2]]
Add vertex:
Vertices of graph:
['a', 'c', 'b', 'z']
Add an edge:
Vertices of graph:
['a', 'c', 'b', 'z']
Edges of graph:
[['a', 'z', 1], ['a', 'd', 2], ['c', 'b', 5], ['c', 'e', 5], ['c', 'd', 3], ['b', 'c', 2], ['z', 'a', 1]]
Adding an edge {"x","y"} with new vertices:
Vertices of graph:
['a', 'c', 'b', 'y', 'x', 'z']
Edges of graph:
[['a', 'z', 1], ['a', 'd', 2], ['c', 'b', 5], ['c', 'e', 5], ['c', 'd', 3], ['b', 'c', 2], ['y', 'x', 1], ['x', 'y', 1], ['z', 'a', 1]]

现在让我们做一些有趣的事情。

出于理解的目的,我们将使用上面的 graph 类。python 中有许多模块,我们可以用来做我接下来要做的任何事情,但是为了理解这些方法,我们将从头开始编写所有的东西。
让我们从一个示例图开始,我们可以用它来达到我们的目的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Vertices of graph:
['Mannheim', 'Erfurt', 'Munchen', 'Numberg', 'Stuttgart', 'Augsburg', 'Kassel', 'Frankfurt', 'Wurzburg', 'Karlsruhe']
Edges of graph:
[['Mannheim', 'Frankfurt', 85], ['Mannheim', 'Karlsruhe', 80], ['Erfurt', 'Wurzburg', 186], ['Munchen', 'Numberg', 167], ['Munchen', 'Augsburg', 84], ['Munchen', 'Kassel', 502], ['Numberg', 'Stuttgart', 183], ['Numberg', 'Wurzburg', 103], ['Numberg', 'Munchen', 167], ['Stuttgart', 'Numberg', 183], ['Augsburg', 'Munchen', 84], ['Augsburg', 'Karlsruhe', 250], ['Kassel', 'Munchen', 502], ['Kassel', 'Frankfurt', 173], ['Frankfurt', 'Mannheim', 85], ['Frankfurt', 'Wurzburg', 217], ['Frankfurt', 'Kassel', 173], ['Wurzburg', 'Numberg', 103], ['Wurzburg', 'Erfurt', 186], ['Wurzburg', 'Frankfurt', 217], ['Karlsruhe', 'Mannheim', 80], ['Karlsruhe', 'Augsburg', 250]]

假设给我们一张图表,上面有德国的城市以及它们之间各自的距离。你想知道如何从法兰克福(起点)到慕尼黑。可能有许多方法可以遍历该图,但您需要找到从法兰克福到慕尼黑至少需要访问多少个城市)这个问题类似于在未加权的图中找出节点之间的距离。

我们这里使用的算法叫做广度优先搜索**。**

我们在上面这段代码中所做的是创建一个队列,并根据级别遍历它。我们以法兰克福为起点。我们循环通过它的邻近城市(曼海姆、维尔茨堡和卡塞尔)并把它们推入队列。我们跟踪他们处于什么水平,以及我们到达他们的路径。因为我们弹出队列的第一个元素,我们确信我们将按照城市等级的顺序访问城市。

查看这篇关于 BFS 的帖子,了解更多关于排队和 BFS 的信息。

({'Augsburg': 3,
  'Erfurt': 2,
  'Frankfurt': 0,
  'Karlsruhe': 2,
  'Kassel': 1,
  'Mannheim': 1,
  'Munchen': 2,
  'Numberg': 2,
  'Stuttgart': 3,
  'Wurzburg': 1},
 {'Augsburg': ':->Frankfurt->Mannheim->Karlsruhe',
  'Erfurt': ':->Frankfurt->Wurzburg',
  'Frankfurt': ':',
  'Karlsruhe': ':->Frankfurt->Mannheim',
  'Kassel': ':->Frankfurt',
  'Mannheim': ':->Frankfurt',
  'Munchen': ':->Frankfurt->Kassel',
  'Numberg': ':->Frankfurt->Wurzburg',
  'Stuttgart': ':->Frankfurt->Wurzburg->Numberg',
  'Wurzburg': ':->Frankfurt'})

我做这个例子是为了展示 BFS 算法是如何工作的。我们可以扩展这个算法,在一个不连通的图中找出连通的部分。假设我们需要在图中找到几组不相连的顶点。

例如,下图有 3 个不相连的子图。我们能找到哪些节点属于某个特定的子图吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[['Kassel',
  'Munchen',
  'Frankfurt',
  'Numberg',
  'Augsburg',
  'Mannheim',
  'Wurzburg',
  'Stuttgart',
  'Karlsruhe',
  'Erfurt'],
 ['Bangalore', 'Kolkata', 'Delhi', 'Mumbai'],
 ['NY', 'ALB', 'TX']]

上面的代码类似于前面的 BFS 代码。我们将图的所有顶点保存在节点列表中。我们从节点列表中取出一个节点,并在其上启动 BFS。当我们访问一个节点时,我们从节点列表中删除该节点。每当 BFS 完成时,我们从节点列表中的另一个节点开始,直到节点列表为空。

如您所见,我们能够在数据中找到不同的组件。仅仅通过使用边和顶点。这个算法可以在不同的数据上运行,以满足我上面介绍的任何用例。

但通常使用零售案例的连接组件将涉及大量数据,您将需要扩展该算法。

PySpark 中的连接组件

下面是这篇论文中关于 MapReduce 中连接组件的实现,以及 Google Research 中之后的实现。阅读 PPT 以更好地理解实施。一些现成的代码供您使用。

或者在 PySpark 中使用 GraphFrames:

要安装图表框架:

我在命令行上运行:py spark—packages graphframes:graph frames:0 . 5 . 0-spark 2.1-s _ 2.11,它打开了我的笔记本,并在我尝试在笔记本中导入后安装了 graph frames。

要格式化的字符串为:graphframes:(最新版本)-spark(你的 spark 版本)-s_(你的 scala 版本)。

查看 本指南介绍如何使用 GraphFrames 了解更多信息。

GraphFrames 库实现了 CC 算法以及各种其他图形算法。

上面的帖子有很多代码,但希望对你有所帮助。我花了很多时间来实现算法,所以想让它对人们来说很容易。

如果你想阅读更多关于图算法的内容,这里有一个由 UCSanDiego 在 Coursera 上开设的大数据图分析课程,我强烈推荐你学习图论的基础知识。

请随时在 LinkedIn 上与我联系,在 Twitter / Medium 上关注我,或者给我发消息征求意见。继续收听,继续学习。

首先发表在我的博客 mlwhiz.com这里

参考

  1. Python 中的图形
  2. 图论博客简介
  3. 加州大学圣地亚哥分校 Coursera 大数据课程的图表分析

做还是不做(数据科学家)

原文:https://towardsdatascience.com/to-be-or-not-to-be-a-data-scientist-13684ba7422?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每次我试图想出一个合适的新标题时,快速的谷歌搜索都会让我意识到这个话题已经被讨论过很多次了,而且大多数相关的标题都被取了出来。我觉得标题有意义比独特更重要,于是就选了上面的这个。请不要评判我。

仍然值得讨论这个问题的原因是缺乏对转行、学习新技能和适应不断变化的生活的挑战部分的覆盖。在这篇文章中,我不会列出“成为数据科学家的 10 大资源”,但我会告诉你我从一名具有基本编程知识的机械工程师到一名从事深度学习的数据科学家的旅程。

从为什么开始

前阵子,我读了西蒙·西内克的书《从为什么开始》。这是我决心改变职业生涯的开始,它让我努力思考做我喜欢的事情。

图片来自 FramingTheDialogue.com 的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你有时间,可以看看西蒙的 Ted 演讲,然后回来。如果你没有时间,直接跳过——这不是强制性的。

如何通过做自己喜欢的事情获得报酬

每天醒来兴奋地去工作,去解决有挑战性和有意义的问题——这是我的目标,这是我的原因。有了“为什么”,我就开始讨论“如何”和“什么”。事实证明,找出原因是一个相对简单的过程,从一些个人反思开始。相反,弄清楚如何做和做什么是一个更困难的过程,而不是一条直线。

当时我在石油和天然气行业工作,在上游石油和天然气行业担任项目经理,前途无量。我甚至还在攻读石油工程的硕士学位。虽然这很有趣,但我没有跳下床去上班。可以肯定的是,这份工作有许多积极的方面,我很喜欢。在项目团队中工作是一种独特的体验,需要建立有意义的关系,作为一个非常注重结果的人,我在建设实体项目中找到了乐趣。不幸的是,我没有找到我想要的智力挑战。

我决定只要有机会,我就会追随我的兴趣。当时,数据科学并不像今天这样普遍,但我知道数据是有价值的,这个领域正在快速发展。另外,我喜欢和它一起工作。

我发现自己在偏远的澳大利亚中部工作,一周工作两个星期,突然有了额外的时间。晚上,在每天工作 12 个小时管理项目后,我会抓紧时间吃晚饭,呆在房间里,然后编程。在两周的休假期间,我将继续开发股票市场交易工具(当时我已经参与了几年),并开始掌握 web 抓取、结构化和非结构化数据的数据挖掘、数据清理、数据可视化和应用程序开发。

我当时并不知道,但这是成为一名数据科学家的核心部分——数据处理技能。除了在股票市场上赚几个钱之外,没有一件事是有目的的;我只是追求个人兴趣。在花了几年时间为澳大利亚市场进行交易、分析和开发工具后,我开始写一个金融专栏。有一段时间,我和妻子环游世界一年。这种情况一直持续到我去德国攻读双学位(机器人学硕士和 MBA)。大约在同一时间,我也开始“正式”自学数据科学。

这有助于我在攻读工程学位期间学习微积分、线性代数和微分方程。我有一些 C++和 Matlab 的经验,但我不能称自己为程序员。我还认为,成为一名数据科学家所需的原始数学技能并不复杂。Khan Academy 上的几本入门,YouTube 上的几个视频,就足以让你变得危险。

我的学业继续着,有点痴迷。我会在早上起床,学习 2-3 个小时,然后去上学。有了双学位,我打算为转行打下坚实的基础。它带有奖学金;这是著名的德国工程界,这是显而易见的。同时,我可以兼职学习数据科学。

原来我讨厌回到学校。结构、不灵活以及缺乏任何与数据科学相关的东西困扰着我。老实说,我从来都不是结构化学习的狂热爱好者,并且很享受在数据科学世界中记录我的冒险经历。我对这所大学或学生没有任何不满;这不是我想做的。我在学校学的是有限元分析和材料工程,我想做的就是回去研究机器学习。这是一个迷人的主题,其可能性令人难以置信。

回想起 Sinek 先生的话和我开始这段旅程的“为什么”,我觉得学校不会把我带到那里。当然,这将导致一个有趣的职业生涯,但我就是不喜欢它。和妻子聊了几个晚上后,我退出了这两个项目,开始了一份数据分析师的工作。这是获得数据工作报酬的第一步,我会在晚上继续学习机器学习。

几个月过去了,我学习得更多了。我所有的业余时间都花在了学习、编码、学习上。我学习了 Spark、Python,研究了大多数传统的机器学习方法,学会了理解神经网络的所有细节,并开始构建自己的项目。我和妻子搬到了保加利亚,我将在那里开办一家咨询公司,我继续研究深度学习。我身后有两股激励的风。

  1. 如果我想和最有趣的人一起工作,解决令人兴奋的问题,我需要站在这个领域的最前沿。
  2. 我每天早上起来都兴奋地想在我选择的领域里学到新的东西。

事后看来,坚持下去并不困难。我被一种兴趣和一种偏执驱使着。总是认为我知道的不够多,我继续学习。另外,我玩得很开心,所以感觉不像工作。

最终,我从书本中站起来,发现自己作为一名数据科学家已经相当精通。从第一天开始编程到现在已经四年了。我的工作让我能够从事前沿的深度学习模型。我们实施上个月可能已经出来的新模型设计,并开始产生新的独特想法。

关于从为什么开始的几点注意事项

我想在此稍作停顿,澄清我的原因、方式和内容:

  • 为什么——我想每天醒来都兴奋地去工作,这样我的生活会更充实。
  • 如何——在令我着迷的领域找到一份职业,与有动力和兴趣的人一起应对有趣的挑战,并在该领域的前沿工作。
  • 什么?我碰巧是一名数据科学家

数据科学从来都不是目标。如果你决定成为一名数据科学家开始你的旅程,你可能会成为一名优秀的数据科学家。你也可能会发现你讨厌它。你愿意花两周时间清理十个来源的数据,再花一周时间进行特性工程,然后测试你的模型,发现它毫无价值吗?

你愿意理解螺母和螺栓——数学,概念,优化是如何工作的?当你的朋友去酒吧,在他们高薪的工程职业生涯中前进的时候,你会花时间在清晨和深夜学习吗?如果不是,那么数据科学(可能)不适合你。我说可能是因为总有例外。我试着为自己设定高标准,这可能不一定适用于其他人,所以对此要有所保留。

战斗当前

作为一个领域,数据科学正在快速变化。你越深入,就越难跟上。你需要致力于学习和研究,仍然愿意回到那些首要原则,与数据搏斗。你需要一系列令人眼花缭乱的技术、分析和个人技能。你停止学习的那一天,就是你开始落伍的那一天。想象一下,如果你不喜欢你正在做的事情,那会有多累。

精英管理

到目前为止,数据科学更多的是基于精英而不是证书。它向许多不同的人开放了这个领域,吸引了比其他领域更喜欢它的人。随着大学开始向人们收取正式学位的费用,数据科学的这一方面正在逐渐衰落——这并不是说这本身有什么问题,而是它将人们吸引到了一个否则他们不会花时间的领域。在数据科学这样的领域,如果你不热爱它,就很难跟上。没有动力,你会发现自己很快就会落后。

数据科学既艰难又令人沮丧

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Via ForeverStudent.com

作为一名数据科学家,就像作为一名软件工程师一样,可能会非常令人沮丧、困难,并且需要大量的时间投入,但这是非常值得的。话虽如此,它可能不会满足你的为什么。对大多数人来说,肯定不是。我恳求你从为什么而不是什么开始。追随你的兴趣,因为这些兴趣也包含机会。可能不是数据科学(统计学上也不是),但如果你专心致志,你会有所发现。每天都要学习,把精力集中在机会所在的地方。如果你这样做了,你会得到一份令人兴奋的职业,让你的生活变得更有意义。

我相信正确的方法可以让任何人爱上他们的职业。如果我的妻子正在阅读——对不起,但是你将不得不分享。

买还是不买?这是一个问题

原文:https://towardsdatascience.com/to-buy-or-not-to-buy-that-is-the-question-3a4d99330dcc?source=collection_archive---------11-----------------------

如何用图论区分积极消费者和橱窗购物者?

从实时信号中了解购物者的真实意图

“预测很难。尤其是关于未来。”尼尔斯·玻尔(也许)

即使电子商务销售额达到历史最高水平,大多数访问某个电子商务网站的人也更有可能不买东西就离开,反之亦然

作为电子商务副总裁,如果知道我们的模型可以在你的店铺点击几下后识别出有动机的顾客,你会怎么做(剧透:只有六个)?对于积极主动的购物者和漫不经心的购物者,哪些是正确的互动策略?

任何一个优秀的销售助理都知道,消费者通过语言和身体行为展示出他们真正兴趣的清晰线索:他们如何在过道里走动,他们问什么问题,他们的穿着等等…如果这在现实世界中是真的,那么在数字世界中,当没有脸可以阅读时,会发生什么呢?

如果用户正在浏览我们的网站,用尽可能少的“点击”来检测她真正的购物意图肯定会非常有帮助:在大数据时代,我们实际上可以跟踪(匿名)浏览我们商店的用户,并精确记录他们的行动。我们能否利用消费者留下的所有数字面包屑,将预测的艺术转化为推销的艺术?

Tooso ,我们正在通过人工智能机器学习帮助市场上一些最大和最具创新性的零售商转变网上购物。由于我们的渠道已经每天从几个电子商务网站获取数百万新事件,我们处于一个理想的位置,可以尝试使用数据来回答我们的问题:

人工智能能在他们的在线旅程中多久(如果有的话)发现真正想买东西的用户?

想象一下你的数码商店的可能性:如果你知道哪些用户会购买,哪些不会,你如何改变你的网站?Tooso 的产品专家正在与我们的零售客户合作,为不同类型的用户开发不同的驱动因素:如果用户的意图是购买,我们可以努力进行追加销售,优化购物车体验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

If the user wants to buy, let’s help him buy more.

另一方面,如果目的是浏览,我们可以尝试让用户受到启发并参与进来:增加品牌知名度,建议跨渠道行动,等等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

If the user is casually browsing, let’s get him involved.

这篇博文中,我们将从数据科学的角度解释我们是如何完成这项任务的,并且我们将概述一些由于我们的进展而正在开发的产品功能。**初步结果表明,只需在网站上进行六次操作,我们就能够可靠地预测购买客户!**我们还希望通过对真实数据进行研究友好的许可,为零售业的人工智能社区做出进一步的贡献:更多信息请见结束语,现在是科学时间。

几个月前,我们启动了 Tooso 实验室。该项目的启动旨在通过将我们的愿景、技能组合和专有数据集与我们在行业和学术界的知名研究人员网络相匹配,为新旧人工智能问题带来新的跨学科解决方案;“点击流预测问题”是我们选择用新方法解决的第一个问题。

这份进展中的报告是 Tooso 实验室和 Lucas Lacasa 博士持续合作的结果,Lucas Lacasa 博士是玛丽女王大学应用数学高级讲师,一位了不起的物理学家,一位相当不错的篮球运动员,也是 Tooso 的好朋友。

从点击流数据到预测

"也许因为我永远不会成为人类,所以我对人类很感兴趣."杰夫林赛

我们将通过使问题更精确一点和上下文更明确一点来开始我们的深入探讨。你可以把你最喜欢的电子商务网站想象成一个网络,即一个正式的结构,其中节点是网站中的页面,而是页面之间的链接:用户登陆该网站后,可以通过在每个页面/节点重复动作来导航网络,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Navigating the network: a shopper’s journey from landing page to the final checkout.

每个用户将在网络中无数可能的路径中仅选择一个:一些路径将是许多用户共同的(例如,从登录页面到主页),一些将是相对罕见的(例如,通过产品描述中的一些链接从一个 SKU 到另一个);一些路径会以购买结束(就像上面的红色路径),但是大部分会在中途中断,也就是当用户离开商店而没有购买时。

多亏了我们的 Apache 许可的 Tooso Analytics 标签,我们的大数据仓库存储了用户路径中的所有动作,因此示例中的事件将被记录为类似下面的列表:

USER 123, TIME 1537517055, URL /landing123, PAGE TYPE landing
USER 123, TIME 1537517059, URL /category1, PAGE TYPE category
USER 123, TIME 1537517065, URL /index, PAGE TYPE home
USER 123, TIME 1537517100, URL /category2, PAGE TYPE category
USER 123, TIME 1537517200, URL /product-01231312, PAGE TYPE sku
USER 123, TIME 1537517210, URL /cart, PAGE TYPE cart
USER 123, TIME 1537517290, URL /checkout, PAGE TYPE checkout

如果我们不是取一个用户,而是取几千个用户,那么得到的集合将会是一个很长的路径列表,其中一些会包含一些购买事件,而大多数不会;列表中的每条路径都是一个独立的时间序列,由严格按时间顺序排列的单个事件组成。

我们的目标是训练机器很好地预测人类行为,这样就有可能从一些初始事件中了解用户是否会购买某些东西。

因此,我们的训练设置将涉及向我们的人工智能输入序列,以训练我们的预测模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Training settings: from labeled sequences to the trained model.

我们的离线预测设置将包括输入 1,2,…将 n 个事件添加到训练好的模型中,并记录对购买行为的预测,以测量几个序列长度的准确性(直觉上,事件越多,预测应该越好):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Offline prediction settings: the model predicts binary buying outcome at each time step in the sequence.

一旦我们对模型的准确性感到满意,就可以以一种简单明了的方式为具有在线预测的实时自适应产品提供动力(假设有一个可靠的系统来接收点击流数据并做出相应的反应)。

既然问题的边界已经明确设定,现在是真正有趣的时候了:我们如何教会机器预测人类购物者?

物理学拯救世界

“向酒吧女招待解释物理定律应该是可能的。”——阿尔伯特·爱因斯坦

从点击流数据中预测购物行为(或者更一般地说,导航模式)的问题已经在学术界和工业界用几种方法进行了研究:从高阶马尔可夫链(如这篇 PLOS 论文中),到 RNN 论文中(如这篇由乐天支持的 SIGIR 论文),最近的论文表明,即使一个简单的时间戳也可能是一个非常强大的预测特征。

作为 Tooso 实验室跨学科哲学的一部分,我们有兴趣以全新的眼光看待这个问题;特别是,我们从开发“廉价的”(从计算的角度来看)方法开始,与更传统的“繁重的”算法相比,这些方法可以在实时设置中有效地使用,而不会损失准确性。

我们的跨学科方法植根于物理学,特别是所谓的可见性图(书呆子警告:查看这篇 PNAS 论文)。如果您考虑一个通用时间序列,可以通过将可以“看到”彼此的数据点(作为节点)链接在一起来构建可见性图(例如,直观地,您可以在它们之间画一条直线,而不穿过中间点):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Getting edges out of a time series through the “visibility” criterion.

这种看似无害的转变开启了建模技术的宇宙,因为可见性图已经成功地用于描述时间序列的结构和各种设置中的潜在动力学(例如,预测阿尔茨海默病湍流)。

成熟可见性分析的关键要素是“主题”,这是“接近”节点之间的连接模式,其中“接近”是通过在时间维度上遍历图形计算的滑动窗口来定义的。例如,对于尺寸为 4 的窗口,可能的图案/样式只有六个,并且它们可以通过简单的不等式检查容易地计算出来(全部细节在此):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

For a window size of 4, there are only six possible motifs.

虽然看起来很简单,但这些图案已经被证明是一种有用的组合工具,可以用来描述混沌过程和其他类型的复杂数据。用这些新概念武装起来(感谢物理!),如何才能接近我们在零售界的原始问题?极客读者可能已经知道答案:我们将把我们的用户轨迹转换成可见性图,并使用“主题”作为特征来回答我们的分类问题:用户会在这个会话中买东西吗?

意图分类的第一步

"一个好的预测者并不比其他人更聪明,他只是更好地组织了他的无知. " —匿名

作为我们的第一个游乐场,我们从我们的在线用户数据集中提取了大约 500,000 条真实客户的点击流轨迹。在对更一般的“购买与不购买”分类问题感兴趣的同时,第一个问题是通过可见性图用最简单的可能模型可以预测什么。

简单有两个天然的优点:首先,简单的模型更容易理解、调试和改进,为我们以后可能想要尝试的任何火箭科学的东西提供了良好的基线;其次,简单的模型更容易在实时、低延迟的环境中设计:因为我们的最终目标是改善我们合作伙伴网站上数百万用户的购物体验,所以在准确性、速度和维护成本之间取得平衡至关重要。

我们的基本预处理相当简单:对于每个轨迹,我们基于传统的电子商务事件类型(例如,1 =页面视图,2 =产品视图等),将系列中的事件映射到整数(例如,1,2,3,4 …)。).因此,我们的示例路径为user 123:

URL /landing123, PAGE TYPE landing
URL /category1, PAGE TYPE category
URL /index, PAGE TYPE home
URL /category2, PAGE TYPE category
URL /product-01231312, PAGE TYPE sku
URL /cart, PAGE TYPE cart
URL /checkout, PAGE TYPE checkout

将成为序列:

1 -> 1-> 1 -> 1 -> 2 -> 3 -> 4

从如此创建的约 500,000 个整数序列中,我们提取了一个平衡样本(~50%/50%)的buy vs no-buy链,保留了序列标签,但移除了购买事件:当我们输入序列来训练我们的模型时,算法因此不能使用购买事件来预测购买(因为那将是人类欺骗多于人工智能)。看着这样转化的数据,连(训练有素!)人眼可以突出一些有趣的特征:

  • 根据行业经验,我们预计buy序列通常比no-buy包含更多的“添加到购物车”事件,事实也确实如此;
  • buy序列中的用户通常会少看件商品,而不是多看件商品,就好像他们的购买偏好在他们的头脑中更加清晰地表达出来。

由于我们的可视化图形机制,我们现在可以对过程采取更“整体”的观点,并实际使用上述特征作为我们的时间序列的一般图形描述的一部分。虽然有更多的数据需要准备(剧透:我们将在未来几个月发布一篇完整的研究论文),但现在我们很乐意分享上述简单预测问题的结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Buy vs no-buy sequence prediction accuracy with different models.

这是什么意思?在我们的可视性图表示上的 SVM 分类器已经拥有 86%的预测准确性。这意味着,给定一个序列和一个标签buyno-buy,该模型几乎可以在 10 次中分辨出 9 次哪个标签是正确的!

这是令人难以置信的第一步:通过利用原始时间序列的非常简单的特征,我们能够在数据中发现足够的模式,从而在预测购物行为方面取得非常重要的结果。

很明显,虽然这对于我们基于可见性的特征提取来说确实令人鼓舞,但一个更现实的用例——如我们的介绍部分所描述的——是仅从少数数据点预测购物行为:为了为我们的合作伙伴释放商业价值,我们真正想要的是以下问题的答案:

当用户轨迹中只有 1,2,3,… N 个事件时,该模型在计算购物事件是否可能在序列的后期发生方面有多好?

为了回答这个进一步的问题,我们从预处理的数据集中提取了每个轨迹的第一个 m 点( m = 4,5,…);像往常一样,我们随机丢弃no-buy轨迹来平衡我们的类。跳过乏味的细节,这些是基于可见性的分类(通过十重交叉验证评估)的结果,用于 m = 4,5,6:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Prediction accuracy with SVM at different values of m (i.e number of actions taken in the sequence).

一点都不差!

在目标网站上仅仅六个动作之后(产品视图、页面视图等。),模型 10 次中有 7 次能够准确判断出用户是否要买某个产品!

最后,请注意,我们在现有文献中做了一些健全性检查:尽管在实现细节上有很大不同,但该模型实现的总体准确性水平与一些最先进的同行评审的论文相当。因此,我们的主要贡献是双重的:

  • 首次将可见性图理论应用于点击流预测场景;
  • 仅使用极其简单、易于计算且理论上很容易理解的特性来实现最佳精度。

正如预期的那样,我们计划在未来几个月发布一份关于我们工作的完整研究报告,并进行一些更正式的比较。

下一步措施和结束语

“真正的奢侈是定制。”—拉普·艾尔坎恩

通过可见性图表进行购物预测是我们第一个“公开”的 Tooso 实验室项目:

我们确实相信更好的科学造就更好的商业,清晰的商业用例可以释放伟大科学的潜力。

我们认为,在我们拥有的资源、时间和机会范围内,为整个领域做出贡献是我们的使命和公司 DNA 的核心部分:生产优秀的产品和推进该领域并不是相互排斥的目标,但它们确实是一枚硬币的两面。

作为这一全新领域的下一步,我们设定了三个中期目标:

  • arXiv 上发布一篇研究文章的预印版本,包括模型的所有细节:预处理、特征选择、验证等。;如果时间和社区的兴趣允许的话,我们也可以选择准备一个更好的版本在这个空间的会议上展示;
  • 对我们的模型做进一步的迭代:当然我们可以用这么少的信息获得如此大的成功,但没有理由就此止步:从搜索行为开始(当然!),我们会更深入,看看用更复杂的特性会获得多少精度;
  • 以研究友好型许可证发布部分原始数据集——仍需要完成一些重要的工作,以确保数据匿名、有用和一致,但进一步为零售业的人工智能社区做出贡献的前景令人兴奋。

在产品方面,我们的团队已经在与我们的业务合作伙伴讨论如何最好地利用我们新模型的预测,努力阐明有趣的“基于意图的”工作流程的细节。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Intent-based workflow, a.k.a.“to each according to his intention”.

无论这项激动人心的工作会产生什么样的产品功能,有一点是肯定无疑的:我们将越来越接近的完全购物个性化的承诺,让网上商店无缝地修改他们的行为,以适应每一个单独的客户。

真正的奢侈确实是定制。

再见,太空牛仔

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们总是从学术界和行业从业者那里寻找疯狂的新想法。如果你对我们空间里的问题感兴趣,从 NLP 到时间序列分析,请伸手与jacopo . taglia bue @ tooso . ai分享你的故事。

别忘了从 LinkedinTwitterInstagram 上的 Tooso 获取最新消息。

感谢

感谢安德烈·波洛尼奥利、亚历山大·维考特伦和整个 Tooso 团队对本文前几稿的有益评论。

特别感谢卢卡斯·拉卡萨,他确保我只是温和地毁掉了我们一起做的出色工作:所有剩下的错误当然都是我的,而且仅仅是我的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值