当前位置: 首页 > 科技观察

小白学习CNN和Keras速成

时间:2023-03-20 01:01:36 科技观察

一、为什么要用Keras在深度学习大行其道的今天,第三方工具层出不穷。比较出名的有Tensorflow、Caffe、Theano、MXNet,在这么多第三方框架中频繁更换无疑是非常低效的。只要能掌握其中一种框架,熟悉它的原理,以后因为各种需求,更换框架也很容易。那么sherlock使用的是哪个框架呢?sherlock使用的是谷歌的开源框架Tensorflow,因为谷歌开源tensorflow之后,它的社区很活跃,版本更新也很稳定,所以选择了这个框架。关于框架之争,在知乎上已经有很多人在吵架了。这就像哪种编程语言更好的问题。对于我们来说,选择一个稳定的框架,学习深度学习才是最重要的。至于哪个框架更好,我们学好之后自然会有自己的见解,所以前期一定不要看知乎听听。母版撕后经常换帧。对于Tensorflow的安装,以及CPU和GPU的版本,网上很多人都写了各种系统安装的详细指南。大家可以自行上网搜索一下,很容易安装成功。选择了Tensorflow之后,我们就可以愉快的开始我们的深度学习之旅了。去Tensorflow中文社区,可以看到一些新手教程,网上也有很多学习资料,推荐看看斯坦福大学的cs224d课件,http://cs224d.stanford.edu/lectures/CS224d-Lecture7.pdf,非常详细的介绍了tensorflow。然后就可以写tensorflow程序了。虽然tensorflow已经是一个封装好的框架,但是你发现写一个简单的神经网络需要很多行。这时候有很多第三方插件帮你写网络,也就是说你要用tensorflow写10行,第三方插件包帮你封装一个功能,就是把这10行汇集到这个函数中,那么就可以用1行,传入同样的参数,达到10行一样的效果,简单又省时,可以快速实现我们的想法。KerasDocumentation是Keras的官方文档,里面可以查看所有的功能,在github上可以看到他的开源代码,非常方便。安装也非常简单。打开终端,输入pipinstallkeras等待安装。这里有一个简单的例子,看看Keras有多简单。fromkeras.modelsimportSequentialmodel=Sequential()引入sequential,sequential是一个空的网络结构,而这个结构是sequential序列,所以叫Sequential,Keras中还有一些其他的网络结构。fromkeras.layersimportDense,Activationmodel.add(Dense(units=64,input_dim=100))model.add(Activation('relu'))model.add(Dense(units=10))model.add(Activation('softmax'))可以看到添加层很简单,只需要写.add,后面是要添加的层的类型即可。model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])写好网络后,可以使用compile编译整个网络,看看参数有没有问题settingsmodel.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.SGD(lr=0.01,momentum=0.9,nesterov=True))也可以自定义优化函数,和上面一样,'sgd'是Keras已经写了一些带有默认参数的优化函数,你可以自己重新定义参数来得到一个优化函数。model.fit(x_train,y_train,epochs=5,batch_size=32)这就像scikit-learn一样训练模型。loss_and_metrics=model.evaluate(x_test,y_test,batch_size=128)这个是用来评估训练结果的。classes=model.predict(x_test,batch_size=128)或通过预测进行预测。看完上面的代码,相信很多熟悉scikit-learn的同学都非常亲切,因为它真的很简单,语法也和scikit-learn很相似。2.开始学习CNN在了解CNN之前,我们需要了解什么是神经网络,这样才能开始了解更高级的卷积神经网络。当然,学习神经网络的方法有很多种。网上很多高手写了很多攻略。有的主张从理论到工程的深度学习,有的希望从工程出发去发现和解决问题。各种方法不同的人尝试,攻略也是大推,让很多菜鸟直接倒在了选材的路上,一直在修知识,热度过后就放弃了。学习,连卷积网络都不知道是什么东西,大大挫伤了大家学习的积极性。今天sherlock就来给大家推荐一份学习资料,保证大家可以快速上手cnn,出门也可以和别人聊天装逼。这是什么材料?就是著名的standfordcs231n课程。CS231nConvolutionalNeuralNetworksforVisualRecognition斯坦福大学在深度学习和人工智能领域确实是一所非常厉害的学校。神经网络的废话不多说了,下面开始学习我们的神经网络吧。这是一张大脑神经的图片,神经网络的发明就是从这里开始的。这就是所谓的神经元,它有各种接收突触,然后通过一个脑神经接收,最后得到输出结果。那么从这张大脑神经图谱中可以抽象出的神经网络是什么呢?就是下面的神经网络模型。怎么理解呢?就是输入一个向量,然后给向量的每个元素分配一个权重,然后将权重求和得到一个结果,再把这个结果输入到一个激活函数中,得到最后的输出结果。激活函数是什么鬼?激活函数是由于人脑的结构。人脑接收信息和得到结果的过程是非线性的。比如你看到一个东西,你不可能保留这个东西的所有特征。YouwillFocusonobservingtheplaceyouinterested.Thisisnonlinear,也就是说需要一个非线性的变化,才能将输入的结果转化为非线性的结果。现在常用的非线性函数是Relu(x)=max(x,0),就是去掉小于0的部分,只保留大于0的部分。这些是单元的输入和输出,这些单元一起就是一个神经网络。这是一个简单的单层网络,或者说输入层是单个训练集的所谓维度的多层网络,输入所有的训练集就可以训练出一个神经网络。Keras实现一个简单的神经网络了解了神经网络的基本结构和原理,我们就可以开始使用keras来实现一个简单的神经网络了。importkerasfromkeras.modelsimportSequentialfromkeras.layersimportDenseimportnumpyasnpimportnecessarypackagex=np.array([[0,1,0],[0,0,1],[1,3,2],[3,2,1]])y=np.array([0,0,1,1]).T设置输入x和ysimple_model=Sequential()simple_model.add(Dense(5,input_shape=(x.shape[1]]),activation='relu',name='layer1'))simple_model.add(Dense(4,activation='relu',name='layer2'))simple_model.add(Dense(1,activation='sigmoid',name='layer3'))输入一个三层神经网络,中间隐藏层的元素个数为5和4,最后一层输出一个结果simple_model.compile(optimizer='sgd',loss='mean_squared_error')complie这个很简单模型simple_model.fit(x,y,epochs=20000)训练模型20000次。simple_model.predict(x[0:1])可以预测第一个输入x的结果与实际是否一致。以上是一个简单的三层网络的keras实现。接下来正式进入卷积神经网络3,卷积神经网络给大家推荐一门不错的课程cs231n。这篇文章也是基于这个想法。基本结构先解释一下什么是卷积。当然,这个卷积不是数学上的卷积。这里的卷积其实代表了一个三维权重。这个解释可能不太容易理解。我们先来看看卷积网络。基本结构。通过上图,我们清楚的了解到卷积网络与一般网络结构的区别。也可以理解为卷积网络是三维的,而一般的网络结构是平面的。了解了卷积层的基本结构之后,我们就需要了解cnn最重要也是最具创新性的部分,卷积层。首先用一张图来对比一下卷积网络创新的地方。通过这个结构,我们可以清楚的看到卷积网络是如何实现的。首先右边是传统的网络结构,之前我们已经详细讲解过了。至于左边的图,我们先看图中最左边的结构。你一定很好奇为什么它是一个32x32x3的立方体。这个32×32代表的是像素点,说白了就是图片的大小。你可以设置这个大小,你可以设置成50×50,或者256×256,这都是看图片的大小,那么3代表什么?3其实代表了RGB的三个通道,什么是RGB?RGB代表红、绿、蓝,这三种颜色的各种组合可以形成多种颜色,所以任何照片都可以用左图来表示。那么中间的小方块是什么意思呢?这是我们要关注的卷积。所谓卷积就是这种小方块。我们设置了一个小方块的大小,但是这个小方块的厚度必须和左边那个大方块的厚度一样。大方块的每个像素由一个0到255的数字表示,这样我们就可以给小方块赋予权重,比如我们把小方块的大小取为3×3,我们要求粗细就是和左边大方块的粗细一样,那么小方块的大小就是3x3x3,我们可以给它3x3x3的权重,然后我们就可以开始计算卷积的结果了,从左上角的小方块开始大方块的角,一个卷积小方块覆盖的面积是3x3x3,然后我们将大方块中的3x3x3个数和小方块中的权重相乘相加,加上一个偏置,得到一个卷积结果,可以抽象的写成Wx+b的形式,就是图中所示的结果,然后我们可以设置小方块的滑动距离,每次可以形成一个卷积计算结果,然后滑动覆盖整个大图形成一层的卷积结果。我们可以看到图中的卷积结果很粗,也就是设置了很多层卷积。总结一下,每一层卷积就是一个卷积核在图片上滑动求值,然后设置多个卷积核就可以组成一个多层卷积层。池化层说完卷积层,接下来就要说说池化层了。为什么会有池化层?是因为连续卷积得到的中间结果会越来越粗。卷积相当于提取图片中的特征,所以卷积层一般会设置得越来越厚,否则无法从前面的结果中提取出更多的特征。这样会导致中间结果越来越大,计算会越来越慢,所以提出了池化层。所谓池化层就是一种缩小图像尺寸的处理方法。我们可以先看下图。通过这张图,我们可以清楚的看到池化层是如何处理的。池化层也需要先设置一个窗口,但是这个小窗口的厚度是1,不是上一层输出结果的厚度。那么有两种处理方式,一种是取这个小窗口所有元素的最大值来表示这个小窗口,一种是取平均值,然后滑动小窗口,在第二个位置做同样的处理,完成上层网络输出块的每一层后,进入大块的下一层做同样的操作。这种处理方法可以使整个大块的尺寸变小。你可以看到上图的左侧。右边是一个简单层厚度的例子,取最大值。实现Lenet在了解完卷积网络的基本结构后,是不是迫不及待想要实现一个简单的神经网络呢?卷积网络发展非常迅速。最早由LeCun提出,Lenet成为cnn的鼻祖。接下来他的学生Alex提出了更深层次的Alexnet,然后在2013年提出了VGGnet,有16层和19层。这些只是加深层次,并没有其他的创新。Google提出了inceptionnet来实现网络结构的创新,并提出了inception机制。FacebookAILab也提出了resnet,residualnetwork,实现了150层的可训练网络结构。我们稍后会放慢这些速度。接下来我们来实现最简单的Lenet,使用mnist手写子体作为训练集。importkerasfromkeras.datasetsimportmnist(x_train,y_train),(x_test,y_test)=mnist.load_data()导入必要的库和数据集x_train=x_train.reshape(-1,28,28,1)x_test=x_test.reshape(-1,28,28,1)x_train=x_train/255。x_test=x_test/255。y_train=keras.utils.to_categorical(y_train)y_test=keras.utils.to_categorical(y_test)处理数据,使得数据的shape为(28,28,1),然后label做一个one-hotencoding过程.例如,如果类别为3,则它变为[0,0,1,0,0,0,0,0,0,0]。fromkeras.layersimportConv2D,MaxPool2D,Dense,Flattenfromkeras.modelsimportSequentiallenet=Sequential()lenet.add(Conv2D(6,kernel_size=3,strides=1,padding='same',input_shape=(28,28,1)))lenet.add(MaxPool2D(pool_size=2,strides=2))lenet.add(Conv2D(16,kernel_size=5,strides=1,padding='valid'))lenet.add(MaxPool2D(pool_size=2,strides=2))lenet.add(Flatten())lenet.add(Dense(120))lenet.add(Dense(84))lenet.add(Dense(10,activation='softmax'))buildlenetlenet.compile('sgd',loss='categorical_crossentropy',metrics=['accuracy'])编译lenet.fit(x_train,y_train,batch_size=64,epochs=50,validation_data=[x_test,y_test])训练50次,结果如下按照lenet.save('myletnet.h5')可以保存训练好的模型summaryOK,这是我们写的一个超级简单的Lenet,训练50次得到的训练准确率达到了0.9939,测试准确率达到了0.9852。