代码详解:用Python构建RNN模拟人脑

Python017

代码详解:用Python构建RNN模拟人脑,第1张

(number_of_records x length_of_sequence x types_of_sequences)

(number_of_records x types_of_sequences) #where types_of_sequences is 1

%pylab inline

import math

sin_wave = np.array([math.sin(x) for x in np.arange(200)])

plt.plot(sin_wave[:50])

X = []

Y = []

seq_len = 50

num_records = len(sin_wave) - seq_len

for i in range(num_records - 50):

X.append(sin_wave[i:i+seq_len])

Y.append(sin_wave[i+seq_len])

X = np.array(X)

X = np.expand_dims(X, axis=2)

Y = np.array(Y)

Y = np.expand_dims(Y, axis=1)

X.shape, Y.shape

((100, 50, 1), (100, 1))

X_val = []

Y_val = []

for i in range(num_records - 50, num_records):

X_val.append(sin_wave[i:i+seq_len])

Y_val.append(sin_wave[i+seq_len])

X_val = np.array(X_val)

X_val = np.expand_dims(X_val, axis=2)

Y_val = np.array(Y_val)

Y_val = np.expand_dims(Y_val, axis=1)

learning_rate = 0.0001

nepoch = 25

T = 50 # length of sequence

hidden_dim = 100

output_dim = 1

bptt_truncate = 5

min_clip_value = -10

max_clip_value = 10

U = np.random.uniform(0, 1, (hidden_dim, T))

W = np.random.uniform(0, 1, (hidden_dim, hidden_dim))

V = np.random.uniform(0, 1, (output_dim, hidden_dim))

def sigmoid(x):

return 1 / (1 + np.exp(-x))

for epoch in range(nepoch):

# check loss on train

loss = 0.0

# do a forward pass to get prediction

for i in range(Y.shape[0]):

x, y = X[i], Y[i] # get input, output values of each record

prev_s = np.zeros((hidden_dim, 1)) # here, prev-s is the value of the previous activation of hidden layerwhich is initialized as all zeroes

for t in range(T):

new_input = np.zeros(x.shape) # we then do a forward pass for every timestep in the sequence

new_input[t] = x[t] # for this, we define a single input for that timestep

mulu = np.dot(U, new_input)

mulw = np.dot(W, prev_s)

add = mulw + mulu

s = sigmoid(add)

mulv = np.dot(V, s)

prev_s = s

# calculate error

loss_per_record = (y - mulv)**2 / 2

loss += loss_per_record

loss = loss / float(y.shape[0])

# check loss on val

val_loss = 0.0

for i in range(Y_val.shape[0]):

x, y = X_val[i], Y_val[i]

prev_s = np.zeros((hidden_dim, 1))

for t in range(T):

new_input = np.zeros(x.shape)

new_input[t] = x[t]

mulu = np.dot(U, new_input)

mulw = np.dot(W, prev_s)

add = mulw + mulu

s = sigmoid(add)

mulv = np.dot(V, s)

prev_s = s

loss_per_record = (y - mulv)**2 / 2

val_loss += loss_per_record

val_loss = val_loss / float(y.shape[0])

print('Epoch: ', epoch + 1, ', Loss: ', loss, ', Val Loss: ', val_loss)

Epoch: 1 , Loss: [[101185.61756671]] , Val Loss: [[50591.0340148]]

...

...

# train model

for i in range(Y.shape[0]):

x, y = X[i], Y[i]

layers = []

prev_s = np.zeros((hidden_dim, 1))

dU = np.zeros(U.shape)

dV = np.zeros(V.shape)

dW = np.zeros(W.shape)

dU_t = np.zeros(U.shape)

dV_t = np.zeros(V.shape)

dW_t = np.zeros(W.shape)

dU_i = np.zeros(U.shape)

dW_i = np.zeros(W.shape)

# forward pass

for t in range(T):

new_input = np.zeros(x.shape)

new_input[t] = x[t]

mulu = np.dot(U, new_input)

mulw = np.dot(W, prev_s)

add = mulw + mulu

s = sigmoid(add)

mulv = np.dot(V, s)

layers.append({'s':s, 'prev_s':prev_s})

prev_s = s

# derivative of pred

dmulv = (mulv - y)

# backward pass

for t in range(T):

dV_t = np.dot(dmulv, np.transpose(layers[t]['s']))

dsv = np.dot(np.transpose(V), dmulv)

ds = dsv

dadd = add * (1 - add) * ds

dmulw = dadd * np.ones_like(mulw)

dprev_s = np.dot(np.transpose(W), dmulw)

for i in range(t-1, max(-1, t-bptt_truncate-1), -1):

ds = dsv + dprev_s

dadd = add * (1 - add) * ds

dmulw = dadd * np.ones_like(mulw)

dmulu = dadd * np.ones_like(mulu)

dW_i = np.dot(W, layers[t]['prev_s'])

dprev_s = np.dot(np.transpose(W), dmulw)

new_input = np.zeros(x.shape)

new_input[t] = x[t]

dU_i = np.dot(U, new_input)

dx = np.dot(np.transpose(U), dmulu)

dU_t += dU_i

dW_t += dW_i

dV += dV_t

dU += dU_t

dW += dW_t

if dU.max() >max_clip_value:

dU[dU >max_clip_value] = max_clip_value

if dV.max() >max_clip_value:

dV[dV >max_clip_value] = max_clip_value

if dW.max() >max_clip_value:

dW[dW >max_clip_value] = max_clip_value

if dU.min() <min_clip_value:

dU[dU <min_clip_value] = min_clip_value

if dV.min() <min_clip_value:

dV[dV <min_clip_value] = min_clip_value

if dW.min() <min_clip_value:

dW[dW <min_clip_value] = min_clip_value

# update

U -= learning_rate * dU

V -= learning_rate * dV

W -= learning_rate * dW

Epoch: 1 , Loss: [[101185.61756671]] , Val Loss: [[50591.0340148]]

Epoch: 2 , Loss: [[61205.46869629]] , Val Loss: [[30601.34535365]]

Epoch: 3 , Loss: [[31225.3198258]] , Val Loss: [[15611.65669247]]

Epoch: 4 , Loss: [[11245.17049551]] , Val Loss: [[5621.96780111]]

Epoch: 5 , Loss: [[1264.5157739]] , Val Loss: [[632.02563908]]

Epoch: 6 , Loss: [[20.15654115]] , Val Loss: [[10.05477285]]

Epoch: 7 , Loss: [[17.13622839]] , Val Loss: [[8.55190426]]

Epoch: 8 , Loss: [[17.38870495]] , Val Loss: [[8.68196484]]

Epoch: 9 , Loss: [[17.181681]] , Val Loss: [[8.57837827]]

Epoch: 10 , Loss: [[17.31275313]] , Val Loss: [[8.64199652]]

Epoch: 11 , Loss: [[17.12960034]] , Val Loss: [[8.54768294]]

Epoch: 12 , Loss: [[17.09020065]] , Val Loss: [[8.52993502]]

Epoch: 13 , Loss: [[17.17370113]] , Val Loss: [[8.57517454]]

Epoch: 14 , Loss: [[17.04906914]] , Val Loss: [[8.50658127]]

Epoch: 15 , Loss: [[16.96420184]] , Val Loss: [[8.46794248]]

Epoch: 16 , Loss: [[17.017519]] , Val Loss: [[8.49241316]]

Epoch: 17 , Loss: [[16.94199493]] , Val Loss: [[8.45748739]]

Epoch: 18 , Loss: [[16.99796892]] , Val Loss: [[8.48242177]]

Epoch: 19 , Loss: [[17.24817035]] , Val Loss: [[8.6126231]]

Epoch: 20 , Loss: [[17.00844599]] , Val Loss: [[8.48682234]]

Epoch: 21 , Loss: [[17.03943262]] , Val Loss: [[8.50437328]]

Epoch: 22 , Loss: [[17.01417255]] , Val Loss: [[8.49409597]]

Epoch: 23 , Loss: [[17.20918888]] , Val Loss: [[8.5854792]]

Epoch: 24 , Loss: [[16.92068017]] , Val Loss: [[8.44794633]]

Epoch: 25 , Loss: [[16.76856238]] , Val Loss: [[8.37295808]]

preds = []

for i in range(Y.shape[0]):

x, y = X[i], Y[i]

prev_s = np.zeros((hidden_dim, 1))

# Forward pass

for t in range(T):

mulu = np.dot(U, x)

mulw = np.dot(W, prev_s)

add = mulw + mulu

s = sigmoid(add)

mulv = np.dot(V, s)

prev_s = s

preds.append(mulv)

preds = np.array(preds)

plt.plot(preds[:, 0, 0], 'g')

plt.plot(Y[:, 0], 'r')

plt.show()

preds = []

for i in range(Y_val.shape[0]):

x, y = X_val[i], Y_val[i]

prev_s = np.zeros((hidden_dim, 1))

# For each time step...

for t in range(T):

mulu = np.dot(U, x)

mulw = np.dot(W, prev_s)

add = mulw + mulu

s = sigmoid(add)

mulv = np.dot(V, s)

prev_s = s

preds.append(mulv)

preds = np.array(preds)

plt.plot(preds[:, 0, 0], 'g')

plt.plot(Y_val[:, 0], 'r')

plt.show()

from sklearn.metrics import mean_squared_error

math.sqrt(mean_squared_error(Y_val[:, 0] * max_val, preds[:, 0, 0] * max_val))

0.127191931509431

自学深度学习是一个漫长而艰巨的过程。您需要有很强的线性代数和微积分背景,良好的Python编程技能,并扎实掌握数据科学、机器学习和数据工程。即便如此,在你开始将深度学习应用于现实世界的问题,并有可能找到一份深度学习工程师的工作之前,你可能需要一年多的学习和实践。然而,知道从哪里开始,对软化学习曲线有很大帮助。如果我必须重新学习Python的深度学习,我会从Andrew Trask写的Grokking deep learning开始。大多数关于深度学习的书籍都要求具备机器学习概念和算法的基本知识。除了基本的数学和编程技能之外,Trask的书不需要任何先决条件就能教你深度学习的基础知识。这本书不会让你成为一个深度学习的向导(它也没有做这样的声明),但它会让你走上一条道路,让你更容易从更高级的书和课程中学习。用Python构建人工神经元

大多数深度学习书籍都是基于一些流行的Python库,如TensorFlow、PyTorch或Keras。相比之下,《运用深度学习》(Grokking Deep Learning)通过从零开始、一行一行地构建内容来教你进行深度学习。

《运用深度学习》

你首先要开发一个人工神经元,这是深度学习的最基本元素。查斯克将带领您了解线性变换的基本知识,这是由人工神经元完成的主要计算。然后用普通的Python代码实现人工神经元,无需使用任何特殊的库。

这不是进行深度学习的最有效方式,因为Python有许多库,它们利用计算机的图形卡和CPU的并行处理能力来加速计算。但是用普通的Python编写一切对于学习深度学习的来龙去是非常好的。

在Grokking深度学习中,你的第一个人工神经元只接受一个输入,将其乘以一个随机权重,然后做出预测。然后测量预测误差,并应用梯度下降法在正确的方向上调整神经元的权重。有了单个神经元、单个输入和单个输出,理解和实现这个概念变得非常容易。您将逐渐增加模型的复杂性,使用多个输入维度、预测多个输出、应用批处理学习、调整学习速率等等。

您将通过逐步添加和修改前面章节中编写的Python代码来实现每个新概念,逐步创建用于进行预测、计算错误、应用纠正等的函数列表。当您从标量计算转移到向量计算时,您将从普通的Python操作转移到Numpy,这是一个特别擅长并行计算的库,在机器学习和深度学习社区中非常流行。

Python的深度神经网络

有了这些人造神经元的基本构造块,你就可以开始创建深层神经网络,这基本上就是你将几层人造神经元叠放在一起时得到的结果

当您创建深度神经网络时,您将了解激活函数,并应用它们打破堆叠层的线性并创建分类输出。同样,您将在Numpy函数的帮助下自己实现所有功能。您还将学习计算梯度和传播错误通过层传播校正跨不同的神经元。

随着您越来越熟悉深度学习的基础知识,您将学习并实现更高级的概念。这本书的特点是一些流行的正规化技术,如早期停止和退出。您还将获得自己版本的卷积神经网络(CNN)和循环神经网络(RNN)。

在本书结束时,您将把所有内容打包到一个完整的Python深度学习库中,创建自己的层次结构类、激活函数和神经网络体系结构(在这一部分,您将需要面向对象的编程技能)。如果您已经使用过Keras和PyTorch等其他Python库,那么您会发现最终的体系结构非常熟悉。如果您没有,您将在将来更容易地适应这些库。

在整本书中,查斯克提醒你熟能生巧他鼓励你用心编写自己的神经网络,而不是复制粘贴任何东西。

代码库有点麻烦

并不是所有关于Grokking深度学习的东西都是完美的。在之前的一篇文章中,我说过定义一本好书的主要内容之一就是代码库。在这方面,查斯克本可以做得更好。

在GitHub的Grokking深度学习库中,每一章都有丰富的jupiter Notebook文件。jupiter Notebook是一个学习Python机器学习和深度学习的优秀工具。然而,jupiter的优势在于将代码分解为几个可以独立执行和测试的小单元。Grokking深度学习的一些笔记本是由非常大的单元格组成的,其中包含大量未注释的代码。

这在后面的章节中会变得尤其困难,因为代码会变得更长更复杂,在笔记本中寻找自己的方法会变得非常乏味。作为一个原则问题,教育材料的代码应该被分解成小单元格,并在关键区域包含注释。

此外,Trask在Python 2.7中编写了这些代码。虽然他已经确保了代码在Python 3中也能顺畅地工作,但它包含了已经被Python开发人员弃用的旧编码技术(例如使用“for i in range(len(array))”范式在数组上迭代)。

更广阔的人工智能图景

Trask已经完成了一项伟大的工作,它汇集了一本书,既可以为初学者,也可以为有经验的Python深度学习开发人员填补他们的知识空白。

但正如泰温·兰尼斯特(Tywin Lannister)所说(每个工程师都会同意),“每个任务都有一个工具,每个工具都有一个任务。”深度学习并不是一根可以解决所有人工智能问题的魔杖。事实上,对于许多问题,更简单的机器学习算法,如线性回归和决策树,将表现得和深度学习一样好,而对于其他问题,基于规则的技术,如正则表达式和几个if-else子句,将优于两者。

关键是,你需要一整套工具和技术来解决AI问题。希望Grokking深度学习能够帮助你开始获取这些工具。

你要去哪里?我当然建议选择一本关于Python深度学习的深度书籍,比如PyTorch的深度学习或Python的深度学习。你还应该加深你对其他机器学习算法和技术的了解。我最喜欢的两本书是《动手机器学习》和《Python机器学习》。

你也可以通过浏览机器学习和深度学习论坛,如r/MachineLearning和r/deeplearning subreddits,人工智能和深度学习Facebook组,或通过在Twitter上关注人工智能研究人员来获取大量知识。

AI的世界是巨大的,并且在快速扩张,还有很多东西需要学习。如果这是你关于深度学习的第一本书,那么这是一个神奇旅程的开始。

时间序列模型

时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征。这是一类相对比较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发生的先后顺序的,同样大小的值改变顺序后输入模型产生的结果是不同的。

举个栗子:根据过去两年某股票的每天的股价数据推测之后一周的股价变化;根据过去2年某店铺每周想消费人数预测下周来店消费的人数等等

RNN 和 LSTM 模型

时间序列模型最常用最强大的的工具就是递归神经网络(recurrent neural network, RNN)。相比与普通神经网络的各计算结果之间相互独立的特点,RNN的每一次隐含层的计算结果都与当前输入以及上一次的隐含层结果相关。通过这种方法,RNN的计算结果便具备了记忆之前几次结果的特点。

典型的RNN网路结构如下:

右侧为计算时便于理解记忆而产开的结构。简单说,x为输入层,o为输出层,s为隐含层,而t指第几次的计算;V,W,U为权重,其中计算第t次的隐含层状态时为St = f(U*Xt + W*St-1),实现当前输入结果与之前的计算挂钩的目的。对RNN想要更深入的了解可以戳这里。

RNN的局限:

由于RNN模型如果需要实现长期记忆的话需要将当前的隐含态的计算与前n次的计算挂钩,即St = f(U*Xt + W1*St-1 + W2*St-2 + ... + Wn*St-n),那样的话计算量会呈指数式增长,导致模型训练的时间大幅增加,因此RNN模型一般直接用来进行长期记忆计算。

LSTM模型

LSTM(Long Short-Term Memory)模型是一种RNN的变型,最早由Juergen Schmidhuber提出的。经典的LSTM模型结构如下:

LSTM的特点就是在RNN结构以外添加了各层的阀门节点。阀门有3类:遗忘阀门(forget gate),输入阀门(input gate)和输出阀门(output gate)。这些阀门可以打开或关闭,用于将判断模型网络的记忆态(之前网络的状态)在该层输出的结果是否达到阈值从而加入到当前该层的计算中。如图中所示,阀门节点利用sigmoid函数将网络的记忆态作为输入计算;如果输出结果达到阈值则将该阀门输出与当前层的的计算结果相乘作为下一层的输入(PS:这里的相乘是在指矩阵中的逐元素相乘);如果没有达到阈值则将该输出结果遗忘掉。每一层包括阀门节点的权重都会在每一次模型反向传播训练过程中更新。更具体的LSTM的判断计算过程如下图所示:

LSTM模型的记忆功能就是由这些阀门节点实现的。当阀门打开的时候,前面模型的训练结果就会关联到当前的模型计算,而当阀门关闭的时候之前的计算结果就不再影响当前的计算。因此,通过调节阀门的开关我们就可以实现早期序列对最终结果的影响。而当你不不希望之前结果对之后产生影响,比如自然语言处理中的开始分析新段落或新章节,那么把阀门关掉即可。(对LSTM想要更具体的了解可以戳这里)

下图具体演示了阀门是如何工作的:通过阀门控制使序列第1的输入的变量影响到了序列第4,6的的变量计算结果。

黑色实心圆代表对该节点的计算结果输出到下一层或下一次计算;空心圆则表示该节点的计算结果没有输入到网络或者没有从上一次收到信号。

Python中实现LSTM模型搭建

Python中有不少包可以直接调用来构建LSTM模型,比如pybrain, kears, tensorflow, cikit-neuralnetwork等(更多戳这里)。这里我们选用keras。(PS:如果操作系统用的linux或者mac,强推Tensorflow!!!)

因为LSTM神经网络模型的训练可以通过调整很多参数来优化,例如activation函数,LSTM层数,输入输出的变量维度等,调节过程相当复杂。这里只举一个最简单的应用例子来描述LSTM的搭建过程。

应用实例

基于某家店的某顾客的历史消费的时间推测该顾客前下次来店的时间。具体数据如下所示:

消费时间

2015-05-15 14:03:512015-05-15 15:32:462015-06-28 18:00:172015-07-16 21:27:182015-07-16 22:04:512015-09-08 14:59:56..

..

具体操作:

1. 原始数据转化

首先需要将时间点数据进行数值化。将具体时间转化为时间段用于表示该用户相邻两次消费的时间间隔,然后再导入模型进行训练是比较常用的手段。转化后的数据如下:

消费间隔04418054..

..

2.生成模型训练数据集(确定训练集的窗口长度)

这里的窗口指需要几次消费间隔用来预测下一次的消费间隔。这里我们先采用窗口长度为3, 即用t-2, t-1,t次的消费间隔进行模型训练,然后用t+1次间隔对结果进行验证。数据集格式如下:X为训练数据,Y为验证数据。

PS: 这里说确定也不太合适,因为窗口长度需要根据模型验证结果进行调整的。

X1    X2    X3    Y0    44    18    044    18    0    54..

..    

注:直接这样预测一般精度会比较差,可以把预测值Y根据数值bin到几类,然后用转换成one-hot标签再来训练会比较好。比如如果把Y按数值范围分到五类(1:0-20,2:20-40,3:40-60,4:60-80,5:80-100)上式可化为:

X1    X2    X3    Y0    44    18    044    18    0    4...

Y转化成one-hot以后则是(关于one-hot编码可以参考这里)

1    0    0    0    00    0    0    0    1...

3. 网络模型结构的确定和调整

这里我们使用python的keras库。(用java的同学可以参考下deeplearning4j这个库)。网络的训练过程设计到许多参数的调整:比如

需要确定LSTM模块的激活函数(activation fucntion)(keras中默认的是tanh);

确定接收LSTM输出的完全连接人工神经网络(fully-connected artificial neural network)的激活函数(keras中默认为linear);

确定每一层网络节点的舍弃率(为了防止过度拟合(overfit)),这里我们默认值设定为0.2;

确定误差的计算方式,这里我们使用均方误差(mean squared error);

确定权重参数的迭代更新方式,这里我们采用RMSprop算法,通常用于RNN网络。

确定模型训练的epoch和batch size(关于模型的这两个参数具体解释戳这里)

一般来说LSTM模块的层数越多(一般不超过3层,再多训练的时候就比较难收敛),对高级别的时间表示的学习能力越强;同时,最后会加一层普通的神经网路层用于输出结果的降维。典型结构如下:

如果需要将多个序列进行同一个模型的训练,可以将序列分别输入到独立的LSTM模块然后输出结果合并后输入到普通层。结构如下:

4. 模型训练和结果预测

将上述数据集按4:1的比例随机拆分为训练集和验证集,这是为了防止过度拟合。训练模型。然后将数据的X列作为参数导入模型便可得到预测值,与实际的Y值相比便可得到该模型的优劣。

实现代码

时间间隔序列格式化成所需的训练集格式

import pandas as pdimport numpy as npdef create_interval_dataset(dataset, look_back):

   """    :param dataset: input array of time intervals    :param look_back: each training set feature length    :return: convert an array of values into a dataset matrix.    """

   dataX, dataY = [], []    for i in range(len(dataset) - look_back):

       dataX.append(dataset[i:i+look_back])

       dataY.append(dataset[i+look_back])    return np.asarray(dataX), np.asarray(dataY)

df = pd.read_csv("path-to-your-time-interval-file")    

dataset_init = np.asarray(df)    # if only 1 columndataX, dataY = create_interval_dataset(dataset, lookback=3)    # look back if the training set sequence length

这里的输入数据来源是csv文件,如果输入数据是来自数据库的话可以参考这里

LSTM网络结构搭建

import pandas as pdimport numpy as npimport randomfrom keras.models import Sequential, model_from_jsonfrom keras.layers import Dense, LSTM, Dropoutclass NeuralNetwork():

   def __init__(self, **kwargs):

       """        :param **kwargs: output_dim=4: output dimension of LSTM layeractivation_lstm='tanh': activation function for LSTM layersactivation_dense='relu': activation function for Dense layeractivation_last='sigmoid': activation function for last layerdrop_out=0.2: fraction of input units to dropnp_epoch=10, the number of epoches to train the model. epoch is one forward pass and one backward pass of all the training examplesbatch_size=32: number of samples per gradient update. The higher the batch size, the more memory space you'll needloss='mean_square_error': loss functionoptimizer='rmsprop'        """

       self.output_dim = kwargs.get('output_dim', 8)        self.activation_lstm = kwargs.get('activation_lstm', 'relu')        self.activation_dense = kwargs.get('activation_dense', 'relu')        self.activation_last = kwargs.get('activation_last', 'softmax')    # softmax for multiple output

       self.dense_layer = kwargs.get('dense_layer', 2)     # at least 2 layers

       self.lstm_layer = kwargs.get('lstm_layer', 2)        self.drop_out = kwargs.get('drop_out', 0.2)        self.nb_epoch = kwargs.get('nb_epoch', 10)        self.batch_size = kwargs.get('batch_size', 100)        self.loss = kwargs.get('loss', 'categorical_crossentropy')        self.optimizer = kwargs.get('optimizer', 'rmsprop')        def NN_model(self, trainX, trainY, testX, testY):

       """        :param trainX: training data set        :param trainY: expect value of training data        :param testX: test data set        :param testY: epect value of test data        :return: model after training        """

       print "Training model is LSTM network!"

       input_dim = trainX[1].shape[1]

       output_dim = trainY.shape[1] # one-hot label

       # print predefined parameters of current model:

       model = Sequential()        # applying a LSTM layer with x dim output and y dim input. Use dropout parameter to avoid overfitting

       model.add(LSTM(output_dim=self.output_dim,

                      input_dim=input_dim,

                      activation=self.activation_lstm,

                      dropout_U=self.drop_out,

                      return_sequences=True))        for i in range(self.lstm_layer-2):

           model.add(LSTM(output_dim=self.output_dim,

                      input_dim=self.output_dim,

                      activation=self.activation_lstm,

                      dropout_U=self.drop_out,

                      return_sequences=True))        # argument return_sequences should be false in last lstm layer to avoid input dimension incompatibility with dense layer

       model.add(LSTM(output_dim=self.output_dim,

                      input_dim=self.output_dim,

                      activation=self.activation_lstm,

                      dropout_U=self.drop_out))        for i in range(self.dense_layer-1):

           model.add(Dense(output_dim=self.output_dim,

                       activation=self.activation_last))

       model.add(Dense(output_dim=output_dim,

                       input_dim=self.output_dim,

                       activation=self.activation_last))        # configure the learning process

       model.compile(loss=self.loss, optimizer=self.optimizer, metrics=['accuracy'])        # train the model with fixed number of epoches

       model.fit(x=trainX, y=trainY, nb_epoch=self.nb_epoch, batch_size=self.batch_size, validation_data=(testX, testY))        # store model to json file

       model_json = model.to_json()        with open(model_path, "w") as json_file:

           json_file.write(model_json)        # store model weights to hdf5 file

       if model_weight_path:            if os.path.exists(model_weight_path):

               os.remove(model_weight_path)

           model.save_weights(model_weight_path) # eg: model_weight.h5

       return model

这里写的只涉及LSTM网络的结构搭建,至于如何把数据处理规范化成网络所需的结构以及把模型预测结果与实际值比较统计的可视化,就需要根据实际情况做调整了。