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

【深度学习】搭建PyTorch神经网络进行气温预测

第一步 数据加载与观察

①导包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import torch.optim as optim
import warnings
warnings.filterwarnings("ignore")
%matplotlib inline

②加载数据

features = pd.read_csv("temps.csv")

#观察数据
features.head()

③整合日期,统一格式

import datetime

years = features["year"]
months = features["month"]
days = features["day"]

dates = [str(int(year)) + "-" +str(int(month)) + "-" +str(int(day)) for year,month,day in  zip(years,months,days)]
dates = [datetime.datetime.strptime(date,"%Y-%m-%d") for date in dates]

④绘图(主要用于观察数据走向)

# 绘图
plt.style.use("fivethirtyeight")
plt.rcParams['font.sans-serif'] = ['SimHei']

# 设置布局
fig,((ax1,ax2),(ax3,ax4)) = plt.subplots(nrows=2,ncols=2,figsize=(10,10))
fig.autofmt_xdate(rotation=45)

# 标签值
ax1.plot(dates,features["actual"])
ax1.set_xlabel("")
ax1.set_ylabel("Temperature")
ax1.set_title("当天真实最大温度")

ax2.plot(dates,features["temp_1"])
ax2.set_xlabel("")
ax2.set_ylabel("Temperature")
ax2.set_title("昨日最大温度")

ax3.plot(dates,features["temp_2"])
ax3.set_xlabel("Date")
ax3.set_ylabel("Temperature")
ax3.set_title("前日最大温度")

ax4.plot(dates,features["friend"])
ax4.set_xlabel("Date")
ax4.set_ylabel("Temperature")
ax4.set_title("朋友预测最大温度")

plt.tight_layout(pad=2)

注1:值得一提的是,如果日期没有转换为datetime类型,而是简单的字符串,在绘图的时候是无法正确显示的

即缺失本句:

dates = [datetime.datetime.strptime(date,"%Y-%m-%d") for date in dates]

注2

除了 `plot()` 方法,matplotlib 的 Axes 对象还提供了多种其他方法来创建不同类型的图表。以下是一些常见的方法:

1. **scatter(x, y, [s], [c])**: 创建散点图。`x` 和 `y` 分别是数据点的横坐标和纵坐标,`s` 是可选参数,用于指定点的大小,`c` 也是可选参数,用于指定点的颜色。

2. **bar(x, height)** 或 **barh(y, width)**: 创建条形图。`bar()` 创建垂直条形图,而 `barh()` 创建水平条形图。

3. **hist(x, bins)**: 创建直方图。`x` 是一个连续型变量的数据集,`bins` 参数指定了直方图中的柱数或区间范围。

4. **step(x, y)**: 创建阶梯图。与线图类似,但是值之间的连接是水平和垂直线段构成的台阶状。

5. **fill_between(x, y1, [y2])**: 在两条曲线之间填充颜色。`y1` 和 `y2` 分别定义了上下边界,默认情况下 `y2=0`。

6. **stackplot(x, y)**: 创建堆叠区域图。

7. **errorbar(x, y, [yerr], [xerr])**: 创建带误差棒的线图。`yerr` 和 `xerr` 分别指定了每个点在y轴和x轴方向上的误差范围。

8. **stem(x, y)**: 创建茎叶图,显示离散序列相对于x的位置。

9. **pie(sizes, [labels])**: 创建饼图。`sizes` 指定各部分的大小,`labels` 是可选参数,用来标记饼图中的各个扇区。

10. **imshow(X)**: 显示图像数据。`X` 是一个二维数组,表示图像的像素值。

11. **contour([X, Y,] Z)** 或 **contourf([X, Y,] Z)**: 创建等高线图或填充的等高线图。`Z` 是一个二维数组,表示高度值;`X` 和 `Y` 可选,提供坐标的网格。

这些只是 matplotlib 提供的一部分绘图方法,每种方法都有自己的参数选项,可以进一步定制图表的外观。对于更复杂或特定领域的图表,还可以使用 seaborn、plotly 等高级绘图库,它们基于 matplotlib 并扩展了其功能。

第二步 预处理

①独热编码

features = pd.get_dummies(features)
features.head()

注1:

pd.get_dummies(features) 是 Pandas 库中的一个函数,用于将分类变量(categorical variable)转换为哑变量(dummy variables),也称为 one-hot 编码。这样做是为了让机器学习算法能够处理非数值型数据,因为大多数机器学习算法需要输入的数据是数值形式的。

这行代码会创建一个新的 DataFrame features,其中原来的分类变量被替换为多个二进制(0 或 1)的列,每个新列代表原始分类变量的一个类别。如果一个样本属于某个类别,则对应的新列为 1;否则为 0。

例如,如果你有一个特征 "color" 包含三个类别:"Red", "Green", 和 "Blue",那么调用 pd.get_dummies() 后会生成三列:color_Red, color_Green, 和 color_Blue,并且每个样本在这三列中只会有一个值为 1,其余为 0。

②处理数据和预测值

labels = np.array(features["actual"])

features = features.drop("actual",axis=1)

feature_list = list(features.columns)

features = np.array(features)

注1:features = np.array(features)

本句将features从Pandas DataFrame的形式转换为Numpy数组,以便后续操作

③标准化数据

from sklearn import preprocessing
input_features = preprocessing.StandardScaler().fit_transform(features)

注1:

  • preprocessing.StandardScaler() 创建了一个 StandardScaler 的实例。StandardScaler 是一个类,它实现了对数据进行标准化的功能。

  • .fit_transform(features) 方法执行了两个操作:

    • fit: 计算训练数据的均值和标准差。这些统计信息将被用来标准化数据。

    • transform: 使用计算出的均值和标准差来标准化数据,即将每个特征减去其均值并除以其标准差,得到新的特征值。

第三步 构建神经网络模型

x = torch.tensor(input_features,dtype=float)
y = torch.tensor(labels,dtype=float)

# 权重参数初始化
weights1 = torch.randn((14,128),dtype=float,requires_grad = True)
biases1 = torch.randn(128,dtype=float, requires_grad = True)
weights2 = torch.randn((128,1),dtype=float,requires_grad = True)
biases2 = torch.randn(1,dtype=float,requires_grad = True)

learning_rate=0.001
losses=[]

for i in range(1000):
    # 计算隐藏层
    hidden = x.mm(weights1)+biases1
    # 加入激活函数
    hidden = torch.relu(hidden)
    # 预测结果
    predictions = hidden.mm(weights2)+biases2
    # 计算损失
    loss = torch.mean((predictions - y)**2)
    losses.append(loss.data.numpy())
    
    if i % 100 ==0:
        print("loss:",loss)
    
    # 反向传播计算
    loss.backward()
    # 更新参数
    weights1.data.add_(-learning_rate * weights1.grad.data)
    biases1.data.add_(-learning_rate * biases1.grad.data)
    weights2.data.add_(-learning_rate * weights2.grad.data)
    biases2.data.add_(-learning_rate * biases2.grad.data)
    # 每次迭代完清空
    weights1.grad.data.zero_()
    biases1.grad.data.zero_()
    weights2.grad.data.zero_()
    biases2.grad.data.zero_()
 

第四步 优化构建神经网络模型的方法

①构建模型

input_size = input_features.shape[1]
hidden_size = 128
output_size = 1
batch_size = 16

my_nn = torch.nn.Sequential(
    torch.nn.Linear(input_size,hidden_size),
    torch.nn.Sigmoid(),
    torch.nn.Linear(hidden_size,output_size)
)

cost = torch.nn.MSELoss(reduction = "mean")
optimizer = torch.optim.Adam(my_nn.parameters(),lr=0.001)

这段代码创建了一个简单的两层神经网络,定义了损失函数为均方误差,并选择了 Adam 作为优化器。Sequential 模块简化了模型构建的过程,使得代码更加简洁易读。此外,通过设置批量大小、隐藏层大小、输出大小等超参数,你可以灵活地调整模型以适应不同的任务需求。

要完成这个模型的训练过程,还需要编写一个训练循环,在其中进行前向传播、计算损失、反向传播以及参数更新。如果你想要进一步提升模型性能或复杂度,还可以考虑添加更多层、选择不同的激活函数、调整优化器及其参数等。

②训练模型

# 训练网络
losses = []
for i in range(1000):
    batch_loss = []
    #MINI-Batch方法来进行训练
    for start in range(0,len(input_features),batch_size):
        end = start+batch_size if start+batch_size<len(input_features) else len(input_features)
        xx = torch.tensor(input_features[start:end],dtype=torch.float,requires_grad = True)
        yy = torch.tensor(labels[start:end],dtype=torch.float,requires_grad = True)
        prediction =a my_nn(xx)
        loss = cost(prediction,yy)
        optimizer.zero_grad()
        loss.backward(retain_graph=True)
        optimizer.step()
        batch_loss.append(loss.data.numpy())
        
    if i%100==0:
        losses.append(np.mean(batch_loss))
        print(i,np.mean(batch_loss))

第五步 绘图观察

①准备数据

x = torch.tensor(input_features,dtype=torch.float)
predict = my_nn(x).data.numpy()

②处理格式

# 转换日期格式
dates = [str(int(year)) + "-" + str(int(month)) + "-" + str(int(day)) for year,month,day in zip(years,months,days)]
dates = [datetime.datetime.strptime(date,"%Y-%m-%d") for date in dates]

# 创建表格来存日期和其对应的标签数值
true_data = pd.DataFrame(data = {"date":dates,"actual":labels})

# 创建表格来村日期和其对应的模拟预测值
months = features[:,feature_list.index("month")]
days = features[:,feature_list.index("day")]
years = features[:,feature_list.index("year")]

test_dates = [str(int(year)) + '-' + str(int(month)) + '-' + str(int(day)) for year, month, day in zip(years, months, days)]
test_dates = [datetime.datetime.strptime(date, '%Y-%m-%d') for date in test_dates]

predictions_data = pd.DataFrame(data={"date":test_dates,"prediction":predict.reshape(-1)})

注1:

  • features 是一个二维数组或类似结构(如 NumPy 数组),其中每一行代表一个样本,每一列代表一个特征。

  • : 表示选取所有行。

  • feature_list.index("month") 返回的是要选择的列的索引。

  • 因此,features[:, feature_list.index("month")] 将选取 features 中对应于 "month" 列的所有元素,形成一个新的一维数组,这个数组包含了所有样本的月份信息。

注2:

predict.reshape(-1) 的具体含义如下:

  • reshape() 方法:这是 NumPy 数组的一个方法,用于改变数组的形状而不改变其数据。

  • -1 参数:当你传递 -1 作为参数时,NumPy 会自动计算该维度的大小,以确保新数组的总元素数量保持不变。换句话说,它会根据其他维度的大小来推断出合适的长度。例如,如果你有一个形状为 (n, 1) 的二维数组,并调用 .reshape(-1),结果将是一个形状为 (n,) 的一维数组。

在你的例子中,假设 predict 是一个形状为 (n, 1) 的二维数组,那么 predict.reshape(-1) 会将其转换为一个形状为 (n,) 的一维数组。这样做是为了确保 predictions_data 中的 prediction 列是一维的,从而与 date 列匹配,并且使得每个日期对应一个预测值。

③绘图

# 真实值
plt.plot(true_data["date"],true_data["actual"],"b-",label="actual")

# 预测值
plt.plot(predictions_data["date"],predictions_data["prediction"],"ro",label="prediction")
plt.xticks(rotation = 60)
plt.legend()

# 图名
plt.xlabel("Date")
plt.ylabel("Maximum Temperature")
plt.title("Actual and Predicted Values")

注1:

plt.legend():在图表中添加一个图例,显示之前定义的标签(如 "actual""prediction"),以便区分不同系列的数据。

注2:

"b-":指定线条样式为蓝色实线(b 表示蓝色,- 表示实线)。

"ro":指定标记样式为红色圆点(r 表示红色,o 表示圆形标记)。


至此,构建神经网络模型实现气温预测已完成。


http://www.kler.cn/a/518092.html

相关文章:

  • Qt 5.14.2 学习记录 —— 십구 事件
  • 豆包MarsCode 蛇年编程大作战 | 高效开发“蛇年运势预测系统”
  • Effective C++读书笔记——item23(用非成员,非友元函数取代成员函数)
  • Redis实现,分布式Session共享
  • S4 HANA Tax相关的定价过程
  • c#使用log4Net配置日志文件
  • idea maven本地有jar包,但还要从远程下载
  • 使用ArcMap或ArcGIS Pro连接达梦数据库创建空间数据库
  • 为什么redis会开小差?Redis 频繁异常的深度剖析与解决方案
  • 【ARM】解决MDK在打开工程的时候提示CMSIS的版本不对问题
  • kettle从入门到精通 第九十一课 ETL之kettle http接口下载文件流
  • Java设计模式:结构型模式→桥接模式
  • LabVIEW太阳能照明监控系统
  • PCI 总线学习笔记(三)
  • Vue3笔记——(五)路由
  • Kubernetes v1.28.0安装dashboard v2.6.1(k8s图形化操作界面)
  • kettle经验篇:分享两个小白常见问题
  • 免费获得Photoshop等设计软件的机会
  • CF 420A.Start Up(Java实现)
  • 14-6-2C++的list