用keras框架较为方便首先安装anaconda,然后通过pip安装keras以下转自wphh的博客。
#coding:utf-8''' GPU run command: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python CPU run command: python 2016.06.06更新:这份代码是keras开发初期写的,当时keras还没有现在这么流行,文档也还没那么丰富,所以我当时写了一些简单的教程。
现在keras的API也发生了一些的变化,建议及推荐直接上看更加详细的教程。
'''#导入各种用到的模块组件from __future__ import absolute_importfrom __future__ import print_functionfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.models import Sequentialfrom import Dense, Dropout, Activation, Flattenfrom keras.layers.advanced_activations import PReLUfrom keras.layers.convolutional import Convolution2D, MaxPooling2Dfrom keras.optimizers import SGD, Adadelta, Adagradfrom keras.utils import np_utils, generic_utilsfrom six.moves import rangefrom data import load_dataimport randomimport numpy as np(1024) # for reproducibility#加载数据data, label = load_data()#打乱数据index = [i for i in range(len(data))]random.shuffle(index)data = data[index]label = label[index]print(data.shape[0], ' samples')#label为0~9共10个类别,keras要求格式为binary class matrices,转化一下,直接调用keras提供的这个函数label = np_utils.to_categorical(label, 10)################开始建立CNN模型################生成一个modelmodel = Sequential()#第一个卷积层,4个卷积核,每个卷积核大小5*5。
1表示输入的图片的通道,灰度图为1通道。
#border_mode可以是valid或者full,具体看这里说明:.conv2d#激活函数用tanh#你还可以在(Activation('tanh'))后加上dropout的技巧: (Dropout(0.5))(Convolution2D(4, 5, 5, border_mode='valid',input_shape=(1,28,28))) (Activation('tanh'))#第二个卷积层,8个卷积核,每个卷积核大小3*3。
4表示输入的特征图个数,等于上一层的卷积核个数#激活函数用tanh#采用maxpooling,poolsize为(2,2)(Convolution2D(8, 3, 3, border_mode='valid'))(Activation('tanh'))(MaxPooling2D(pool_size=(2, 2)))#第三个卷积层,16个卷积核,每个卷积核大小3*3#激活函数用tanh#采用maxpooling,poolsize为(2,2)(Convolution2D(16, 3, 3, border_mode='valid')) (Activation('relu'))(MaxPooling2D(pool_size=(2, 2)))#全连接层,先将前一层输出的二维特征图flatten为一维的。
#Dense就是隐藏层。16就是上一层输出的特征图个数。
4是根据每个卷积层计算出来的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4#全连接有128个神经元节点,初始化方式为normal(Flatten())(Dense(128, init='normal'))(Activation('tanh'))#Softmax分类,输出是10类别(Dense(10, init='normal'))(Activation('softmax'))##############开始训练模型###############使用SGD + momentum#model.compile里的参数loss就是损失函数(目标函数)sgd = SGD(lr=0.05, decay=1e-6, momentum=0.9, nesterov=True)model.compile(loss='categorical_crossentropy', optimizer=sgd,metrics=["accuracy"])#调用fit方法,就是一个训练过程. 训练的epoch数设为10,batch_size为100.#数据经过随机打乱shuffle=True。
verbose=1,训练过程中输出的信息,0、1、2三种方式都可以,无关紧要。show_accuracy=True,训练时每一个epoch都输出accuracy。
#validation_split=0.2,将20%的数据作为验证集。
(data, label, batch_size=100, nb_epoch=10,shuffle=True,verbose=1,validation_split=0.2)"""#使用data augmentation的方法#一些参数和调用的方法,请看文档datagen = ImageDataGenerator( featurewise_center=True, # set input mean to 0 over the dataset samplewise_center=False, # set each sample mean to 0 featurewise_std_normalization=True, # divide inputs by std of the dataset samplewise_std_normalization=False, # divide each input by its std zca_whitening=False, # apply ZCA whitening rotation_range=20, # randomly rotate images in the range (degrees, 0 to 180) width_shift_range=0.2, # randomly shift images horizontally (fraction of total width) height_shift_range=0.2, # randomly shift images vertically (fraction of total height) horizontal_flip=True, # randomly flip images vertical_flip=False) # randomly flip images# compute quantities required for featurewise normalization # (std, mean, and principal components if ZCA whitening is applied)(data)for e in range(nb_epoch): print('-'*40) print('Epoch', e) print('-'*40) print("Training...") # batch train with realtime data augmentation progbar = generic_utils.Progbar(data.shape[0]) for X_batch, Y_batch in (data, label): loss,accuracy = model.train(X_batch, Y_batch,accuracy=True) (X_batch.shape[0], values=[("train loss", loss),("accuracy:", accuracy)] )"""。
谷歌人工智能写作项目:神经网络伪原创
上周末利用python简单实现了一个卷积神经网络,只包含一个卷积层和一个maxpooling层,pooling层后面的多层神经网络采用了softmax形式的输出文案狗。
实验输入仍然采用MNIST图像使用10个featuremap时,卷积和pooling的结果分别如下所示。
部分源码如下:[python] viewplain copy#coding=utf-8'''''Created on 2014年11月30日@author: Wangliaofan'''import numpyimport structimport matplotlib.pyplot as pltimport mathimport randomimport copy#testfrom BasicMultilayerNeuralNetwork import BMNN2def sigmoid(inX):if (-inX)== 0.0:return 999999999.999999999return 1.0/((-inX))def difsigmoid(inX):return sigmoid(inX)*(1.0-sigmoid(inX))def tangenth(inX):return (1.0*(inX)-1.0*(-inX))/(1.0*(inX)+1.0*(-inX))def cnn_conv(in_image, filter_map,B,type_func='sigmoid'):#in_image[num,feature map,row,col]=>in_image[Irow,Icol]#features map[k filter,row,col]#type_func['sigmoid','tangenth']#out_feature[k filter,Irow-row+1,Icol-col+1]shape_image=numpy.shape(in_image)#[row,col]#print "shape_image",shape_imageshape_filter=numpy.shape(filter_map)#[k filter,row,col]if shape_filter[1]>shape_image[0] or shape_filter[2]>shape_image[1]:raise Exceptionshape_out=(shape_filter[0],shape_image[0]-shape_filter[1]+1,shape_image[1]-shape_filter[2]+1)out_feature=numpy.zeros(shape_out)k,m,n=numpy.shape(out_feature)for k_idx in range(0,k):#rotate 180 to calculate convc_filter=numpy.rot90(filter_map[k_idx,:,:], 2)for r_idx in range(0,m):for c_idx in range(0,n):#conv_temp=numpy.zeros((shape_filter[1],shape_filter[2]))(in_image[r_idx:r_idx+shape_filter[1],c_idx:c_idx+shape_filter[2]],c_filter)(conv_temp)if type_func=='sigmoid':out_feature[k_idx,r_idx,c_idx]=sigmoid(sum_temp+B[k_idx])elif type_func=='tangenth':out_feature[k_idx,r_idx,c_idx]=tangenth(sum_temp+B[k_idx])else:raise Exceptionreturn out_featuredef cnn_maxpooling(out_feature,pooling_size=2,type_pooling="max"):k,row,col=numpy.shape(out_feature)max_index_Matirx=numpy.zeros((k,row,col))out_row=int(numpy.floor(row/pooling_size))out_col=int(numpy.floor(col/pooling_size))out_pooling=numpy.zeros((k,out_row,out_col))for k_idx in range(0,k):for r_idx in range(0,out_row):for c_idx in range(0,out_col):temp_matrix=out_feature[k_idx,pooling_size*r_idx:pooling_size*r_idx+pooling_size,pooling_size*c_idx:pooling_size*c_idx+pooling_size]out_pooling[k_idx,r_idx,c_idx](temp_matrix)max_index=numpy.argmax(temp_matrix)#print max_index#print max_index/pooling_size,max_index%pooling_sizemax_index_Matirx[k_idx,pooling_size*r_idx+max_index/pooling_size,pooling_size*c_idx+max_index%pooling_size]=1return out_pooling,max_index_Matirxdef poolwithfunc(in_pooling,W,B,type_func='sigmoid'):k,row,col=numpy.shape(in_pooling)out_pooling=numpy.zeros((k,row,col))for k_idx in range(0,k):for r_idx in range(0,row):for c_idx in range(0,col):out_pooling[k_idx,r_idx,c_idx]=sigmoid(W[k_idx]*in_pooling[k_idx,r_idx,c_idx]+B[k_idx])return out_pooling#out_feature is the out put of convdef backErrorfromPoolToConv(theta,max_index_Matirx,out_feature,pooling_size=2):k1,row,col=numpy.shape(out_feature)error_conv=numpy.zeros((k1,row,col))k2,theta_row,theta_col=numpy.shape(theta)if k1!=k2:raise Exceptionfor idx_k in range(0,k1):for idx_row in range( 0, row):for idx_col in range( 0, col):error_conv[idx_k,idx_row,idx_col]=\max_index_Matirx[idx_k,idx_row,idx_col]*\float(theta[idx_k,idx_row/pooling_size,idx_col/pooling_size])*\difsigmoid(out_feature[idx_k,idx_row,idx_col])return error_convdef backErrorfromConvToInput(theta,inputImage):k1,row,col=numpy.shape(theta)#print "theta",k1,row,coli_row,i_col=numpy.shape(inputImage)if row>i_row or col> i_col:raise Exceptionfilter_row=i_row-row+1filter_col=i_col-col+1detaW=numpy.zeros((k1,filter_row,filter_col))#the same with conv valid in matlabfor k_idx in range(0,k1):for idx_row in range(0,filter_row):for idx_col in range(0,filter_col):subInputMatrix=inputImage[idx_row:idx_row+row,idx_col:idx_col+col]#print "subInputMatrix",numpy.shape(subInputMatrix)#rotate theta 180#print numpy.shape(theta)theta_rotate=numpy.rot90(theta[k_idx,:,:], 2)#print "theta_rotate",theta_rotate(subInputMatrix,theta_rotate)detaW[k_idx,idx_row,idx_col](dotMatrix)detaB=numpy.zeros((k1,1))for k_idx in range(0,k1):detaB[k_idx](theta[k_idx,:,:])return detaW,detaBdef loadMNISTimage(absFilePathandName,datanum=60000):images=open(absFilePathandName,'rb')()index=0magic, numImages , numRows , numColumns = struct.unpack_from('>IIII' , buf , index)print magic, numImages , numRows , numColumnsindex += struct.calcsize('>IIII')if magic != 2051:raise Exceptiondatasize=int(784*datanum)datablock=">"+str(datasize)+"B"#nextmatrix=struct.unpack_from('>47040000B' ,buf, index)nextmatrix=struct.unpack_from(datablock ,buf, index)nextmatrix=numpy.array(nextmatrix)/255.0#nextmatrix=nextmatrix.reshape(numImages,numRows,numColumns)#nextmatrix=nextmatrix.reshape(datanum,1,numRows*numColumns)nextmatrix=nextmatrix.reshape(datanum,1,numRows,numColumns)return nextmatrix, numImagesdef loadMNISTlabels(absFilePathandName,datanum=60000):labels=open(absFilePathandName,'rb')()index=0magic, numLabels = struct.unpack_from('>II' , buf , index)print magic, numLabelsindex += struct.calcsize('>II')if magic != 2049:raise Exceptiondatablock=">"+str(datanum)+"B"#nextmatrix=struct.unpack_from('>60000B' ,buf, index)nextmatrix=struct.unpack_from(datablock ,buf, index)nextmatrix=numpy.array(nextmatrix)return nextmatrix, numLabelsdef simpleCNN(numofFilter,filter_size,pooling_size=2,maxIter=1000,imageNum=500):decayRate=0.01MNISTimage,num1=loadMNISTimage("F:\Machine Learning\UFLDL\data\common\\train-images-idx3-ubyte",imageNum)print num1row,col=numpy.shape(MNISTimage[0,0,:,:])out_Di=numofFilter*((row-filter_size+1)/pooling_size)*((col-filter_size+1)/pooling_size)MLP=BMNN2.MuiltilayerANN(1,[128],out_Di,10,maxIter)MLP.setTrainDataNum(imageNum)MLP.loadtrainlabel("F:\Machine Learning\UFLDL\data\common\\train-labels-idx1-ubyte")MLP.initialweights()#MLP.printWeightMatrix()rng = numpy.random.RandomState(23455)W_shp = (numofFilter, filter_size, filter_size)W_bound = (numofFilter * filter_size * filter_size)W_k=rng.uniform(low=-1.0 / W_bound,high=1.0 / W_bound,size=W_shp)B_shp = (numofFilter,)B= numpy.asarray(rng.uniform(low=-.5, high=.5, size=B_shp))cIter=0while cIter。
。
200+这个是hintonmatlab代码的C++改写版.convnetjs-Star,SAE,首选的肯定是LIBSVM这个库;RBM#47.DeepLearnToolbox-Star,包括了CNN;C++SVM方面,Java。
2。
下面主要一些DeepLearning的GitHub项目吧;SdA#47:2200+实现了卷积神经网络,还实现了Rasmussen的共轭梯度ConjugateGradient算法,DBN,C/CRBM/CDBN#47:Python。
3,CAE等主流模型,实现的模型有DBN#47,可以用来做分类,语言是Python;LR等,从算法与实现上都比较全:800+实现了深度学习网络.rbm-mnist-Star,应该是应用最广的机器学习库了,强化学习等.DeepLearning(yusugomo)-Star,Scala:1000+Matlab实现中最热的库存,提供了5种语言的实现。
5;dA#47:500+这是同名书的配套代码。4.Neural-Networks-And-Deep-Learning-Star!1,回归。
从Siri到谷歌翻译,深度神经网络已经在机器理解自然语言方面取得了巨大突破。
这些模型大多数将语言视为单调的单词或字符序列,并使用一种称为循环神经网络(recurrentneuralnetwork/RNN)的模型来处理该序列。
但是许多语言学家认为语言最好被理解为具有树形结构的层次化词组,一种被称为递归神经网络(recursiveneuralnetwork)的深度学习模型考虑到了这种结构,这方面已经有大量的研究。
虽然这些模型非常难以实现且效率很低,但是一个全新的深度学习框架PyTorch能使它们和其它复杂的自然语言处理模型变得更加容易。
虽然递归神经网络很好地显示了PyTorch的灵活性,但它也广泛支持其它的各种深度学习框架,特别的是,它能够对计算机视觉(computervision)计算提供强大的支撑。
PyTorch是FacebookAIResearch和其它几个实验室的开发人员的成果,该框架结合了Torch7高效灵活的GPU加速后端库与直观的Python前端,它的特点是快速成形、代码可读和支持最广泛的深度学习模型。
开始SPINN链接中的文章()详细介绍了一个递归神经网络的PyTorch实现,它具有一个循环跟踪器(recurrenttracker)和TreeLSTM节点,也称为SPINN——SPINN是深度学习模型用于自然语言处理的一个例子,它很难通过许多流行的框架构建。
这里的模型实现部分运用了批处理(batch),所以它可以利用GPU加速,使得运行速度明显快于不使用批处理的版本。
SPINN的意思是堆栈增强的解析器-解释器神经网络(Stack-augmentedParser-InterpreterNeuralNetwork),由Bowman等人于2016年作为解决自然语言推理任务的一种方法引入,该论文中使用了斯坦福大学的SNLI数据集。
该任务是将语句对分为三类:假设语句1是一幅看不见的图像的准确标题,那么语句2(a)肯定(b)可能还是(c)绝对不是一个准确的标题?
(这些类分别被称为蕴含(entailment)、中立(neutral)和矛盾(contradiction))。
例如,假设一句话是「两只狗正跑过一片场地」,蕴含可能会使这个语句对变成「户外的动物」,中立可能会使这个语句对变成「一些小狗正在跑并试图抓住一根棍子」,矛盾能会使这个语句对变成「宠物正坐在沙发上」。
特别地,研究SPINN的初始目标是在确定语句的关系之前将每个句子编码(encoding)成固定长度的向量表示(也有其它方式,例如注意模型(attentionmodel)中将每个句子的每个部分用一种柔焦(softfocus)的方法相互比较)。
数据集是用句法解析树(syntacticparsetree)方法由机器生成的,句法解析树将每个句子中的单词分组成具有独立意义的短语和子句,每个短语由两个词或子短语组成。
许多语言学家认为,人类通过如上面所说的树的分层方式来组合词意并理解语言,所以用相同的方式尝试构建一个神经网络是值得的。
下面的例子是数据集中的一个句子,其解析树由嵌套括号表示:((Thechurch)((has(cracks(in(theceiling)))).))这个句子进行编码的一种方式是使用含有解析树的神经网络构建一个神经网络层Reduce,这个神经网络层能够组合词语对(用词嵌入(wordembedding)表示,如GloVe)、和/或短语,然后递归地应用此层(函数),将最后一个Reduce产生的结果作为句子的编码:X=Reduce(“the”,“ceiling”)Y=Reduce(“in”,X)...etc.但是,如果我希望网络以更类似人类的方式工作,从左到右阅读并保留句子的语境,同时仍然使用解析树组合短语?
或者,如果我想训练一个网络来构建自己的解析树,让解析树根据它看到的单词读取句子?
这是一个同样的但方式略有不同的解析树的写法:Thechurch)hascracksintheceiling)))).))或者用第3种方式表示,如下:WORDS:Thechurchhascracksintheceiling.PARSES:SSRSSSSSRRRRSRR我所做的只是删除开括号,然后用「S」标记「shift」,并用「R」替换闭括号用于「reduce」。
但是现在可以从左到右读取信息作为一组指令来操作一个堆栈(stack)和一个类似堆栈的缓冲区(buffer),能得到与上述递归方法完全相同的结果:1.将单词放入缓冲区。
2.从缓冲区的前部弹出「The」,将其推送(push)到堆栈上层,紧接着是「church」。3.弹出前2个堆栈值,应用于Reduce,然后将结果推送回堆栈。
4.从缓冲区弹出「has」,然后推送到堆栈,然后是「cracks」,然后是「in」,然后是「the」,然后是「ceiling」。
5.重复四次:弹出2个堆栈值,应用于Reduce,然后推送结果。6.从缓冲区弹出「.」,然后推送到堆栈上层。7.重复两次:弹出2个堆栈值,应用于Reduce,然后推送结果。
8.弹出剩余的堆栈值,并将其作为句子编码返回。我还想保留句子的语境,以便在对句子的后半部分应用Reduce层时考虑系统已经读取的句子部分的信息。
所以我将用一个三参数函数替换双参数的Reduce函数,该函数的输入值为一个左子句、一个右子句和当前句的上下文状态。该状态由神经网络的第二层(称为循环跟踪器(Tracker)的单元)创建。
Tracker在给定当前句子上下文状态、缓冲区中的顶部条目b和堆栈中前两个条目s1\s2时,在堆栈操作的每个步骤(即,读取每个单词或闭括号)后生成一个新状态:context[t+1]=Tracker(context[t],b,s1,s2)容易设想用你最喜欢的编程语言来编写代码做这些事情。
对于要处理的每个句子,它将从缓冲区加载下一个单词,运行跟踪器,检查是否将单词推送入堆栈或执行Reduce函数,执行该操作;然后重复,直到对整个句子完成处理。
通过对单个句子的应用,该过程构成了一个大而复杂的深度神经网络,通过堆栈操作的方式一遍又一遍地应用它的两个可训练层。
但是,如果你熟悉TensorFlow或Theano等传统的深度学习框架,就知道它们很难实现这样的动态过程。你值得花点时间回顾一下,探索为什么PyTorch能有所不同。
图论图1:一个函数的图结构表示深度神经网络本质上是有大量参数的复杂函数。深度学习的目的是通过计算以损失函数(loss)度量的偏导数(梯度)来优化这些参数。
如果函数表示为计算图结构(图1),则向后遍历该图可实现这些梯度的计算,而无需冗余工作。
每个现代深度学习框架都是基于此反向传播(backpropagation)的概念,因此每个框架都需要一个表示计算图的方式。
在许多流行的框架中,包括TensorFlow、Theano和Keras以及Torch7的nngraph库,计算图是一个提前构建的静态对象。
该图是用像数学表达式的代码定义的,但其变量实际上是尚未保存任何数值的占位符(placeholder)。图中的占位符变量被编译进函数,然后可以在训练集的批处理上重复运行该函数来产生输出和梯度值。
这种静态计算图(staticcomputationgraph)方法对于固定结构的卷积神经网络效果很好。但是在许多其它应用中,有用的做法是令神经网络的图结构根据数据而有所不同。
在自然语言处理中,研究人员通常希望通过每个时间步骤中输入的单词来展开(确定)循环神经网络。
上述SPINN模型中的堆栈操作很大程度上依赖于控制流程(如for和if语句)来定义特定句子的计算图结构。在更复杂的情况下,你可能需要构建结构依赖于模型自身的子网络输出的模型。
这些想法中的一些(虽然不是全部)可以被生搬硬套到静态图系统中,但几乎总是以降低透明度和增加代码的困惑度为代价。
该框架必须在其计算图中添加特殊的节点,这些节点代表如循环和条件的编程原语(programmingprimitive),而用户必须学习和使用这些节点,而不仅仅是编程代码语言中的for和if语句。
这是因为程序员使用的任何控制流程语句将仅运行一次,当构建图时程序员需要硬编码(hardcoding)单个计算路径。
例如,通过词向量(从初始状态h0开始)运行循环神经网络单元(rnn_unit)需要TensorFlow中的特殊控制流节点tf.while_loop。
需要一个额外的特殊节点来获取运行时的词长度,因为在运行代码时它只是一个占位符。
#TensorFlow#(thiscoderunsonce,duringmodelinitialization)#“words”isnotareallist(it’saplaceholdervariable)so#Ican’tuse“len”cond=lambdai,h:i
在这样的框架(也称为运行时定义(define-by-run))中,计算图在运行时被建立和重建,使用相同的代码为前向通过(forwardpass)执行计算,同时也为反向传播(backpropagation)建立所需的数据结构。
这种方法能产生更直接的代码,因为控制流程的编写可以使用标准的for和if。
它还使调试更容易,因为运行时断点(run-timebreakpoint)或堆栈跟踪(stacktrace)将追踪到实际编写的代码,而不是执行引擎中的编译函数。
可以在动态框架中使用简单的Python的for循环来实现有相同变量长度的循环神经网络。
#PyTorch(alsoworksinChainer)#(thiscoderunsoneveryforwardpassofthemodel)#“words”isaPythonlistwithactualvaluesinith=h0forwordinwords:h=rnn_unit(word,h)PyTorch是第一个define-by-run的深度学习框架,它与静态图框架(如TensorFlow)的功能和性能相匹配,使其能很好地适合从标准卷积神经网络(convolutionalnetwork)到最疯狂的强化学习(reinforcementlearning)等思想。
所以让我们来看看SPINN的实现。代码在开始构建网络之前,我需要设置一个数据加载器(dataloader)。
通过深度学习,模型可以通过数据样本的批处理进行操作,通过并行化(parallelism)加快训练,并在每一步都有一个更平滑的梯度变化。
我想在这里可以做到这一点(稍后我将解释上述堆栈操作过程如何进行批处理)。以下Python代码使用内置于PyTorch的文本库的系统来加载数据,它可以通过连接相似长度的数据样本自动生成批处理。
运行此代码之后,train_iter、dev_iter和test_itercontain循环遍历训练集、验证集和测试集分块SNLI的批处理。
fromtorchtextimportdata,datasetsTEXT=.ParsedTextField(lower=True)TRANSITIONS=.ShiftReduceField()LABELS=data.Field(sequential=False)train,dev,test=.splits(TEXT,TRANSITIONS,LABELS,wv_type='glove.42B')TEXT.build_vocab(train,dev,test)train_iter,dev_iter,test_iter=data.BucketIterator.splits((train,dev,test),batch_size=64)你可以在中找到设置训练循环和准确性(accuracy)测量的其余代码。
让我们继续。
如上所述,SPINN编码器包含参数化的Reduce层和可选的循环跟踪器来跟踪句子上下文,以便在每次网络读取单词或应用Reduce时更新隐藏状态;以下代码代表的是,创建一个SPINN只是意味着创建这两个子模块(我们将很快看到它们的代码),并将它们放在一个容器中以供稍后使用。
importtorchfromtorchimportnn#subclasstheModuleclassfromPyTorch’sneuralnetworkpackageclassSPINN(nn.Module):def__init__(self,config):super(SPINN,self).__init__()self.config=configself.reduce=Reduce(config.d_hidden,config.d_tracker)ifconfig.d_trackerisnotNone:self.tracker=Tracker(config.d_hidden,config.d_tracker)当创建模型时,SPINN.__init__被调用了一次;它分配和初始化参数,但不执行任何神经网络操作或构建任何类型的计算图。
在每个新的批处理数据上运行的代码由SPINN.forward方法定义,它是用户实现的方法中用于定义模型向前过程的标准PyTorch名称。
上面描述的是堆栈操作算法的一个有效实现,即在一般Python中,在一批缓冲区和堆栈上运行,每一个例子都对应一个缓冲区和堆栈。
我使用转移矩阵(transition)包含的「shift」和「reduce」操作集合进行迭代,运行Tracker(如果存在),并遍历批处理中的每个样本来应用「shift」操作(如果请求),或将其添加到需要「reduce」操作的样本列表中。
然后在该列表中的所有样本上运行Reduce层,并将结果推送回到它们各自的堆栈。
defforward(self,buffers,transitions):#Theinputcomesinasasingletensorofwordembeddings;#Ineedittobealistofstacks,oneforeachexamplein#thebatch,thatwecanpopfromindependently.Thewordsin#eachexamplehavealreadybeenreversed,sothattheycan#bereadfromlefttorightbypoppingfromtheendofeach#list;theyhavealsobeenprefixedwithanullvalue.buffers=[list(torch.split(b.squeeze(1),1,0))forbintorch.split(buffers,1,1)]#wealsoneedtwonullvaluesatthebottomofeachstack,#sowecancopyfromthenullsintheinput;thesenulls#areallneededsothatthetrackercanrunevenifthe#bufferorstackisemptystacks=[[buf[0],buf[0]]forbufinbuffers]ifhasattr(self,'tracker'):self.tracker.reset_state()fortrans_batchintransitions:ifhasattr(self,'tracker'):#IdescribedtheTrackerearlierastaking4#arguments(context_t,b,s1,s2),buthereI#providethestackcontentsasasingleargument#whilestoringthecontextinsidetheTracker#objectitself.tracker_states,_=self.tracker(buffers,stacks)else:tracker_states=itertools.repeat(None)lefts,rights,trackings=[],[],[]batch=zip(trans_batch,buffers,stacks,tracker_states)fortransition,buf,stack,trackinginbatch:iftransition==SHIFT:stack.append(())eliftransition==REDUCE:rights.append(())lefts.append(())trackings.append(tracking)ifrights:reduced=iter(self.reduce(lefts,rights,trackings))fortransition,stackinzip(trans_batch,stacks):iftransition==REDUCE:stack.append(next(reduced))return[()forstackinstacks]在调用self.tracker或self.reduce时分别运行Tracker或Reduce子模块的向前方法,该方法需要在样本列表上应用前向操作。
在主函数的向前方法中,在不同的样本上进行独立的操作是有意义的,即为批处理中每个样本提供分离的缓冲区和堆栈,因为所有受益于批处理执行的重度使用数学和需要GPU加速的操作都在Tracker和Reduce中进行。
为了更干净地编写这些函数,我将使用一些helper(稍后将定义)将这些样本列表转化成批处理张量(tensor),反之亦然。
我希望Reduce模块自动批处理其参数以加速计算,然后解批处理(unbatch)它们,以便可以单独推送和弹出。
用于将每对左、右子短语表达组合成父短语(parentphrase)的实际组合函数是TreeLSTM,它是普通循环神经网络单元LSTM的变型。
该组合函数要求每个子短语的状态实际上由两个张量组成,一个隐藏状态h和一个存储单元(memorycell)状态c,而函数是使用在子短语的隐藏状态操作的两个线性层(nn.Linear)和将线性层的结果与子短语的存储单元状态相结合的非线性组合函数tree_lstm。
在SPINN中,这种方式通过添加在Tracker的隐藏状态下运行的第3个线性层进行扩展。图2:TreeLSTM组合函数增加了第3个输入(x,在这种情况下为Tracker状态)。
在下面所示的PyTorch实现中,5组的三种线性变换(由蓝色、黑色和红色箭头的三元组表示)组合为三个nn.Linear模块,而tree_lstm函数执行位于框内的所有计算。
图来自Chenetal.(2016)。
。
这两个概念实际上是互相交叉的,例如,卷积神经网络(Convolutionalneuralnetworks,简称CNNs)就是一种深度的监督学习下的机器学习模型,而深度置信网(DeepBeliefNets,简称DBNs)就是一种无监督学习下的机器学习模型。
一维构筑、二维构筑、全卷积构筑。
卷积神经网络(ConvolutionalNeuralNetworks,CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(FeedforwardNeuralNetworks),是深度学习(deeplearning)的代表算法之一。
卷积神经网络具有表征学习(representationlearning)能力,能够按其阶层结构对输入信息进行平移不变分类(shift-invariantclassification),因此也被称为“平移不变人工神经网络(Shift-InvariantArtificialNeuralNetworks,SIANN)”。
卷积神经网络的连接性:卷积神经网络中卷积层间的连接被称为稀疏连接(sparseconnection),即相比于前馈神经网络中的全连接,卷积层中的神经元仅与其相邻层的部分,而非全部神经元相连。
具体地,卷积神经网络第l层特征图中的任意一个像素(神经元)都仅是l-1层中卷积核所定义的感受野内的像素的线性组合。
卷积神经网络的稀疏连接具有正则化的效果,提高了网络结构的稳定性和泛化能力,避免过度拟合,同时,稀疏连接减少了权重参数的总量,有利于神经网络的快速学习,和在计算时减少内存开销。
卷积神经网络中特征图同一通道内的所有像素共享一组卷积核权重系数,该性质被称为权重共享(weightsharing)。
权重共享将卷积神经网络和其它包含局部连接结构的神经网络相区分,后者虽然使用了稀疏连接,但不同连接的权重是不同的。权重共享和稀疏连接一样,减少了卷积神经网络的参数总量,并具有正则化的效果。
在全连接网络视角下,卷积神经网络的稀疏连接和权重共享可以被视为两个无限强的先验(pirior),即一个隐含层神经元在其感受野之外的所有权重系数恒为0(但感受野可以在空间移动);且在一个通道内,所有神经元的权重系数相同。
。
卷积神经网络(ConvolutionalNeuralNetworks,CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(FeedforwardNeuralNetworks),是深度学习(deeplearning)的代表算法之一。
卷积神经网络具有表征学习(representationlearning)能力,能够按其阶层结构对输入信息进行平移不变分类(shift-invariantclassification),因此也被称为“平移不变人工神经网络。