【需求实现】Tensorflow2的曲线拟合(一):数据集分割

news2024/11/17 9:57:43

神经网络中输入多少数据就输出多少数据的情况如何实现

  • 导读
  • 数据集长什么样?
  • 怎么分割数据集?
    • 时间窗口分析模板
    • 我知道你很急,但你先别急
  • 换个思路

导读

在实习的过程中遇到了这样一种需求:给定一条序列,并另外给定一条期望序列,要求做出拟合。同时,给定序列的时候并不是只给一条,而是给了几万条,要寻找出普遍共性。在实现的过程中,中间也是踩了很多坑,所以最后写出这个经验总结帖,以免忘记。

数据集长什么样?

出于公司数据保密的原则,这里就采用模拟数据:

给定一条 f ( x ) = sin ⁡ ( x ) f(x)=\sin(x) f(x)=sin(x),再给定一条 g ( x ) = cos ⁡ ( 2 x ) + 0.3 g(x)=\cos(2x)+0.3 g(x)=cos(2x)+0.3。当然,为了让数据看起来不那么规则,我们在 g ( x ) g(x) g(x)中加入高斯噪声 N ( 0 , 1 ) N(0,1) N(0,1)。最后,数据集中一共 1 1 1万组数据,每组有 2 2 2条序列,每条序列 50 50 50个浮点数。

这就是基本情况了。

为了更直观的感受数据集,这里就直接画图画出来。

在绘图之前,有一个问题需要格外强调一下:这里样本是 f ( x ) f(x) f(x) g ( x ) g(x) g(x),我们只需要找出 f ( x ) f(x) f(x) g ( x ) g(x) g(x)之间的关系。所以在某种意义上来说,样本是 x x x无关的,无论 x x x怎么样都不会影响到后续神经网络的迭代学习过程。这也解释了为什么接下来绘图都将从 x = 0 x=0 x=0开始,而不是从 x = k π 2 ( k = 0 , 1 , 2 , … ) x=\frac{k\pi}{2}(k=0,1,2,\ldots) x=2(k=0,1,2,)开始。

在这里插入图片描述

图1 数据集大概长什么样子

不太好看的样子

怎么分割数据集?

按照正常标准而言,需要按照 6 : 2 : 2 6:2:2 6:2:2的比例分割为训练集、验证集以及测试集。

当然你也可以为了方便,只按照 7 : 3 7:3 7:3的比例分割为训练集与测试集。因为验证集在验证的过程中并不会对模型产生直接的修改,而是给你一个大概的参考。

那么具体又应该如何划分呢?这里可是有 1 × 1 0 4 × 2 × 50 = 1 0 6 1\times10^4\times2\times50=10^6 1×104×2×50=106个浮点数,并且自变量与因变量在数目上是 1 : 1 1:1 1:1的比例,各 5 × 1 0 5 5\times10^5 5×105个。

P.S.:我属于比较笨的类型,解决问题先套模板。所以在接下来的分析过程中,也是采用逐个尝试的方式进行讲解。

时间窗口分析模板

考虑到是序列的话,那有没有可能是时间序列分析?也就是经典的股票预测模板?

当然是有可能的。

于是,就开始了一系列的操作:

  • 首先将 1 1 1万组数据合并为 1 1 1组数据,然后按照固定的步长顺序分割,形成一个个一维数组,在Python中存储为list类型;
  • 然后将这一个个一维数组拼起来,形成一个庞大的二维数组,并使用pandas中的DataFrame存储为二维表;
  • 最后,考虑样本数据本身就具有一定的随机性,所以不考虑随机打乱顺序的过程,直接按顺序取一定比例,最后将数据集划分为 6 : 2 : 2 6:2:2 6:2:2

这样思考当然是正确的,也必然是能够在一定程度上拟合的。

如何写代码呢?在这里我主要借鉴了这个教程:49.52实战(一)RNN股价预测

import pandas as pd
"获取数据集"
data:pd.DataFrame = pd.read_json('my.data.json')
TRAIN_SIZE:int = int(len(data) * 0.6)
VALID_SIZE:int = int(len(data) * 0.2)
train_data:pd.DataFrame = data.loc[:TRAIN_SIZE, :]
valid_data:pd.DataFrame = data.loc[TRAIN_SIZE + 1 : TRAIN_SIZE + VALID_SIZE, :]
test_data:pd.DataFrame = data.loc[VALID_SIZE + 1 :, :]
"按序列步长切割数据集"
def load_data(data, x, y, n_prev = 100):
	docX, docY = [], []
	for i in range(len(data) - n_prev):
		docX.append(data[x].iloc[i : i + n_prev].tolist())
		docY.append(data[y].iloc[i + n_prev].tolist())
	alsX:np.array = np.array(docX)
	alsY:np.array = np.array(docY)
	return alsX, alsY
length_of_sequences = 10
X_train, y_train = load_data(train_data, 'sin', 'cos', n_prev = length_of_sequences)
X_valid, y_valid = load_data(valid_data, 'sin', 'cos', n_prev = length_of_sequences)

将其中 60 % 60\% 60%的数据提取出来作为训练集,然后设置序列长度为 10 10 10,按顺序构成格式为 ( 1000 , 10 ) (1000, 10) (1000,10)的数据集。之后再通过numpy中的reshape函数转化为(1000, 10, 1)就好啦!

但,真的就是这样吗?

我知道你很急,但你先别急

看似一切都很正常,对吧?现在是不是认为把这段代码粘在你的notebook里面之后,就会迎来走向算法应用的一大步了?

当然不是。

我们的任务是什么? 1 1 1万组数据中找出 f ( x ) f(x) f(x) g ( x ) g(x) g(x)的关联关系

怎么找?输入数据然后运行模型最后验证模型

关键在哪?关键在于如何验证模型。

不妨我们再回去看看上面画的图1,我们只知道 f ( x ) f(x) f(x)对应的 g ( x ) g(x) g(x)。也就是说,我们必须要保证输入 f ( x ) f(x) f(x)中的 50 50 50个浮点数,并输出 50 50 50个预测出来的浮点数,才能与 g ( x ) g(x) g(x)进行比较。如果按照上面这个方法分割数据集,即使我们通过神经网络学出来也只能输入 ( 1000 , 10 ) (1000, 10) (1000,10)的数据。这就意味着只有 50 50 50个浮点数的 g ( x ) g(x) g(x)完全不能验证结果,就算验证也只能通过自己验证,这样也就完全不能通过样本给出有说服力的答案。

答案很明显,我们只能让 f ( x ) f(x) f(x)中的每一个浮点数通过神经网络输出一个浮点数,或者说,只能输入 50 50 50个浮点数,并输出 50 50 50个浮点数,才能够获得能够验证效果的模型。其他的模型都不能够验证效果。

换个思路

那么我们又该如何做呢?如果我们去深度学习框架的官方说明文档中,会不会有提示呢?

当然有。

深度学习的框架既然能够为人所用,那么就需要点名道姓地指出自己的框架能够在什么情景下怎么使用。

P.S.:由于我使用的是Tensorflow 2.12 2.12 2.12版本,所以我这边就用Tensorflow的说明文档进行说明。

在这说明文档的这一栏:Keras 中的循环神经网络 (RNN),其中有段话是这么描述的:

输出和状态

默认情况下,RNN层的输出为每个样本包含 1 1 1个向量。此向量是与最后一个时间步骤相对应的RNN单元输出,包含关于整个输入序列的信息。此输出的形状为(batch_size, units),其中 units对应于传递给层构造函数的 units 参数。

如果您设置了return_sequences=TrueRNN层还能返回每个样本的整个输出序列(每个样本的每个时间步骤一个向量)。此输出的形状为(batch_size, timesteps, units)

然后紧接着给了一个案例:

from tensorflow import keras
# 构建一个模型容器
model = keras.Sequential()
# 第一层加入一个`Embedding`,确定输入是匹配的
model.add(keras.layers.Embedding(input_dim=1000, output_dim=64))
# `GRU`接收64的输入后,将输出`(batch_size, timesteps, 256)`
model.add(keras.layers.GRU(256, return_sequences=True))
# `SimpleRNN`在文档中有提到,是全连接`RNN`,接收GRU的输出后输出`(batch_size, 128)`
model.add(keras.layers.SimpleRNN(128))
# 全连接层,决定整个网络的最终输出
model.add(keras.layers.Dense(10))
# 简单总结一下网络结构
model.summary()

那么,接下来就是按照这个网络设置数据集了。

如何设置呢?

当然,我们有一种极其粗暴的方法:用循环,把每组数据的两条序列全部扔进去,循环 1 1 1万次。我们的模型会随着循环的累计而不断拟合,最终达到我们想要的精度。

简单用代码整理一下思路就是:

"""
取消`tensorflow`本身一大串不明所以的输出
替换为轻便的`tqdm`进度条
其中`verbose`取值有0,1,2
分别代表【不输出】、【输出每个epoch的进度】、【完整输出】
最后用一个变量保存`model.complie`方法中指定的输出值
方便训练结束之后的可视化
"""
from tqdm import trange
for i in trange(int(1e4)):
  record = model.fit(x_train[i, 'sin'], y_train[i, 'cos'], verbose = 0)

这种简单粗暴的方式往往在快速出成果的demo中有奇效,但也只适用于时间不够的情况了。

实际上,稍微有点不管什么编程语言的经验的话,都知道一个常识:循环一定是CPU。这也就意味着你的训练速度将会是龟速。就算GPU参与了,那也只是参与了相当有限的矩阵运算,然后就回到CPU那边处理循环了。执行效率不如隔壁数学系大学生算的更快更便宜

那么为了提高效率,我们应该怎么办呢?

我们不妨发挥联想:图像处理方面又该如何做呢?

对于一张大图,往往都是分割为好几张子图,每个子图代表一个矩阵;然后每个子图都有一个标签,这样对应起来就是由若干矩阵构成的数组,与同样数目的标签构成的数组。

在这个任务中呢,对照着这个例子,我们大概也能够有一个基本的概念:

首先是已经帮我们分好了 1 1 1万组样本,就不需要分割子图;其次就是每组样本有自变量有因变量,对应起来虽然不是矩阵对标签,但数字对数字也算一种样本与标签,而且数量一致。

这样的话,应该就完美了。

简单用代码整理一下思路就是:

import numpy as np
import pandas as pd
data:pd.DataFrame = pd.read_json('my.data.json')
TRAIN_SIZE:int = int(len(data) * 0.6)
VALID_SIZE:int = int(len(data) * 0.2)
COL_SIZE:int = 75
ROW_SIZE:int = 1
X_train:np.array = np.array(data.loc[:TRAIN_SIZE, 'sin'].values.tolist()).reshape(TRAIN_SIZE, COL_SIZE, ROW_SIZE)
y_train:np.array = np.array(data.loc[:TRAIN_SIZE, 'cos'].values.tolist()).reshape(TRAIN_SIZE, COL_SIZE, ROW_SIZE)

这里写的比较简短,把几个步骤压缩到一起去了,所以我解释一下流程:

  • 首先,这里提取出所有的训练样本中的自变量,也就是 f ( x ) = sin ⁡ ( x ) f(x)=\sin(x) f(x)=sin(x),获得DataFrame类型的data.loc[:TRAIN_SIZE, 'sin']
  • 其次,我们可以看到读取的是json数据。在json数据中,如果给了一个序列的话,在read_json读取后则会以list形式出现,即使我们使用np.array方法强行转化后,也保持原来的list类型,在后续迭代的过程中会报错:list类型不支持转化为Tensor类型。所以,我们需要强行把所有的数据拉出来:
    • 先用values方法,获得类型为:array(list[],list[],...)
    • 再用tolist方法,获得类型为list[[],[],...]
    • 最后用np.array方法初始化,获得np.array类型
  • 完成这个过程后,为了使得这个数据集能够进一步转化为Tensor,需要转化为 ( x , y , 1 ) (x,y,1) (x,y,1)的3D形式,也就是reshape方法

同理也可以获得因变量。

到这里,正确又高效的划分才彻底结束。

接下来就能愉快地训练了。

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

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

相关文章

vue如何封装一个上传多张图片的组件

上传图片不管是后台还是前端小程序,上传图片都是一个比不可少的功能有时候需要好几个页面都要上传图片,每个页面都写一个非常不方便,这时候就没有封装起来用的方便。跟上我的步伐带你了解如何封装 首先:创建一个文件夹在component…

【FFmpeg实战】过滤器 ---- h264_mp4toannexb

原文地址:https://www.cnblogs.com/vczf/p/13818609.html H264有两种封装方式:字节流AnnexB格式 AVCC格式。 1. AnnexB格式 ---- 用于实时播放 开始前缀(00000001或000001)+NALU数据  绝大部分编码器的默认输出格式…

leetcode题目1481. 不同整数的最少数目

题目 不同整数的最少数目 给你一个整数数组 arr 和一个整数 k 。现需要从数组中恰好移除 k 个元素,请找出移除后数组中不同整数的最少数目。 示例 1: 输入:arr [5,5,4], k 1 输出:1 解释:移除 1 个 4 &#xff0c…

初识消息队列

消息队列 字面意思就是存放消息的队列(Message Queue 简称MQ),最简单的消息队列模型包括了三个角色: 消息队列:存储和管理信息,也被称为消息代理生产者:发送消息到消息队列消费者:从消息队列中获取消息并…

基于TensorFlow和Keras的狗猫数据集的分类实验

文章目录 前言一、环境配置1、anaconda安装2、修改jupyter notebook工作目录3、配置TensorFlow、Keras 二、数据集分类1、分类源码2、训练流程 三、模型调整1.图像增强2、网络模型添加dropout层 四、使用VGG19优化提高猫狗图像分类1、构建网络模型2、初始化一个VGG19网络实例3、…

C语言--消失的数字

文章目录 1.法一&#xff1a;映射法2.法二&#xff1a;异或法3.法三&#xff1a;差值法4.法四&#xff1a;排序查找 1.法一&#xff1a;映射法 时间复杂度&#xff1a;O&#xff08;N&#xff09; 空间复杂度&#xff1a;O&#xff08;N&#xff09; #include<stdio.h>…

第4章 信息系统管理

文章目录 4.1.1 管理基础1 层次结构2 系统管理 4.1.2 规划和组织1 规划模型2 组织模型1&#xff09;业务战略&#xff08;竞争力优势模型&#xff1a;差异化、总成本领先、专注 战略&#xff09;2&#xff09;组织机制战略&#xff08;莱维特钻石模型&#xff1a;信息与控制、人…

【C++学习】类和对象 | 再谈构造函数 | 构造函数中的隐式类型转换 | static静态成员

目录 1. 再谈构造函数 2. 构造函数中的隐式类型转换 3. static静态成员 写在最后&#xff1a; 1. 再谈构造函数 我们之前使用构造函数初始化&#xff1a; #include <iostream> using namespace std;class Date { public:Date(int year 2023, int month 7, int da…

arcgis js 通过某一个经纬度 定位报错,并且图标变得很大【已解决】

报错 svg.js:42 Error: attribute transform: Expected number, “…0000,0.02102085,NaN,NaN)”. svg.js:49 Error: attribute x: Expected length, “NaN”. svg.js:49 Error: attribute y: Expected length, “NaN”. 图标特别大&#xff0c;也看不到地图 分析 这个方法中…

智驾“平价”,小鹏G6打特斯拉是认真的

作者|张祥威编辑|德新 “小鹏在辅助驾驶领域不是遥遥领先&#xff0c;而是领先友商 12 - 36 个月。” “希望L4的能力能够在2027年到来&#xff0c;或者更早一点。” “G6的销量肯定要过万&#xff0c;这是最起码的。” G6上市发布期间&#xff0c;小鹏的高管各种喊话。 抛开80…

(嵌入式)STM32G061C8T6、STM32G061C6T6、STM32G061C8U6 64MHz 64KB/32KB 闪存(MCU)

STM32G0 32位微控制器 (MCU) 适合用于消费、工业和家电领域的应用&#xff0c;并可随时用于物联网 (IoT) 解决方案。这些微控制器具有很高的集成度&#xff0c;基于高性能ARM Cortex-M0 32位RISC内核&#xff0c;工作频率高达64MHz。该器件包含内存保护单元 (MPU)、高速嵌入式内…

算法笔记--滑动窗口

力扣209.长度最小子数组 https://leetcode.cn/problems/minimum-size-subarray-sum/ 在这道题中要注意的不仅仅是滑动窗口的问题&#xff0c;更重要的问题是在循环控制中&#xff0c;不恰当的语法使用会导致这道题出现很严重的问题&#xff0c;这导致我做这道题做了很多天&…

亿级数据毫秒级响应?

作为一名深陷在增删改查泥潭中练习时长三年的夹娃练习生&#xff0c;偶尔会因为没有开发任务不知道周报写什么而苦恼。 正愁这周写啥呢&#xff0c;组长过来交代了个跟进第三方公司性能测试报告的工作&#xff0c;我一寻思这活不最好干了吗&#xff0c;正愁不知道周报咋写呢&a…

github上传文件及其问题解决

文章目录 1. github上上传文件夹2. <filename> does not have a commit checked out3. this exceeds GitHubs file size limit of 100.00 MB4. error: src refspec master does not match any 1. github上上传文件夹 首先在github上create a new repository&#xff0c;…

C语言王国探险记之字符串+注释

王国探险记系列 文章目录&#xff08;3&#xff09; 前言 一&#xff0c;什么是字符串呢&#xff1f; 1&#xff0c;那C语言是怎么表示字符串的呢? "hello world.\n" 2&#xff0c;证明字符串的结束标志是一个 \0 的转义字符 3&#xff0c;证明字符串的结束标…

云原生之深入解析Flink on k8s的运行模式与实战操作

一、概述 Flink 核心是一个流式的数据流执行引擎&#xff0c;并且能够基于同一个 Flink 运行时&#xff0c;提供支持流处理和批处理两种类型应用。其针对数据流的分布式计算提供了数据分布&#xff0c;数据通信及容错机制等功能。Flink 官网不同版本的文档flink on k8s 官方文…

linux-2.6.22.6内核网卡驱动框架分析

网络协议分为很多层&#xff0c;而驱动这层对应于实际的物理网卡部分&#xff0c;这也是最底层的部分&#xff0c;以cs89x0.c这个驱动程序为例来分析下网卡驱动程序框架。 正常开发一个驱动程序时&#xff0c;一般都遵循以下几个步骤&#xff1a; 1.分配某个结构体 2.设置该结…

IDEA将java项目打包为jar包

方法 首先在src -> resources目录下建立一个文件夹&#xff0c;然后再在新建文件夹里面建立META-INF文件夹&#xff08;不推荐直接建立META-INF&#xff0c;否则后面打包完的jar包需要手动修改配置&#xff09; 然后点击File -> Project Structure -> Artifacts -&g…

第三章:Faster R-CNN网络详解(《Faster R-CNN: 基于区域提议网络的实时目标检测》)

(目标检测篇&#xff09;系列文章目录 第一章:R-CNN网络详解 第二章:Fast R-CNN网络详解 第三章:Faster R-CNN网络详解 第四章:YOLO v1网络详解 第五章:YOLO v2网络详解 第六章:YOLO v3网络详解 文章目录 系列文章目录技术干货集锦前言一、摘要二、正文分析 1.引入库2.读…

Mysql的逻辑架构_读写锁_事物

概览 一. MySql的逻辑架构1. 逻辑架构图2. 连接管理与安全性 二. 并发控制1. 读写锁2. 锁粒度 三. 事务1. 特性2. 隔离级别3. 死锁4. 事物日志&#xff1f;5.MySql中的事物 mysql最与众不同的特性&#xff1a;存储引擎架构 架构的设计&#xff1a; 将查询处理(Query Processin…