记录一下,这个是在national university of singapore,黄教授给我们布置的任务,做了一个北京的已知十年的打印量,预测100天的打印机大作业,我们使用了lstm模型,就是两层神经网络,同时dropout的加入为了防止过拟合问题,验证集是最后的100个,后续优化打算往里面使用聚类,加入neuralprophet,效果应该会更好,也可以加入GANs
import numpy as np # 导入NumPy库,用于数学运算
import pandas as pd # 导入Pandas库,用于数据分析
import datetime # 导入datetime库,用于处理日期和时间
from sklearn.preprocessing import MinMaxScaler # 从sklearn库导入MinMaxScaler,用于数据标准化
from tensorflow.keras.models import Sequential # 从Keras库导入Sequential模型,用于构建神经网络
from tensorflow.keras.layers import LSTM, Dense, Dropout # 从Keras库导入LSTM, Dense, Dropout层
import matplotlib.pyplot as plt # 导入matplotlib.pyplot,用于数据可视化
# 定义一个转换数据的函数
def transform(path):
df = pd.read_csv(open(path, 'rb'), low_memory=False) # 读取CSV文件到DataFrame
printerIdx = np.array(df['printerIndex']) # 从DataFrame中提取打印机索引
usage = np.array(df['usage']) # 提取使用数据
date = np.array(df['date']) # 提取日期数据
numofkinds = len(np.unique(printerIdx)) # 计算不同打印机种类的数量
numofday = len(np.unique(date)) # 计算不同日期的数量
date = np.unique(date) # 获取唯一的日期数组
usage = np.reshape(usage, [numofkinds, numofday]) # 重塑使用数据数组以匹配打印机种类和日期
df_output = pd.DataFrame(usage) # 创建新的DataFrame来存储使用数据
df_output.columns = date # 将日期设置为DataFrame的列
return df_output # 返回处理后的数据集
# 定义数据加载函数
def DataLoading(path):
Dataset = transform(path) # 调用transform函数处理数据
TOTALDAYNUM = Dataset.shape[1] # 获取数据集中的日期总数
TOTALDEVICENUM = Dataset.shape[0] # 获取数据集中的设备总数
# 遍历日期列,将字符串转换为datetime对象
for colIdx in range(TOTALDAYNUM):
tmpDate = datetime.datetime.strptime(Dataset.columns[colIdx], '%Y-%m-%d %H:%M:%S.%f')
Dataset.rename(columns={Dataset.columns[colIdx]: tmpDate}, inplace=True)
Dataset = Dataset.transpose() # 转置数据集
Dataset.index.name = 'Datetime' # 将索引名称设置为Datetime
Dataset.reset_index(inplace=True) # 重置索引
# 遍历设备列,重命名列以匹配打印机索引
for colIdx in range(TOTALDEVICENUM):
tmpColName = 'PrinterIdx' + str(Dataset.columns[colIdx + 1])
Dataset.rename(columns={Dataset.columns[colIdx + 1]: tmpColName}, inplace=True)
date = Dataset.iloc[:, 0].values # 获取日期列
return Dataset, date # 返回处理后的数据集和日期
# 定义LSTM预测、可视化和保存结果的函数
def predict_and_save(path, save_path):
# 加载数据
Dataset, date = DataLoading(path)
# 标准化数据
scaler = MinMaxScaler(feature_range=(0, 1)) # 创建MinMaxScaler实例
scaled_data = scaler.fit_transform(Dataset.iloc[:, 1:].values) # 对数据进行标准化
# 定义创建时间序列数据集的函数
def create_dataset(data, look_back=100):
X, Y = [], [] # 初始化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 = 100 # 设置时间步长
X, Y = create_dataset(scaled_data, look_back) # 创建数据集
# 划分训练集和测试集
trainX, testX = X[:-look_back], X[-look_back:] # 分割X数据集
trainY, testY = Y[:-look_back], Y[-look_back:] # 分割Y数据集
# 调整形状以适配LSTM网络
trainX = np.reshape(trainX, (trainX.shape[0], trainX.shape[1], trainX.shape[2]))
testX = np.reshape(testX, (testX.shape[0], testX.shape[1], testX.shape[2]))
# 构建LSTM模型
model = Sequential() # 创建Sequential模型
model.add(LSTM(50, return_sequences=True, input_shape=(trainX.shape[1], trainX.shape[2])))
model.add(Dropout(0.2)) # 添加Dropout层防止过拟合
model.add(LSTM(50))
model.add(Dropout(0.2)) # 再次添加Dropout层防止过拟合
model.add(Dense(Dataset.shape[1] - 1)) # 添加Dense层进行预测
model.compile(optimizer='adam', loss='mean_squared_error') # 编译模型
# 训练模型
model.fit(trainX, trainY, epochs=50, batch_size=32, validation_data=(testX, testY))
# 预测未来100天的打印量
futureX = testX[-1].reshape(1, look_back, Dataset.shape[1] - 1) # 准备输入数据
predictions = [] # 初始化预测结果列表
for _ in range(100): # 进行100次预测
pred = model.predict(futureX) # 预测
predictions.append(pred[0]) # 添加预测结果
futureX = np.roll(futureX, -1, axis=1) # 滚动输入数据
futureX[0, -1] = pred # 更新最后一个时间步的数据
# 反标准化预测结果
predictions = scaler.inverse_transform(predictions)
# 后处理:确保所有预测值为非负数
predictions = np.clip(predictions, 0, None)
# 保存结果到CSV
prediction_df = pd.DataFrame(predictions, columns=Dataset.columns[1:]) # 创建DataFrame
future_dates = pd.date_range(start=date[-1], periods=101, freq='D')[1:] # 生成未来日期
prediction_df['Date'] = future_dates # 添加日期列
prediction_df.set_index('Date', inplace=True) # 将日期设置为索引
# 保存到指定路径
prediction_df.to_csv(save_path) # 保存CSV文件
print(f"Predictions saved to {save_path}") # 打印保存信息
# 可视化
plt.figure(figsize=(12, 6)) # 创建图形
for column in prediction_df.columns: # 遍历列
plt.plot(prediction_df.index, prediction_df[column], label=column) # 绘制折线图
plt.title('Predicted Printer Usage for the Next 100 Days') # 设置标题
plt.xlabel('Date') # 设置X轴标签
plt.ylabel('Predicted Usage') # 设置Y轴标签
plt.legend(loc='upper right') # 设置图例位置
plt.show() # 显示图形
# 使用示例
data_path = 'D:\\桌面\\singapore\\Model_Beijing_Assignment.csv' # 数据文件路径
save_path = 'D:\\桌面\\singapore\\prediction.CSV' # 预测结果保存路径
predict_and_save(data_path, save_path) # 调用函数进行预测并保存结果
最后还加了可视化,挺直观的
数据集也已经绑定