DeepLearning in Pytorch|我的第一个NN-共享单车预测

目录

概要

一、数据准备

导入数据

数据可视化

二、设计神经网络

版本一

版本二(正片)

三、测试

小结


概要

我的第一个深度学习神经网络模型---利用Pytorch设计人工神经网络对某地区租赁单车的使用情况进行预测

输入节点为1个,隐含层为10个,输出节点数为1的小型人工神经网络,用数据的下标预测单车数量。

PS:

1.该神经网络无法达到解决实际问题的要求,但它结构简单,包含了神经网络的基本元素,可以达到初步入门深度学习以及熟悉Pytorch使用的效果,同时在实践过程中引出了过拟合现象。

2.Pytorch 2.2.1 (CPU) Python 3.6.13|Anaconda 环境

3.《深度学习原理与Pytorch实践》学习笔记

一、数据准备

导入数据

#导入需要使用的库
import numpy as np
import pandas as pd #读取csv文件的库
import matplotlib.pyplot as plt #绘图
import torch
import torch.optim as optim

这里我们使用来自GitHub的开源数据用作构建神经网络

#读取数据到内存中,rides为一个dataframe对象
data_path = 'dir/hour.csv' #文件路径
rides = pd.read_csv(data_path)
rides.head()

 可以看到成功读入的数据如下:c180d12fed994374b19958b1235a8648.png

数据可视化

我们用数据序号(0,1,2,3,···)与数据cnt(count)构建神经网络(hhh实际解决问题时当然不会这样做)

#我们取出最后一列的前50条记录来进行预测
counts = rides['cnt'][:50]#获得变量x,它是1,2,……,50
x = np.arange(len(counts))# 将counts转成预测变量(标签):y
y = np.array(counts)# 绘制一个图形,展示曲线长的样子
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
plt.plot(x, y, 'o-') # 绘制原始数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.show()

 这里我们取出前五十条记录用于模型,绘制出序号与cnt关系,大致数据分布图如下:

6e8d79ce91d948f0ae6f3135c89ca57e.png

二、设计神经网络

我们构建一个单一输入,10个隐含层单元,1个输出单元的人工神经网络预测器

版本一

#取出数据库中的最后一列的前50条记录来进行预测
counts = rides['cnt'][:50]#创建变量x,它是1,2,……,50
x = torch.tensor(np.arange(len(counts), dtype = float), requires_grad = True)# 将counts转成预测变量(标签):y
y = torch.tensor(np.array(counts, dtype = float), requires_grad = True)# 设置隐含层神经元的数量
sz = 10# 初始化所有神经网络的权重(weights)和阈值(biases)
weights = torch.randn((1, sz), dtype = torch.double, requires_grad = True) #1*10的输入到隐含层的权重矩阵
biases = torch.randn(sz, dtype = torch.double, requires_grad = True) #尺度为10的隐含层节点偏置向量
weights2 = torch.randn((sz, 1), dtype = torch.double, requires_grad = True) #10*1的隐含到输出层权重矩阵learning_rate = 0.001 #设置学习率
losses = []# 将 x 转换为(50,1)的维度,以便与维度为(1,10)的weights矩阵相乘
x = x.view(50, -1)
# 将 y 转换为(50,1)的维度
y = y.view(50, -1)for i in range(100000):# 从输入层到隐含层的计算hidden = x * weights + biases# 将sigmoid函数作用在隐含层的每一个神经元上hidden = torch.sigmoid(hidden)#print(hidden.size())# 隐含层输出到输出层,计算得到最终预测predictions = hidden.mm(weights2)##print(predictions.size())# 通过与标签数据y比较,计算均方误差loss = torch.mean((predictions - y) ** 2) #print(loss.size())losses.append(loss.data.numpy())# 每隔10000个周期打印一下损失函数数值if i % 10000 == 0:print('loss:', loss)#对损失函数进行梯度反传loss.backward()#利用上一步计算中得到的weights,biases等梯度信息更新weights或biases中的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)# 清空所有变量的梯度值。# 因为pytorch中backward一次梯度信息会自动累加到各个变量上,因此需要清空,否则下一次迭代会累加,造成很大的偏差weights.grad.data.zero_()biases.grad.data.zero_()weights2.grad.data.zero_()

运行过程:7f9cf5dc759d4399b9bfa03035dc4496.png 

程序运行大约14min

# 打印误差曲线
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()

打印出误差曲线如下 

2519015d83b14c7dbf929bb8e857d6c5.png

由该曲线可以看出,随着时间的推移,神经网络预测的误差的确在一步步减小。而且,大约到20000步后,误差基本就不会出现明显的下降了

x_data = x.data.numpy() # 获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') # 绘制原始数据yplot, = plt.plot(x_data, predictions.data.numpy())  #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction under 1000000 epochs']) #绘制图例
plt.show()

我们可以把训练好的网络对这50个数据点的预测曲线绘制出来,并与标准答案y进行对比: 

378621bc550142e0859e83852b78f0c7.png

预测曲线在第一个波峰比较好地拟合了数据,但在这之后却偏差较大

版本二(正片)

上面的程序之所以跑得慢,是因为x的取值范围1~50。 而由于所有权重和biases的取值范围被设定为-1,1的正态分布随机数,这样就导致 我们输入给隐含层节点的数值范围为-50~50, 要想将sigmoid函数的多个峰值调节到我们期望的位置需要耗费很多的计算时间

我们的解决方案就是将输入变量的范围归一化

#取出最后一列的前50条记录来进行预测
counts = rides['cnt'][:50]#创建归一化的变量x,它的取值是0.02,0.04,...,1
x = torch.tensor(np.arange(len(counts), dtype = float) / len(counts), requires_grad = True)# 创建归一化的预测变量y,它的取值范围是0~1
y = torch.tensor(np.array(counts, dtype = float), requires_grad = True)#隐藏神经元个数
sz = 10# 初始化所有神经网络的权重(weights)和阈值(biases)
weights = torch.randn((1, sz), dtype = torch.double, requires_grad = True) #1*10的输入到隐含层的权重矩阵
biases = torch.randn(sz, dtype = torch.double, requires_grad = True) #尺度为10的隐含层节点偏置向量
weights2 = torch.randn((sz, 1), dtype = torch.double, requires_grad = True) #10*1的隐含到输出层权重矩阵learning_rate = 0.001 #设置学习率
losses = []# 将 x 转换为(50,1)的维度,以便与维度为(1,10)的weights矩阵相乘
x = x.view(50, -1)
# 将 y 转换为(50,1)的维度
y = y.view(50, -1)for i in range(100000):# 从输入层到隐含层的计算hidden = x * weights + biases# 将sigmoid函数作用在隐含层的每一个神经元上hidden = torch.sigmoid(hidden)# 隐含层输出到输出层,计算得到最终预测predictions = hidden.mm(weights2)# + biases2.expand_as(y)# 通过与标签数据y比较,计算均方误差loss = torch.mean((predictions - y) ** 2) losses.append(loss.data.numpy())# 每隔10000个周期打印一下损失函数数值if i % 10000 == 0:print('loss:', loss)#对损失函数进行梯度反传loss.backward()#利用上一步计算中得到的weights,biases等梯度信息更新weights或biases中的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)# 清空所有变量的梯度值。# 因为pytorch中backward一次梯度信息会自动累加到各个变量上,因此需要清空,否则下一次迭代会累加,造成很大的偏差weights.grad.data.zero_()biases.grad.data.zero_()weights2.grad.data.zero_()

运行程序,耗时约9min 

plt.semilogy(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()

  绘出损失曲线:d5d5eb5946d344128eaf55a1b5d5ee8a.png

x_data = x.data.numpy() # 获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') # 绘制原始数据
yplot, = plt.plot(x_data, predictions.data.numpy())  #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction']) #绘制图例
plt.show()

得到曲线如下: 

7ab00ced5e4f44338319cfd32d3fc143.png

显然拟合效果更好了!

三、测试

我们就需要用训练好的模型来做预测,将后面50条数据(50~100)作为测试集。此时x取值是51, 52, …, 100,同样也要除以50: 

counts_predict = rides['cnt'][50:100] #读取待预测的接下来的50个数据点#首先对接下来的50个数据点进行选取,注意x应该取51,52,……,100,然后再归一化
x = torch.tensor((np.arange(50, 100, dtype = float) / len(counts)), requires_grad = True)
#读取下50个点的y数值,不需要做归一化
y = torch.tensor(np.array(counts_predict, dtype = float), requires_grad = True)x = x.view(50, -1)
y = y.view(50, -1)# 从输入层到隐含层的计算
hidden = x * weights + biases# 将sigmoid函数作用在隐含层的每一个神经元上
hidden = torch.sigmoid(hidden)# 隐含层输出到输出层,计算得到最终预测
predictions = hidden.mm(weights2)# 计算预测数据上的损失函数
loss = torch.mean((predictions - y) ** 2) 
print(loss)x_data = x.data.numpy() # 获得x包裹的数据
plt.figure(figsize = (10, 7)) #设定绘图窗口大小
xplot, = plt.plot(x_data, y.data.numpy(), 'o') # 绘制原始数据
yplot, = plt.plot(x_data, predictions.data.numpy())  #绘制拟合数据
plt.xlabel('X') #更改坐标轴标注
plt.ylabel('Y') #更改坐标轴标注
plt.legend([xplot, yplot],['Data', 'Prediction']) #绘制图例
plt.show()

得到结果如下:

直线是我们的模型给出的预测曲线,圆点是实际数据所对应的曲线。

62f5c9ff256e4f41bafb5906d352a872.png模型预测与实际数据竟然完全对不上!为什么我们的神经网络可以非常好地拟合已知的50个数据点,却在测试集上出错了呢?因为y(单车数量)与x(数据序号)根本没有关系!这就是在机器学习中最常见的困难---过拟合

过拟合(Overfitting)是指机器学习模型在训练数据上表现很好,但在测试数据上表现较差的情况。过拟合通常发生在模型过度复杂或者训练数据量太少的情况下。

对于我们的单车预测模型,问题显然在于我们要求模型学习 单车数量y 与 数据序号x 之间的关系,模型通过学习我们给出的前五十组数据(训练集)学会了它所认为的样本特征,但当我们引入后面50组样本(测试集)时,我们发现模型学到的特征是没有意义的,它只能反映训练集中的某些特点。

如果要解决这个问题,我们就应该让模型学习关于样本的更多特征,如:星期几、是否节假日、温度、湿度等(显然这些才是真正会影响x的因素)。当然从理论上讲,这样得到的神经网络更复杂,但显然他的预测更能达到我们想要的效果。

小结

对于我们的单车预测模型,问题显然在于我们要求模型学习 单车数量y 与 数据序号x 之间的关系,模型通过学习我们给出的前五十组数据(训练集)学会了它所认为的样本特征,但当我们引入后面50组样本(测试集)时,我们发现模型学到的特征是没有意义的,它只能反映训练集中的某些特点。

如果要解决这个问题,我们就应该让模型学习关于样本的更多特征,如:星期几、是否节假日、温度、湿度等(显然这些才是真正会影响x的因素)。当然从理论上讲,这样得到的神经网络更复杂,但显然他的预测更能达到我们想要的效果。

主要参考资料:《深度学习原理与Pytorch实践》

参考代码:bike1.py · che.melsm/DeepLearning Project - Gitee.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/739174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大预言模型——ChatGPT,Claude3、Sora、等技术

原文链接:大预言模型——ChatGPT,Claude3、Sora、等技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247596849&idx3&sn111d68286f9752008bca95a5ec575bb3&chksmfa823ad6cdf5b3c0c446eceb5cf29cccc3161d746bdd9f26cc060f78c359ec3e2a8f35…

【Rust】——use关键字

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

预测建模案例-预防机器故障

预测分析是一种使用当前数据和历史数据来预测活动、行为和趋势的高级分析形式。它涉及将统计分析技术、数据查询和机器学习算法应用于数据集。预测分析还涉及创建预测模型,以对特定操作或事件发生的可能性设置数值或评分。 预测分析寻找数据模式并预测未来趋势&…

Java开发从入门到精通(一):Redis

目录: Redis介绍 Redis是单线程多路IO复用技术 Redis基础操作 Redis使用场景 Redis支持的java客户端 Memcache与Redis的区别 Mysql和Redis的区别 Redis的8种数据类型,以及每种数据类型的使用场景 Redis事务 1、Redis介绍 Redis是一个开源的键值存储系统。…

【Unity】二进制文件 数据持久化(修改版)【个人复习笔记/有不足之处欢迎斧正/侵删】

变量的本质都是二进制,在内存中都以字节的形式存储着,通过sizeof方法可以看到常用变量类型占用的字节空间长度(1byte 8bit,1bit(位)不是0就是1) 二进制文件读写的本质:将各类型变量转换为字节数组&#xf…

day1-C++

1>提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数要求使用C风格字符串完成。 代码&#xff1a; #include <iostream> #include <string.h> using namespace std;int main() {string str ;int low 0, …

智慧公厕系统架构分析及应用探索

智慧公厕是运用物联网技术和云计算平台&#xff0c;实现对公共厕所的智能管理和优化的未来式公共厕所信息化整体解决方案。该系统由应用层、平台层、传输层和感知层组成&#xff0c;各层相互配合&#xff0c;共同构建一个高效、智能的公厕运营环境。 一、感知层&#xff1a; …

Android Kotlin知识汇总(三)Kotlin 协程

Kotlin的重要优势及特点之——结构化并发 Kotlin 协程让异步代码像阻塞代码一样易于使用。协程可大幅简化后台任务管理&#xff0c;例如网络调用、本地数据访问等任务的管理。本主题介绍如何使用 Kotlin 协程解决以下问题&#xff0c;从而让您能够编写出更清晰、更简洁的应用代…

Vue基础之Vuex状态管理

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a; 给自己一个梦想&#xff0c;给世界一个惊喜。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章目录 什么是Vuex&…

Jira自动化的实用工具——ScriptRunner简介及最佳实践

近日&#xff0c;龙智举办的DevSecOps研讨会年终专场“趋势展望与实战探讨&#xff1a;如何打好DevOps基础、赋能创新”在上海圆满落幕。龙智Atlassian技术与顾问咨询团队&#xff0c;以及清晖、JamaSoftware、CloudBees等生态伙伴的嘉宾发表了主题演讲&#xff0c;分享他们在D…

免费分享一套SpringBoot+Vue体育馆(预约)管理系统,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue体育馆(预约)管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue体育馆(预约)管理系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue体育馆(预约)管理系统 Java毕…

【高通camera hal bug分析】高通自带相机镜像问题

首先打了两个log&#xff0c;一个是开启镜像的log&#xff0c;还有一个是没有开启镜像的log&#xff0c;如果我们开启镜像以后&#xff0c;观察开启镜像log发现 , 这段代码走的没有任何问题&#xff0c;因为Flip的值等于1了。 关闭镜像log如下&#xff1a; 如果我们不开启镜像…

java中常用的查询算法

1、线性查找 直接从左往右遍历&#xff0c;有则返回 适合数组或链表 public static void main(String[] args) {int[] arr { 12, 34, 32, 56, 78, 23, 34, 56, 67 };int num 34;System.out.println(fangno(arr, num));}public static ArrayList fangno(int[] arr, int num…

Java集合八股文总结

Java集合八股文总结 Collection Set TreeSet 基于红黑树实现&#xff0c;支持有序性操作&#xff0c;例如根据一个范围查找元素的操作。但是查找效率不如 HashSet&#xff0c;HashSet 查找的时间复杂度为 O(1)&#xff0c;TreeSet 则为 O(logN)。HashSet 基于哈希表实现&…

Linux下的系统字体分类

在上次解决Avalo在/usrnia启动问题的时候涉及到了字体&#xff0c;因此特意了解了一下&#xff0c;/share/fonts/目录下存储了不同类型的字体文件&#xff0c;其各代表的意义如下&#xff1a; 我使用的是ubuntu20.04版本&#xff0c;该目录下的文件夹有&#xff1a; /usr/shar…

Google 在 MySQL 中推进矢量搜索,在 LLM 支持方面超越 Oracle

谷歌已将向量搜索引入其 MySQL 数据库服务&#xff0c;这一步领先了 MySQL 的所属公司 Oracle&#xff0c;迄今为止&#xff0c;Oracle 尚未给 MySQL 添加任何大型语言模型&#xff08;LLM&#xff09;方面的功能。 谷歌云数据库副总裁安迪古特曼斯 (Andi Gutmans) 表示&#…

el-form表单中,对非表单内字段增加校验的方法

1、问题说明&#xff1a; 在开发表单的时候&#xff0c;可能会遇到el-form-item中绑定的值不在表单绑定的数据对象中。 此时用prop绑定该字段名是无效的&#xff0c;需要单独对这个字段进行校验。 在el-form-item中有一个属性 error 。用于表单域验证错误信息&#xff0c;设…

Java SE入门及基础(37)

Object 类常用方法 Object类中定义的方法大多数都是属于 native 方法&#xff0c; native 表示的是本地方法&#xff0c;实现方式是在 C 中。 1. getClass() public final Class getClass () //The getClass() method returns a Class object, which has methods you can…

【算法】KY67 整数奇偶排序

描述 输入10个整数&#xff0c;彼此以空格分隔。重新排序以后输出(也按空格分隔)&#xff0c;要求: 1.先输出其中的奇数,并按从大到小排列&#xff1b; 2.然后输出其中的偶数,并按从小到大排列。 输入描述&#xff1a; 任意排序的10个整数&#xff08;0&#xff5e;100&#x…

灰度发布难以追踪?你可能用错了工具

灰度发布进行可观测性的主要方式是通过收集和分析用户在使用新版本产品或服务时的数据&#xff0c;以此来评估新版本的性能、稳定性和用户满意度。这个过程通常包括以下几个步骤&#xff1a; 定义观测指标&#xff1a;首先&#xff0c;需要定义一套合适的观测指标&#xff08;…