记录一下,这个是在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文件到DataFrameprinterIdx = 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' # 将索引名称设置为DatetimeDataset.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)# 保存结果到CSVprediction_df = pd.DataFrame(predictions, columns=Dataset.columns[1:]) # 创建DataFramefuture_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) # 调用函数进行预测并保存结果
最后还加了可视化,挺直观的
数据集也已经绑定