30天吃掉tensorflow2 1_4学习笔记

1-4,时间序列数据建模流程范例

一,准备数据

本文的数据集取自tushare,数据集在本项目的 data目录下。

数据长这样:

代码:

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import tensorflow as tf

from tensorflow.keras import models,layers,losses,metrics,callbacks

%matplotlib inline

%config InlineBackend.figure_format = 'svg'



df = pd.read_csv("./data/covid-19.csv",sep = "\t")

df.plot(x = "date",y = ["confirmed_num","cured_num","dead_num"],figsize=(10,6))

plt.xticks(rotation=60)





dfdata = df.set_index("date")

dfdiff = dfdata.diff(periods=1).dropna()

dfdiff = dfdiff.reset_index("date")



dfdiff.plot(x = "date",y = ["confirmed_num","cured_num","dead_num"],figsize=(10,6))

plt.xticks(rotation=60)

dfdiff = dfdiff.drop("date",axis = 1).astype("float32")





#用某日前8天窗口数据作为输入预测该日数据

WINDOW_SIZE = 8



def batch_dataset(dataset):

    dataset_batched = dataset.batch(WINDOW_SIZE,drop_remainder=True)

    return dataset_batched



ds_data = tf.data.Dataset.from_tensor_slices(tf.constant(dfdiff.values,dtype = tf.float32)) \

   .window(WINDOW_SIZE,shift=1).flat_map(batch_dataset)



ds_label = tf.data.Dataset.from_tensor_slices(

    tf.constant(dfdiff.values[WINDOW_SIZE:],dtype = tf.float32))
ds_train = tf.data.Dataset.zip((ds_data,ds_label)).batch(38).cache()

 

首先是.diff方法,看代码介绍,这个是用来计算dataset的数据中的变化情况的

可以看到指定了axis参数后,之后的变化都是和指定的那一列相比

 

.dropna方法则是顾名思义,去掉所有NaN的空值

 

reset_index这个方法则是让dadaset数据填上默认的索引

这里的数据是以8天作为一个周期,用前面的数据来预测,把第8天的数据作为对应的结果

.cache方法是一次性将所有数据读入缓存中以提升速度,因为这个项目里的数据量较少

二,定义模型 

使用Keras接口有以下3种方式构建模型:使用Sequential按层顺序构建模型,使用函数式API构建任意结构模型,继承Model基类构建自定义模型。

教学项目里选择使用了函数式API构建任意结构模型。

#考虑到新增确诊,新增治愈,新增死亡人数数据不可能小于0,设计如下结构

class Block(layers.Layer):

    def __init__(self, **kwargs):

        super(Block, self).__init__(**kwargs)

   

    def call(self, x_input,x):

        x_out = tf.maximum((1+x)*x_input[:,-1,:],0.0)

        return x_out

   

    def get_config(self): 

        config = super(Block, self).get_config()

        return config

tf.keras.backend.clear_session()

x_input = layers.Input(shape = (None,3),dtype = tf.float32)

x = layers.LSTM(3,return_sequences = True,input_shape=(None,3))(x_input)

x = layers.LSTM(3,return_sequences = True,input_shape=(None,3))(x)

x = layers.LSTM(3,return_sequences = True,input_shape=(None,3))(x)

x = layers.LSTM(3,input_shape=(None,3))(x)

x = layers.Dense(3)(x)



#考虑到新增确诊,新增治愈,新增死亡人数数据不可能小于0,设计如下结构

#x = tf.maximum((1+x)*x_input[:,-1,:],0.0)

x = Block()(x_input,x)

model = models.Model(inputs = [x_input],outputs = [x])

model.summary()

这里使用了lstm,输入输出都是3维数据,分别代表着现存确诊,治愈人数和死亡人数

最后加了个block层,是为了将输出数据中的小于0的数据设置为0,其实这里我有些没看懂,我在这里猜测,其实神经网络中运算的和最后dense层给出的是一个0-1的变化率,所以最后通过1+x和x_input相乘得到最后的实际人数,这么猜测是因为样本里的数据都是几万几万的,一般激活函数都是在-1~1这个区间变化比较明显,所以神经网络中其实计算的是人数的变化率? 

三,训练模型

训练模型通常有3种方法,内置fit方法,内置train_on_batch方法,以及自定义训练循环。此处我们选择最常用也最简单的内置fit方法。

注:循环神经网络调试较为困难,需要设置多个不同的学习率多次尝试,以取得较好的效果。


 

#自定义损失函数,考虑平方差和预测目标的比值

class MSPE(losses.Loss):

    def call(self,y_true,y_pred):

        err_percent = (y_true - y_pred)**2/(tf.maximum(y_true**2,1e-7))

        mean_err_percent = tf.reduce_mean(err_percent)

        return mean_err_percent

   

    def get_config(self):

        config = super(MSPE, self).get_config()

        return config

import os

import datetime



optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)

model.compile(optimizer=optimizer,loss=MSPE(name = "MSPE"))



stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

logdir = os.path.join('data', 'autograph', stamp)



## 在 Python3 下建议使用 pathlib 修正各操作系统的路径

# from pathlib import Path

# stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

# logdir = str(Path('./data/autograph/' + stamp))



tb_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)

#如果loss在100个epoch后没有提升,学习率减半。

lr_callback = tf.keras.callbacks.ReduceLROnPlateau(monitor="loss",factor = 0.5, patience = 100)

#当loss在200个epoch后没有提升,则提前终止训练。

stop_callback = tf.keras.callbacks.EarlyStopping(monitor = "loss", patience= 200)

callbacks_list = [tb_callback,lr_callback,stop_callback]



history = model.fit(ds_train,epochs=500,callbacks = callbacks_list)

四,评估模型

评估模型一般要设置验证集或者测试集,由于此例数据较少,我们仅仅可视化损失函数在训练集上的迭代情况。

import matplotlib.pyplot as plt

def plot_metric(history, metric):

    train_metrics = history.history[metric]

    epochs = range(1, len(train_metrics) + 1)

    plt.plot(epochs, train_metrics, 'bo--')

    plt.title('Training '+ metric)

    plt.xlabel("Epochs")

    plt.ylabel(metric)

    plt.legend(["train_"+metric])

    plt.show()

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值