Tensorflow 时间序列数据的处理

数据集简介

数据来源:Kaggle Ubiquant Market Prediction

数据集描述了多个投资项目在一个时间序列下的300个匿名特征("f_0"至"f_299")以及一个目标特征("target")。要求根据后续时间节点的匿名特征预测目标特征。

本文的主要目标是构建特定长度的时间序列RNN网络训练和测试集。

训练集和验证集、测试集的划分

由于给出的要求是预测后续时间点的目标特征,模型的建立是基于过去的模式在将来依然存在。因此,对于这样的模型,跨时间划分训练集、验证集和测试集是合理的。数据集中给出了时间序号("time_id")从0开始至1219,共计3141410条。取其中百分之二作为测试集,从时间序号1201至1219。

窗口序列数据的获取和应用

解决该问题的思路很简单。将该数据集中各投资项目视为独立的时间序列,可以先根据investment_id划分数据集,再在划分后的数据集上分别通过滑动窗口的方法获取定长的时间序列数据。

但在实际应用中会遇到一些问题。首先,通过滑动窗口的方法获取的时间序列数据有较大的重复性。假设目标的时间序列长度为20,若将窗口序列数据集直接写入磁盘会占用原数据集近二十倍的空间。

相对应的,在训练过程中完全采用实时计算获取窗口序列也不是一个可取的方法。计算窗口序列的过程会在每个epoch中重复执行,计算函数的效率直接影响到训练的速度。

一个折中的方案是只将窗口序列中各时间点的数据在原数据集中对应的序号的记录下来作为序号数据集写入磁盘。在训练过程中通过读取原数据集和序号数据集生成batch。

由于RNN网络允许不定长的时间序列作为输入,而非矩阵形式的批次回影响输入的效率,故通过全零填充未达到要求长度的窗口序列并为此在原数据集中插入一行全零行(注意:全零行的插入需要在标准化、归一化等预处理操作之后)。

MIN_LEN = 20 # 最小窗口序列长度,低于该长度的窗口序列会被全零行填充
FEATURE_NUM = 300
ZERO_INDEX = 3141410 # 全零行序号
def form_indexes(data,time_range): # data:原数据集 time_range:时间序列范围
id_list = sorted(data['investment_id'].unique())
if 0 in id_list:
id_list.remove(0)
indexes_list = []
for id in tqdm(id_list): sub_data = data[data['investment_id']==id].sort_values(by=['time_id'])
time_list = tuple(sorted(sub_data['time_id'].unique()))
for t in range(time_range[0],time_range[1]):
if t in time_list:
i_t = time_list.index(t)
temp = list(sub_data[max(i_t-MIN_LEN+1,0):i_t+1].index.values)
indexes = [ZERO_INDEX]*(MIN_LEN-len(temp)) + temp
return indexes_list

在训练前构建窗口序列数据训练集和测试集(验证集)

通过tf.data.Dataset的from_generator方法构建数据集的益处在于只有在数据被使用时(读取或预读取)才会运行生成器函数,不会占用过多内存,同时shuffle和分批次等操作都能较为简便的完成。

train_indexset= pd.read_parquet('trainindex.parquet')
val_indexset= pd.read_parquet('valindex.parquet') def gen_func(train_val_or_test): # 生成器函数
if train_val_or_test == 1:
for indexes in train_indexset.iterrows():
features = data.iloc[indexes[1].values].values[:,4:]
label = data.iloc[indexes[1].values[-1]]['target']
yield (features,label)
elif train_val_or_test == 2:
for indexes in val_indexset.iterrows():
features = data.iloc[indexes[1].values].values[:,4:]
label = data.iloc[indexes[1].values[-1]]['target']
yield (features,label)
else:
print("error input")
raise ValueError # 指定输出的形状和数据类型
featureSpec = tf.TensorSpec(
shape=[MIN_LEN,FEATURE_NUM],
dtype=tf.dtypes.float32,
name=None
) labelSpec = tf.TensorSpec(
shape=[],
dtype=tf.dtypes.float32,
name=None
) train_data = tf.data.Dataset.from_generator(generator=gen_func,args=[1] ,output_signature=(featureSpec,labelSpec))
val_data = tf.data.Dataset.from_generator(generator=gen_func,args=[2] ,output_signature=(featureSpec,labelSpec))

以下模型和超参数只做展示用途所用,不具有指导意义。

MIN_LEN = 20
FEATURE_NUM = 300
BATCH_SIZE = 1000
EPOCH_NUM = 50 def build_RNNmodel():
model = tf.keras.models.Sequential(
[
tf.keras.layers.Masking(mask_value=0.,
input_shape=(MIN_LEN, FEATURE_NUM)),
tf.keras.layers.LSTM(1024,activation='tanh',
return_sequences=True,
dropout=0.5,
kernel_initializer=tf.initializers.TruncatedNormal(stddev=0.01),
),
tf.keras.layers.LSTM(256,activation='tanh',
dropout=0.5,
kernel_initializer=tf.initializers.TruncatedNormal(stddev=0.01),
),
tf.keras.layers.Dense(1,activation='relu')
]
)
return model
train_batchs = train_data.batch(batch_size=BATCH_SIZE).prefetch(BATCH_SIZE)
val_batchs = val_data.batch(batch_size=BATCH_SIZE).prefetch(BATCH_SIZE)
# 设置prefetch可以预读取后续批次数据提高运行速度 model = build_RNNmodel()
model.compile(loss='mae', optimizer=tf.keras.optimizers.Adam(0.0001)) history = model.fit(train_batchs,epochs=EPOCH_NUM,validation_data=val_batchs)

这里只取了一部分整体数据的一部分作为演示,每个batch有1000条窗口序列,每个epoch有451个batch,运行一个epoch的时间约为530秒。

Tensorflow 窗口时间序列数据的处理的更多相关文章

  1. TensorFlow实现时间序列预测

    常常会碰到各种各样时间序列预测问题,如商场人流量的预测.商品价格的预测.股价的预测,等等.TensorFlow新引入了一个TensorFlow Time Series库(以下简称为TFTS),它可以帮 ...

  2. DWT小波变换及其在时间序列数据预测中的应用

    Given data: 时间序列数据. Goal:做预测 方法:在滑动窗口中取DWT特征,并验证. 实验验证: Load forcast 数据集. 问题: 小波变换的物理意义是什么? 小波变换的数学意 ...

  3. 大数据DDos检测——DDos攻击本质上是时间序列数据,t+1时刻的数据特点和t时刻强相关,因此用HMM或者CRF来做检测是必然! 和一个句子的分词算法CRF没有区别!

    DDos攻击本质上是时间序列数据,t+1时刻的数据特点和t时刻强相关,因此用HMM或者CRF来做检测是必然!——和一个句子的分词算法CRF没有区别!注:传统DDos检测直接基于IP数据发送流量来识别, ...

  4. geotrellis使用(二十三)动态加载时间序列数据

    目录 前言 实现方法 总结 一.前言        今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...

  5. EXTJS中grid的数据特殊显示,不同窗口的数据传递

    //EXTJS中grid的数据特殊显示renderer : function(value, metaData, record, rowIndex, colIndex, store, view) { v ...

  6. MetricGraphics.js – 时间序列数据的可视化

    MetricsGraphics.js 是建立在D3的基础上,被用于可视化和布局的时间序列数据进行了优化.它提供以产生一个原则性的,一致的和响应式的方式的图形常见类型的简单方法.该库目前支持折线图,散点 ...

  7. OpenStack/Gnocchi简介——时间序列数据聚合操作提前计算并存储起来,先算后取的理念

    先看下 http://www.cnblogs.com/bonelee/p/6236962.html 这里对于环形数据库的介绍,便于理解归档这个操作! 转自:http://blog.sina.com.c ...

  8. js实现非模态窗口增加数据后刷新父窗口数据

    父窗口是由两个部分组成,一个html的table,一部分是extjs的gird. 点击grid面板[增加]按钮将会弹出非模态窗口进行新数据的编辑页面 下面是按钮的触发函数代码: var a = win ...

  9. mysql 生成时间序列数据 - 存储过程

    由于时间自动转换为int值, 做一步转化,也可在调用时处理 use `test`; CREATE table test.test1 as SELECT state, id, `规格条码`, `色号条码 ...

随机推荐

  1. synchronized和Lock的区别是什么?

    原创2020-11-19 11:38:29011024区别:1.lock是一个接口,而synchronized是java的一个关键字.2.synchronized在发生异常时会自动释放占有的锁 ...

  2. 为什么在重写 equals 方法的时候需要重写 hashCode 方法?

    因为有强制的规范指定需要同时重写 hashcode 与 equal 是方法,许多容器类, 如 HashMap.HashSet 都依赖于 hashcode 与 equals 的规定.

  3. 学习Haproxy (八)

    Unix套接字命令(Unix Socket commands) socat是一个多功能的网络工具,名字来由是"Socket CAT",可以看作是netcat的N倍加强版,socat ...

  4. 学习saltstack (三)

    salt是一个新的基础平台管理工具,2011-02-20诞生,创造者Thoms SHatch,起名salt原因生活中常见.易记,使用saltstack.com原因这个域名没有被注册,Because s ...

  5. 遇到MyBatis-Plus的错误之“Table 'mybatis_plus.user' doesn't exist”

    一.问题 Table 'mybatis_plus.user' doesn't exist 二.原因 表中没有user表 三.解决方案 生成user表既可 四.结果图 运行后显示查询出来的数据 五.总结 ...

  6. 菜鸟的谷歌浏览器devtools日志分析经验

    1 别管什么性能,尽可能输出详细的必要日志.(除非你明显感觉到性能变低,而且性能变低的原因是由于日志输出太多而引起的) 2 不要总是使用console.log,试试console.info, cons ...

  7. c++语法拾遗,一些细节与特性

    写了2年多的C+STL的acmer,在学习<C++ primer>时总结的一些少见的语法特性与细节.总体还是和题目说的一样这是一篇 c++ 拾遗. 1 变量和基本类型 1.1 基本类型 1 ...

  8. Python使用逻辑回归估算OR值

    第一种是统计学方法,需要用到 statsmodels包 statsmodels是统计和计量经济学的package,包含了用于参数评估和统计测试的实用工具 第二种是机器学习,需要使用sklearn中的L ...

  9. CCS基础样式表

    一.css样式表 1.样式表分类 1.内联式 <p >This is an apple</p> 2.内嵌样式表 作为一个独立的区域 内嵌在网页里面,必须写在head标签里面 & ...

  10. Java 将Map按Value值降序排列

    1 /** 2 * 将集合按照降序排列-FLOAT 3 * @param nowPartTwoData 4 * @return 5 */ 6 private static List<Map.En ...