(二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

深度学习pytorch系列第二篇,第一篇实现的是分类任务,这篇是回归任务,大差不差,重在理解,具体的理解内容我都以注释的形式放在了代码中,方便大家阅读


一、数据集

想要复现的可以下载
链接:网盘链接
提取码:k6a4

二、导入数据以及展示部分

1.导入数据集以及对数据集进行处理

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
# 过滤警告
import warnings
warnings.filterwarnings("ignore")
# 读取数据
features = pd.read_csv('data/temps.csv')
#
#看看数据长什么样子
# print(features.head())
# print('数据维度:', features.shape)
# 数据维度:(348, 9),348条数据,每条8个特征x,1个标签y
# 处理时间数据
import datetime
# 分别得到年,月,日
years = features['year']
months = features['month']
days = features['day']
#
# # datetime格式
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]
# 在打印的结果中,每个datetime.datetime对象的后面两个0表示小时和分钟,没有时默认为0
# print(dates[:5])
# 独热编码
# # 将字符串进行onehot
# # 周一 周二 周三 周四 周五 周六 周天
# # 如果是周一,编码就是
# # 1000000
# Pandas库中的get_dummies函数,是一种独热编码(One-Hot Encoding)的方法
features = pd.get_dummies(features)

# print(features.head(5))
# print(features.shape)
# 此时的数据维度:(348, 15),多的7个是日期的七天
# 取标签
labels = np.array(features['actual'])
# 在特征中去掉标签,features.drop,去掉标签列
features= features.drop('actual', axis = 1)
# 名字单独保存一下,以备后患
feature_list = list(features.columns)
# 转换成合适的格式
features = np.array(features)
# print(features.shape)
# print(features)
"""
数据标准化
由于神经网络在训练的过程中具有倾向性,数值越大,认为越重要
# 但是在月份这种重要程度与数值无关的特征上,这种倾向性就会出错
# 因此进行标准化,使数据以零点为中心均匀分布
# (x-u)/σ
# x-u  去均值
# /σ  除以标准差:让离散数据更加收敛
标准化通常是针对特征而不是标签的。
标准化的目的是使特征具有相同的尺度,以便模型能够更好地学习权重并提高模型的性能。
标签(也称为目标变量)通常不需要标准化,因为它们是模型试图预测的值,而不是用于学习权重的输入。
"""
from sklearn import preprocessing
input_features = preprocessing.StandardScaler().fit_transform(features)
"""
[ 0.         -1.5678393  -1.65682171 -1.48452388 -1.49443549 -1.3470703
 -1.98891668  2.44131112 -0.40482045 -0.40961596 -0.40482045 -0.40482045
 -0.41913682 -0.40482045]
 标准化处理后的数据以零点为中心,均匀分布
"""

上述代码中的初始数据集为:
在这里插入图片描述
处理完成后的数据样貌:
在这里插入图片描述

2.展示数据(看看就好)

代码如下(示例):

# 该段是展示一下数据的样貌
plt.style.use('fivethirtyeight')
# 设置布局
# 4个子图,两行两列
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize = (10,10))
# 坐标倾斜45度
fig.autofmt_xdate(rotation = 45)

# 标签值
ax1.plot(dates, features['actual'])
ax1.set_xlabel(''); ax1.set_ylabel('Temperature'); ax1.set_title('Max Temp')
# 昨天
ax2.plot(dates, features['temp_1'])
ax2.set_xlabel(''); ax2.set_ylabel('Temperature'); ax2.set_title('Previous Max Temp')
#
# 前天
ax3.plot(dates, features['temp_2'])
ax3.set_xlabel('Date'); ax3.set_ylabel('Temperature'); ax3.set_title('Two Days Prior Max Temp')
#
# 朋友感觉的值
ax4.plot(dates, features['friend'])
ax4.set_xlabel('Date'); ax4.set_ylabel('Temperature'); ax4.set_title('Friend Estimate')
# 子图之间间隔多少
plt.tight_layout(pad=2)
plt.show()

展示图如下:
在这里插入图片描述


三(1)、搭建网络进行预测(理解版)

该过程是一步一步构建网络,促进理解,后边会附上更为简单的网络结构


x = torch.tensor(input_features, dtype=float)
y = torch.tensor(labels, dtype=float)
# # 权重参数初始化
# (14, 128),将14个特征转成128个神经元,可以理解为转成128个特征
# requires_grad = True,是否求导,也就是是否记录梯度
weights = torch.randn((14, 128), dtype=float, requires_grad=True)
biases = 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(weights) + biases
    # 加入激活函数,非线性映射
    hidden = torch.relu(hidden)
    # 预测结果  :h1*w2+b2=预测值
    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()

    # 更新参数
    #     grad.data  取梯度,然后乘以学习率,应该沿着梯度的反方向更新
    weights.data.add_(- learning_rate * weights.grad.data)
    biases.data.add_(- learning_rate * biases.grad.data)
    weights2.data.add_(- learning_rate * weights2.grad.data)
    biases2.data.add_(- learning_rate * biases2.grad.data)

    # 每次迭代都得记得清空
    #     每次迭代过程都是独立的,之前计算的梯度要清零
    # 在torch中,如果不清零,梯度就会累加
    weights.grad.data.zero_()
    biases.grad.data.zero_()
    weights2.grad.data.zero_()
    biases2.grad.data.zero_()
print(predictions.shape)
print(predictions)

三(2)、搭建网络进行预测(应用版)

实际应用中,往往会这样实现

# 更简单的构建网络模型
# 取特征个数
# 0是样本数;1是特征数
input_size = input_features.shape[1]
# print(input_size)  14 有14个特征
# 隐层个数
hidden_size = 128
output_size = 1
batch_size = 16
# Sequential序列模块,按顺序执行
my_nn = torch.nn.Sequential(
    # 计算隐层,相当于wx+b,参数是自动更新的
    torch.nn.Linear(input_size, hidden_size),
#     激活函数
    torch.nn.Sigmoid(),
#     预测结果  :h1*w2+b2=预测值
    torch.nn.Linear(hidden_size, output_size),
)
# 计算损失
# reduction='mean  平均损失
cost = torch.nn.MSELoss(reduction='mean')
# 优化器
# my_nn.parameters() 更新nn中所有参数
optimizer = torch.optim.Adam(my_nn.parameters(), lr = 0.001)
# ADM优化器,比SGD(梯度下降)效果好,效率高
# 训练网络
losses = []
# 迭代1000次
for i in range(1000):
    #     每次取一个batch的数据,每次只取一批数据
    batch_loss = []
    # MINI-Batch方法来进行训练
    #   for start in range(0, len(input_features), batch_size):
    # 从0开始,到整个数据结束,取batch,间隔是一个batch_size大小
    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 = my_nn(xx)
        loss = cost(prediction, yy)
        #         通过优化器进行梯度清零
        optimizer.zero_grad()
        #     反向传播
        loss.backward(retain_graph=True)
        #     更新参数
        optimizer.step()
        #     将每一个batch的损失相加
        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)})
# 真实值
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.show()
# 图名
plt.xlabel('Date'); plt.ylabel('Maximum Temperature (F)'); plt.title('Actual and Predicted Values');
# 层数越来越对,就会过拟合
# 什么是过拟合?过拟合(Overfitting)是指机器学习模型在训练数据上表现得很好,但在未见过的新数据上表现较差的现象。

在这里插入图片描述

总结

pytorch学习的第二篇啦,慢慢更新ing

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值