- 回归类型数据挖掘任务
基于ARIMA和多层神经网络模型的地铁站点日客流量预测。有郑州市2015年8月-11月各地铁闸机刷卡数据集。对每日各地铁站的客流量进行分析并进行可视化。基于上一步的分析结果,分别采用ARIMA模型和多层神经网络模型对数据进行建模,训练优化模型并分别给出评估指标。
原始数据如下所示,共分为4个文件,近15GB。
2.1总体流程
2.2数据分析
2.2.1读取数据
使用pandas读取下列文件,并将读取到的DataFrame进行合并。
acc_08_final_mini.csv
acc_09_final_mini.csv
acc_10_final_mini.csv
acc_11_final_mini.csv
得到的DataFrame如图所示:
代码:
python
import pandas as pd
# 创建一个空的DataFrame列表来存储所有读取的DataFrame
df_list = []
# 循环读取所有CSV文件
for year in range(8, 12): # 从2008年到2011年
filename = fr'C:\Users\zjl15\PycharmProjects\pythonProject1\shixundata\2\acc_{year:02d}_final_mini.csv' # 注意fr的使用
df = pd.read_csv(filename) # 读取CSV文件
df_list.append(df) # 将读取的DataFrame添加到列表中
# 使用concat函数进行纵向合并(堆叠)
combined_df = pd.concat(df_list, ignore_index=True)
# 显示合并后的DataFrame
print(combined_df)
特征含义:
|-----|------------------|---------------|------------|
| 特征名 | TRADE_TYPE | TRADE_ADDRESS | TRADE_DATE |
| 含义 | 交易类型 21:进站 22:出站 | 交易站点 | 交易时间 |
2.2.2分析数据
2.2.2.1日期处理
提取TRADE_DATE中的日期部分作为新的TRADE_DATE的内容。
建议使用pandas库的apply函数。
2.2.2.2分组统计
统计各个站点每天的客流量,并将客流量数据作为1列加入到原数据中,列名为COUNT。建议使用pandas库的groupby函数和transform函数。
2.2.2.3删除TRADE_TYPE列
因本次分析不考虑交易类型这个因素,因此要删掉TRADE_TYPE列。建议使用pandas库的drop函数。
2.2.2.4排序去重
将数据按照TRADE_ADDRESS和TRADE_DATE两列进行排序,并进行去重处理。建议使用pandas库的sort_values函数和drop_duplicates函数。
python
# 将 TRADE_DATE 列转换为 datetime 类型
combined_df['TRADE_DATE'] = pd.to_datetime(combined_df['TRADE_DATE'], format='%Y-%m-%d-%H.%M.%S.%f')
# 使用 apply 函数提取日期部分并创建新的列
combined_df['DATE_ONLY'] = combined_df['TRADE_DATE'].apply(lambda x: x.date())
#去除TRADE_DATE列
df=combined_df.drop(columns=['TRADE_DATE'])
# 使用 groupby 和 transform 计算每个站点每天的交易数量并将结果作为新列加入原数据
df['COUNT'] = df.groupby(['DATE_ONLY', 'TRADE_ADDRESS'])['TRADE_TYPE'].transform('count')
#去除TRADE_TYPE列
df=df.drop(columns=['TRADE_TYPE'])
# 按照 TRADE_ADDRESS 和 DATE_ONLY 进行排序
df_sorted = df.sort_values(by=['TRADE_ADDRESS', 'DATE_ONLY'])
# 去重处理
df_unique = df_sorted.drop_duplicates(subset=['TRADE_ADDRESS', 'DATE_ONLY'])
# 根据日期和站点对数据进行分组,并计算客流量总和
grouped_data = df_unique.groupby(['DATE_ONLY', 'TRADE_ADDRESS'])['COUNT'].sum().unstack()
2.2.2.5绘制所有站点8月1日-11月30日的客流量折线图
python
# 绘制折线图
grouped_data.plot(figsize=(12, 8))
plt.title('Daily Traffic for Each Station')
plt.xlabel('Date')
plt.ylabel('Traffic Count')
plt.legend(title='Station', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
2.3模型构建
2.3.1 ARIMA模型(以 121站 点 为例)
以2.2.2.4步骤中的数据为基础,筛选出TRADE_ADDRESS=121的行。
以121站点客流量数据为例,使用时间序列分析方法进行建模。
python
# 从原始数据中筛选出TRADE_ADDRESS=121的行
data_121 = df_unique[df_unique['TRADE_ADDRESS'] == 121]
#重新定义一个变量,将数据备份
data = data_121
#删除多余的列
data_121 = data_121.drop(columns=['TRADE_ADDRESS','DATE_ONLY'])
2.3.1.1划分训练集和测试集
共122条记录,前115条为训练集,后7条为测试集
python
# 划分训练集和测试集
train_set = data_121.iloc[:115]
test_set = data_121.iloc[115:]
2.3.1.2平稳性检验
对训练集进行平稳性检验,分别采用时序图、自相关图、ADF单位根检测方法。
(1)绘制时序图
(2)绘制自相关图
(3)ADF单位根检测
通过检验,发现该序列为非平稳序列。如想使用ARIMA模型进行建模分析,需处理转换为平稳序列。
python
# 绘制时序图
plt.figure(figsize=(12, 6))
plt.plot(train_set['COUNT'])
plt.title('Traffic Count at Station 121 (Training Set)')
plt.xlabel('Date')
plt.ylabel('Traffic Count')
plt.show()
# 绘制自相关图
fig, ax = plt.subplots(2, 1, figsize=(12, 8))
sm.graphics.tsa.plot_acf(train_set['COUNT'], lags=30, ax=ax[0])
sm.graphics.tsa.plot_pacf(train_set['COUNT'], lags=30, ax=ax[1])
plt.show()
# ADF单位根检测
result = adfuller(train_set['COUNT'])
print('ADF Statistic:', result[0])
print('p-value:', result[1])
print('Critical Values:', result[4])
2.3.1.3差分处理
使用2阶差分对训练集进行处理。
对差分处理后的训练集再次进行平稳性检验,分别采用时序图、自相关图、ADF单位根检测方法。
python
# 对训练集进行2阶差分处理
train_set_diff = train_set['COUNT'].diff().diff().dropna()
# 绘制2阶差分后的时序图
plt.figure(figsize=(12, 6))
plt.plot(train_set_diff)
plt.title('Differenced Traffic Count at Station 121 (Training Set)')
plt.xlabel('Date')
plt.ylabel('Differenced Traffic Count')
plt.show()
# 绘制2阶差分后的自相关图
fig, ax = plt.subplots(2, 1, figsize=(12, 8))
sm.graphics.tsa.plot_acf(train_set_diff, lags=30, ax=ax[0])
sm.graphics.tsa.plot_pacf(train_set_diff, lags=30, ax=ax[1])
plt.show()
# ADF单位根检测(2阶差分后)
result_diff = adfuller(train_set_diff)
print('ADF Statistic (after differencing):', result_diff[0])
print('p-value (after differencing):', result_diff[1])
print('Critical Values (after differencing):', result_diff[4])
2.3.1.4纯随机性检验
对差分处理后的训练集进行纯随机性检验。
python
# 计算自相关系数
acf = sm.tsa.acf(train_set_diff, fft=False)
# 绘制自相关函数图
plt.figure(figsize=(12, 6))
plt.bar(range(len(acf)), acf)
plt.xlabel('Lag')
plt.ylabel('ACF')
plt.title('Autocorrelation Function')
plt.show()
2.3.1.5 ARIMA模型建模
选择合适的参数q和q来构建ARIMA模型。
2.3.1.6 ARIMA模型训练
- 使用差分处理后的数据对ARIMA模型进行训练
- 绘制训练集真实值和预测值对比图
参考代码:
python
# 定义 ARIMA 模型的参数 (p, d, q)
p = 6 # 自回归阶数
d = 2 # 差分阶数
q = 6 # 移动平均阶数
# 训练 ARIMA 模型
model = ARIMA(train_set, order=(p, d, q))
model_fit = model.fit()
# 使用训练好的模型进行预测
# 绘制训练集真实值和预测值对比图
plt.figure(figsize=(12, 6))
plt.plot(train_set, label='Actual')
plt.plot(forecast, label='Predicted', color='red')
plt.title('Comparison of Actual and Predicted Values')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.show()
2.3.2多层神经网络模型
2.3.2.1 特征构造
构造多层神经网络模型所需特征。
- 筛选121站点数据
以2.2.2.4步骤中的数据为基础,筛选出TRADE_ADDRESS=121的行。
- 删掉TRADE_ADDRESS列
因所有行均为121站点的数据,所以TRADE_ADDRESS没有意义,删掉。建议使用pandas库的drop函数。
- 从TRADE_DATE列中提取出星期几数据
对TRADE_DATE列进行计算,根据日期推算出星期几,然后赋值给新的一列TRADE_DAY。建议使用pandas库的apply函数。
- 从TRADE_DAY列中提取出周末数据
对TRADE_DAY列进行计算,得出是否为周末,然后赋值给新的一列WEEKEND(1:周末,0:工作日)。建议使用pandas库的apply函数。
- 从TRADE_DATE列中提取出月份数据
对TRADE_DATE列进行计算,提取出月份信息,然后赋值给新的一列MONTH。建议使用pandas库的apply函数。
- 从TRADE_DATE列中提取出日数据
对TRADE_DATE列进行计算,提取出日信息,然后赋值给新的一列DAY。建议使用pandas库的apply函数。
- 删掉TRADE_DATE列
TRADE_DATE里的信息已经提取完毕,可以删掉。建议使用pandas库的drop函数。
- 对数据的列进行重新排序
顺序为:['MONTH','DAY','TRADE_DAY','WEEKEND', 'COUNT']
python
#删掉TRADE_ADDRESS列
df = data.drop(columns=['TRADE_ADDRESS'])
# 将 DATE_ONLY 列转换为日期时间类型
df['DATE_ONLY'] = pd.to_datetime(df['DATE_ONLY'])
# 使用 apply 函数计算星期几,并赋值给新列 DAY_OF_WEEK
df['DAY_OF_WEEK'] = df['DATE_ONLY'].dt.day_name()
# 使用 dt.dayofweek + 1 将星期几转换为数字表示,并赋值给新列 DAY_OF_WEEK_NUM
df['DAY_OF_WEEK_NUM'] = df['DATE_ONLY'].dt.dayofweek + 1
#删除DAY_OF_WEEK
df2 = df.drop(columns=['DAY_OF_WEEK'])
# 将 TRADE_DATE 列转换为日期时间类型
df2['DATE_ONLY'] = pd.to_datetime(df2['DATE_ONLY'])
# 使用 apply 函数结合 dt.month 提取出月份信息,并赋值给新列 MONTH
df2['MONTH'] = df2['DATE_ONLY'].apply(lambda x: x.month)
# 使用 apply 函数结合 dt.day 提取出日信息,并赋值给新列 DAY
df2['DAY'] = df2['DATE_ONLY'].apply(lambda x: x.day)
#删除DATE_ONLY
df2 = df2.drop(columns=['DATE_ONLY'])
# 自定义函数来判断是否为周末
def is_weekend(day_of_week):
return 1 if day_of_week >= 6 else 0
# 使用 apply 函数调用自定义函数对 DAY_OF_WEEK_NUM 列进行计算,生成 WEEKEND 列
df2['WEEKEND'] = df2['DAY_OF_WEEK_NUM'].apply(is_weekend)
#按指定顺序排好['MONTH', 'DAY', 'DAY_OF_WEEK_NUM', 'WEEKEND', 'COUNT']
df2 = df2[['MONTH', 'DAY', 'DAY_OF_WEEK_NUM', 'WEEKEND', 'COUNT']]
- 绘制数据的多变量联合分布图
使用seaborn库的pairplot方法绘制数据的联合分布图。
python
# 绘制多变量联合分布图
sns.pairplot(df2)
plt.show()
2.3.2.2划分训练集和测试集
- 提取特征x和目标值y
根据2.3.2.1构建出的数据集,提取出特征x和目标值y。
- 划分训练集和测试集
共122条记录,前115条为训练集,后7条为测试集。
python
# 提取特征 x
X = df2[['MONTH', 'DAY', 'DAY_OF_WEEK_NUM', 'WEEKEND']] # 选择需要作为特征的列
# 提取目标值 y
y = df2['COUNT'] # 选择目标列
# 划分训练集和测试集
# 划分训练集和测试集
X_train = X[:115] # 前115条作为训练集
X_test = X[115:] # 后7条作为测试集
y_train = y[:115] # 对应的目标值作为训练集
y_test = y[115:] # 对应的目标值作为测试集
2.3.2.3模型构建
模型参数:
参考代码
python
#构建多层神经网络模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(64,activation='relu',input_shape=[len(X_train.keys())]),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(64,activation='relu'),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(64,activation='relu'),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(1)
])
# 编译模型
model.compile(optimizer='adam', loss='mse', metrics=['mae','mse'])
model.summary()
# 训练模型并保存历史数据
history = model.fit(X_train, y_train, epochs=3000, validation_split=0.3)
2.3.2.4模型编译
编译参数参考:
python
# 优化器
optimizer='adam'
# 损失函数
loss='mse'
# 评估指标
metrics=['mae','mse']
2.3.2.5模型训练
使用fit函数对训练集进行拟合训练,并将训练过程中产生的历史数据history保存至变量中。
训练参数参考:
python
# 迭代次数
epochs=1000
# 验证集比例
validation_split=0.2
2.3.2.6训练过程可视化
对history中保存下来的训练过程中的mae和mse的变化情况进行绘图。
参考代码:
python
# 获取训练过程中的指标数值
mae = history.history['mae']
mse = history.history['loss']
val_mae = history.history['val_mae']
val_mse = history.history['val_mse']
#可视化mae、mse
plt.plot(mae, label='MAE')
plt.plot(val_mae, label='Validation MAE')
plt.title('MAE vs')
plt.legend()
plt.show()
plt.plot(mse, label='MSE')
plt.plot(val_mse, label='Validation MSE')
plt.title('MSE')
plt.legend()
plt.show()
print('MAE:', mae)
print('MSE:', mse)
2.4模型评估
2.4.1 ARIMA模型评估
2.4.1.1测试
- 绘制测试集真实值和预测值对比图
- 计算模型在测试集上的MAE,MSE,RMSE,MAPE
python
# 获取训练过程中的指标数值
mae = history.history['mae']
mse = history.history['loss']
val_mae = history.history['val_mae']
val_mse = history.history['val_mse']
plt.plot(mae, label='MAE')
plt.plot(val_mae, label='Validation MAE')
plt.title('MAE vs')
plt.legend()
plt.show()
plt.plot(mse, label='MSE')
plt.plot(val_mse, label='Validation MSE')
plt.title('MSE')
plt.legend()
plt.show()
# history.plot()
# plt.plot(history)
# plt.show()
print('MAE:', mae)
print('MSE:', mse)
y_arima = model_fit.forecast(7)
print('预测未来'+str(len(y_arima))+'天的客流量:\n',y_arima)
y_arima.index = test_set.index
# # # 创建一个新的DataFrame来保存预测值,索引与测试集相同
# test_set = pd.read_csv(r'test.csv')
# print(test_set)
# test_set.to_csv('test_set.xlsx', index=False)
# y_arima = pd.Series(y_arima, index=test_set.index)
test_set['p'] = y_arima
plt.figure()
plt.plot(test_set, label='Actual')
# plt.plot(y_arima, label='Predicted', color='red')
plt.legend(['y_true','y_arima'])
plt.show()
2.4.2多层神经网络模型评估
2.4.2.1测试
- 根据测试集的预测结果和真实值、ARIMA模型预测结果进行对比并绘图
参考代码:
python
y_test = pd.DataFrame(y_test)
y_mlp = pd.DataFrame(y_mlp)
y_mlp.index = y_arima.index
y_test['P1']=y_arima
y_test['P2']=y_mlp
print(y_test)
plt.figure()
plt.plot(y_test, label='Actual')
plt.legend(['y_true','y_arima','y_mlp'])
plt.show()
完整代码:
python
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
from statsmodels.stats.diagnostic import acorr_ljungbox
from statsmodels.tsa.vector_ar.var_model import VAR
from sklearn import metrics
import numpy as np
import tensorflow as tf
from statsmodels.tsa.arima.model import ARIMA
import matplotlib.pyplot as plt
import seaborn as sns
#%%
import pandas as pd
# 创建一个空的DataFrame列表来存储所有读取的DataFrame
df_list = []
# 循环读取所有CSV文件
for year in range(8, 12): # 从2008年到2011年
filename = fr'C:\Users\zjl15\PycharmProjects\pythonProject1\shixundata\2\acc_{year:02d}_final_mini.csv' # 注意fr的使用
df = pd.read_csv(filename) # 读取CSV文件
df_list.append(df) # 将读取的DataFrame添加到列表中
# 使用concat函数进行纵向合并(堆叠)
combined_df = pd.concat(df_list, ignore_index=True)
# 显示合并后的DataFrame
print(combined_df)
#%%
# #如果你需要将合并后的DataFrame保存到新的CSV文件
# combined_df.to_csv('combined_final_mini.csv')
#%%
# 将 TRADE_DATE 列转换为 datetime 类型
combined_df['TRADE_DATE'] = pd.to_datetime(combined_df['TRADE_DATE'], format='%Y-%m-%d-%H.%M.%S.%f')
# 使用 apply 函数提取日期部分并创建新的列
combined_df['DATE_ONLY'] = combined_df['TRADE_DATE'].apply(lambda x: x.date())
# 打印结果
print(combined_df)
#%%
df=combined_df.drop(columns=['TRADE_DATE'])
print(df)
#%%
# 使用 groupby 和 transform 计算每个站点每天的交易数量并将结果作为新列加入原数据
df['COUNT'] = df.groupby(['DATE_ONLY', 'TRADE_ADDRESS'])['TRADE_TYPE'].transform('count')
# 打印结果
print(df)
#%%
df=df.drop(columns=['TRADE_TYPE'])
print(df)
#%% md
#%%
# 按照 TRADE_ADDRESS 和 DATE_ONLY 进行排序
df_sorted = df.sort_values(by=['TRADE_ADDRESS', 'DATE_ONLY'])
# 去重处理
df_unique = df_sorted.drop_duplicates(subset=['TRADE_ADDRESS', 'DATE_ONLY'])
# 打印结果
print(df_unique)
#%%
# 根据日期和站点对数据进行分组,并计算客流量总和
grouped_data = df_unique.groupby(['DATE_ONLY', 'TRADE_ADDRESS'])['COUNT'].sum().unstack()
# 绘制折线图
grouped_data.plot(figsize=(12, 8))
plt.title('Daily Traffic for Each Station')
plt.xlabel('Date')
plt.ylabel('Traffic Count')
plt.legend(title='Station', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
#%%
# 从原始数据中筛选出TRADE_ADDRESS=121的行
data_121 = df_unique[df_unique['TRADE_ADDRESS'] == 121]
data = data_121
print(data_121)
data_121 = data_121.drop(columns=['TRADE_ADDRESS','DATE_ONLY'])
print(data_121)
#%%
# 划分训练集和测试集
train_set = data_121.iloc[:115]
test_set = data_121.iloc[115:]
print("训练集:")
print(train_set)
print("\n测试集:")
print(test_set)
#%%
# 绘制时序图
plt.figure(figsize=(12, 6))
plt.plot(train_set['COUNT'])
plt.title('Traffic Count at Station 121 (Training Set)')
plt.xlabel('Date')
plt.ylabel('Traffic Count')
plt.show()
# 绘制自相关图
fig, ax = plt.subplots(2, 1, figsize=(12, 8))
sm.graphics.tsa.plot_acf(train_set['COUNT'], lags=30, ax=ax[0])
sm.graphics.tsa.plot_pacf(train_set['COUNT'], lags=30, ax=ax[1])
plt.show()
# ADF单位根检测
result = adfuller(train_set['COUNT'])
print('ADF Statistic:', result[0])
print('p-value:', result[1])
print('Critical Values:', result[4])
#%%
# 对训练集进行2阶差分处理
train_set_diff = train_set['COUNT'].diff().diff().dropna()
# 绘制2阶差分后的时序图
plt.figure(figsize=(12, 6))
plt.plot(train_set_diff)
plt.title('Differenced Traffic Count at Station 121 (Training Set)')
plt.xlabel('Date')
plt.ylabel('Differenced Traffic Count')
plt.show()
# 绘制2阶差分后的自相关图
fig, ax = plt.subplots(2, 1, figsize=(12, 8))
sm.graphics.tsa.plot_acf(train_set_diff, lags=30, ax=ax[0])
sm.graphics.tsa.plot_pacf(train_set_diff, lags=30, ax=ax[1])
plt.show()
# ADF单位根检测(2阶差分后)
result_diff = adfuller(train_set_diff)
print('ADF Statistic (after differencing):', result_diff[0])
print('p-value (after differencing):', result_diff[1])
print('Critical Values (after differencing):', result_diff[4])
#%%
# 计算残差序列
residuals = train_set_diff # 这里填入差分处理后的训练集数据的残差序列
# 进行Ljung-Box检验
lb_test_stat, lb_p_value = acorr_ljungbox(residuals, lags=1)
# 输出检验结果
print("Ljung-Box test statistic:", lb_test_stat)
print("P-values:", lb_p_value)
#%%
# 定义 ARIMA 模型的参数 (p, d, q)
p = 6 # 自回归阶数
d = 2 # 差分阶数
q = 6 # 移动平均阶数
# 训练 ARIMA 模型
model = ARIMA(train_set, order=(p, d, q))
model_fit = model.fit()
print(model_fit.summary())
# 使用训练好的模型进行预测
forecast = model_fit.predict(typ='levels')
print(forecast)
# 绘制训练集真实值和预测值对比图
plt.figure(figsize=(12, 6))
plt.plot(train_set, label='Actual')
plt.plot(forecast, label='Predicted', color='red')
plt.title('Comparison of Actual and Predicted Values')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.show()
#%% md
#%%
y_arima = model_fit.forecast(7)
print('预测未来'+str(len(y_arima))+'天的客流量:\n',y_arima)
y_arima.index = test_set.index
# # # 创建一个新的DataFrame来保存预测值,索引与测试集相同
# test_set = pd.read_csv(r'test.csv')
# print(test_set)
# test_set.to_csv('test_set.xlsx', index=False)
# y_arima = pd.Series(y_arima, index=test_set.index)
test_set['p'] = y_arima
plt.figure()
plt.plot(test_set, label='Actual')
# plt.plot(y_arima, label='Predicted', color='red')
plt.legend(['y_true','y_arima'])
plt.show()
#%%
# (2)删掉TRADE_ADDRESS列
df = data.drop(columns=['TRADE_ADDRESS'])
print(df)
#%%
# 将 DATE_ONLY 列转换为日期时间类型
df['DATE_ONLY'] = pd.to_datetime(df['DATE_ONLY'])
# 使用 apply 函数计算星期几,并赋值给新列 DAY_OF_WEEK
df['DAY_OF_WEEK'] = df['DATE_ONLY'].dt.day_name()
# 使用 dt.dayofweek + 1 将星期几转换为数字表示,并赋值给新列 DAY_OF_WEEK_NUM
df['DAY_OF_WEEK_NUM'] = df['DATE_ONLY'].dt.dayofweek + 1
# 显示结果
print(df)
#%%
df2 = df.drop(columns=['DAY_OF_WEEK'])
print(df2)
#%%
# 将 TRADE_DATE 列转换为日期时间类型
df2['DATE_ONLY'] = pd.to_datetime(df2['DATE_ONLY'])
# 使用 apply 函数结合 dt.month 提取出月份信息,并赋值给新列 MONTH
df2['MONTH'] = df2['DATE_ONLY'].apply(lambda x: x.month)
# 使用 apply 函数结合 dt.day 提取出日信息,并赋值给新列 DAY
df2['DAY'] = df2['DATE_ONLY'].apply(lambda x: x.day)
# 显示结果
print(df2)
#%%
df2 = df2.drop(columns=['DATE_ONLY'])
print(df2)
#%%
# 自定义函数来判断是否为周末
def is_weekend(day_of_week):
return 1 if day_of_week >= 6 else 0
# 使用 apply 函数调用自定义函数对 DAY_OF_WEEK_NUM 列进行计算,生成 WEEKEND 列
df2['WEEKEND'] = df2['DAY_OF_WEEK_NUM'].apply(is_weekend)
print(df2)
#%%
df2 = df2[['MONTH', 'DAY', 'DAY_OF_WEEK_NUM', 'WEEKEND', 'COUNT']]
print(df2)
#%%
# 绘制多变量联合分布图
sns.pairplot(df2)
plt.show()
#%%
from sklearn.model_selection import train_test_split
# 提取特征 x
X = df2[['MONTH', 'DAY', 'DAY_OF_WEEK_NUM', 'WEEKEND']] # 选择需要作为特征的列
# 提取目标值 y
y = df2['COUNT'] # 选择目标列
# 划分训练集和测试集
# 划分训练集和测试集
X_train = X[:115] # 前115条作为训练集
X_test = X[115:] # 后7条作为测试集
y_train = y[:115] # 对应的目标值作为训练集
y_test = y[115:] # 对应的目标值作为测试集
print(X_train)
print(y_train)
print(X_test)
print(y_test)
#%%
#构建模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(64,activation='relu',input_shape=[len(X_train.keys())]),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(64,activation='relu'),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(64,activation='relu'),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(1)
])
# 编译模型
model.compile(optimizer='adam', loss='mse', metrics=['mae','mse'])
model.summary()
# 训练模型并保存历史数据
history = model.fit(X_train, y_train, epochs=3000, validation_split=0.3)
#%%
#model.save('roch_classification2_cnn.keras')
#%%
# 获取训练过程中的指标数值
mae = history.history['mae']
mse = history.history['loss']
val_mae = history.history['val_mae']
val_mse = history.history['val_mse']
plt.plot(mae, label='MAE')
plt.plot(val_mae, label='Validation MAE')
plt.title('MAE vs')
plt.legend()
plt.show()
plt.plot(mse, label='MSE')
plt.plot(val_mse, label='Validation MSE')
plt.title('MSE')
plt.legend()
plt.show()
# history.plot()
# plt.plot(history)
# plt.show()
print('MAE:', mae)
print('MSE:', mse)
#%%
y_mlp = model.predict(X_test)
#%%
y_test = pd.DataFrame(y_test)
y_mlp = pd.DataFrame(y_mlp)
y_mlp.index = y_arima.index
y_test['P1']=y_arima
y_test['P2']=y_mlp
print(y_test)
plt.figure()
plt.plot(y_test, label='Actual')
plt.legend(['y_true','y_arima','y_mlp'])
plt.show()
#%%
# 计算MAE,MSE,RMSE,MAPE
from sklearn import metrics
import math
MAE = metrics.mean_absolute_error(X_test.iloc[:,0],X_test.iloc[:,1])
MSE = metrics.mean_squared_error(X_test.iloc[:,0],X_test.iloc[:,1])
RMSE = math.sqrt(MSE)
MAPE = metrics.mean_absolute_percentage_error(X_test.iloc[:,0],X_test.iloc[:,1])
print('MAE:',MAE)
print('MSE:',MSE)
print('RMSE:',RMSE)
print('MAPE:',MAPE)
#%%
from sklearn.ensemble import RandomForestRegressor
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import mean_squared_error
# 初始化随机森林回归器
rf_regressor = RandomForestRegressor(n_estimators=2500,max_depth=100,random_state=42)
# 训练随机森林模型
rf_regressor.fit(X_train, y_train)
# 使用训练好的模型进行预测
y_regressor_pred = rf_regressor.predict(X_test)
print(y_regressor_pred)
y_regressor_pred = pd.DataFrame(y_regressor_pred)
print(y_regressor_pred)
y_regressor_pred.index = y_mlp.index
y_test['P3'] = y_regressor_pred
print(y_test)
plt.figure()
plt.plot(y_test, label='Actual')
plt.legend(['y_true','y_arima','y_mlp','y_regressor_pred'])
plt.show()
# 计算均方误差
mse = mean_squared_error(y_test['COUNT'], y_test['P3'])
print("Mean Squared Error:", mse)
#%%
from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error
# 1. 准备数据集
# 假设数据集已准备好,包含特征和目标变量
# 4. 定义模型
model = XGBRegressor(
n_estimators=3000, # 树的数量
max_depth=5, # 树的最大深度
learning_rate=0.3, # 学习率
random_state=42
)
# 5. 训练模型
model.fit(X_train, y_train)
# 6. 模型评估
y_XGBRegressor_pred = model.predict(X_test)
y_XGBRegressor_pred = pd.DataFrame(y_XGBRegressor_pred)
y_XGBRegressor_pred.index = y_mlp.index
y_test['P4'] = y_XGBRegressor_pred
print(y_test)
plt.figure()
plt.plot(y_test, label='Actual')
plt.legend(['y_true','y_arima','y_mlp','y_regressor_pred','y_XGBRegressor_pred'])
plt.show()
# 计算均方误差
mse = mean_squared_error(y_test['COUNT'], y_test['P3'])
print("Mean Squared Error:", mse)
mse = mean_squared_error(y_test['COUNT'], y_XGBRegressor_pred)
print("Mean Squared Error:", mse)
#%%
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error
# 4. 定义模型
model = SVR(kernel='rbf', C=1.0, epsilon=0.1)
# 5. 训练模型
model.fit(X_train, y_train)
# 6. 模型评估
y_SVR_pred = model.predict(X_test)
y_SVR_pred = pd.DataFrame(y_SVR_pred)
y_SVR_pred.index = y_mlp.index
y_test['P5'] = y_SVR_pred
print(y_test)
plt.figure()
plt.plot(y_test, label='Actual')
plt.legend(['y_true','y_arima','y_mlp','y_regressor_pred','y_XGBRegressor_pred','y_SVR_pred'])
plt.show()
# 计算均方误差
mse = mean_squared_error(y_test['COUNT'], y_test['P5'])
print("Mean Squared Error:", mse)
mse = mean_squared_error(y_test['COUNT'], y_SVR_pred)
print("Mean Squared Error:", mse)
#%%