• (二)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]
     标准化处理后的数据以零点为中心,均匀分布
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

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

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

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


    三(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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    三(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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    四、 对预测结果进行一个展示,蓝色真实值,红色预测值

    # 转换日期格式
    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)是指机器学习模型在训练数据上表现得很好,但在未见过的新数据上表现较差的现象。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    总结

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

  • 相关阅读:
    java计算机毕业设计济南旅游网站MyBatis+系统+LW文档+源码+调试部署
    CVE-2022-32532 Apache Shiro RegExPatternMatcher 认证绕过复现
    jsp公交查询系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
    不甘于被强势厂商捆绑,中国移动未来或自研5G基站
    为什么 Python 适合初学者?如何开始学习 Python?
    数百个模型放在面前,金融机构要如何高效管理
    负载均衡 dubbo
    微信小程序毕业设计健康食谱菜谱系统微信小程序+后台管理系统|前后分离VUE.js
    Flink 数据源
    0.网络是怎么连接的 --- 前言
  • 原文地址:https://blog.csdn.net/weixin_42421914/article/details/134464369