当前位置: 首页 > news >正文

【机器学习实战中阶】使用SARIMAX,ARIMA预测比特币价格,时间序列预测

在这里插入图片描述

数据集说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
比特币价格预测(轻量级CSV)关于数据集
致谢
这些数据来自CoinMarketCap,并且可以免费使用该数据。
https://coinmarketcap.com/ 数据集:链接: 价格预测器 源代码与数据集

算法说明

SARIMAX(Seasonal AutoRegressive Integrated Moving Average with eXogenous regressors)和 ARIMA(AutoRegressive Integrated Moving Average)都是用于时间序列分析和预测的强大工具,但它们之间存在一些关键区别。这些差异主要体现在模型的灵活性、处理季节性和外生变量的能力上。

1. 季节性成分

  • ARIMA:适用于非季节性的数据,即没有明显周期模式的时间序列。它通过自回归(AR)、差分(I)和移动平均(MA)三个部分来捕捉时间序列中的趋势和平稳性特征。

  • SARIMAX:是ARIMA模型的一种扩展,特别设计用来处理具有季节性模式的数据。除了包含ARIMA的所有组件外,SARIMAX还增加了额外的参数来描述季节性影响,如季节性自回归(SAR)、季节性差分(SI)和季节性移动平均(SMA)。因此,SARIMAX可以更好地捕捉时间序列中的长期周期波动。

2. 外生变量的支持

  • ARIMA:传统上的ARIMA模型仅依赖于时间序列本身的历史值来进行预测,不直接支持外部变量的影响。

  • SARIMAX:允许引入外生变量(exogenous variables),即那些可能影响目标时间序列但不属于该序列内部结构的因素。例如,在预测销售量时,节假日、促销活动等外部因素可以通过外生变量的形式加入到模型中,以提高预测精度。

3. 数学表示

  • ARIMA(p, d, q):其中(p)代表自回归项的阶数,(d)代表差分阶数,(q)代表移动平均项的阶数。

  • SARIMAX(p, d, q) × (P, D, Q)_m:这里不仅包含了非季节性的(p), (d), (q)参数,还有额外的季节性参数(P)(季节性自回归阶数)、(D)(季节性差分阶数)、(Q)(季节性移动平均阶数),以及(m)为季节周期长度。

4. 应用场景

  • ARIMA:适合用于没有明显季节性的平稳或经过适当变换后变得平稳的时间序列数据。

  • SARIMAX:更适合那些展示出显著季节性和/或受其他外部因素影响较大的时间序列数据。比如,零售业销售额通常会显示出明显的月度或年度季节性变化,而天气条件、经济指标等外部因素也可能对销售产生重要影响。

综上所述,选择使用ARIMA还是SARIMAX取决于您的具体需求和数据特性。如果您的时间序列包含明显的季节性并且您有可用的外生变量信息,那么SARIMAX可能是更好的选择;否则,对于简单的非季节性数据,ARIMA已经足够强大且易于实现。

接下来我们从详细代码方案开始

# 这个 Python 3 环境附带了许多有用的分析库
# 它是由 kaggle/python 容器镜像定义的:https://github.com/kaggle/docker-python
# 例如,这里有几个有用的数据包可以加载
import numpy as np  # 线性代数库
import pandas as pd  # 数据处理库,用于处理 CSV 文件的输入输出(如:pd.read_csv)
import seaborn; seaborn.set()  # seaborn 是一个基于 matplotlib 的数据可视化库,这里通过 seaborn.set() 来设置默认的绘图风格
from sklearn.metrics import mean_squared_error  # 用于计算平均平方误差,一种常见的评估回归预测模型的方式
# 输入数据文件位于 "../input/" 目录下。
# 例如,运行此代码(通过点击运行或按下 Shift+Enter)将列出输入目录中的文件# 任何你写入当前目录的结果都会作为输出保存。
import matplotlib.pylab as plt  # 导入 matplotlib 的子模块 pyplab(pylab),用于绘制图像
%matplotlib inline  # 魔法命令,使图表内嵌在 jupyter notebook 中
from matplotlib.pylab import rcParams  # 从 pyplab 中导入 rcParams,用于设置图表的参数
rcParams['figure.figsize'] = 15, 6  # 设置图表的默认尺寸为宽度15英寸,高度6英寸
from statsmodels.tsa.stattools import adfuller  # 引入 adfuller 模块,用于进行时间序列平稳性检验
from statsmodels.tsa.seasonal import seasonal_decompose  # 引入 seasonal_decompose 模块,用于对时间序列数据进行分解
from statsmodels.tsa.stattools import acf, pacf  # 引入 acf 和 pacf 模块,用于计算时间序列的自相关和偏自相关函数
from statsmodels.tsa.arima_model import ARIMA  # 引入 ARIMA 模型,用于时间序列数据的预测

加载数据并研究行和列的值

# 加载 bitcoin_price_Training - Training.csv 文件,作为一个包含时间序列数据的 DataFrame 对象
data = pd.read_csv("../input/bitcoin_price_Training - Training.csv")
# 打印数据表的前五行,以查看数据格式
print(data.head(5))
# 打印数据表的最后五行,以查看最近的数据
print(data.tail(5))
# 查看每一列的数据类型
data.dtypes
# 获取数据表的信息,包括行数、列数、列名、数据类型等
data.info()
# 生成数据表的描述统计信息,如计数、均值、最小值、最大值等
data.describe()# 重新加载数据,设置日期列为索引
data = pd.read_csv("../input/bitcoin_price_Training - Training.csv", index_col='Date')
# 再次打印前五行,检查日期是否正确设置为索引
print(data.head(5))# 检查数据表的信息,确认索引列已正确设置
data.info()
# 将索引从字符串格式转化为日期时间格式
data.index = pd.to_datetime(data.index)
# 打印索引,确认转换成功
print(data.index)
# 再次打印数据表的前五行,查看转换后的数据
data.head(5)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

将数据集按时间顺序排序,从最旧到最近

# 将数据按索引排序,从最旧的数据到最近的数据
data = data.sort_index()
# 打印排序后的前五行数据,确认排序成功
data.head()

在这里插入图片描述

绘制比特币收盘价的折线图

# 绘制比特币每日收盘价的折线图
data['Close'].plot()
# 设置 y 轴标签为"每日比特币价格"
plt.ylabel("每日比特币价格")

在这里插入图片描述

为了建立模型,我将侧重于预测比特币的收盘价,因此创建一个新的对象,排除其他列

# 从数据中提取收盘价列,创建一个新的 Series 对象
data = data['Close']
# 将原始数据按周重采样并累计,创建周比特币价格数据
weekly = data.resample('W').sum()
# 绘制比特币每周价格的折线图
weekly.plot()# 设置 y 轴标签为"周比特币价格"
plt.ylabel('周比特币价格')

在这里插入图片描述

按年份统计并绘制比特币平均收盘价格

# 通过数据中的日期索引按年份进行分组,并计算每年的均值
by_year = data.groupby(data.index.year).mean()
# 绘制按年份分组的比特币平均收盘价折线图
by_year.plot()

在这里插入图片描述

按星期几统计并绘制比特币平均收盘价格

# 通过数据中的日期索引按星期几进行分组,这里是累加每个星期几的所有数据
by_weekday = data.groupby(data.index.dayofweek).sum()
# 将原始 0-6 的数字索引替换为对应的星期几名称
by_weekday.index = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
# 绘制按星期几分组的比特币价格累加图
by_weekday.plot()

在这里插入图片描述

# 通过数据中的日期索引按星期几进行分组,这一次是计算每个星期几的收盘价平均值
by_weekday = data.groupby(data.index.dayofweek).mean()
# 再次替换数字索引为星期几名称
by_weekday.index = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
# 绘制按星期几分组的比特币平均收盘价折线图
by_weekday.plot()

在这里插入图片描述

按年内第几天统计并绘制比特币平均收盘价格

# 通过数据中的日期索引按年内第几天进行分组,并计算每一天的均值
by_day = data.groupby(data.index.dayofyear).mean()
# 绘制按日内第几天分组的比特币平均收盘价折线图
by_day.plot()

在这里插入图片描述

按月份统计并绘制比特币平均收盘价格

# 通过数据中的日期索引按月份进行分组,并计算每个月份的均值
by_month = data.groupby(data.index.month).mean()
# 绘制按月份分组的比特币平均收盘价折线图
by_month.plot()

在这里插入图片描述

按季度统计并绘制比特币平均收盘价格

# 通过数据中的日期索引按季度进行分组,并计算每个季度的均值
by_quarter = data.groupby(data.index.quarter).mean()
# 绘制按季度分组的比特币平均收盘价折线图
by_quarter.plot()

在这里插入图片描述

按季度再次分组绘制,这次仅为了展示分组操作

# 通过数据中的日期索引按季度进行分组
by_quarter = data.groupby(data.index.quarter)
# 这次我们只调用 plot 方法,不计算平均值,用于展示不同季度的数据分布
by_quarter.plot()

在这里插入图片描述

绘制按季度统计的比特币平均收盘价格,以及年度的对比图

# 计算每个季度的数据平均值
by_quarter_overall = data.groupby(data.index.quarter).mean()
# 绘制季度的比特币平均收盘价折线图
by_quarter_overall.plot()

在这里插入图片描述

按工作日与周末统计并绘制比特币平均收盘价格

# 使用 numpy 的 np.where 函数识别交易日为工作日(1-5)或周末(5-0)
weekend = np.where(data.index.weekday < 5, 'Weekday', 'Weekend')
# 将数据按工作日周末及年份分组,计算每组的平均收盘价
by_time = data.groupby([weekend, data.index.year]).mean()
# 创建一个包含1行2列的子图,用于同时展示工作日和周末的价格对比
fig, ax = plt.subplots(1, 2, figsize=(14, 5))
# 绘制工作日的平均收盘价格
by_time.loc['Weekday'].plot(ax=ax[0], title='工作日')
# 绘制周末的平均收盘价格
by_time.loc['Weekend'].plot(ax=ax[1], title='周末')

在这里插入图片描述

最后,绘制比特币的价格时间序列图

# 将数据赋值给 ts
ts = data
# 绘制比特币价格的时间序列图
plt.plot(ts)

在这里插入图片描述

以上代码主要用于加载比特币的历史价格数据,对数据进行预处理、转换、排序,并按不同的时间单位(如周、月、季及工作日与周末)对价格数据进行分组统计,最终绘制出这些统计结果的折线图。这有助于分析比特币价格随时间的变化趋势及其季节性特征。

继续干

这一部分内容的灵感来源于:https://www.analyticsvidhya.com/blog/2016/02/time-series-forecasting-codes-python/

from statsmodels.tsa.stattools import adfuller
def test_for_stationary(input_data):r_mean = input_data.rolling(window = 7, center=False).mean()  # 计算7日移动平均值,中心设为Falser_std = input_data.rolling(window = 7, center=False).std()   # 计算7日移动标准差,中心设为False# 绘制数据given = plt.plot(input_data, color='blue', label='原始时间序列')rolling_mean = plt.plot(r_mean, color='red', label='7日移动平均')rolling_std = plt.plot(r_std, color='green', label='7日移动标准差')plt.legend(loc='best')plt.title('7日移动平均与标准差')plt.show(block=False)  # 显示图表# 执行Dickey-Fuller检验print('Dickey-Fuller检验结果:')dftest = adfuller(input_data)dfoutput = pd.Series(dftest[0:4], index=['检验统计量', 'p值', '使用滞后数量', '使用观察数量'])for key, value in dftest[4].items():dfoutput['临界值 (%s)'%key] = value  # 添加临界值到输出中print(dfoutput)test_for_stationary(ts)

在这里插入图片描述

总结:
这段代码定义了一个名为test_for_stationary的函数,用于检查时间序列的平稳性。函数首先计算了7日移动平均值和7日移动标准差,并绘制了这两个指标与原始时间序列的图表,以便于直观地观察时间序列的平稳性。接着,代码执行了Dickey-Fuller检验,该检验是为了确定时间序列是否有单位根,从而判断其是否平稳。检验结果包括检验统计量、p值、使用的滞后数量、使用的观察数量以及不同显著性水平下的临界值。最后,函数调用test_for_stationary(ts)对时间序列ts进行了检验。


消除趋势的数据转换

ts_logtransformed = np.log(ts)  # 对时间序列进行对数转换,消除趋势
plt.plot(ts_logtransformed)  # 绘制对数转换后的时间序列图表

在这里插入图片描述

总结:
这段代码对时间序列ts进行了对数转换,目的是消除时间序列中的趋势成分。对数转换后的结果被绘制出来,以便于观察转换效果。

ts_logtransformed.head(10)  # 查看转换后的时间序列的前10行数据Rolling_average = ts_logtransformed.rolling(window = 7, center=False).mean()  # 计算对数转换后的时间序列的7日移动平均值
plt.plot(ts_logtransformed, label='对数转换后的序列')
plt.plot(Rolling_average, color='red', label='7日移动平均')
plt.legend(loc='best')
plt.title('7日移动平均')
plt.show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Rolling_average.head(10)

在这里插入图片描述
总结:
这段代码计算了对数转换后的时间序列的7日移动平均值,并绘制了原对数转换序列和7日移动平均值的图表,用以观察去除趋势的效果。

log_Rolling_difference = ts_logtransformed - Rolling_average  # 对数转换后的序列减去7日移动平均值
log_Rolling_difference.head(10)  # 查看差分后的前10行数据
log_Rolling_difference.tail(10)  # 查看差分后的后10行数据# 用0替换上述数据框中的NAN,以避免将来出现错误
log_Rolling_difference.dropna(inplace=True)
plt.plot(log_Rolling_difference)test_for_stationary(log_Rolling_difference)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:
这段代码对对数转换后的时间序列进行了7日移动平均值的差分,通过减去7日移动平均值来进一步去除趋势。差分后的结果被绘制出,并检查了其平稳性。差分后的序列应该更加接近平稳性。


使用指数加权移动平均值来改进解决方案

expwighted_avg = ts_logtransformed.ewm(halflife=7, min_periods=0, adjust=True, ignore_na=False).mean()  # 计算指数加权移动平均值,半衰期设为7天
plt.plot(ts_logtransformed, label='对数转换后的序列')
plt.plot(expwighted_avg, color='red', label='指数加权移动平均值')
plt.legend(loc='best')
plt.title('指数加权移动平均值')
plt.show()

在这里插入图片描述

总结:
这段代码计算了对数转换后的时间序列的指数加权移动平均值,半衰期设为7天。指数加权移动平均值可以更加灵活地捕捉时间序列的变化,因为它对较近的数据点赋予了更高的权重。绘制了原对数转换序列和指数加权移动平均值的图表,用以观察去除趋势的效果。

expwighted_avg.head(10)  # 查看指数加权移动平均值的前10行数据log_expmovwt_diff = ts_logtransformed - expwighted_avg  # 对数转换后的序列减去指数加权移动平均值test_for_stationary(log_expmovwt_diff)

在这里插入图片描述
在这里插入图片描述

总结:
这段代码通过减去指数加权移动平均值来进一步去除对数转换后的时间序列中的趋势。差分后的结果被绘制出,并检查了其平稳性。差分后的序列应该更加接近平稳性。


现在时间序列已经平稳,DS(检验统计量)值小于1%的临界值。由于权重是从起始索引分配的,因此检验结果有效。


消除趋势和季节性的其他方法

这里我将实现差分和分解方法来消除趋势和季节性。

# 绘制对数转换后的时间序列
ts_logtransformed.plot()

在这里插入图片描述

总结:
这段代码绘制了对数转换后的时间序列,用以观察时间序列的变化趋势和季节性成分。


通过差分消除季节性

时间序列中的季节性成分可以通过差分来消除。如果存在一个月的季节性成分,那么可以通过从当前值中减去上一个月的值来消除。例如,10月1日的值减去9月1日的值,10月2日的值减去9月2日的值,以此类推。差分后的序列将不包含第一个月的数据,因为第一个月的数据无法进行差分。

# 尝试不同的季节性差分,并测试平稳性数据
ts_diff_logtrans = ts_logtransformed - ts_logtransformed.shift(7)  # 通过7天差分来消除季节性
plt.plot(ts_diff_logtrans)
ts_diff_logtrans.head(10)ts_diff_logtrans.dropna(inplace=True)  # 删除缺失值
test_for_stationary(ts_diff_logtrans)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:
这段代码通过对数转换后的时间序列进行了7天的差分,以消除季节性成分。差分后的序列被绘制出,并检查了其平稳性。差分后的序列应该更加接近平稳性。


通过分解消除趋势和季节性

decomposition = seasonal_decompose(ts_logtransformed)  # 对时间序列进行季节性分解trend = decomposition.trend  # 提取趋势成分
seasonal = decomposition.seasonal  # 提取季节性成分
residual = decomposition.resid  # 提取残差成分plt.subplot(411)
plt.plot(ts_logtransformed, label='原序列')
plt.legend(loc='best')
plt.subplot(412)
plt.plot(trend, label='趋势')
plt.legend(loc='best')
plt.subplot(413)
plt.plot(seasonal, label='季节性')
plt.legend(loc='best')
plt.subplot(414)
plt.plot(residual, label='残差')
plt.legend(loc='best')
plt.tight_layout()  # 调整子图布局
plt.show()

在这里插入图片描述

总结:
这段代码通过seasonal_decompose函数对对数转换后的时间序列进行了季节性分解,提取了趋势成分、季节性成分和残差成分。分解后的成分分别被绘制在四个子图中,以便于观察时间序列的不同成分。最后,对残差成分进行了平稳性检验。

decomposed_TS = residual  # 将残差成分作为分解后的时间序列
decomposed_TS.dropna(inplace=True)  # 删除缺失值
test_for_stationary(decomposed_TS)  # 检查残差成分的平稳性

在这里插入图片描述


预测

# ACF和PACF图
lag_acf = acf(ts_diff_logtrans, nlags=30)  # 计算自相关函数(ACF),滞后30期
lag_pacf = pacf(ts_diff_logtrans, nlags=50, method='ols')  # 计算偏自相关函数(PACF),滞后50期,使用普通最小二乘法# 绘制ACF图
plt.subplot(121)
plt.plot(lag_acf)
plt.axhline(y=0, linestyle='--', color='gray')  # 绘制0线
plt.axhline(y=-1.96/np.sqrt(len(ts_diff_logtrans)), linestyle='--', color='gray')  # 绘制下置信区间线
plt.axhline(y=1.96/np.sqrt(len(ts_diff_logtrans)), linestyle='--', color='gray')  # 绘制上置信区间线
plt.title('自相关函数')# 绘制PACF图
plt.subplot(122)
plt.plot(lag_pacf)
plt.axhline(y=0, linestyle='--', color='gray')  # 绘制0线
plt.axhline(y=-1.96/np.sqrt(len(ts_diff_logtrans)), linestyle='--', color='gray')  # 绘制下置信区间线
plt.axhline(y=1.96/np.sqrt(len(ts_diff_logtrans)), linestyle='--', color='gray')  # 绘制上置信区间线
plt.title('偏自相关函数')
plt.tight_layout()  # 调整子图布局
plt.show()from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
from matplotlib import pyplot
pyplot.figure()
pyplot.subplot(211)
plot_acf(ts_diff_logtrans, ax=pyplot.gca(),lags=40)
pyplot.subplot(212)
plot_pacf(ts_diff_logtrans, ax=pyplot.gca(), lags=50)
pyplot.show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:
这段代码计算并绘制了时间序列ts_diff_logtrans的自相关函数(ACF)和偏自相关函数(PACF)图。ACF图用于确定移动平均(MA)参数q,而PACF图用于确定自回归(AR)参数p。图表中的虚线表示置信区间,可以用来判断哪些滞后值显著。

从图表中的一些观察结果

在这个图表中,两侧的虚线表示置信区间。这些虚线可以用来确定自回归(AR)和移动平均(MA)参数pq

  • p值是PACF图中首次超过上置信区间的滞后值。在这个例子中,p=2,PACF在第2天显示了一个显著的滞后值。
  • q值是ACF图中首次超过上置信区间的滞后值。在这个例子中,q=18,ACF在第18天显示了一个显著的滞后值。

PACF在第7天、第8天、第12天、第15天等处可能也有一些显著的滞后值,这表明差分后的数据中仍然存在一些季节性成分。我们可以通过尝试不同的ARIMA模型来识别最佳模型,通过计算每个模型的残差平方和(RSS)来比较模型的性能。RSS值越低,模型的拟合效果越好。

# 从 statsmodels.tsa.arima.model 导入 ARIMA
from statsmodels.tsa.statespace.sarimax import SARIMAX as ARIMAts_diff_logtrans = ts_diff_logtrans.fillna(0)  # 用0填充缺失值,避免将来出现错误# 构建和拟合ARIMA模型 (p=8, d=1, q=0)
model = ARIMA(ts_logtransformed, order=(8, 1, 0))  
results_AR = model.fit(disp=-1)  # 拟合模型,disp=-1表示不显示迭代过程
plt.plot(ts_diff_logtrans)  # 绘制差分后的序列
plt.plot(results_AR.fittedvalues, color='red', label='模型拟合值 (p=8)')  # 绘制模型拟合值
RSS = results_AR.fittedvalues - ts_diff_logtrans  # 计算残差
RSS.dropna(inplace=True)  # 删除缺失值
plt.title('RSS: %.4f' % sum(RSS**2))  # 设置图表标题,显示RSS值
plt.legend(loc='best')  # 设置图例位置
plt.show()  # 显示图表# 构建和拟合ARIMA模型 (p=2, d=1, q=0)
model = ARIMA(ts_logtransformed, order=(2, 1, 0))  
results_AR = model.fit(disp=-1)  # 拟合模型,disp=-1表示不显示迭代过程
plt.plot(ts_diff_logtrans)  # 绘制差分后的序列
plt.plot(results_AR.fittedvalues, color='red', label='模型拟合值 (p=2)')  # 绘制模型拟合值
RSS = results_AR.fittedvalues - ts_diff_logtrans  # 计算残差
RSS.dropna(inplace=True)  # 删除缺失值
plt.title('RSS: %.4f' % sum(RSS**2))  # 设置图表标题,显示RSS值
plt.legend(loc='best')  # 设置图例位置
plt.show()  # 显示图表# 打印模型摘要
print(results_AR.summary())

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:
这段代码构建并拟合了两个ARIMA模型,一个是p=8, d=1, q=0,另一个是p=2, d=1, q=0。每个模型的拟合值和残差都被绘制出来,并计算了残差平方和(RSS)。RSS值越低,模型的拟合效果越好。最后,打印了模型的摘要信息,包括模型参数和统计检验结果。

# 构建和拟合ARIMA模型 (p=0, d=1, q=18)
model = ARIMA(ts_logtransformed, order=(0, 1, 18))  
results_MA = model.fit(disp=-1)  # 拟合模型,disp=-1表示不显示迭代过程
plt.plot(ts_diff_logtrans)  # 绘制差分后的序列
plt.plot(results_MA.fittedvalues, color='red', label='模型拟合值 (q=18)')  # 绘制模型拟合值
RSS = results_MA.fittedvalues - ts_diff_logtrans  # 计算残差
RSS.dropna(inplace=True)  # 删除缺失值
plt.title('RSS: %.4f' % sum(RSS**2))  # 设置图表标题,显示RSS值
plt.show()  # 显示图表# 打印模型摘要
print(results_MA.summary())

在这里插入图片描述
在这里插入图片描述

总结:
这段代码构建并拟合了一个ARIMA模型,参数为p=0, d=1, q=18。模型的拟合值和残差被绘制出来,并计算了残差平方和(RSS)。RSS值越低,模型的拟合效果越好。最后,打印了模型的摘要信息,包括模型参数和统计检验结果。

# 绘制对数转换后的时间序列和模型残差
plt.plot(ts_logtransformed, label='log_tranfromed_data')
plt.plot(results_MA.resid, color='green', label='Residuals')
plt.title('MA Model Residual plot')
plt.legend(loc='best')
plt.show()# 绘制残差的密度图
results_MA.resid.plot(kind='kde')
plt.title('Density plot of the residual error values')
plt.show()# 打印残差的描述统计信息
print(results_MA.resid.describe())

在这里插入图片描述
在这里插入图片描述

总结:
这段代码绘制了对数转换后的时间序列和MA模型的残差,用以观察模型的拟合效果。残差的密度图被绘制出来,以检查残差的分布情况。最后,打印了残差的描述统计信息,包括均值、标准差、最小值、最大值等。这些统计信息可以帮助我们了解残差的分布特征。

ARIMA 组合模型

介绍部分

ARIMA 组合模型

model = ARIMA(ts_logtransformed, order=(8, 1, 18))  
results_ARIMA = model.fit(trend= 'nc', disp=-1)  
plt.plot(ts_diff_logtrans)
plt.plot(results_ARIMA.fittedvalues, color='red', label = 'p =8, q =18')
RSS =results_ARIMA.fittedvalues-ts_diff_logtrans
RSS.dropna(inplace=True)
plt.title('RSS: %.4f'% sum(RSS**2))
plt.legend(loc='best')

在这里插入图片描述

上面的图表和模型展示了不同的残差 RSS(残差平方和)。评估所有这些模型可能会很困难,因此我们对所有可能的 ARIMA 参数进行网格搜索。我们寻找不同的 p、d、q 组合,并找到最佳组合。p 的取值为 7、10、13、16、19,d 的取值为 0 到 2,模型运行 10 次,这需要一些时间来完成。

以下是一个 Python 代码,用于评估不同模型的性能,以找到最佳的 ARIMA 超参数。

代码部分

代码总结:
这段代码的目的是通过网格搜索来评估不同 ARIMA 模型的性能,找到最佳的 p 和 d 参数组合。代码的逻辑是通过遍历不同的 p 和 d 值,计算每个组合的 RSS(残差平方和),并选择 RSS 最小的组合作为最佳模型。

import warnings# 定义函数来评估 ARIMA 模型的性能
def evaluate_arima_model(data_set, arima_order):model = ARIMA(data_set, order=arima_order)  # 创建 ARIMA 模型results_ARIMA = model.fit(disp=-1)  # 拟合模型RSS_diff = results_ARIMA.fittedvalues - ts_diff_logtrans  # 计算残差RSS = RSS_diff**2  # 计算残差平方和return RSS# 定义函数来评估不同 p 和 d 值的组合
def evaluate_models(dataset, p_values, d_values):best_score, best_cfg = float("inf"), None  # 初始化最佳得分和最佳配置for p in p_values:  # 遍历 p 值for d in d_values:  # 遍历 d 值order = (p, d, 18)  # 设置 ARIMA 模型的阶数try:rss = evaluate_arima_model(dataset, order)  # 评估模型if rss < best_score:  # 如果当前 RSS 小于最佳 RSSbest_score, best_cfg = rss, order  # 更新最佳得分和最佳配置print('ARIMA%s RSS=%.3f' % (order, rss))  # 打印当前模型的 RSSexcept:continueprint('Best ARIMA%s RSS=%.3f' % (best_cfg, best_score))  # 打印最佳模型的 RSSp_values = range(8, 20, 3)  # 设置 p 值的范围
d_values = range(0, 3)  # 设置 d 值的范围
warnings.filterwarnings('ignore')  # 忽略警告
evaluate_models(ts_logtransformed, p_values, d_values)  # 评估模型

代码总结:
这段代码的目的是生成 ARIMA 模型的摘要,并绘制残差图。代码的逻辑是通过拟合 ARIMA 模型,生成模型的摘要信息,并绘制残差图以评估模型的性能。

# 打印 ARIMA 模型的摘要
print(results_ARIMA.summary())# 绘制对数变换后的数据和残差图
plt.plot(ts_logtransformed, label='log_transformed_data')
plt.plot(results_ARIMA.resid, color='green', label='Residuals')
plt.title('ARIMA Model Residual plot')
plt.legend(loc='best')# 绘制残差误差值的密度图
results_ARIMA.resid.plot(kind='kde')
plt.title('Density plot of the residual error values')
print(results_ARIMA.resid.describe())

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

test = pd.read_csv("../input/bitcoin_price_1week_Test - Test.csv",index_col= 'Date')
test.index = pd.to_datetime(test.index)
test = test['Close']
test = test.sort_index()
test

在这里插入图片描述

代码总结:
这段代码的目的是使用 ARIMA 模型进行预测和预测结果的累积求和。代码的逻辑是通过拟合 ARIMA 模型,生成预测值,并对预测值进行累积求和,最终将结果转换回原始尺度。

# 使用 ARIMA 模型进行预测
predictions_ARIMA_diff = pd.Series(results_ARIMA.fittedvalues, copy=True)
print(predictions_ARIMA_diff.head())# 对预测值进行累积求和
predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum()
print(predictions_ARIMA_diff_cumsum.head())# 将累积求和的结果转换回对数尺度
predictions_ARIMA_log = pd.Series(ts_logtransformed.iloc[0], index=ts_logtransformed.index)
predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum, fill_value=0)
predictions_ARIMA_log.head()# 将对数尺度的预测值转换回原始尺度
predictions_ARIMA = np.exp(predictions_ARIMA_log)
plt.plot(data)
plt.plot(predictions_ARIMA)
plt.title('RMSE: %.4f' % np.sqrt(sum((predictions_ARIMA - data)**2) / len(data)))

在这里插入图片描述
在这里插入图片描述

dates = [pd.Timestamp('2017-08-01'), pd.Timestamp('2017-08-02'), pd.Timestamp('2017-08-03'),pd.Timestamp('2017-08-04'), pd.Timestamp('2017-08-05'), pd.Timestamp('2017-08-06'), pd.Timestamp('2017-08-07')]forecast = pd.Series(results_ARIMA.forecast(steps=7)[0],dates)
forecast = np.exp(forecast)
print(forecast)
error = mean_squared_error(test, forecast)
print('Test MSE: %.3f' % error)plt.plot(forecast, color ='green', label ='Predicted rates')
plt.plot(test, color = 'red', label = 'Observed from test data')
plt.title('RMSE: %.4f'% np.sqrt(sum((forecast-test)**2)/len(data)))
plt.legend(loc = 'best')

在这里插入图片描述
在这里插入图片描述
代码总结:
这段代码的目的是使用 MA 模型进行预测,并计算预测值与实际值之间的均方误差(MSE)。代码的逻辑是通过拟合 MA 模型,生成预测值,并计算预测值与实际值之间的误差。

# 使用 MA 模型进行预测
predictions_MA_diff = pd.Series(results_MA.fittedvalues, copy=True)
print(predictions_MA_diff.head())# 对预测值进行累积求和
predictions_MA_diff_cumsum = predictions_MA_diff.cumsum()
print(predictions_MA_diff_cumsum.head())# 将累积求和的结果转换回对数尺度
predictions_MA_log = pd.Series(ts_logtransformed.iloc[0], index=ts_logtransformed.index)
predictions_MA_log = predictions_MA_log.add(predictions_MA_diff_cumsum, fill_value=0)
predictions_MA_log.head()# 将对数尺度的预测值转换回原始尺度
predictions_MA = np.exp(predictions_MA_log)
plt.plot(data)
plt.plot(predictions_MA)
plt.title('RMSE: %.4f' % np.sqrt(sum((predictions_MA - data)**2) / len(data)))# 计算预测值与实际值之间的均方误差
error = mean_squared_error(test, forecast)
print('Test MSE: %.3f' % error)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是翻译后的文章内容,包括对代码部分的注释和总结:

# 定义日期列表
dates = [pd.Timestamp('2017-08-01'), pd.Timestamp('2017-08-02'), pd.Timestamp('2017-08-03'),pd.Timestamp('2017-08-04'), pd.Timestamp('2017-08-05'), pd.Timestamp('2017-08-06'), pd.Timestamp('2017-08-07')]# 使用移动平均模型对未来的7天进行预测,并将预测结果存储在 forecast 变量中
forecast = pd.Series(results_MA.forecast(steps=7)[0], dates)
# 对预测结果进行指数变换,恢复到原始数据的尺度
forecast = np.exp(forecast)
# 打印预测结果
print(forecast)# 计算测试数据与预测数据之间的均方误差(MSE)
error = mean_squared_error(test, forecast)
# 打印测试均方误差(MSE)
print('Test MSE: %.3f' % error)# 以下代码的目的是绘制预测结果和测试数据的图表
plt.plot(forecast, color='green', label='Predicted rates')  # 绘制预测结果,颜色为绿色,标签为 Predicted rates
plt.plot(test, color='red', label='Observed from test data')  # 绘制测试数据,颜色为红色,标签为 Observed from test data
# 设置图表标题,并显示均方根误差(RMSE)
plt.title('RMSE: %.4f' % np.sqrt(sum((forecast - test) ** 2) / len(data)))
plt.legend(loc='best')  # 设置图例位置为最佳

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

消除上述时间序列中的季节性是一个需要进行大量工作的任务。可以扩展使用更多方法,如曲线拟合和差分,来识别季节性并从数据中去除季节性成分。

改进的模型可以是从前一年的相同日历月的平均币价中减去,而不是从相同日期中减去。

我们可以通过将数据集重新采样为月平均价格来开始。重新采样方法处理了闰年的概念,同时消除了偏移(例如2月只有28天)。

# 将数据重新采样为月平均价格
monthly_mean = data.resample('M').mean()
# 打印前13个月的月平均价格
print(monthly_mean.head(13))
# 绘制月平均价格的图表
monthly_mean.plot()

在这里插入图片描述

以下是另一种方法来评估预测性能:

# 对测试数据进行对数变换
test_logtransformed = np.log(test)# 初始化历史数据列表,包含对数变换后的训练数据
history = [x for x in ts_logtransformed]
# 初始化预测结果列表
predictions = list()
# 遍历测试数据的每个时间点
for t in range(len(test)):# 使用移动平均模型进行预测output = results_MA.forecast()yhat = output[0]  # 获取预测结果predictions.append(yhat)  # 将预测结果添加到预测列表中# 获取实际观察值并添加到历史数据列表中obs = test_logtransformed[t]history.append(obs)print('predicted=%f, expected=%f' % (yhat, obs))  # 打印预测值和实际值# 计算对数变换后的测试数据与预测数据之间的均方误差(MSE)
error = mean_squared_error(test_logtransformed, predictions)
# 打印测试均方误差(MSE)
print('Test MSE: %.3f' % error)

在这里插入图片描述

消除上述时间序列中的季节性是一个需要进行大量工作的任务。可以扩展使用更多方法,如曲线拟合和差分,来识别季节性并从数据中去除季节性成分。

改进的模型可以是从前一年的相同日历月的平均币价中减去,而不是从相同日期中减去。

我们可以通过将数据集重新采样为月平均价格来开始。重新采样方法处理了闰年的概念,同时消除了偏移(例如2月只有28天)。

代码总结:
这段代码的目的是使用 Prophet 模型进行时间序列预测。代码的逻辑是通过拟合 Prophet 模型,生成未来 7 天的预测值,并绘制预测结果。

from prophet import Prophet# 准备数据
data_prophet = data.copy()
data_prophet = pd.DataFrame(data_prophet)
data_prophet.reset_index(drop=False, inplace=True)
data_prophet.columns = ['ds', 'y']# 创建并拟合 Prophet 模型
m = Prophet()
m.fit(data_prophet)# 生成未来 7 天的预测数据
future = m.make_future_dataframe(periods=7, freq='D')
forecast = m.predict(future)# 绘制预测结果
m.plot(forecast)
data.plot()# 绘制预测结果的组件
m.plot_components(forecast)# 提取预测值并计算均方误差
forecasted_values = forecast[['ds', 'yhat']].tail(7)
forecasted_values = forecasted_values.set_index('ds')
forecasted_values.columns = ['y']
mean_squared_error(forecasted_values['y'], test)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码总结:
这段代码的目的是使用 LSTM 模型进行时间序列预测。代码的逻辑是通过创建和训练 LSTM 模型,对时间序列数据进行预测。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler# 创建 LSTM 模型
model = Sequential()
model.add(LSTM(50, input_shape=(1, 1)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')# 数据预处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)# 训练模型
model.fit(scaled_data, epochs=100, batch_size=1, verbose=2)

总结

本文介绍了如何使用 ARIMA 和 MA 模型进行时间序列预测,并通过网格搜索找到最佳的超参数组合。此外,还介绍了如何使用 Prophet 和 LSTM 模型进行时间序列预测。通过这些方法,可以有效地预测时间序列数据,并评估模型的性能。

相关文章:

【机器学习实战中阶】使用SARIMAX,ARIMA预测比特币价格,时间序列预测

数据集说明 比特币价格预测&#xff08;轻量级CSV&#xff09;关于数据集 致谢 这些数据来自CoinMarketCap&#xff0c;并且可以免费使用该数据。 https://coinmarketcap.com/ 数据集:链接: 价格预测器 源代码与数据集 算法说明 SARIMAX&#xff08;Seasonal AutoRegressive …...

各语言镜像配置汇总

镜像配置汇总 Nodejs [ npm ]Python [ pip ] Nodejs [ npm ] // # 记录日期&#xff1a;2025-01-20// 查询当前使用的镜像 npm get registry// 设置淘宝镜像 npm config set registry https://registry.npmmirror.com/// 恢复为官方镜像 npm config set registry https://regi…...

细说STM32F407单片机电源低功耗StopMode模式及应用示例

目录 一、停止模式基础知识 1、进入停止模式 2、停止模式的状态 3、退出停止模式 4、SysTick定时器的影响 二、停止模式应用示例 1、示例功能和CubeMX项目配置 &#xff08;1&#xff09;时钟 &#xff08;2&#xff09;RTC &#xff08;3&#xff09;ADC1 &#xf…...

PHP语言的循环实现

PHP语言的循环实现详解 在当今的编程世界中&#xff0c;循环是一种不可或缺的基本构造&#xff0c;它使得我们能够重复执行某些操作&#xff0c;极大地提高了代码的复用性和可读性。在PHP语言中&#xff0c;循环的种类以及使用方式繁多&#xff0c;本文将全面探讨PHP中的循环实…...

求两个矩阵的乘积

求两个矩阵的乘积 分数 15 全屏浏览 切换布局 作者 C课程组-hwr-zy 单位 浙江大学 输入三个正整数m&#xff0c;l&#xff0c;n(0<m&#xff0c;n&#xff0c;l<10)&#xff0c;再输入两个的矩阵a&#xff08;mxl&#xff09;和b&#xff08;lxn&#xff09;。要求把a和…...

警惕IDEA 2024版重大Bug问题:LomBok失效、Gradle冲突、Spring Boot启动错误

一直以来我认为工具类的软件是越新越好&#xff0c;因为工具代表着一定的先进性&#xff1b;但是IDEA 2024好好的给我上了一课&#xff0c;比如lombok 不起作用、比如Spring Boot 3.4.x 启动报错、再比如MyBatis log plus冲突、再比如Gradle插件冲突. 一、Lombok 失效问题 请不…...

Go语言的正则表达式

Go语言的正则表达式&#xff1a;深度解析与应用实例 引言 正则表达式&#xff08;Regular Expression&#xff0c;简称 regex&#xff09;是一种用于匹配字符串的强大工具&#xff0c;广泛应用于文本处理、数据验证、解析和提取等场景。Go语言作为一种现代编程语言&#xff0…...

通过ssh连接debian

使用方法 ssh usernameipaddress [inputpasswd]root用户默认无法由ssh连接&#xff0c; 可以通过修改配置 sudo vim /etc/ssh/sshd_config去掉PermitRootLogin前的‘#’,并修改为 PermitRootLogin yes 重启sshd服务 sudo systemctl restart sshd参考 https://linuxconfig.or…...

计算机创造的奇迹——C语言

一.简介 C语言是一种较早的程序设计语言&#xff0c;诞生于1972年的贝尔实验室。1972 年&#xff0c;Dennis Ritchie 设计了C语言&#xff0c;它继承了B语言的许多思想&#xff0c;并加入了数据类型的概念及其他特性。 尽管C 语言是与 UNIX 操作系统一起被开发出来的&#xff…...

磁盘阵列服务器和普通服务器的区别

磁盘阵列服务器&#xff08;RAID Server&#xff09;和普通服务器在多个方面存在显著区别。以下是它们的主要区别&#xff1a; 1. 存储架构 磁盘阵列服务器 RAID 技术&#xff1a;使用 RAID&#xff08;冗余独立磁盘阵列&#xff09;技术&#xff0c;将多个硬盘组合成一个逻…...

搭建一个人脸识别pipeline

文章目录 概要入门所需设置你的开发环境人脸识别的工作原理数据加载和预处理建立你的人脸识别模型评估你的模型总结概要 人脸识别已发展成为一项关键技术,现已嵌入从安全系统到社交媒体平台等各个领域。在本文中,我们将逐步指导您在短短 30 分钟内使用 Python 和机器学习创建…...

Docker 之mysql从头开始——Docker下mysql安装、启动、配置、进入容器执行(查询)sql

一、Docker 之mysql安装配置 步骤一&#xff1a;拉取镜像 1. 查看是否包含已安装的mysql。 docker images | grep mysql 2. 如上图所示&#xff0c;我们有mysql镜像&#xff0c;所以不必对mysql镜像进行拉取&#xff0c;如若没有上图中的惊喜&#xff0c;使用如下命令进行拉取…...

LeetCodeHOT100:60. n个骰子的点数、4. 寻找两个正序数组的中位数

LeetCodeHOT100&#xff1a; 剑指 Offer 60. n个骰子的点数4. 寻找两个正序数组的中位数96. 不同的二叉搜索树 剑指 Offer 60. n个骰子的点数 题目&#xff1a;把n个骰子扔在地上&#xff0c;所有骰子朝上一面的点数之和为s。输入n&#xff0c;打印出s的所有可能的值出现的概率…...

apisix的authz-casbin

目录 1、apisix的auth-casbin官方介绍 2、casbin介绍和使用 2.1基本知识&#xff1a; 2.2使用例子 3、配置插件 4、postman调用 5、auth-casbin的坑 1、apisix的auth-casbin官方介绍 authz-casbin | Apache APISIX -- Cloud-Native API Gateway 2、casbin介绍和使用 c…...

数学基础 --线性代数之理解矩阵乘法

理解矩阵乘法的解析 矩阵乘法&#xff08;Matrix Multiplication&#xff09;是线性代数中的核心操作之一。在数学、几何和工程实际中&#xff0c;它不仅是一种代数运算规则&#xff0c;还承载着丰富的几何和映射意义。本文将从多个角度深入解析矩阵乘法&#xff0c;帮助读者理…...

TCP Window Full是怎么来的

wireshark查看包时&#xff0c;会看到TCP Window Full&#xff0c;总结下它的特点&#xff1a; 1. Sender会显示 TCP Window Full 2. “Sender已发出&#xff0c;但&#xff0c;Receiver尚未ack的字节”&#xff0c;即Sender的 bytes in flights 3. Sender的 bytes in fligh…...

【22】Word:小李-高新技术企业政策❗

目录 题目​ NO1.2 NO3 NO4 NO5.6 NO7.8 NO9.10 若文章中存在删除空白行等要求&#xff0c;可以到最后来完成。注意最后一定要检查此部分&#xff01;注意&#xff1a;大多是和事例一样即可&#xff0c;不用一摸一样&#xff0c;但也不要差太多。 题目 NO1.2 F12Fn&a…...

大数据,Hadoop,HDFS的简单介绍

大数据 海量数据&#xff0c;具有高增长率、数据类型多样化、一定时间内无法使用常规软件工具进行捕捉、管理和处理的数据集 合 大数据的特征: 4V Volume : 巨大的数据量 Variety : 数据类型多样化 结构化的数据 : 即具有固定格式和有限长度的数据 半结构化的数据 : 是…...

Python预训练视觉和大语言模型——精彩试读

基础模型永久改变了机器学习。从BERT到ChatGPT&#xff0c;从CLIP到Stable Diffusion&#xff0c;当数十亿个参数、大数据集与成百上千个GPU相结合时&#xff0c;结果刷新了纪录。《Python预训练视觉和大语言模型》呈现的真知灼见和示例代码将帮你在AWS和Amazon SageMaker上从头…...

html全局遮罩,通过websocket来实现实时发布公告

1.index.html代码示例 <div id"websocket" style"display:none;position: absolute;color:red;background-color: black;width: 100%;height: 100%;z-index: 100; opacity: 0.9; padding-top: 30%;padding-left: 30%; padding-border:1px; "onclick&q…...

【如何做好应用架构?】

一、应用架构定义 应用架构描述了各种用于支持业务架构并对数据架构所定义的各种数据进行出来的应用功能。这些应该功能指的是用来管理在数据架构中定义的数据&#xff0c;并对业务架构中定义的各项业务功能进行支持的能力。 其核心目标是确保应用系统高效、灵活、安全的支撑…...

1 Studying《蓝牙核心规范5.3》

目录 [Vol 0][Part B 蓝牙规范要求] 3 定义 3.1 蓝牙产品类型 4 核心配置 4.1 基本速率核心配置 4.2 增强型数据速率核心配置 4.4 低功耗核心配置 4.5 基本速率和低功耗结合的核心配置 4.6 主机控制器接口核心配置 [Vol 1][Part A 架构]1 概述 1.1 BR/EDR操作概述 …...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(十一)

下载buildroot https://buildroot.org/download.html下载交叉工具链 使用ST官方交叉工具链的话&#xff0c;在buildroot配置外部工具会有问题&#xff0c;所以直接使用正点原子的交叉编译工具 buildroot构建根文件系统 - 参考正点原子 配置 buildroot tar -vxf buildroot-20…...

​​​​​​​6板块公共数据典型应用场景【政务服务|公共安全|公共卫生|环境保护|金融风控|教育科研]

1. 政务服务 1.1 城市规划与管理 公共数据在城市规划与管理中可发挥关键作用。通过汇聚自然资源、建筑物、人口分布等基础数据,构建数字孪生城市模型,辅助城市总体规划编制、决策仿真模拟。在城市基础设施建设、安全运营、应急管理等方面,公共数据也是不可或缺的基础支撑。例…...

27.【新型数据架构】-数据共享架构

27.【新型数据架构】-数据共享架构:降低数据获取成本,实时数据访问,保持数据新鲜度,促进数据经济发展,打破数据孤岛,标准化数据交换,增强数据安全性,完整审计追踪,合规性保障 一、数据共享架构的本质:打破壁垒的“数字立交桥” 传统企业或组织间的数据往往呈现“烟囱…...

Framework开发之IMS逻辑浅析1--关键线程及作用

关键线程:EventHub,InputReader,InputDispatcher EventHub: 由于Android继承Linux,Linux的思想是一切皆文件,而输入的类型不止一种(触碰&#xff0c;写字笔&#xff0c;键盘等)&#xff0c;每种类型都对应一种驱动设备&#xff0c;而每个硬件驱动设备又对应Linux的一个目录文件…...

【Redis】笔记|第9节|Redis Stack扩展功能

Redis Stack 扩展功能笔记&#xff08;基于 Redis 7&#xff09; 一、Redis Stack 概述 定位&#xff1a;Redis OSS 扩展模块&#xff08;JSON、搜索、布隆过滤器等&#xff09;&#xff0c;提供高级数据处理能力。核心模块&#xff1a; RedisJSON&#xff1a;原生 JSON 支持…...

分形几何在医学可视化中的应用:从理论到Python实战

分形几何在医学可视化中的应用&#xff1a;从理论到Python实战 前言 分形几何作为描述自然界复杂结构的数学工具&#xff0c;正通过其自相似性和分数维度特性&#xff0c;革新医学影像分析领域。本文系统阐述分形几何在医学影像中的创新应用&#xff0c;涵盖从图像预处理、分…...

四自由度机械臂Simulink仿真设计与实现

四自由度机械臂Simulink仿真设计与实现 摘要 本文详细介绍了基于MATLAB/Simulink的四自由度机械臂建模、仿真与控制实现。通过建立完整的运动学和动力学模型,设计PID控制器,实现轨迹跟踪功能,并利用3D可视化技术进行仿真验证。全文涵盖理论建模、Simulink实现和仿真分析三…...

基于dify的营养分析工作流:3分钟生成个人营养分析报告

你去医院做体检&#xff0c;需要多久拿到体检报告呢&#xff1f;医院会为每位病人做一份多维度的健康报告吗&#xff1f;"人工报告需1小时/份&#xff1f;数据误差率高达35%&#xff1f;传统工具无法个性化&#xff1f; Dify工作流AI模型的组合拳&#xff0c;正在重塑健康…...