基于python的卷积神经网络,Python实现卷积神经网络

怎样用python构建一个卷积神经网络模型

上周末利用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。

怎样用python构建一个卷积神经网络

用keras框架较为方便首先安装anaconda,然后通过pip安装keras以下转自wphh的博客AI爱发猫 www.aifamao.com

#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)] )"""。

如何用9行Python代码编写一个简易神经网络

python是一款应用非常广泛的脚本程序语言,谷歌公司的网页就是用python编写。python在生物信息、统计、网页制作、计算等多个领域都体现出了强大的功能。

python和其他脚本语言如java、R、Perl一样,都可以直接在命令行里运行脚本程序。

工具/原料python;CMD命令行;windows操作系统方法/步骤1、首先下载安装python,建议安装2.7版本以上,3.0版本以下,由于3.0版本以上不向下兼容,体验较差。

2、打开文本编辑器,推荐editplus,notepad等,将文件保存成.py格式,editplus和notepad支持识别python语法。

脚本第一行一定要写上#!usr/bin/python表示该脚本文件是可执行python脚本如果python目录不在usr/bin目录下,则替换成当前python执行程序的目录。

3、编写完脚本之后注意调试、可以直接用editplus调试。调试方法可自行百度。

脚本写完之后,打开CMD命令行,前提是python已经被加入到环境变量中,如果没有加入到环境变量,请百度4、在CMD命令行中,输入“python”+“空格”,即”python“;将已经写好的脚本文件拖拽到当前光标位置,然后敲回车运行即可。

如何用PyTorch实现递归神经网络

从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)。

如何利用Python做简单的验证码识别

1   摘要验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越来越严峻。

本文介绍了一套字符验证码识别的完整流程,对于验证码安全和OCR识别技术都有一定的借鉴意义。

然后经过了一年的时间,笔者又研究和get到了一种更强大的基于CNN卷积神经网络的直接端到端的验证识别技术(文章不是我的,然后我把源码整理了下,介绍和源码在这里面):基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)2   关键词关键词:安全,字符图片,验证码识别,OCR,Python,SVM,PIL3   免责声明本文研究所用素材来自于某旧Web框架的网站 完全对外公开 的公共图片资源。

本文只做了该网站对外公开的公共图片资源进行了爬取, 并未越权 做任何多余操作。本文在书写相关报告的时候已经 隐去 漏洞网站的身份信息。本文作者 已经通知 网站相关人员此系统漏洞,并积极向新系统转移。

本报告的主要目的也仅是用于 OCR交流学习 和引起大家对 验证安全的警觉 。

4   引言关于验证码的非技术部分的介绍,可以参考以前写的一篇科普类的文章:互联网安全防火墙(1)--网络验证码的科普里面对验证码的种类,使用场景,作用,主要的识别技术等等进行了讲解,然而并没有涉及到任何技术内容。

本章内容则作为它的 技术补充 来给出相应的识别的解决方案,让读者对验证码的功能及安全性问题有更深刻的认识。

5   基本工具要达到本文的目的,只需要简单的编程知识即可,因为现在的机器学习领域的蓬勃发展,已经有很多封装好的开源解决方案来进行机器学习。

普通程序员已经不需要了解复杂的数学原理,即可以实现对这些工具的应用了。

主要开发环境:python3.5pythonSDK版本PIL图片处理库libsvm开源的svm机器学习库关于环境的安装,不是本文的重点,故略去。

6   基本流程一般情况下,对于字符型验证码的识别流程如下:准备原始图片素材图片预处理图片字符切割图片尺寸归一化图片字符标记字符图片特征提取生成特征和标记对应的训练数据集训练特征标记数据生成识别模型使用识别模型预测新的未知图片集达到根据“图片”就能返回识别正确的字符集的目标7   素材准备7.1   素材选择由于本文是以初级的学习研究目的为主,要求 “有代表性,但又不会太难” ,所以就直接在网上找个比较有代表性的简单的字符型验证码(感觉像在找漏洞一样)。

最后在一个比较旧的网站(估计是几十年前的网站框架)找到了这个验证码图片。原始图:放大清晰图:此图片能满足要求,仔细观察其具有如下特点。

有利识别的特点 :由纯阿拉伯数字组成字数为4位字符排列有规律字体是用的统一字体以上就是本文所说的此验证码简单的重要原因,后续代码实现中会用到不利识别的特点 :图片背景有干扰噪点这虽然是不利特点,但是这个干扰门槛太低,只需要简单的方法就可以除去7.2   素材获取由于在做训练的时候,需要大量的素材,所以不可能用手工的方式一张张在浏览器中保存,故建议写个自动化下载的程序。

主要步骤如下:通过浏览器的抓包功能获取随机图片验证码生成接口批量请求接口以获取图片将图片保存到本地磁盘目录中这些都是一些IT基本技能,本文就不再详细展开了。

关于网络请求和文件保存的代码,如下:defdownloads_pic(**kwargs):  pic_name=('pic_name',None)  url='httand_code_captcha/'  res=(url,stream=True)  withopen(pic_path+pic_name+'.bmp','wb')asf:    forchunkinres.iter_content(chunk_size=1024):      ifchunk: #filteroutkeep-alivenewchunks        f.write(chunk)        f.flush()    f.close()循环执行N次,即可保存N张验证素材了。

下面是收集的几十张素材库保存到本地文件的效果图:8   图片预处理虽然目前的机器学习算法已经相当先进了,但是为了减少后面训练时的复杂度,同时增加识别率,很有必要对图片进行预处理,使其对机器识别更友好。

针对以上原始素材的处理步骤如下:读取原始图片素材将彩色图片二值化为黑白图片去除背景噪点8.1   二值化图片主要步骤如下:将RGB彩图转为灰度图将灰度图按照设定阈值转化为二值图image=(img_path)imgry=image.convert('L') #转化为灰度图table=get_bin_table()out=imgry.point(table,'1')上面引用到的二值函数的定义如下:呵呵11121314  def get_bin_table(threshold=140):    """    获取灰度转二值的映射table    :paramthreshold:    :return:    """    table = []    for i in range(256):        if i

二值化后带噪点的 6937 的像素点输出后如下图:1111000111111000111111100001111100000011111011101111011101111101111011110011011110011100111101111010110110101011011101111101111111110110101111110101111111101111110100011111011100111111001111111110111111001110111110000011111110010111110111111101110001111111101011010110111111011111110111101111111110111101111011111101111111011110111101110011110111101111110111001110000111111000011101100001110111011111如果你是近视眼,然后离屏幕远一点,可以隐约看到 6937 的骨架了。

8.2   去除噪点在转化为二值图片后,就需要清除噪点。本文选择的素材比较简单,大部分噪点也是最简单的那种 孤立点,所以可以通过检测这些孤立点就能移除大量的噪点。

关于如何去除更复杂的噪点甚至干扰线和色块,有比较成熟的算法: 洪水填充法FloodFill ,后面有兴趣的时间可以继续研究一下。

本文为了问题简单化,干脆就用一种简单的自己想的 简单办法 来解决掉这个问题:对某个 黑点 周边的九宫格里面的黑色点计数如果黑色点少于2个则证明此点为孤立点,然后得到所有的孤立点对所有孤立点一次批量移除。

下面将详细介绍关于具体的算法原理。

将所有的像素点如下图分成三大类顶点A非顶点的边界点B内部点C种类点示意图如下:其中:A类点计算周边相邻的3个点(如上图红框所示)B类点计算周边相邻的5个点(如上图红框所示)C类点计算周边相邻的8个点(如上图红框所示)当然,由于基准点在计算区域的方向不同,A类点和B类点还会有细分:A类点继续细分为:左上,左下,右上,右下B类点继续细分为:上,下,左,右C类点不用细分然后这些细分点将成为后续坐标获取的准则。

主要算法的python实现如下:defsum_9_region(img,x,y):  """  9邻域框,以当前点为中心的田字框,黑点个数  :paramx:  :paramy:  :return:  """  #todo判断图片的长宽度下限  cur_pixel=img.getpixel((x,y)) #当前像素点的值  width=img.width  height=img.height  ifcur_pixel==1: #如果当前点为白色区域,则不统计邻域值    return0  ify==0: #第一行    ifx==0: #左上顶点,4邻域      #中心点旁边3个点      sum=cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x+1,y))\         +img.getpixel((x+1,y+1))      return4-sum    elifx==width-1: #右上顶点      sum=cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x-1,y))\         +img.getpixel((x-1,y+1))      return4-sum    else: #最上非顶点,6邻域      sum=img.getpixel((x-1,y))\         +img.getpixel((x-1,y+1))\         +cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x+1,y))\         +img.getpixel((x+1,y+1))      return6-sum  elify==height-1: #最下面一行    ifx==0: #左下顶点      #中心点旁边3个点      sum=cur_pixel\         +img.getpixel((x+1,y))\         +img.getpixel((x+1,y-1))\         +img.getpixel((x,y-1))      return4-sum    elifx==width-1: #右下顶点      sum=cur_pixel\         +img.getpixel((x,y-1))\         +img.getpixel((x-1,y))\         +img.getpixel((x-1,y-1))      return4-sum    else: #最下非顶点,6邻域      sum=cur_pixel\         +img.getpixel((x-1,y))\         +img.getpixel((x+1,y))\         +img.getpixel((x,y-1))\         +img.getpixel((x-1,y-1))\         +img.getpixel((x+1,y-1))      return6-sum  else: #y不在边界    ifx==0: #左边非顶点      sum=img.getpixel((x,y-1))\         +cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x+1,y-1))\         +img.getpixel((x+1,y))\         +img.getpixel((x+1,y+1))      return6-sum    elifx==width-1: #右边非顶点      #print('%s,%s'%(x,y))      sum=img.getpixel((x,y-1))\         +cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x-1,y-1))\         +img.getpixel((x-1,y))\         +img.getpixel((x-1,y+1))      return6-sum    else: #具备9领域条件的      sum=img.getpixel((x-1,y-1))\         +img.getpixel((x-1,y))\         +img.getpixel((x-1,y+1))\         +img.getpixel((x,y-1))\         +cur_pixel\         +img.getpixel((x,y+1))\         +img.getpixel((x+1,y-1))\         +img.getpixel((x+1,y))\         +img.getpixel((x+1,y+1))      return9-sumTips:这个地方是相当考验人的细心和耐心程度了,这个地方的工作量还是蛮大的,花了半个晚上的时间才完成的。

计算好每个像素点的周边像素黑点(注意:PIL转化的图片黑点的值为0)个数后,只需要筛选出个数为 1或者2 的点的坐标即为 孤立点 。这个判断方法可能不太准确,但是基本上能够满足本文的需求了。

经过预处理后的图片如下所示:对比文章开头的原始图片,那些 孤立点 都被移除掉,相对比较 干净 的验证码图片已经生成。

9   图片字符切割由于字符型 验证码图片 本质就可以看着是由一系列的 单个字符图片 拼接而成,为了简化研究对象,我们也可以将这些图片分解到 原子级 ,即: 只包含单个字符的图片。

于是,我们的研究对象由 “N种字串的组合对象” 变成 “10种阿拉伯数字” 的处理,极大的简化和减少了处理对象。9.1   分割算法现实生活中的字符验证码的产生千奇百怪,有各种扭曲和变形。

关于字符分割的算法,也没有很通用的方式。这个算法也是需要开发人员仔细研究所要识别的字符图片的特点来制定的。当然,本文所选的研究对象尽量简化了这个步骤的难度,下文将慢慢进行介绍。

使用图像编辑软件(PhoneShop或者其它)打开验证码图片,放大到像素级别,观察其它一些参数特点:可以得到如下参数:整个图片尺寸是40*10单个字符尺寸是6*10左右字符和左右边缘相距2个像素字符上下紧挨边缘(即相距0个像素)这样就可以很容易就定位到每个字符在整个图片中占据的像素区域,然后就可以进行分割了,具体代码如下:defget_crop_imgs(img):  """  按照图片的特点,进行切割,这个要根据具体的验证码来进行工作.#见原理图  :paramimg:  :return:  """  child_img_list=[]  foriinrange(4):    x=2+i*(6+4) #见原理图    y=0    child_img=((x,y,x+6,y+10))    child_img_list.append(child_img)  returnchild_img_list然后就能得到被切割的 原子级 的图片元素了:9.2   内容小结基于本部分的内容的讨论,相信大家已经了解到了,如果验证码的干扰(扭曲,噪点,干扰色块,干扰线……)做得不够强的话,可以得到如下两个结论:4位字符和40000位字符的验证码区别不大纯字母不区分大小写。

分类数为26区分大小写。分类数为52纯数字。分类数为10数字和区分大小写的字母组合。

分类数为62纯数字 和 数字及字母组合 的验证码区别不大在没有形成 指数级或者几何级 的难度增加,而只是 线性有限级 增加计算量时,意义不太大。

10   尺寸归一本文所选择的研究对象本身尺寸就是统一状态:6*10的规格,所以此部分不需要额外处理。但是一些进行了扭曲和缩放的验证码,则此部分也会是一个图像处理的难点。

11   模型训练步骤在前面的环节,已经完成了对单个图片的处理和分割了。后面就开始进行 识别模型 的训练了。

整个训练过程如下:大量完成预处理并切割到原子级的图片素材准备对素材图片进行人为分类,即:打标签定义单张图片的识别特征使用SVM训练模型对打了标签的特征文件进行训练,得到模型文件12   素材准备本文在训练阶段重新下载了同一模式的4数字的验证图片总计:3000张。

然后对这3000张图片进行处理和切割,得到12000张原子级图片。

在这12000张图片中删除一些会影响训练和识别的强干扰的干扰素材,切割后的效果图如下:13   素材标记由于本文使用的这种识别方法中,机器在最开始是不具备任何数字的观念的。

所以需要人为的对素材进行标识,告诉 机器什么样的图片的内容是1……。这个过程叫做 “标记”。

具体打标签的方法是:为0~9每个数字建立一个目录,目录名称为相应数字(相当于标签)人为判定 图片内容,并将图片拖到指定数字目录中每个目录中存放100张左右的素材一般情况下,标记的素材越多,那么训练出的模型的分辨能力和预测能力越强。

例如本文中,标记素材为十多张的时候,对新的测试图片识别率基本为零,但是到达100张时,则可以达到近乎100%的识别率14   特征选择对于切割后的单个字符图片,像素级放大图如下:从宏观上看,不同的数字图片的本质就是将黑色按照一定规则填充在相应的像素点上,所以这些特征都是最后围绕像素点进行。

字符图片 宽6个像素,高10个像素 ,理论上可以最简单粗暴地可以定义出60个特征:60个像素点上面的像素值。但是显然这样高维度必然会造成过大的计算量,可以适当的降维。

通过查阅相应的文献 [2],给出另外一种简单粗暴的特征定义:每行上黑色像素的个数,可以得到10个特征每列上黑色像素的个数,可以得到6个特征最后得到16维的一组特征,实现代码如下:defget_feature(img):  """  获取指定图片的特征值,  1.按照每排的像素点,高度为10,则有10个维度,然后为6列,总共16个维度  :paramimg_path:  :return:一个维度为10(高度)的列表  """  width,height=  pixel_cnt_list=[]  height=10  foryinrange(height):    pix_cnt_x=0    forxinrange(width):      ifimg.getpixel((x,y))==0: #黑色点        pix_cnt_x+=1    pixel_cnt_list.append(pix_cnt_x)  forxinrange(width):    pix_cnt_y=0    foryinrange(height):      ifimg.getpixel((x,y))==0: #黑色点        pix_cnt_y+=1    pixel_cnt_list.append(pix_cnt_y)  returnpixel_cnt_list然后就将图片素材特征化,按照 libSVM 指定的格式生成一组带特征值和标记值的向量文。

python简单神经网络的实现 求问这儿是怎么实现syn0均值为0的,以及我在Python3中运行发现l1的shape也不对

np.random.random返回[0,1)区间的随机数,2*np.random.random -1返回[-1,1)的随机数,具体可以看网页链接看这个神经网络结构应该就输入输出两层,l1的shape为(l0,syn0),[4*3],[3*1]的矩阵相乘得到[4*1]的矩阵,y=np.array([[0,1,1,0]]).T,y也是[4*1]的矩阵。

学:如何用Python实现7种机器学习算法(附

1.线性回归算法在线性回归中,我们想要建立一个模型,来拟合一个因变量y与一个或多个独立自变量(预测变量)x之间的关系。

是一个目标变量,它是一个标量线性回归模型可以理解为一个非常简单的神经网络:...2.Logistic回归算法在Logistic回归中,我们试图对给定输入特征的线性组合进行建模,来得到其二元变量的输出结果。

例如,我们可以尝试使用竞选候选人花费的金钱和时间信息来预测选举的结果(胜或负)。

猜你喜欢

转载自blog.csdn.net/kfc67269/article/details/126308249