S-RNN深度学习框架仿真

1.代码阅读

  我选择的文章是"Structural-RNN: Deep Learning on Spatio-Temporal Graphs",是康奈尔和斯坦福的学者发表于2016年CVPR的一篇文章,作者提出了一种结合高阶时空图像和循环神经网络的方法,赋予了深度循环神经网络更加直观的高阶时空架构,并利用这种新结构解决一些实际问题,均取得了较好的效果。我综合课本和Github上开源的代码对该文章进行了仿真实现,在这里对实验过程及结果进行说明。

1.1 代码结构

  S-RNN结构是基于Theano实现的,Theano是一个Python库,可以在CPUGPU上运行快速数值计算,它能巧妙的采用一系列代码优化从硬件中攫取尽可能多的性能,并且充分加速Numpy库和Scipy库的计算,在用Python进行深度学习是,Theano库由于其优越的性能被广泛使用,能创建深度学习模型,对库进行包装,在很大程度上简化程序。

  本篇文章中的S-RNN基于Theano库搭建了NeuralModels库,他能很好地建立循环神经网络,并且能快速方便的对循环神经网络进行建模。NeuralModels的地址为:

  https://github.com/asheshjain399/NeuralModels

  在安装好NeuralModels库之后,我们可以方便的构建S-RNN结构,并且用它来实现文章中提到的动作检测和行为预测。

  使用S-RNN结构进行动作检测和行为预测的代码地址如下:

  https://github.com/asheshjain399/RNNexp

  所以代码仿真的整体顺序为:

  1. 安装Theano环境
  2. 安装NeuralModels
  3. 使用S-RNN实现文中提到的实验内容
1.2 NeuralModels库文件的结构与功能

  通过学习NeuralModels库文件的代码,可知库文件的结构如下:

021617 0810 SRNN1 - S-RNN深度学习框架仿真

1-1 NeuralModels库文件

  接下来对各个文件的功能进行说明:

  NeuralModels是一个Python编写的神经网络模型,包含了各种深度神经网络层的定义,优化方法以及几个模型。

  在layers目录是一些层的定义,在深度学习框架中有许多层是具有特定功能并且通用的,NeuralModels库中的说明如下:

layers/LSTM.py

  这一层是使用Gradient clippingLSTM算法层,在这里关键理解两个概念,第一是什么是Gradient Clipping,其次什么是LSTM算法。

  首先解释一下LSTM算法的概念:

  LSTM是对循环神经网络(RNN)的一种改进,普通的循环神经网络虽然有记忆功能,能够把之前的信息连接到当前的任务上,但是实际上,要想达到好的效果,还有很多依赖因素。例如,我们有一个语言模型用来基于先前的词来预测下一个词。如果我们试着预测"the clouds are in the sky"最后的词,我们并不需要任何其他的上下文——因此下一个词很显然就应该是 sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN 可以学会使用先前的信息。但是同样会有一些更加复杂的场景。假设我们试着去预测"I grew up in France... I speak fluent French"最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France 的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。不幸的是,在这个间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。而LSTM网络通过刻意的设计有效避免了长期依赖问题。对于LSTM模型的解释这里不再多做赘述,我在代码学习的过程中主要是通过这篇文章来了解的:http://www.jianshu.com/p/9dc9f41f0b29/

  Gradient Clipping在循环神经网络中非常常见,当梯度进行传播时,如果他们连续乘以小于1的数字,最后可能消失,这也就是我们所说的Vanishing Gradient Problem.当然,如果连续乘以大于1的数字,梯度可能特别大,这被称为梯度爆炸,Gradient Clipping可以把梯度限制在两个数字之间,使梯度变化的范围可控。

layers/multilayerLSTM.py

  用这一层网络可以创建一个具有Skip-input and output connectionLSTM堆栈,在不需要使用Skip-input and output connection的情况下,就会简单的创建一个多层LSTM数组。

  什么是Skip connection呢,他是被用来连接高等级和低等级特征值的一种方法,例如一个动作序列当中的上下文语义特征和单纯图像的像素特征,前者是高级特征,后者是低级特征,使用Skip Connection可以把二者结合起来。

layers/simpleRNN.py

  这是简单的循环神经网络层。

layers/softmax.py

  Softmax层,一般是深度神经网络结构的输出层。Softmax函数将多个标量映射为一个概率分布,其输出的每一个值范围在(0,1)。公式如以下所示:

021617 0810 SRNN2 - S-RNN深度学习框架仿真

  softmax函数经常用在神经网络的最后一层,作为输出层,进行多分类。关于Softmax层我主要是通过该链接进行理解的:

  http://www.jianshu.com/p/cb93d5e39bca

l​ayers/OneHot.py

  OneHot层生成一个one-hot的矢量表示,通常用于有限大小的词汇的架构输入层。方便后期的计算和处理。

  我对它的具体理解主要参考该网页:

  http://www.cnblogs.com/lzh-cnblogs/p/3764749.html

layers/TemporalInputFeatures.py

  这一层也是用于处理数据的输入层,输入的数据的大小为T*N*D

T: the number of time-steps.

N: the number of sequences.

D: the Dimension of each feature vector.

layers/ConcatenateFeatures.py

  连接两个层,是1-1的连接,

layers/ConcatenateVectors.py

  多个层的数据连接到一个层,即多个层的向量直接叠加到一起。

layers/DenseInputFeatures.py

  多维数据的输入层

layers/unConcatenateVectors.py

  单个层的多维数据变换到一维,即每个维度的向量直接叠加到一起。

  在models目录是一些已经预实现的模型,具体说明如下:

model/DRA.py​​

  这是在时空图上计算S-RNN的模型,也是我们的文章中主要使用的部分。在DRA模型中,边缘RNN和节点RNN都是以RNN的名字为key,一系列layersvalue的字典。

  节点和边缘的连接线也是一个字典,它的key是节点RNN的名字,value是另外一个字典,这个字典的key值是与那个节点RNN相连的边缘RNNvalue值为一个两维的列表,表示用unConcatenateLayer中选择的要素。

  节点的标签也是一个字典,它的key为节点的名称,而值是一个Theano的矩阵。

model/DRAanticipation.py

  使用DRA的模型并且预测对应的输出。

model/MultipleRNNsCombined.py

  这个模型可以连接来自多个RNN的高级特征,并能够将最终得到的特征向量输送到最后的combined_layer

  它的输入是一系列的RNN层:[[layers_1],[layers_2],...,[layers_N]],其中layers_N代表一个RNN

  Combined_layer是最后的一层,可以连接之前的rnn层传递来的向量。

model/noisyRNN.py

  这是一个带噪声的RNN实现。

model/RNN.py

  这是一个简化的RNN实现。

model/SharedRNN.py

  通过因子分享可以实现RNN的结构化。

model/SharedRNNOutput.py

  使用因子分享的RNN并且得到预测的结果。

1.3 算法关键技术的程序实现
1.3.1 得到数据文件的时空关系

  文章中是把时空图作为S-RNN网络的向量输入,来进行深度学习的,那么怎么得到数据文件的时空关系呢,作者是手动标出并且进行处理的。

  具体代码可以见/structural_rnn/CRFProblems/H3.6m文件夹的内容,在文件夹中dataParser文件夹和mhmublv文件夹中是对数据进行分组和矢量变换的文件,首先读取时空关系文件,以/structural_rnn/CRFProblems/H3.6m/crf文件为例,里面的内容为:

  下面有一个5*5的矩阵,代表各个node之间的关系,每个节点分别是:脊椎,左手,右手,左腿,右腿,对于第一行,对脊椎来说,它与左手,右手,左腿,右腿都有交互,因此数据为0,1,1,1,1;但是对于第二行的左手来说,它只与脊椎和右手有交互,因此为1,0,1,0,0。以此类推可以认为的分割出其中的时空关系,并且对节点进行分组。在通过相关库函数进行具体转换,可以得到时空图数据集。

1.3.2 S-RNN框架的实现

  S-RNN框架得实现主要参考/NeuralModels-master/models/DRA.py文件中的内容。在该文件中定义了S-RNN框架的一个类。

  如前文已经叙述过的,在DRA模型中,边缘RNN(edgeRNN)和节点RNN(nodeRNN)都是以RNN的名字为key,一系列layers为value的字典。

  节点和边缘的连接线(nodeToEdgeConnections)也是一个字典,它的key是节点RNN的名字,value是另外一个字典(edgeListComplete),这个字典的key值是与那个节点RNN相连的边缘RNNvalue值为一个两维的列表,表示用unConcatenateLayer中选择的要素。

  节点的标签也是一个字典(nodeLabel),它的key为节点的名称,而值是一个Theano的矩阵。

  函数中的初始化如下图所示:

021617 0810 SRNN3 - S-RNN深度学习框架仿真

  首先,由于nodeRNN和edgeRNN都是value为一系列layers的字典,我们自下而上的构建网络,网络示意图如下:

021617 0810 SRNN4 - S-RNN深度学习框架仿真

1-2 S-RNN示意图

  采用自下而上的方式构建网络,首先遍历每一个nodeRNN节点,对于每一个nodeRNN节点,都可以通过nodeToedgeConnection得到与之相连的edgeRNN的列表,遍历该列表中的所有edgeRNN元素,每一个edgeRNN内部可能都有许多层,首先连接每个edgeRNN内部的层得到这些edgeRNN的输出,这一部分的代码如下:

021617 0810 SRNN5 - S-RNN深度学习框架仿真

  第二步是使用Concatenate层将edgeRNN的输出和nodeRNN连接到一起的所以先将nodeRNN和edgeRNN内部的层连接起来,具体代码如下图所示:

021617 0810 SRNN6 - S-RNN深度学习框架仿真

  最后连接每个nodeRNN内部的层,并且计算相应的nodelabel输出。这样利用前文已经提到过的layers可以实现S-RNN的框架。

1.3.3 节点间的因子分享

  文章中为了减少计算量,简化模型,还利用了节点间的因子分享方法,即在实际问题中一些结点或者边缘在语义上是相似的,可以分成一类,并且共享参数,这样一边面可以减少参数数量,另外一方面也可以增强框架适用于不同问题的灵活性。

  具体的实现可以参考/NeuralModels-master/models/SharedRNN.py中的内容。

  在SharedRNN中,分为shared_layers和其他普通层,首先将shared_layers部分的层内容相连,再将shared_layers分别和其他层相连,计算输出。具体代码截图如下:

021617 0810 SRNN7 - S-RNN深度学习框架仿真

1.3.4 相关函数作用说明

  除了以上内容外,在models的代码中还有一些具体函数,有特定的功能,并且这些函数的功能比较典型。以/NeuralModels-master/models/DRA.py中的相关函数为例进行说明:

fitModel

  fitmodel的参数是各种参数,这个函数的主要作用就是训练模型,并且利用测试集得出错误率或者预测结果。在模型已经存在的条件下,也可以读取相关模型,直接进行后期的预测。

saveForecastError

  saveForecastError的作用是计算测试集的正确率。

saveForecastMotion

  saveForecastMotion的作用是存储预测的动作信息。

saveCellState

  saveCellState的作用是存储S-RNN过程中间态的计算信息,可以利用他们来进行一些动作的识别和区分。

predict_output

  predict_output的作用是预估节点的输出。

predict_sequence

  predict_sequence的作用是预估序列的输出。

predict_nextstep

  predict_nextstep的作用预估下一步内容。

predict_cell

  predict_cell的作用预估中间的cells。

1.4 使用S-RNN结构的实例解析
1.4.1 Character-rnn的结构

  Character-rnn/NeuralModels-master/character-rnn/目录中,其中char-rnn.py是主程序,generateTrainDataOntext.py是读入数据的文件,数据集是一个4M大小的文本文件shakespeare_input.txt。这部分的作用是利用NeuralModels库构造多层RNN网络,学习莎士比亚作品并且进行预测输出。

  在主函数中,首先定义一些参数,如训练样本数目,测试样本数目,每个样本的长度,迭代次数,衰变速率等等。然后使用creatTrain函数首先将文本转化为向量输入。接着定义网络层,在本例中以OneHot为输入层,三个LSTM层为中间层,softmax层为输出层定义RNN网络,并且将得到的checkpoints文件存储到当前目录的checkpoints的文件夹当中,这一部分的代码如下图所示。

021617 0810 SRNN8 - S-RNN深度学习框架仿真

  程序很简单,在这里我想强调一下generateTrainDataonText.py的具体实现过程,这能帮助我们理解如何将文本文件转化成我们所需要的矢量输入。

  首先读入文本文件,利用Counter函数得到文本出现过的所有字符以及他们对应的次数的字典。

021617 0810 SRNN9 - S-RNN深度学习框架仿真

  然后创建字典,将文本中出现的所有字符与某个数字意义对应。这里创建两个字典,一个的key是字符,value是数字,用于将文本正变换为向量。另一个key是数字,value是字符,用于将数字向量反变换为文本。具体实现是在sample_text函数中实现的。这样说明可能会有点难以理解,我以比较直观的方式简单说明一下。

  例如一开始创建了一个字典,将b字符与数字21对应,o字符与数字5对应,k字符与数字14对应,空格字符与数字18对应。那么book 这个单词可以表示为21 5 5 14 18这个向量,通过这种方式,可以把整篇文章改成数字表示,并且截取固定长度的数字为一个单位,做成向量,用他们作为SRNN框架的输入。便能很方便的进行后续的计算和操作。最后我们预测出的结果也会是数字,利用之前得到的字典将数字反变换成字符即为我们最后的结果。
  实际上很多文本文件的矢量化都可以用这种方式来进行,这也是本文的代码中使用的主要方法。

1.4.2 基于H3.6数据集的人体移动预测的代码结构

  这是本文中主要提的一个通过S-RNN框架结合时空图预测人体运动规律的例子,它使用的是已经归一化处理过的h3.6m数据集,数据集在附件中,在本文提供的数据集中,图片数据已经被数字化。

  人体移动预测模型的代码可以在该网址下载:

  https://github.com/asheshjain399/RNNexp/tree/srnn/structural_rnn

  本实验的地址为:RNNexp-srnn/structural_rnn,其中的文件列表如下:

021617 0810 SRNN10 - S-RNN深度学习框架仿真

  H3.6m文件夹是将H3.6m数据库根据时空关系转化为数据输入的文件,具体实现在1.3.1节已经说过了,这里不再赘述。

  其中hyperParameterTuning.py是主程序,其中可以设置srnn模型,lstm3lr模型和erd模型的参数,基于这些参数可以训练出对应的模型并基于模型进行进一步的预测。

  loadDRA.py用以读入h3.6m数据集,H3.6m中的文件主要对数据集进行处理。generateMotionForecast.py文件和forecastTrajectories.py可以生成预测的文件。

  basedir文件中写入h3.6数据集存放的地址,生成的checkpoints文件也会放在对应的地址中。

1.4.3 人类行为预测模型的代码结构

  人类行为预测模型的代码目录在/RNNexp-srnn/actibity-anticipation目录中,这个例子是通过对节点RNN和边缘RNN进行学习得出每个节点对应的标签。

  文件目录如下:

021617 0810 SRNN11 - S-RNN深度学习框架仿真

  其中activity-dra.py文件是使用s-rnn模型估计活动,而activity-rnn-full-model.py是计算分享因子的rnn模型,activity-rnn.py是直接使用rnn模型,activity_prediction_sharedrnn.py是使用分享因子的rnn进行预测,而activity_prediction_rnn.py是直接使用rnn进行预测,readData文件读取数据。

  其中使用的库文件和技术在前文均有说明,在此不在赘述。

  此外给出的实例文件中还给了用S-RNN框架进行行车预测的代码,但由于文章中对该案例只是提到并没有太大说明,且该部分的原理和前几个例子类似,因此并不对这一部分进行具体分析和仿真。其中使用的库文件和技术在前文均有说明。

2.实验过程与相关问题

2.1 实验环境搭建过程

2.1.1 Theano环境搭建过程

  要使用S-RNN框架,必须安装NeuralModels库,而要安装NeuralModels库,则需要使用到Theano库,因此必须先在系统上安装Theano。

  实际上,在作者给出的以下网址中:

  https://github.com/asheshjain399/NeuralModels

  作者提出使用 python setup.py develop指令即可自动安装NeuralModels框架,但是在实际的安装过程中,使用github的方法直接安装NeuralModels,Numpy库Scipy库和Theano库都会出现一些问题,因此需要自行安装numpy库,scipy库和matplotlib库。

  一开始我是在自己笔记本的虚拟机上使用apt-get指令安装Numpy和Scipy,然后使用pip安装Theano的,但是在安装好后,发现使用该框架的计算速度非常慢,character-rnn例程在我的电脑上跑了三天才跑完,后来才发现直接安装的python库是没有加速的,所以要自己按照特定的步骤安装numpy和scipy,并且经过测试才行。

  因为之前没有安装过类似的开发环境,这次的环境搭建过程花费了很多时间,收货也很多,在这里对该过程详细叙述一下,其中也有过程中遇到的问题与解决方法。

  之前提到过,直接安装Scipy库和Numpy库进行数学运算时,由于没有加速,所以运算速度很慢,因此我们需要安装以下其他的库进行加速,在这里对相关库先进行介绍:

BLAS(Basic Linear Algebra Subprograms):

  是基础线性代数子程序库,里面拥有大量已经编写好的关于线性代数运算的程序;

LAPACK(Linear Algebra PACKage)

  包含了求解科学与工程计算中最常见的数值线性代数问题,如求解线性方程组、线性最小二乘问题、特征值问题和奇异值问题等;

ATLAS:

  是python下的一个线性代数库,是基于另外两个线性代数库BLAS和lapack的;

NumPy

  提供了一个在python中做科学计算的基础库,它重在数值计算,甚至可以说是用于多维数组处理的库;

SciPy:

  是基于numpy,提供了一个在python中做科学计算的工具集,也就是说它是更上一个层次的库;

Theano:

  则是基于NumPy以及SciPy的一个更高级的用于科学计算的库。

  要安装Theano,就需要先安装好numpy和scipy;要安装numpy和scipy,就需要ATLAS;要安装ATLAS,就需要安装BLAS和LAPACK;所以在这里我们的安装顺序应该是BLAS-LAPACK-ATLAS-Numpy-Scipy-Theano。

  因为一开始我的numpy和scipy库是通过apt-get指令安装的,所以没有与Atlas库建立依赖,因此当我试用以下两句指令进行Numpy库和Scipy库的测试时,显示有failures,测试并不通过。

  所以先要卸载之前安装的numpy和scipy:

  之后使用pip指令安装Numpy和Scipy,测试通过

  在安装完成之后,ubuntu进入到/NeuralModels-master/目录下,执行python setup.py develop指令安装NeuralModels库,此时出现问题:

  这是因为缺少matplotlib库造成的,解决方法是安装metplotlib

  先装预装库

  安装freetype:

  安装matplotlib

  这样matplotlib的问题解决。

  然后又出现问题:

  解决方案:

sudo apt-get install python-tk

  问题解决,然后再次出现问题:

  解决方案:

pip install -U --force --user nose

  至此Theano框架安装成功,并且使用Atlas加速,运行character-r程序的速度提升到了三小时。

  但是在这样的环境下,计算速度依旧不快,并且由于我是在电脑的虚拟机上运行的,一方面不能使用GPU加速,另外一方面经常会出现内存冲突的问题导致程序中断,因此后期使用了另一台带有双显卡的计算机,并且尝试对Theano进行进一步加速。

2.1.2 对Theano框架进行加速

  通过之前的安装我发现,使用不同的安装方式,最后运行的速度会有很大的差别,并且不能用虚拟机安装类似的深度学习框架进行深度学习,因为虚拟机不能使用GPU加速运算,也不能充分利用硬件资源,运算速度受到较大限制。

  此外,加速Theano库的方式有两种,第一种方法是我们之前用的,先安装Atlas,然后再Atlas的基础上安装Numpy和Scipy,这样的运行速度会快10倍左右,因为Atlas会对python的库进行加速。当然还有一种更快的方法是使用OpenBlas对Numpy和Scipy进行加速,这样的速度是目前最快的,并且Theano默认是使用OpenBlas加速,所以使用起来也更方便。因此在这里我重新使用这种方法安装环境并进行测试。在这之后,为了充分发挥服务器的性能,我也进行了一定的配置,使用GPU加速。接下来将配置过程以及相关问题进行说明:

  1.安装OpenBlas

  这一部分主要参考以下链接:

  http://deeplearning.net/software/theano_versions/dev/install_ubuntu.html

  http://www.linuxdiyf.com/linux/15610.html

  https://github.com/xianyi/OpenBLAS

  在github上下载好Openblas的代码以后:

  http://www.jb51.net/LINUXjishu/211594.html

  之后按照前一部分的说明安装Numpy和Scipy,网络上有一种方法是让我们下载源文件直接编译,我尝试过之后发现有很多问题,并且测试也不能通过,因此最后我使用的还是pip安装。测试成功。

  2.安装Cuda

  为了使用GPU加速,需要安装cuda和Nvidia SDK以及相关硬件驱动,然后设置.theanorc文件将其设置为硬件加速。

  在工程目录中新建.theanorc文件,例如我的电脑名字是达达,则建立在/home/dada/目录下

  在我的安装过程中,出现了下列问题:

我是参照以下链接解决的:

  http://www.th7.cn/system/lin/201604/162762.shtml

  至此,环境的安装工作完成,跑char-rnn.py的例程,此时使用GPU加速+openblas是10分钟,如果是atlas且没有GPU加速我跑了4小时,如果atlas也没有我跑了3天。由此可见正确的环境对深度学习速度的重大影响。

2.2 代码编译过程的问题与解决方案

  在以上环境安装好,并且其中遇到的问题解决后,代码都能正常运行,接下来简要提一下每个例子的编译过程和遇到的问题,以及最后的解决方案。

2.2.1 Character-rnn的实现

  Character-rnn是验证NeuralModels库是否安装好的示例文件,运行指令为:

python char-rnn.py
  ​​​前面已经提到,不同的主机运行环境,编译和运算的速度也不一样,使用直接安装的
Theano库需要三天时间才能完成训练过程,使用AtlasTheano的配置需要3小时,而使用openblasgpu加速只需要10分钟。

  代码的编译需要安装numpy库,scipy库,matplotlib库,python-tk库,nose库等,不然会报错。

  此外,如果电脑的虚拟内存不足,可能会在中途直接结束退出,我碰到过几次这样的情况,所以电脑的性能还是很重要的。

  通过学习Character-rnn的代码,我们也能很方便的构建自己所需要的深度学习网络架构。比如如果我想要创建一个有三层LSTM层的RNN网络,并且输入结构是已经计算好的特征向量,而输  出是一个softmax层,则可以按照这样的顺序建立模型:

2.2.2 基于H3.6数据集的人体移动预测的实现

  该实例使用H3.6m数据集,对人体行为进行预测。

  编译过程如下,首先下载H3.6m数据集,并且在basedir中输入H3.6m数据集存储的地址,原本的H3.6m数据集是图片,但是作者已经预处理成了文本形式。

  在/structural_rnn/CRFProblems文件夹中,是将H3.6m库根据时空关系分离所使用的库,在函数运行的过程中,会首先调用该文件的函数将数据集分离成时空图的相关变量。

  可以使用S-RNN框架,ERD框架和LSTM-3LR框架对函数进行训练,使用的指令如下:

  其中的model可以是srnnerd或者lstm3lr中的一种,分别代表使用对应的框架进行训练。在hyperParameterTuning.py函数中,可以对模型的参数进行定义,具体参数有收敛于这,学习速率,迭代次数,噪声比,序列场地,梯度,节点和文本大小,训练对象等等,通过修改这些值可以改变框架的性能,让它适应不同的问题。

  hyperParameterTuning.py函数内部会调用trainDRA.py文件,这个文件可以建立我们的模型并对它进行训练,将训练结果输入到对应的结果文件夹中。

  一旦训练结束,trainDRA.py文件也会自动调用generateMotionData.py文件,改文件会生成预测的结果并输入到generate.py文件夹中。

  当然,在程序运行结束之后,我们也可以使用如下指令利用已经训练好的模型生成预测结果:

  其中的modelsrnnerd或者lstm3lr中的一种,分别代表使用对应的框架进行预测,而path指的是之前生成的存放checkpoint的地址,该程序是存放在H3.6m数据集对应的文件夹中。

  在使用虚拟机运行该模型的训练时,还出现了一个问题:

  这是因为虚拟机的内存不够,换了服务器之后问题解决。

  在文章中,作者还提到,可以使用该框架生成混合人体移动模型,在实际运行中是在已经生成checkpoint数据点之后,调用generatemixMotion.py文件,指令如下:

  可以在checkpoint的目录下生成混合移动模型的结果。

2.2.3 人类行为检测的实现

  在文章中,作者还提到,可以使用S-RNN框架用于人体行为的检测和预测,作者使用的是CAD-120数据集,CAD-120数据集是康奈尔大学使用Kinect传感器记录的人类活动序列,一共有10个高级活动:做谷物,服药,堆放物体,拆卸物体,微波炉加热食物,拾取物体,清洁物体,采取食物,安排物体;还有10个子活动标签:到达,移动,倾倒,吃,喝,打开,放置,关闭,擦洗;12个物品提供标签:可达,可移动,可倾倒,可倾倒,可收藏,可饮用,可打开,可放置,可关闭,可洗涤,洗涤器。所以使用这个数据集本身可以较好的得到视频序列中的时空关系。

  在作者的github链接中没有给出该实验的数据集,但是直接使用CAD120数据的RAW文件,并无法直接转化为时空图和相关的矢量输入,因此这个实验难以编译复现,故本人只是对代码进行了分析,并没有编译这个实验过程。

  但是Activity-anticipation的原理和之前H3.5m数据库的原理基本是类似的,所以对于文章的理解并没有大影响。

2.3 实验结果数据分析
2.3.1 Character-rnn实验结果数据分析

  运行Character-rnn的实验数据在文件夹checkpoints中,在运行完成之后,里面有30个checkpoint文件,相当于经过30次迭代之后每次迭代的训练结果文件,还有一个文件是logfile,这是训练过程中输出的loss_rate的log,代表文件的收敛程度。

  在进行数据分析之前,先接受几个比较重要的概念,在character-rnn.py文件中,一开始定义了一些变量:

021617 0810 SRNN12 - S-RNN深度学习框架仿真

  epoch:1个epoch等于使用训练集中的全部样本训练一次,这里相当于所有样本训练30次,因此会得到30个checkpoint文件,并且由于每一次训练都是基于前一次的训练基础,因此训练过程中loss会不断减小。

  batch_size: 一次Forword运算以及BP运算中所需要的训练样本数目,其实深度学习每一次参数的更新所需要损失函数并不是由一个{data:label}获得的,而是由一组数据加权得到的,这一组数据的数量就是[batch size]。当然batch size 越大,所需的内存就越大,要量力而行.

  Learning_rate_decay: 权值衰减的作用是防止过拟合,在损失函数中,weight decay是放在像前面的一个系数,正泽祥一般指示魔性的复杂度,所以weight decay的作用是调节模型复杂度对损失函数的影响,若weight decay很大,则复杂的模型损失函数的值也就越大。

  观察数据可知loss一直在减少,到epoch为30次是在510左右波动,基本不变,仔细观察也能发现算到后面loss趋于稳定,此时预测输出的文本结果如下:

  以上是根据前面的内容预测出来的话,虽然还是比较乱,但是可以看出一定的预测效果。

2.3.2 H3.6m数据集预测结果分析

  使用S-RNN框架对H3.6m数据集进行人体运动估计的时候,首先使用s-rnn框架,生成文件在目录checkpoints_dra_T_150_bs_100_tg_10_ls_10_fc_10_demo中,其中checkpoint开头的文件是生成的训练结果,forecast_error_iteration开头的文件是预测的匹配率,forecast_iteration开头的文件是生成的短时预测的结果,而forecast_iterationlong开头的文件是生成的长时间活动预测的结果,ground_truth_forecast开头的文件时短时预测的参照文件,而ground_truth_longforecast是长时间预测的参考文件。

  我对srnn,erd和lstm3LR进行了比较,其中srnn的训练速度明显快于erd和lstm3lr算法,同样参数下,srnn的运行结果erd和lstm3lr的结果,和文章中给出的结果一致。

3. 理解体会
3.1 实验仿真感想

  整体来说这次实验的仿真过程有很多收获,首先对S-RNN框架,深度神经网络结构有了更多的了解,此外亲手完成代码的复现,也让我熟悉了这套框架,并且了解了一些问题和注意要点。

  对于这篇文章我也有了更深的了解,首先期中存在的几个问题都在仿真的过程中得到了答案:

  我期中时列出的问题如下:

  1. 首先,本文并没有说明是如何把一个序列的图像变成时空图的,即我们并不知道如何分割出其中的人和物,并且知道人和物的边缘关系,时空关系等。我觉得有两种可能,第一是已经认为标定了节点和边缘,后期不用进行分割,只要直接计算即可,但是这样的实用性就不强,因为它没有考虑到分割的问题,以及有误识别或误分割对S-RNN的影响。另外一种方式则是使用一些开源的人体检测和物体检测算法,提取出其中的人和物,比如可以使用轮廓提取+HOG特征检测+SVM分类的方法,但是对于不同的应用环境,需要检测的对象并不相同,这样检测算法也需要改变,这样这个系统不能称之为具有普适性,因为他的数据集预处理需要采用不同的处理方式。当然还有可能有其他的处理方式我并没有想到,后期可以看一些关于时空图处理的文章加以分析。
  2. RNNs网络有很多参数需要调节,如网络层数,每一层的神经元个数,迭代步长,收敛阈值,收敛上限等等,不同的RNNs网络最后得到的结果可能完全不同,所以在进行代码仿真时这部分还需要进行长时间的调参。
  3. 在时空图因子参数化的过程中,作者每个结点用一个因子函数表示,而每个边缘也用一个因子函数表示表示,展开后如图2-7-c建立S-RNN架构的数学模型,但是文章中并没有说函数的具体表示方法,当然这里也可能是随机确定权值,需要用梯度法或其他方法迭代计算,但因为文章还没说,目前并不是很清晰。

  现在看来,第一个问题,把序列的图像先转化成对应的文本文件,可以用H3.6m试验中类似的方法,手动的标出各个节点的时空关系,然后利用character-rnn中吧harrypoter文本转化为向量类似的方法和CRF的现成库文件,实现时空图关系的标定和相关向量的输入获取。

  第二个问题在代码中已经详细的列出了相关的参数,并且我也查了一些资料,具体了解了他们的应用与相关的功能,收获颇多。

  第三个问题也是有已经确定的参数和网络层的种类决定的,并且nodeRNNedgeRNN以及相关连接线的定义方式在之前也已经有过说明。

  S-RNN框架充分利用了共享因子和结构化的设计,通用型较强,这在这几个实验当中都有体现,计算复杂度与RNN网络内部的层数有关。不过因为深度学习方面接触的其他算法较少,所以性能方面我并没有特别明显的感受,今后多接触一些其他的算法可以对文章有更多的体会。

  此外,值得一提的是,我现在也能利用Theano框架,自己建立一些深度循环神经网络用以机器学习或预测问题,把知识转化为实用技能是一个很大的收获。

3.2 参考文献与网站

[1] Jain A, Zamir A R, Savarese S, et al. Structural-RNN: Deep Learning on Spatio-Temporal Graphs[J]. arXiv preprint arXiv:1511.05298, 2015.

[2] Sridhar M, Cohn A G, Hogg D C. Learning functional object categories from a relational spatio-temporal representation[C]//ECAI 2008: 18th European Conference on Artificial Intelligence (Frontiers in Artificial Intelligence and Applications). IOS Press, 2008: 606-610.

[3] http://asheshjain.org/srnn.

[4] https://www.zybuluo.com/hanbingtao/note/476663

[5] https://www.zybuluo.com/hanbingtao/note/541458

[6] https://github.com/asheshjain399/NeuralModels

[7] https://github.com/asheshjain399/RNNexp/tree/srnn/structural_rnn

[8] http://blog.csdn.net/xuezhisdc/article/details/47065475

[9] http://www.deeplearning.net/software/theano/

[10] http://www.openblas.net/

[11] https://github.com/xianyi/OpenBLAS/wiki/Installation-Guide

[12] http://www.csdn.net/article/2015-08-07/2825415

[13] http://www.th7.cn/system/lin/201604/162762.shtml

[14] http://stackoverflow.com/questions/41678837/no-module-named-nose-parameterized-during-theano-installation

[15] http://www.jb51.net/LINUXjishu/211594.html

[16] http://www.linuxdiyf.com/linux/15610.html