分享

最强总结,十大时间序列算法 !!

 昵称69125444 2024-07-23

哈喽,我是小白~

今儿咱们一起来看看时间序列分析算法。

时间序列分析方法很重要,主要由于:

  1. 趋势识别:帮助我们识别数据中的长期趋势和季节性变化,为预测未来趋势提供依据。
  2. 异常检测:能够检测数据中的异常值和异常模式,及时发现潜在问题。
  3. 决策支持:为政策制定和战略规划提供数据驱动的洞察,帮助优化决策过程。

所以,基于它的重要性,我们一起来看今天分享的有:

  • 自回归
  • 移动平均
  • 自回归滑动平均
  • 自回归积分滑动平均
  • 季节性自回归积分滑动平均
  • 向量自回归
  • 向量自回归滑动平均
  • 长短期记忆网络
  • Prophet
  • 变分自编码器

一起来看看~

1. 自回归 (AR, Autoregressive Model)

自回归模型假设当前值  是过去若干时刻值的线性组合。

原理

模型利用前 p 个时间点的数据预测当前时间点的数据。

核心公式

其中:

  •  是常数项,
  •  是自回归系数,
  •  是白噪声误差。

自回归模型的推导可以通过对时间序列数据进行线性回归得到,即:

使用最小二乘法求解系数 

核心案例

案例中,使用了股票价格数据,展示如何拟合AR模型并进行预测,并生成两个以上的数据分析图形。

使用一个股票价格的时间序列数据,首先对数据进行预处理,然后拟合一个自回归模型,最后生成几个图形,包括时间序列图、ACF图、PACF图和预测图。

使用 yfinance 库来获取股票价格数据。

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.ar_model import AutoReg
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 下载数据
ticker = 'AAPL'  # 以苹果公司股票为例
start_date = '2020-01-01'
end_date = '2023-01-01'
data = yf.download(ticker, start=start_date, end=end_date)
close_prices = data['Close']

# 绘制时间序列图
plt.figure(figsize=(147))
plt.plot(close_prices, label='Close Price')
plt.title('Apple Stock Close Prices')
plt.xlabel('Date')
plt.ylabel('Close Price')
plt.legend()
plt.show()

# ACF和PACF图
fig, (ax1, ax2) = plt.subplots(21, figsize=(1410))
plot_acf(close_prices, ax=ax1, lags=50)
plot_pacf(close_prices, ax=ax2, lags=50)
plt.show()

# 拟合自回归模型
lags = 30
model = AutoReg(close_prices, lags=lags)
model_fit = model.fit()

# 模型预测
pred_start = len(close_prices)
pred_end = pred_start   50
predictions = model_fit.predict(start=pred_start, end=pred_end)

# 绘制预测结果
plt.figure(figsize=(147))
plt.plot(close_prices, label='Observed')
plt.plot(predictions, label='Forecast', linestyle='--')
plt.title('Apple Stock Close Price Forecast')
plt.xlabel('Date')
plt.ylabel('Close Price')
plt.legend()
plt.show()
  1. 时间序列图:展示了苹果公司股票的每日收盘价。
  2. ACF和PACF图:用于检查时间序列的自相关性和部分自相关性,帮助确定AR模型的阶数。
  3. 预测图:展示了拟合AR模型后的未来50天的股票价格预测。

图片

2. 移动平均 (MA, Moving Average Model)

移动平均模型假设当前值  是过去若干时刻误差的线性组合。

原理

模型利用前 q 个时间点的误差预测当前时间点的数据。

核心公式

其中:

  •  是常数项,
  •  是移动平均系数,
  •  是白噪声误差。

通过假设误差项  是独立同分布的白噪声,可以用最小二乘法或极大似然估计法求解系数 

核心案例

假设我们有一个月度的销售数据,该数据包含一些季节性和随机波动。我们将使用移动平均模型来平滑数据,并比较平滑后的数据与原始数据。此外,我们还将计算并绘制残差。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 生成模拟的时间序列数据
np.random.seed(42)
n_periods = 120
date_range = pd.date_range(start='2010-01', periods=n_periods, freq='M')
seasonal_pattern = np.sin(2 * np.pi * date_range.month / 12)
random_noise = np.random.normal(scale=0.5, size=n_periods)
sales = 10   seasonal_pattern   random_noise

# 创建数据框
data = pd.DataFrame({'Date': date_range, 'Sales': sales})
data.set_index('Date', inplace=True)

# 绘制原始数据
plt.figure(figsize=(146))
plt.plot(data.index, data['Sales'], label='Original Sales Data')
plt.title('Monthly Sales Data')
plt.xlabel('Date')
plt.ylabel('Sales')
plt.legend()
plt.show()

# 使用移动平均模型进行平滑
window_size = 12
data['Sales_MA'] = data['Sales'].rolling(window=window_size).mean()

# 绘制平滑后的数据
plt.figure(figsize=(146))
plt.plot(data.index, data['Sales'], label='Original Sales Data')
plt.plot(data.index, data['Sales_MA'], label=f'{window_size}-month Moving Average', color='red')
plt.title('Monthly Sales Data with Moving Average')
plt.xlabel('Date')
plt.ylabel('Sales')
plt.legend()
plt.show()

# 计算残差
data['Residual'] = data['Sales'] - data['Sales_MA']

# 绘制残差
plt.figure(figsize=(146))
plt.plot(data.index, data['Residual'], label='Residuals', color='green')
plt.title('Residuals from Moving Average Model')
plt.xlabel('Date')
plt.ylabel('Residual')
plt.legend()
plt.show()

# 绘制自相关图和偏自相关图
fig, axes = plt.subplots(12, figsize=(166))
plot_acf(data['Residual'].dropna(), ax=axes[0], lags=40)
plot_pacf(data['Residual'].dropna(), ax=axes[1], lags=40)
axes[0].set_title('ACF of Residuals')
axes[1].set_title('PACF of Residuals')
plt.show()
  1. 生成时间序列数据:使用正弦函数生成季节性模式,并添加随机噪声。
  2. 绘制原始数据:绘制原始的月度销售数据。
  3. 计算移动平均:使用滚动窗口方法计算移动平均。
  4. 绘制平滑后的数据:比较平滑后的数据与原始数据。
  5. 计算并绘制残差:计算残差并绘制残差时间序列。
  6. 绘制自相关图和偏自相关图:分析残差的自相关性和偏自相关性。

图片

3. 自回归滑动平均 (ARMA, Autoregressive Moving Average Model)

ARMA模型结合了自回归和移动平均模型。

原理

模型利用前 p 个时间点的数据和前 q 个时间点的误差预测当前时间点的数据。

核心公式

ARMA模型是将自回归模型和移动平均模型结合,利用两者的推导方法,对两个模型的参数进行联合估计。

核心案例

代码中,我们使用Python中的 statsmodels 库来进行ARMA建模和分析,并使用 matplotlib 来绘制图形。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 生成示例时间序列数据
np.random.seed(42)
n = 200
ar_params = np.array([0.75-0.25])
ma_params = np.array([0.650.35])
ar = np.r_[1, -ar_params]  # add zero-lag and negate
ma = np.r_[1, ma_params]   # add zero-lag
y = np.random.normal(size=n)
x = np.convolve(y, ma)[:n]   np.random.normal(size=n)
time_series = pd.Series(x)

# 绘制原始时间序列数据
plt.figure(figsize=(126))
plt.plot(time_series, label='Original Time Series')
plt.title('Original Time Series')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.show()

# 绘制自相关图 (ACF) 和偏自相关图 (PACF)
fig, axes = plt.subplots(12, figsize=(166))
plot_acf(time_series, ax=axes[0], title='Autocorrelation Function (ACF)')
plot_pacf(time_series, ax=axes[1], title='Partial Autocorrelation Function (PACF)')
plt.show()

# 建立并拟合ARMA模型
model = ARIMA(time_series, order=(202))
arma_result = model.fit()

# 打印模型摘要
print(arma_result.summary())

# 绘制拟合后的时间序列和残差图
plt.figure(figsize=(126))
plt.plot(time_series, label='Original Time Series')
plt.plot(arma_result.fittedvalues, color='red', label='Fitted Values')
plt.title('Original and Fitted Time Series')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.show()

# 绘制残差图
residuals = arma_result.resid
plt.figure(figsize=(126))
plt.plot(residuals, label='Residuals')
plt.title('Residuals of ARMA Model')
plt.xlabel('Time')
plt.ylabel('Residual')
plt.legend()
plt.show()
  1. 生成示例时间序列数据:我们生成一个包含200个数据点的时间序列,使用自回归参数 ar_params 和移动平均参数 ma_params
  2. 绘制原始时间序列数据:使用 matplotlib 绘制原始时间序列数据。
  3. 绘制ACF和PACF图:使用 statsmodels 库的 plot_acf 和 plot_pacf 函数绘制自相关函数 (ACF) 和偏自相关函数 (PACF) 图。
  4. 建立并拟合ARMA模型:使用 statsmodels 库中的 ARIMA 函数建立ARMA模型并进行拟合。
  5. 打印模型摘要:打印拟合结果的摘要,包含模型参数和统计信息。
  6. 绘制拟合后的时间序列和残差图:绘制原始时间序列与模型拟合值的对比图,以及模型残差图。

图片

4. 自回归积分滑动平均 (ARIMA, Autoregressive Integrated Moving Average Model)

ARIMA模型扩展了ARMA模型,适用于非平稳时间序列。

原理

模型通过对数据进行差分处理,使其平稳,然后再应用ARMA模型。

核心公式

其中:

  •  是滞后算子,
  •  是差分次数。

通过对原始序列  进行 d 次差分,使其变为平稳序列 ,然后对平稳序列应用ARMA模型进行参数估计。

核心案例

当然可以!下面是一个关于时间序列分析的案例,使用 ARIMA 模型来分析和预测数据。我们将使用 Python 的 pandasnumpymatplotlib 和 statsmodels 库来完成这项任务。具体案例为模拟一个经济数据的时间序列,例如股票价格或经济指标。

案例概述

创建一个模拟的时间序列数据,应用 ARIMA 模型进行建模和预测,并画出原始数据、ACF (自相关函数) 图和预测结果图。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 1. 创建模拟时间序列数据
np.random.seed(42)
n = 200
time = np.arange(n)
data = np.sin(0.1 * time)   0.5 * np.random.randn(n)

# 转换为 Pandas DataFrame
df = pd.DataFrame(data, columns=['Value'])
df.index = pd.date_range(start='2020-01-01', periods=n, freq='D')

# 2. 绘制原始时间序列图
plt.figure(figsize=(147))
plt.subplot(311)
plt.plot(df.index, df['Value'], label='Original Data')
plt.title('Original Time Series')
plt.xlabel('Date')
plt.ylabel('Value')
plt.legend()

# 3. 绘制自相关函数 (ACF) 和偏自相关函数 (PACF) 图
plt.subplot(312)
plot_acf(df['Value'], ax=plt.gca(), lags=30)
plt.title('ACF of Time Series')

plt.subplot(313)
plot_pacf(df['Value'], ax=plt.gca(), lags=30)
plt.title('PACF of Time Series')

plt.tight_layout()
plt.show()

# 4. 应用 ARIMA 模型
from statsmodels.tsa.arima.model import ARIMA

# 拟合 ARIMA 模型
model = ARIMA(df['Value'], order=(500))  # (p, d, q) 这里 d=0 是因为数据没有差分
model_fit = model.fit()

# 打印模型摘要
print(model_fit.summary())

# 5. 预测未来 20 个时间点
forecast = model_fit.forecast(steps=20)

# 创建预测数据的时间序列
forecast_index = pd.date_range(start=df.index[-1]   pd.Timedelta(days=1), periods=20, freq='D')
forecast_df = pd.DataFrame(forecast, index=forecast_index, columns=['Forecast'])

# 6. 绘制预测结果图
plt.figure(figsize=(147))
plt.plot(df.index, df['Value'], label='Original Data')
plt.plot(forecast_df.index, forecast_df['Forecast'], color='red', linestyle='--', label='Forecast')
plt.title('Forecast using ARIMA Model')
plt.xlabel('Date')
plt.ylabel('Value')
plt.legend()
plt.show()
  1. 数据生成: 使用正弦函数加上随机噪声生成模拟时间序列数据。
  2. 图形展示:
    • 原始时间序列图:展示生成的时间序列数据。
    • 自相关函数 (ACF) 图和偏自相关函数 (PACF) 图:用于确定 ARIMA 模型的参数。
  3. ARIMA 模型:
    • 使用 ARIMA 类来拟合模型并进行预测。
    • 打印模型摘要以查看拟合结果。
  4. 预测结果图: 展示 ARIMA 模型的预测结果与原始数据。

图片

5. 季节性自回归积分滑动平均 (SARIMA, Seasonal ARIMA)

SARIMA模型扩展了ARIMA模型,适用于季节性时间序列。

原理

模型结合了季节性自回归、季节性差分和季节性移动平均成分。

核心公式

其中:

  •  是季节周期,
  •  是季节差分次数。

将季节性成分加入到ARIMA模型中,结合季节性自回归、季节性差分和季节性移动平均,对模型进行参数估计。

核心案例

以下是一个关于月度航空乘客数量数据的案例分析,该数据集包含1949年1月到1960年12月之间的月度航空乘客数量。我们使用SARIMA模型对该数据进行建模,并绘制相关的图形进行数据分析。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.stattools import adfuller, acf, pacf

# 加载航空乘客数据集
file = 'airline-passengers.csv'
data = pd.read_csv(file, index_col='Month', parse_dates=True)
data.index.freq = 'MS'

# 绘制原始数据
plt.figure(figsize=(106))
plt.plot(data, label='Monthly Airline Passengers')
plt.title('Monthly Airline Passengers from 1949 to 1960')
plt.xlabel('Date')
plt.ylabel('Number of Passengers')
plt.legend()
plt.show()

# 进行ADF检验
adf_result = adfuller(data['Passengers'])
print(f'ADF Statistic: {adf_result[0]}')
print(f'p-value: {adf_result[1]}')

# 绘制ACF和PACF图
lag_acf = acf(data['Passengers'], nlags=40)
lag_pacf = pacf(data['Passengers'], nlags=40, method='ols')

plt.figure(figsize=(126))
plt.subplot(121)
plt.stem(range(len(lag_acf)), lag_acf, linefmt='b-', markerfmt='bo', basefmt='r-')
plt.axhline(y=0, linestyle='--', color='gray')
plt.axhline(y=-1.96/np.sqrt(len(data)), linestyle='--', color='gray')
plt.axhline(y=1.96/np.sqrt(len(data)), linestyle='--', color='gray')
plt.title('Autocorrelation Function')

plt.subplot(122)
plt.stem(range(len(lag_pacf)), lag_pacf, linefmt='b-', markerfmt='bo', basefmt='r-')
plt.axhline(y=0, linestyle='--', color='gray')
plt.axhline(y=-1.96/np.sqrt(len(data)), linestyle='--', color='gray')
plt.axhline(y=1.96/np.sqrt(len(data)), linestyle='--', color='gray')
plt.title('Partial Autocorrelation Function')
plt.tight_layout()
plt.show()

# 拟合SARIMA模型
model = SARIMAX(data['Passengers'], order=(111), seasonal_order=(11112))
results = model.fit()

# 打印模型总结
print(results.summary())

# 绘制预测结果
data['forecast'] = results.predict(start=120, end=144, dynamic=True)
plt.figure(figsize=(106))
plt.plot(data['Passengers'], label='Actual Passengers')
plt.plot(data['forecast'], label='Forecasted Passengers', color='red')
plt.title('Actual vs Forecasted Passengers')
plt.xlabel('Date')
plt.ylabel('Number of Passengers')
plt.legend()
plt.show()
  1. 加载并绘制月度航空乘客数据的原始数据图。
  2. 使用ADF检验检查数据的平稳性。
  3. 绘制自相关函数(ACF)和偏自相关函数(PACF)图,以帮助确定模型的阶数。
  4. 使用SARIMA模型拟合数据并打印模型总结。
  5. 绘制实际数据与预测数据的对比图。

图片

6. 向量自回归 (VAR, Vector Autoregression)

VAR模型是自回归模型的多变量扩展,适用于多变量时间序列。

原理

模型利用多个时间序列的历史数据进行联合预测。

核心公式

其中:

  •  是多变量时间序列向量,
  •  是系数矩阵。

对多变量时间序列进行线性回归,使用最小二乘法求解系数矩阵 

核心案例

使用美国经济时间序列数据集,该数据集包括了消费、收入和投资的月度数据。这个数据集可以在 statsmodels 库中找到。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.api import VAR

# 加载数据集
from statsmodels.datasets.macrodata import load_pandas
data = load_pandas().data

# 选择感兴趣的变量
df = data[['realgdp''realcons''realinv']]

# 设置时间索引
dates = pd.date_range(start='1959Q1', periods=len(df), freq='Q')
df.index = dates

# 绘制原始数据的时间序列图
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(108))
df.plot(subplots=True, ax=axes)
plt.tight_layout()
plt.show()

# 计算一阶差分
df_diff = df.diff().dropna()

# 绘制差分后的数据
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(108))
df_diff.plot(subplots=True, ax=axes)
plt.tight_layout()
plt.show()

# 构建并训练VAR模型
model = VAR(df_diff)
results = model.fit(maxlags=15, ic='aic')

# 打印模型摘要
print(results.summary())

# 绘制模型残差的时间序列图
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(108))
for i, column in enumerate(df_diff.columns):
    axes[i].plot(results.resid[:, i])
    axes[i].set_title(f'Residuals of {column}')
plt.tight_layout()
plt.show()

# 预测未来的时间序列
lag_order = results.k_ar
forecast = results.forecast(df_diff.values[-lag_order:], steps=10)
forecast_index = pd.date_range(start=df.index[-1], periods=10, freq='Q')
forecast_df = pd.DataFrame(forecast, index=forecast_index, columns=df.columns)

# 绘制预测结果
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(108))
for i, column in enumerate(df.columns):
    axes[i].plot(df.index, df[column], label='Original')
    axes[i].plot(forecast_df.index, forecast_df[column], label='Forecast')
    axes[i].set_title(f'{column} - Original vs Forecast')
    axes[i].legend()
plt.tight_layout()
plt.show()
  1. 加载了包含美国经济数据的宏观经济数据集。
  2. 选择了实际GDP、实际消费和实际投资作为分析变量。
  3. 绘制了原始数据和一阶差分后的数据的时间序列图。
  4. 构建并训练了VAR模型,并打印了模型摘要。
  5. 绘制了模型残差的时间序列图。
  6. 预测了未来10个季度的时间序列,并绘制了预测结果与原始数据的对比图。

图片

    7. 向量自回归滑动平均 (VARMA, Vector Autoregressive Moving Average)

VARMA模型结合了向量自回归和移动平均模型。

原理

模型利用多个时间序列的历史数据和误差进行联合预测。

核心公式

其中:

  •  是误差系数矩阵。

结合VAR模型和MA模型的推导方法,对两个模型的参数进行联合估计。

核心案例

时间序列分析中的向量自回归滑动平均(VARMA)模型通常用于分析多个相关联的时间序列变量之间的动态关系。

假设我们有两个变量,分别是销售量和广告支出,我们想分析它们之间的动态关系。我们将构建一个VARMA(1,1)模型来说明。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.statespace.varmax import VARMAX
from statsmodels.tsa.vector_ar.var_model import VAR

# 生成模拟数据
np.random.seed(42)
n_obs = 100
sales = np.random.normal(loc=100, scale=15, size=n_obs)
advertising = np.random.normal(loc=50, scale=10, size=n_obs)

# 创建DataFrame
data = pd.DataFrame({'Sales': sales, 'Advertising': advertising})

# 拆分数据为训练集和测试集
train = data.iloc[:80]
test = data.iloc[80:]

# 拟合VARMA模型
model = VARMAX(train, order=(11))
results = model.fit(maxiter=1000, disp=False)
print(results.summary())

# 预测未来值
forecast = results.forecast(steps=len(test))

# 绘制销售量和广告支出的时间序列及预测结果
plt.figure(figsize=(147))

plt.subplot(211)
plt.plot(train['Sales'], label='Actual Sales (Train)')
plt.plot(test.index, forecast['Sales'], label='Forecasted Sales')
plt.title('Sales Forecast using VARMA(1,1)')
plt.legend()

plt.subplot(212)
plt.plot(train['Advertising'], label='Actual Advertising (Train)')
plt.plot(test.index, forecast['Advertising'], label='Forecasted Advertising')
plt.title('Advertising Forecast using VARMA(1,1)')
plt.legend()

plt.tight_layout()
plt.show()
  1. 我们首先生成了模拟数据,模拟了销售量和广告支出的时间序列。
  2. 将数据分为训练集和测试集。
  3. 使用VARMAX模型拟合了VARMA(1,1)模型。
  4. 对测试集进行预测,并绘制了销售量和广告支出的实际数据以及预测结果的时间序列图。

图片

8. 长短期记忆网络 (LSTM, Long Short-Term Memory)

LSTM是一种特殊的递归神经网络(RNN),适用于捕捉长时间依赖关系。

原理

LSTM通过引入记忆单元和门控机制,有效解决了RNN的梯度消失问题。

核心公式

LSTM通过记忆单元  和三个门控单元(遗忘门 ,输入门  和输出门 )进行信息控制。推导过程可以通过反向传播算法进行参数优化。

核心案例

使用Keras来构建和训练LSTM模型,并使用Matplotlib来绘制数据分析图形。我们使用一个简单的模拟时间序列数据来演示LSTM模型的应用。该数据代表某种时间序列,例如每日温度变化。

import numpy as np
import matplotlib.pyplot as plt

# 生成模拟时间序列数据
np.random.seed(0)
time_steps = 100
data = np.sin(np.linspace(010 * np.pi, time_steps))   np.random.normal(00.5, time_steps)

# 绘制原始数据
plt.figure(figsize=(146))
plt.plot(data, label='Original Data')
plt.title('Simulated Time Series Data')
plt.xlabel('Time Step')
plt.ylabel('Value')
plt.legend()
plt.show()

# 构建LSTM模型
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

# 准备训练数据
def create_dataset(data, look_back=1):
    X, y = [], []
    for i in range(len(data) - look_back):
        X.append(data[i:(i   look_back)])
        y.append(data[i   look_back])
    return np.array(X), np.array(y)

look_back = 3
X, y = create_dataset(data, look_back)
X = X.reshape(X.shape[0], X.shape[1], 1)  # LSTM 需要 3D 输入

# 构建 LSTM 模型
model = Sequential()
model.add(LSTM(50, input_shape=(look_back, 1)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

# 训练模型
model.fit(X, y, epochs=100, batch_size=1, verbose=2)

# 预测并绘制结果
train_predict = model.predict(X)
train_predict_plot = np.empty_like(data)
train_predict_plot[:] = np.nan
train_predict_plot[look_back:len(train_predict)   look_back] = train_predict.flatten()

# 绘制原始数据与预测数据对比图
plt.figure(figsize=(146))
plt.plot(data, label='Original Data')
plt.plot(train_predict_plot, label='LSTM Prediction')
plt.title('LSTM Prediction vs Original Data')
plt.xlabel('Time Step')
plt.ylabel('Value')
plt.legend()
plt.show()

# 绘制损失函数变化图
history = model.history
loss = history.history['loss']

plt.figure(figsize=(146))
plt.plot(loss, label='Training Loss')
plt.title('Model Training Loss Over Epochs')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

两个数据分析图形:一个是原始数据与LSTM预测数据的对比图,另一个是训练过程中损失函数的变化图。

图片

9. Prophet

Prophet是由Facebook开发的时间序列预测工具,适用于包含节假日效应、趋势变化和周期性变化的数据。

原理

模型将时间序列分解为趋势、季节性和节假日效应部分。

核心公式

其中:

  •  表示趋势部分,
  •  表示季节性部分,
  •  表示节假日效应。

通过对各部分进行独立建模和参数估计,最终结合各部分得到预测结果。

核心案例

下面是一个使用 Facebook 的 Prophet 库进行时间序列分析的案例。在这个案例中,我们将使用 Prophet 对一个时间序列进行建模和预测,并绘制多个图形来展示数据分析的结果。

我们将使用一个示例数据集,该数据集包含了某网站每日的访问量。我们将进行以下步骤:

  1. 导入数据并预处理。
  2. 使用 Prophet 进行建模和预测。
  3. 绘制原始数据及预测结果。
  4. 绘制预测中的趋势和季节性成分。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from prophet import Prophet

# 生成示例数据
dates = pd.date_range(start='2020-01-01', periods=730, freq='D')
data = np.random.poisson(lam=200, size=730)   np.linspace(0100730)
df = pd.DataFrame({'ds': dates, 'y': data})

# 初始化并训练Prophet模型
model = Prophet(yearly_seasonality=True, daily_seasonality=False)
model.fit(df)

# 创建未来的数据框架并进行预测
future = model.make_future_dataframe(periods=365)
forecast = model.predict(future)

# 绘制原始数据及预测结果
fig1 = model.plot(forecast)
plt.title('Original Data and Forecast')
plt.xlabel('Date')
plt.ylabel('Website Traffic')

# 绘制趋势和季节性成分
fig2 = model.plot_components(forecast)
plt.show()

# 绘制实际数据与预测值的对比
plt.figure(figsize=(106))
plt.plot(df['ds'], df['y'], label='Actual')
plt.plot(forecast['ds'], forecast['yhat'], label='Forecast', linestyle='--')
plt.fill_between(forecast['ds'], forecast['yhat_lower'], forecast['yhat_upper'], color='gray', alpha=0.2)
plt.title('Actual vs Forecast')
plt.xlabel('Date')
plt.ylabel('Website Traffic')
plt.legend()
plt.show()

# 绘制残差图
residuals = df['y'] - forecast['yhat'][:len(df)]
plt.figure(figsize=(106))
plt.plot(df['ds'], residuals)
plt.axhline(0, linestyle='--', color='red')
plt.title('Residuals')
plt.xlabel('Date')
plt.ylabel('Residual')
plt.show()
  1. 数据生成和预处理:使用 pandas 生成了从 2020 年 1 月 1 日开始的 730 天的日期范围。生成了一个示例数据集,模拟了网站的每日访问量。

  2. 模型训练:初始化 Prophet 模型,并设置年度季节性为真,每日季节性为假。使用示例数据集训练模型。

  3. 预测:创建一个包含未来 365 天的日期的数据框架,并使用训练好的模型进行预测。绘制原始数据及预测结果图,展示了实际数据与预测值的对比。

  4. 趋势和季节性成分:绘制趋势和季节性成分图,展示了预测中的长期趋势和季节性波动。

  5. 实际数据与预测值的对比:将实际数据与预测值进行对比,展示了预测模型的拟合效果。

  6. 残差图:计算残差(实际值减去预测值),并绘制残差图,展示了模型的预测误差。

图片

图片

10. 变分自编码器 (VAE, Variational Autoencoders)

VAE是一种生成模型,适用于捕捉复杂时间序列数据的潜在结构。

原理

VAE通过变分推断,将复杂的时间序列数据映射到潜在空间,然后再从潜在空间重构数据。

核心公式

VAE使用变分推断的方法,最大化对数似然函数:

其中:

  •  是Kullback-Leibler散度。

VAE通过神经网络来参数化  和 ,使用反向传播算法进行优化。

这些方法各自有其适用的场景和优缺点,选择合适的方法取决于具体的数据特征和分析需求。

核心案例

这里,是一个使用变分自编码器(VAE)进行时间序列分析的案例:

  1. 生成正弦波时间序列数据。
  2. 构建和训练变分自编码器(VAE)。
  3. 使用VAE对时间序列数据进行编码和解码。
  4. 绘制原始时间序列与重构时间序列的对比图。
  5. 绘制VAE潜在空间的可视化图。
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset

# 生成正弦波时间序列数据
def generate_sine_wave(seq_length, num_samples):
    x = np.linspace(0, np.pi * 2 * num_samples, seq_length * num_samples)
    y = np.sin(x)
    data = y.reshape(num_samples, seq_length, 1)
    return data

seq_length = 50
num_samples = 1000
data = generate_sine_wave(seq_length, num_samples)

# 数据集类
class TimeSeriesDataset(Dataset):
    def __init__(self, data):
        self.data = torch.tensor(data, dtype=torch.float32)
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, idx):
        return self.data[idx]

dataset = TimeSeriesDataset(data)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# 定义VAE模型:
class VAE(nn.Module):
    def __init__(self, input_dim, hidden_dim, latent_dim):
        super(VAE, self).__init__()
        # 编码器
        self.encoder = nn.Sequential(
            nn.Linear(input_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, latent_dim * 2)  # 输出mean和logvar
        )
        # 解码器
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, input_dim),
            nn.Sigmoid()
        )

    def reparameterize(self, mean, logvar):
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return mean   eps * std

    def forward(self, x):
        x = x.view(x.size(0), -1)
        mean_logvar = self.encoder(x)
        mean, logvar = mean_logvar[:, :latent_dim], mean_logvar[:, latent_dim:]
        z = self.reparameterize(mean, logvar)
        x_recon = self.decoder(z)
        return x_recon, mean, logvar

# 训练VAE模型:
input_dim = seq_length
hidden_dim = 128
latent_dim = 16
num_epochs = 50
learning_rate = 0.001

vae = VAE(input_dim, hidden_dim, latent_dim)
optimizer = optim.Adam(vae.parameters(), lr=learning_rate)
criterion = nn.MSELoss()

def loss_function(recon_x, x, mean, logvar):
    recon_loss = criterion(recon_x, x)
    kld_loss = -0.5 * torch.sum(1   logvar - mean.pow(2) - logvar.exp())
    return recon_loss   kld_loss

for epoch in range(num_epochs):
    vae.train()
    train_loss = 0
    for batch in dataloader:
        optimizer.zero_grad()
        recon_batch, mean, logvar = vae(batch)
        loss = loss_function(recon_batch, batch.view(-1, input_dim), mean, logvar)
        loss.backward()
        train_loss  = loss.item()
        optimizer.step()
    print(f'Epoch {epoch 1}, Loss: {train_loss / len(dataloader.dataset)}')

# 绘制原始时间序列与重构时间序列的对比图
vae.eval()
with torch.no_grad():
    for batch in dataloader:
        recon_batch, mean, logvar = vae(batch)
        break

recon_batch = recon_batch.view(-1, seq_length).numpy()
original_batch = batch.numpy()

plt.figure(figsize=(126))
plt.plot(original_batch[0], label='Original')
plt.plot(recon_batch[0], label='Reconstructed')
plt.legend()
plt.title('Original vs Reconstructed Time Series')
plt.show()


# 绘制VAE潜在空间的可视化图
latent_vectors = []
vae.eval()
with torch.no_grad():
    for batch in dataloader:
        _, mean, _ = vae(batch)
        latent_vectors.append(mean.numpy())

latent_vectors = np.concatenate(latent_vectors, axis=0)

plt.figure(figsize=(108))
plt.scatter(latent_vectors[:, 0], latent_vectors[:, 1], alpha=0.5)
plt.title('Latent Space Visualization')
plt.xlabel('Latent Dimension 1')
plt.ylabel('Latent Dimension 2')
plt.show()

图片

最后

以上就是今天所有的内容了。
如果对你来说比较有用,记得点赞、收藏,慢慢学习~
下期会有更多干货等着你!~

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多