用一维卷积处理序列问题,提出优化方法:结合CNN和RNN来处理长序列

引言:CNN在计算机视觉问题上表现出色,原因在于它能够进行卷积运算,从局部输入图块中提取特征,并能将表示模块化,同时可以高效地利用数据,同样也让它对序列处理特别有效,时间可以被看做一个空间维度,就像二维图像的高或宽。对于某些序列处理问题,这种一维卷积的效果甚至可以媲美RNN,而且计算代价通常要小很多。近年,一维卷积网络通常与空洞卷积核一起使用,在音频生成和机器翻译领域取得了巨大的成功。

一:理解序列数据的一维卷积

使用一维卷积,从序列中提取局部一维序列段,这种一维卷积可以识别序列中的局部模式。对每个序列段执行相同的输入变换,所以在句子中某个位置学到的模式稍后可以在其他位置被识别,这使得一维卷积神经网络具有平移不变性。如图:

 二:序列数据的一维池化

一维也可以做池化运算:从输入中提取一维序列段,然后输出其最大值或平均值。用于降低一维输入的长度。

三:一维卷积代码

from keras.datasets import imdb
from keras.preprocessing import  sequence
from keras.utils import pad_sequences
import numpy as np
np.set_printoptions(threshold=np.inf)


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))
print(len(x_test))
print('pad sequences (samples x time)')
x_train=pad_sequences(x_train,maxlen=max_len)
x_test=pad_sequences(x_test,maxlen=max_len)
print('x_train',x_train.shape)
print('x_test',x_test.shape)

#一维卷积的构架与二维相同,它是Conv1D层和MaxPoolong1D层的堆叠,最后是一个全局池化层或Flatten层,将三维输出转换为二维输出,可以向模型中添加一个或多个Dense层

from keras.models import Sequential#用于构建线性堆叠神经网络模型
from keras import layers
from keras.optimizers import  RMSprop #优化器,负责根据损失函数的梯度调整网络参数,以最小化损失
model=Sequential()
model.add(layers.Embedding(max_features,128,input_length=max_len))
model.add(layers.Conv1D(32,7,activation='relu'))
model.add(layers.MaxPool1D(5))
model.add(layers.Conv1D(32,7,activation='relu'))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(1))

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

import matplotlib.pyplot as plt
acc=history.history['acc']
val_acc=history.history['val_acc']
loss=history.history['loss']
val_loss=history.history['val_loss']
epochs=range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label='T acc')
plt.plot(epochs,val_acc,'b',label='V acc')
plt.title('T and V acc')
plt.legend()
plt.show()

时间原因,epochs只取了4。可以将以上结果与循环网络进行比较,发现验证精度相似,更让我们确信,在单词级的情感分类任务上,一维卷积可以代替RNN,而且速度快,计算代价低。

四、结合CNN和RNN来处理长序列

一维卷积神经网络分别处理每个输入序列段,所以它对时间步的顺序不敏感,与RNN不同。为了识别长期的模式,可以将许多卷积层和池化层堆叠在一起,这样上面的层能够观察到原始输入中更长的序列段,但这仍不是一种引入顺序敏感性的好方法。可以选择结合卷积神经网络的速度和轻量与RNN的顺序敏感性,可以在RNN前使用一维卷积作为预处理步骤。对于那些非常长,以至于RNN无法处理的序列,这个方法嘎嘎好用!卷积网络可以将长的输入序列转换为高级特征组成的更短序列(下采样)。然后提取的特征组成的这些序列成为网络中RNN的输入。我们将这个方法运用到温度预测数据集,该数据集在作者上一篇博客介绍过了,这里就不进行介绍。这种方法允许操作更长的序列,所以我们可以查看更早的数据(通过增大数据生成器的lookback参数)或查看分辨率更高的时间序列(通过减小生成器的step参数)。这里将step减半,得到时间序列的长度变为之前的两倍,温度数据的采样频率变为每30min一个数据点。

import os
import numpy as np
data_dir='jena_climate_2009_2016'
fname=os.path.join('jena_climate_2009_2016.csv')
f=open(fname)
data=f.read()
f.close()

lines=data.split('\n')#按照指定的分割符进行分割

header=lines[0].split(',')

lines=lines[1:]
print(len(header)) #15
print(len(lines))  #420451

import numpy as np
float_data=np.zeros((len(lines),len(header)-1))
#print(float_data.shape) #(420451,14)

for i ,line in enumerate(lines):
    values=[float(x) for x in line.split(',')[1:]]
    float_data[i,:]=values
#print(float_data.shape) #(420451,14)

from matplotlib import pyplot as plt
temp=float_data[:,1]#温度,单位摄氏度
plt.plot(range(1440),temp[:1440])
plt.show()


#data=0 浮点数数据组成的原始数组
lookback=720#输入数据应该包括过去多少个时间步
steps=6#数据采样的周期
dealy=144#目标应该在未来多少个时间步之后

#数据标准化
mean=float_data[:200000].mean(axis=0)
float_data-=mean
std=float_data[:200000].std(axis=0)
float_data/=std



#生成时间序列样本及其目标的生成器
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#如果没有指定最大索引,则将其设置为数据长度减去延迟1天
    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:
                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]))
        targets=np.zeros((len(rows),))
        for j,row in enumerate(rows):
            indices=range(row[j]-lookback,rows[j],step)
            samples[j]=data[indices]
            targets[j]=data[row[j]+delay][1]
        yield samples,targets #无限生成样本和目标数据

step=3
lookback=720
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
test_steps=(len(float_data)-300001-lookback)//128

#下面是模型,开始是两个Conv1D,然后是一个GRU
from keras.models import Sequential
from keras import layers
from keras.optimizers import RMSprop

model=Sequential()
model.add(layers.Conv1D(32,5,activation='relu',input_shape=(None,float_data.shape[-1])))
model.add(layers.MaxPool1D(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=4,validation_data=val_gen,validation_steps=val_steps)

import matplotlib.pyplot as plt
acc=history.history['acc']
val_acc=history.history['val_acc']
loss=history.history['loss']
val_loss=history.history['val_loss']
epochs=range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label='T acc')
plt.plot(epochs,val_acc,'b',label='V acc')
plt.title('T and V acc')
plt.legend()
plt.show()

从验证随时来看,这种架构的效果不如只用正则化GRU,但速度快。他查看了两倍的数据量,在本例可能用处并不能完全发挥出来,但对其他某些数据可能效果非常好!

欢迎读者批评指正,有任何问题可以评论发私信等!感谢读者,恳求点赞+关注,谢谢啦!

以下是我的github主页,欢迎光临!

StatisticAdam (github.com)

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值