卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
零.说明:
本文的所有代码均可在 DML 找到,欢迎点星星。
注.CNN的这份代码非常慢,基本上没有实际使用的可能,所以我只是发出来,代表我还是实践过而已
一.引入:
CNN这个模型实在是有些年份了,最近随着深度学习的兴起又开始焕发青春了,把imagenet测试的准确度提高了非常多,一个是Alex的工作,然后最近好像Zeiler又有突破性的成果,可惜这些我都没看过,主要是imagenet的数据太大了,我根本没有可能跑得动,所以学习的积极性有些打折扣。不说那么多,还是先实现一个最基础的CNN再说吧:
二.实现:
好吧,基本是根据DeepLearnToolbox的结构按照 Notes on Convolutional Neural Networks 来写的,大家可以先看这里的代码讲解:【面向代码】学习
Deep Learning(三)Convolution Neural Network(CNN)
本来是想根据Notes那篇文章来写的,只是最后发现如果给subsampling层加上sigmoid之后整个结构就不收敛了~~~,我用numeric_grad_check检测发现梯度计算也是对的,不明所以~~~这份代码我也上传了(old),不过下面的代码最后就只能改成稍简化版的,貌似通常情况下CNN的pooling(subsampling)层也是没有sigmoid的,先这样吧,这个东西理解起来简单还是写了我两个下午……伤……
代码: DML/CNN/cnn.py
- from __future__ import division
- import numpy as np
- import scipy as sp
- from scipy.signal import convolve as conv
- from dml.tool import sigmoid,expand,showimage
- from numpy import rot90
- '''
- this algorithm have refered to the DeepLearnToolBox(https://github.com/rasmusbergpalm/DeepLearnToolbox)
- also:[1]:"Notes on Convolutional Neural Networks" Jake Bouvrie 2006 - How to implement CNNs
- I want to implement as [1] described,where the subsampling layer have sigmoid function
- but finally it does not converge,but I can pass the gradcheck!!
- (this version is dml/CNN/cnn.py.old ,if you can figure out what is wrong in the code,PLEASE LET ME KNOW)
- at last I changed code back to simple version,delete the sigmoid in 's' layer
- ps:this code in python is too slow!don't use it do anything except reading.
- '''
- class LayerC:
- def __init__(self,types='i',out=0,scale=0,kernelsize=0):
- self.types=types
- self.a=None
- self.b=None
- self.d=None
- if (types=='i'):
- pass
- elif (types=='c'):
- self.out=out
- self.kernelsize=kernelsize
- self.k=None
- elif (types=='s'):
- self.scale=scale
- self.Beta={}
- self.dBeta={}
- class CNNC:
- def __init__(self,X,y,layers,opts):
- self.X=np.array(X)
- self.y=np.array(y)
- self.layers=layers
- self.opts=opts
- inputmap = 1
- mapsize = np.array(self.X[0].shape)
- for i in range(len(self.layers)):
- if self.layers[i].types=='s':
- mapsize = mapsize / self.layers[i].scale
- assert np.sum(np.floor(mapsize)== mapsize)==mapsize.size
- self.layers[i].b={}
- self.layers[i].db={}
- for j in range(inputmap):
- self.layers[i].b.setdefault(j,0)
- self.layers[i].db.setdefault(j,0)
- self.layers[i].Beta.setdefault(j,1)
- self.layers[i].dBeta.setdefault(j,0.0)
- pass
- if self.layers[i].types=='c':
- mapsize = mapsize - self.layers[i].kernelsize + 1
- fan_out = self.layers[i].out*self.layers[i].kernelsize**2
- self.layers[i].k={}
- self.layers[i].dk={}
- self.layers[i].b={}
- self.layers[i].db={}
- for j in range(self.layers[i].out):
- fan_in = inputmap*self.layers[i].kernelsize**2
- for t in range(inputmap):
- self.layers[i].k.setdefault(t,{})
- self.layers[i].k[t].setdefault(j)
- self.layers[i].k[t][j]=(np.random.rand(self.layers[i].kernelsize,self.layers[i].kernelsize)-
- 0.5)*2*np.sqrt(6/(fan_out+fan_in))
- self.layers[i].dk.setdefault(t,{})
- self.layers[i].dk[t].setdefault(j)
- self.layers[i].dk[t][j]=np.zeros(self.layers[i].k[t][j].shape)
- self.layers[i].b.setdefault(j,0)
- self.layers[i].db.setdefault(j,0)
- inputmap=self.layers[i].out
- if self.layers[i].types=='i':
- pass
- fvnum = np.prod(mapsize)*inputmap;
- onum = self.y.shape[0];
- self.ffb=np.zeros((onum,1))
- self.ffW=(np.random.rand(onum, fvnum)-0.5)*2*np.sqrt(6/(onum+fvnum))
- def cnnff(self,x):
- #print x
- self.layers[0].a={}
- self.layers[0].a.setdefault(0)
- self.layers[0].a[0]=x.copy()
- inputmap=1
- n=len(self.layers)
- for l in range(1,n):
- if self.layers[l].types=='s':
- for j in range(inputmap):
- temp=np.ones((self.layers[l].scale,self.layers[l].scale))/(self.layers[l].scale**2)
- z=conv(self.layers[l-1].a[j],np.array([temp]), 'valid')
- z=np.array(z)[:,::self.layers[l].scale,::self.layers[l].scale]
- if self.layers[l].a==None:
- self.layers[l].a={}
- self.layers[l].a.setdefault(j)
- self.layers[l].a[j] =z
- if self.layers[l].types=='c':
- if self.layers[l].a==None:
- self.layers[l].a={}
- for j in range(self.layers[l].out): #for each outmaps
- z = np.zeros(self.layers[l-1].a[0].shape - np.array([0,self.layers[l].kernelsize-1,self.layers[l].kernelsize-1]))
- for i in range(inputmap): #cumulate from inputmaps
- z+=conv(self.layers[l-1].a[i],np.array([self.layers[l].k[i][j]]),'valid')
- self.layers[l].a.setdefault(j)
- self.layers[l].a[j]=sigmoid(z+self.layers[l].b[j])
- inputmap = self.layers[l].out
- self.fv=None
- for j in range(len(self.layers[n-1].a)):
- sa=self.layers[n-1].a[j].shape
- p=self.layers[n-1].a[j].reshape(sa[0],sa[1]*sa[2]).copy()
- if (self.fv==None):
- self.fv=p
- else:
- self.fv=np.concatenate((self.fv,p),axis=1)
- self.fv=self.fv.transpose()
- self.o=sigmoid(np.dot(self.ffW,self.fv) + self.ffb)
- def cnnbp(self,y):
- n=len(self.layers)
- self.e=self.o-y
- self.L=0.5*np.sum(self.e**2)/self.e.shape[1]
- self.od=self.e*(self.o*(1-self.o))
- self.fvd=np.dot(self.ffW.transpose(),self.od)
- if self.layers[n-1].types=='c':
- self.fvd=self.fvd*(self.fv*(1-self.fv))
- sa=self.layers[n-1].a[0].shape
- fvnum=sa[1]*sa[2]
- for j in range(len(self.layers[n-1].a)):
- if self.layers[n-1].d==None:
- self.layers[n-1].d={}
- self.layers[n-1].d.setdefault(j)
- self.layers[n-1].d[j]=self.fvd[(j*fvnum):((j+1)*fvnum),:].transpose().reshape(sa[0],sa[1],sa[2])
- for l in range(n-2,-1,-1):
- if self.layers[l].types=='c':
- for j in range(len(self.layers[l].a)):
- if self.layers[l].d==None:
- self.layers[l].d={}
- self.layers[l].d.setdefault(j)
- self.layers[l].d[j]=self.layers[l].a[j]*(1-self.layers[l].a[j])*
- np.kron(self.layers[l+1].d[j],np.ones(( self.layers[l+1].scale,self.layers[l+1].scale))/(self.layers[l+1].scale**2))
- elif self.layers[l].types=='s':
- for j in range(len(self.layers[l].a)):
- if self.layers[l].d==None:
- self.layers[l].d={}
- self.layers[l].d.setdefault(j)
- z=np.zeros(self.layers[l].a[0].shape)
- for i in range(len(self.layers[l+1].a)):
- rotated=np.array([rot90(self.layers[l+1].k[j][i],2)])
- z=z+conv(self.layers[l+1].d[i],rotated,'full')
- self.layers[l].d[j]=z
- for l in range(1,n):
- m=self.layers[l].d[0].shape[0]
- if self.layers[l].types=='c':
- for j in range(len(self.layers[l].a)):
- for i in range(len(self.layers[l-1].a)):
- #self.layers[l].dk[i][j]=rot90(conv(self.layers[l-1].a[i],rot90(self.layers[l].d[j],2),'valid'),2)
- self.layers[l].dk[i][j]=self.layers[l].dk[i][j]*0
- for t in range(self.layers[l].d[0].shape[0]):
- self.layers[l].dk[i][j]+=rot90(conv(self.layers[l-1].a[i][t],rot90(self.layers[l].d[j][t],2),'valid'),2)
- self.layers[l].dk[i][j]=self.layers[l].dk[i][j]/m
- self.layers[l].db[j]=np.sum(self.layers[l].d[j])/m
- self.dffW=np.dot(self.od,self.fv.transpose())/self.od.shape[1]
- self.dffb = np.mean(self.od,1).reshape(self.ffb.shape);
- def cnnapplygrads(self,alpha=0.1):
- n=len(self.layers)
- for l in range(1,n):
- if self.layers[l].types=='c':
- for j in range(len(self.layers[l].a)):
- for i in range(len(self.layers[l-1].a)):
- self.layers[l].k[i][j]-=alpha*self.layers[l].dk[i][j]
- self.layers[l].b[j]-=alpha*self.layers[l].db[j]
- pass
- self.ffW-=alpha*self.dffW
- self.ffb-=alpha*self.dffb
- def train(self):
- m=self.X.shape[0]
- batchsize=self.opts['batchsize']
- numbatches = m/batchsize
- print numbatches
- self.rL = []
- for i in range(self.opts['numepochs']):
- print 'the %d -th epoch is running'% (i+1)
- kk=np.random.permutation(m)
- for j in range(numbatches):
- print 'the %d -th batch is running , totally %d batchs'% ((j+1),numbatches)
- batch_x=self.X[kk[(j)*batchsize:(j+1)*batchsize],:,:].copy()
- batch_y=self.y[:,kk[(j)*batchsize:(j+1)*batchsize]].copy()
- self.cnnff(batch_x)
- self.cnnbp(batch_y)
- self.cnnapplygrads(alpha=self.opts['alpha'])
- if len(self.rL)==0:
- self.rL.append(self.L)
- else:
- p=self.rL[len(self.rL)-1]
- self.rL.append(p*0.99+0.1*self.L)
- print self.L
- def gradcheck(self,test_x,test_y):
- #github上有这部分代码
- def test(self,test_x,test_y):
- self.cnnff(np.array(test_x))
- p=self.o.argmax(axis=0)
- bad= np.sum(p!=np.array(test_y).argmax(axis=0))
- print p,np.array(test_y).argmax(axis=0)
- print bad
- print np.array(test_y).shape[1]
- er=bad/np.array(test_y).shape[1]
- print er
- def pred(self,test_x):
- self.cnnff(np.array(test_x))
- p=self.o.argmax(axis=0)
- return p
三.测试
因为python跑这个实在是太慢了,主要原因我觉得是convolution函数(我用的scipy.signal.convolve)比matlab里慢太多了,所以跑MNIST以50为一个patch跑SGD一轮要二三十分钟,所以建议不要使用这份代码,你可以去用DeepLearnToolbox比这都快……
使用代码来测试:test/CNN_test/test_cnn.py
- layers=[LayerC('i'),
- LayerC('c',out=6,kernelsize=5),
- LayerC('s',scale=2),
- LayerC('c',out=12,kernelsize=5),
- LayerC('s',scale=2)]
- opts={}
- opts['batchsize']=40
- opts['numepochs']=1
- opts['alpha']=1
- a=CNNC(X,groundTruth,layers,opts)
- #a.gradcheck(test_x[1:3,:,:],test_groundTruth[:,1:3])
- a.train()
- a.test(test_x,test_groundTruth)
这是一轮的结果,89.99%的准确度,应该还是正常的:
卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现的更多相关文章
- 卷积神经网络(Convolutional Neural Networks)CNN
申明:本文非笔者原创,原文转载自:http://www.36dsj.com/archives/24006 自今年七月份以来,一直在实验室负责卷积神经网络(Convolutional Neural ...
- 小白也能弄懂的卷积神经网络(Convolutional Neural Networks )
本系列主要是讲解卷积神经网络 - Convolutional Neural Networks 的系列知识,本系列主要帮助大家入门,我相信这是所有入门深度学习的初学者都必须学习的知识,这里会用更加直接和 ...
- 卷积神经网络LeNet Convolutional Neural Networks (LeNet)
Note This section assumes the reader has already read through Classifying MNIST digits using Logisti ...
- 卷积神经网络(Convolutional Neural Network,CNN)
全连接神经网络(Fully connected neural network)处理图像最大的问题在于全连接层的参数太多.参数增多除了导致计算速度减慢,还很容易导致过拟合问题.所以需要一个更合理的神经网 ...
- 【转载】 卷积神经网络(Convolutional Neural Network,CNN)
作者:wuliytTaotao 出处:https://www.cnblogs.com/wuliytTaotao/ 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,欢迎 ...
- “卷积神经网络(Convolutional Neural Network,CNN)”之问
目录 Q1:CNN 中的全连接层为什么可以看作是使用卷积核遍历整个输入区域的卷积操作? Q2:1×1 的卷积核(filter)怎么理解? Q3:什么是感受野(Receptive field)? Q4: ...
- 卷积神经网络CNN学习笔记
CNN的基本结构包括两层: 特征提取层:每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征.一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来: 特征映射层:网络的每个计算层由多 ...
- paper 162:卷积神经网络(CNN)解析
卷积神经网络(CNN)解析: 卷积神经网络CNN解析 概揽 Layers used to build ConvNets 卷积层Convolutional layer 池化层Pooling Layer ...
- 卷积神经网络CNN的原理(一)---基本概念
什么是卷积神经网络呢?这个的确是比较难搞懂的概念,特别是一听到神经网络,大家脑海中第一个就会想到复杂的生物学,让人不寒而栗,那么复杂啊.卷积神经网络是做什么用的呢?它到底是一个什么东东呢? 卷积神经网 ...
随机推荐
- NOIP提高组2004 合并果子题解
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
- POJ 1329 Circle Through Three Points(三角形外心)
题目链接 抄的外心模版.然后,输出认真一点.1Y. #include <cstdio> #include <cstring> #include <string> # ...
- GUI之绘画控制
一.绘制的动力 GUI的绘画是根据消息动作驱动的 主循环应该是 二.绘制的过程 绘画过程应该是这样的: 首先窗口存在上下层关系-> 在绘制时应该从底部窗口开始绘制,逐一绘制 下面是一些特殊的窗口 ...
- Rational Rose 2007 破解版安装过程
Rational Rose 2007 破解版安装过程 首先通过网站将软件下载,然后依照以下步骤进行: 选择第二项,下一步 一直点击next,出现如下,可以修改安装的目的文件夹 设置完路径之后出现如下, ...
- spring mvc 拦截器 拦截子目录
项目中碰到这一个问题: 对于/user/loginpage,/user/login这一类的url,放行: 对于/user/{userId}/xxx(xxx不为空)的操作,需要拦截,url-patter ...
- java设计模式。。。转载
maowang I am a slow walker,but I never walk backwards! 博客园 首页 新随笔 联系 订阅 管理 随笔 - 125 文章 - 0 评论 - 12 ...
- 对JS原型的一些理解
一.首先给出一道经典的原型题目: var F = function(){}; Object.prototype.a = function(){}; Function.prototype.b = fun ...
- Top Deep Learning Projects in github
Top Deep Learning Projects A list of popular github projects related to deep learning (ranked by sta ...
- webform连接ACCESS数据库
1.先建立一个名叫mydb.accdb的access数据库 2.他它复制到webform中,放在App_Data文件夹下. 3.在App_Code文件夹下建好封装语句,查询方法,连接语句,其中stud ...
- c# 集合及特殊集合
1.ArrayList集合 习题:输入人数,输入分数,存到集合里面,之后再读取出来,求平均分,排序打印. 2.Stack 集合 3.Queue 队列集合 每日一语:脚跟立定以后,你必须拿你的力量 ...