python深度学习--一维cnn处理序列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunChao3555/article/details/88692527
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pylab
from pandas import DataFrame, Series
from keras import models, layers, optimizers, losses, metrics
from keras.models import Sequential
from keras.utils.np_utils import to_categorical

#一维卷积神经网络[通常与空洞卷积核(dilated kernel)一起使用]已经在音 频生成和机器翻译领域取得了巨大成功。另外,对于文本分类和时间序列预测等简单任务,小型的一维卷积神经网络可以替代RNN,而且速度更快

#序列的一维卷积:可以识别序列中的局部模式。因为对每个序列段执行相同的输入变换,所以在句子中某个位置学到的模式稍后可以在其他位置被识别,这使得一维卷积神经网络具有平移不变性(对于时间平移而言)
#一维卷积神经网络的工作原理:每个输出时间步都是利用输入序列在时间维度上的一小段得到的

#序列的一维池化:从输入中提取一维序列段(即子序列),然后输出其最大值(最大池化)或平均值(平均池化)。与二维卷积神经网络一样,该运算也是 用于降低一维输入的长度(子采样)

#实现一维卷积神经网络
#Keras 中的一维卷积神经网络是 Conv1D 层,其接口类似于 Conv2D
from keras.datasets import imdb
from keras.preprocessing import sequence
fname='F:/jena_climate_2009_2016.csv'#jena天气数据集(2009—2016 年的数据,每 10 分钟记录 14 个不同的量)
#对于.csv数据格式等用pandas操作更加方便
df=pd.read_csv(fname,)

#数据类型不同,所以需要标准化
#预处理数据的方法是,将每个时间序列减去其平均值,然后除以其标准差
df=df.drop(['Date Time'],axis=1)
float_data=df.ix[:,:]
# print(train_data)
mean=float_data.mean(axis=0)
# print(mean)
float_data-=mean
std=float_data.std(axis=0)
float_data /=std
# print(float_data)

#生成时间序列样本及其目标的生成器
def generator(data,lookback,delay,min_index,max_index,shuffle=False,batch_size=128,step=6):
    if max_index is None:
        max_index=len(data)-delay-1
        #[0--min_index--lookback--max_index--delay--len(data)]
        #                       i
    i=min_index+lookback
    while 1:
        if shuffle:
            rows=np.random.randint(min_index+lookback,max_index,size=batch_size)
        else:
            if i+batch_size>=max_index:#表明取到最后一批(数量<batch_size)
                i=min_index+lookback
            rows=np.arange(i,min(i+batch_size,max_index))
            i+=len(rows)
        samples=np.zeros((len(rows),lookback//step,data.shape[-1]))#按小时批量抽取数据点,每个点包含14个特征
        # print(samples)
        targets=np.zeros((len(rows),))
        for j,row in enumerate(rows):
            indices=range(rows[j]-lookback,rows[j],step)#6步(每小时)一个点索引
            samples[j]=data.ix[indices,:]
            t=data.ix[rows[j]+delay,:]
            targets[j]=t[1]#144步(24小时后的温度数组)
        yield samples,targets

#准备训练生成器、验证生成器和测试生成器
#因为这种方法允许操作更长 的序列,所以我们可以查看更早的数据(通过增大数据生成器的 lookback 参数)或查看分辨 率更高的时间序列(通过减小生成
# 器的 step 参数)。这里我们任意地将 step 减半,得到时间序列的长度变为之前的两倍,温度数据的采样频率变为每 30 分钟一个数据点。
lookback=720
step=3#每30分钟观测一次
delay=144

train_gen=generator(
    float_data,
    lookback=lookback,
    delay=delay,
    min_index=0,
    max_index=200000,
    shuffle=True,
    step=step)
val_gen=generator(
    float_data,
    lookback=lookback,
    delay=delay,
    min_index=200001,
    max_index=300000,
    step=step)
test_gen=generator(
    float_data,
    lookback=lookback,
    delay=delay,
    min_index=300001,
    max_index=None,
    step=step)

val_steps = (300000 - 200001 - lookback) //128
print(val_steps)
test_steps = (len(float_data) - 300001 - lookback) //128

def acc_loss_plot(history):
    fig=plt.figure()
    ax1=fig.add_subplot(2,1,1)
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(1, len(loss) + 1)
    ax1.plot(epochs, acc, 'bo', label='Training acc')
    ax1.plot(epochs, val_acc, 'b', label='Validation acc')
    ax1.set_title('Training and validation accuracy')
    ax2=fig.add_subplot(2,1,2)
    ax2.plot(epochs, loss, 'bo', label='Training loss')
    ax2.plot(epochs, val_loss, 'b', label='Validation loss')
    ax2.set_title('Training and validation loss')
    plt.legend()
    plt.tight_layout()
    plt.show()
###---------------------------------------------------------------------
max_features=10000
max_len=500
print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')
print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)

from keras.optimizers import RMSprop
def build_1D_cnn_imdb():
    model=Sequential()
    model.add(layers.Embedding(max_features,128,input_length=max_len))
    model.add(layers.Conv1D(32,7,activation='relu'))
    model.add(layers.MaxPooling1D(5,))
    model.add(layers.Conv1D(32,7,activation='relu'))
    model.add(layers.GlobalAveragePooling1D())
    model.add(layers.Dense(1))
    print(model.summary())

    model.compile(optimizer=RMSprop(lr=1e-4), loss='binary_crossentropy', metrics=['acc'])
    history = model.fit(x_train, y_train, epochs=10,
    batch_size=128, validation_split=0.2)
    return history

# acc_loss_plot(build_1D_cnn_imdb())#验证精度略低于LSTM,83%
###-----------------------------------------------------------------------
#结合CNN和RNN来处理长序列
#为了识别更长期的模式,你可以将许多卷积层和池化层堆叠在一起,这样上面的层能够观察到原始输入中更长的序列段,但仅仅使用CNN不是一种引入顺序敏感性的好方法,可用jena温度预测问题上使用1D CNN进行验证
def build_1D_cnn_jena():
    model = Sequential()
    model.add(layers.Conv1D(32, 5, activation='relu', input_shape=(None, float_data.shape[-1])))
    model.add(layers.MaxPooling1D(3))
    model.add(layers.Conv1D(32, 5, activation='relu'))
    model.add(layers.MaxPooling1D(3))
    model.add(layers.Conv1D(32, 5, activation='relu'))
    model.add(layers.GlobalMaxPooling1D())
    model.add(layers.Dense(1))
    model.compile(optimizer=RMSprop(), loss='mae')
    history = model.fit_generator(train_gen,
                                  steps_per_epoch=500, epochs=20,
                                  validation_data=val_gen,
                                  validation_steps=val_steps)
    return history
# acc_loss_plot(build_1D_cnn_jena())#0.46左右
# 比基于常识的基准还要高
'''
因为卷积神经网络在输入时间序列的所有位置寻找模式,它并不知道所看到某个模式的时间位置(距开始多长时间,距结束多长时间等)。对于这个具体的预测问题,对最新数据点的解释与对较早数据点的解释应该并不相同,所以卷积神经网络无法得到有意义的结果.
卷积神经网络的这种限制对于 IMDB 数据来说并不是问题,因为对于与正面情绪或负面情绪相关联的关键词模式,无论出现在输入句子中的什么位置,它所包含的信息量是一样的
'''

'''
要想结合卷积神经网络的速度与轻量以及RNN的顺序敏感性,一种方法是在RNN前面使用一维CNN作预处理。对于那些非常长,以至于RNN无法处理的序列(比如包含上千个时间步的序列),这种方法尤其有用。
'''
#卷积神经网络可以将长的输入序列转换为高级特征组成的更短序列(下采样)。然后,提取的特征组成的这些序列成为网络中RNN的输入

def build_cnn_joint_rnn():
    model = Sequential()
    model.add(layers.Conv1D(32, 5, activation='relu', input_shape=(None, float_data.shape[-1])))
    model.add(layers.MaxPooling1D(3))
    model.add(layers.Conv1D(32, 5, activation='relu'))
    model.add(layers.GRU(32, dropout=0.1, recurrent_dropout=0.5))
    model.add(layers.Dense(1))
    model.summary()
    model.compile(optimizer=RMSprop(), loss='mae')
    history = model.fit_generator(train_gen,
                                  steps_per_epoch=500,
                                  epochs=20,
                                  validation_data=val_gen,
                                  validation_steps=val_steps)
    return history
acc_loss_plot(build_cnn_joint_rnn())#[注意修改acc_loss_plot(),history中没有acc]#0.25
#从验证损失来看,这种架构的效果不如只用正则化 GRU,但速度要快很多。它查看了两倍的数据量,在本例中可能不是非常有用,但对于其他数据集可能非常重要。

 IMDB数据集使用一维cnn

 

jena温度预测数据集使用一维cnn


'''
    1.二维卷积神经网络在二维空间中处理视觉模式时表现很好,与此相同,一维卷积神经网络在处理时间模式时表现也很好。对于某些问题,特别是自然语言处理任务,它可以替代RNN,并且速度更快。
    2.通常情况下,一维卷积神经网络的架构与计算机视觉领域的二维卷积神经网络很相似,它将 Conv1D 层和 MaxPooling1D 层堆叠在一起,最后是一个全局池化运算或展平操作。
    3.因为RNN在处理非常长的序列时计算代价很大,但一维卷积神经网络的计算代价很小, 所以在RNN之前使用一维卷积神经网络作为预处理步骤是一个好主意,这样可以使序列变短,并提取出有用的表示交给RNN来处理
'''
'''
你可以用RNN进行时间序列回归(“预测未来”)、时间序列分类、时间序列异常检测和序列标记(比如找出句子中的人名或日期)。
同样,你可以将一维卷积神经网络用于机器翻译(序列到序列的卷积模型,比如 SliceNet)、文档分类和拼写校正。
'''

猜你喜欢

转载自blog.csdn.net/SunChao3555/article/details/88692527