首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

CNN 入门讲解:图片在卷积神经网络中是怎么变化的

微信公众号:follow_bobo

首发于知乎:蒋竺波

这一期我们主要一边写代码

一边看图片经过卷积层发生了什么变化

经过采样层发生了什么变化

经过激活层发生了什么变化

相当于实践了前向传播

走着

----------我又来当分割线了---------------------

看到代码不要慌,很容易看懂的。

第一步:把需要的functions 全部先导进去,我们这里主要是使用keras

import cv2

from keras import backend as K

from keras.layers import Conv2D, MaxPooling2D, BatchNormalization,Activation, Dropout, Dense,UpSampling2D,Input,add

from keras.models import Model, Sequential, load_model

import numpy as np

------------------------------------------------------------------------------------------

我们今天的网络结构如下,没有经过训练的:

model = Sequential()

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_1'))#加入一个卷积层,filter数量为3,卷积核size为(3,3)

model.add(MaxPooling2D(pool_size=(3,3)))#加入一个pooling 层,size为(3,3)

model.add(Activation('relu'))# 加入激活函数'ReLu', 只保留大于0 的值

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Activation('relu'))

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_3'))

model.add(Activation('relu'))

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_4'))

model.add(Activation('relu'))

model.add(Flatten())#把上层输出平铺

model.add(Dense(8, activation='relu',name='dens_1'))#加入全连接层,分为8类

-----------------------------------------------------------------------------------------------

因为conv2d这个function 对于权值是随机初始化的

每运行一次程序权值就变了,权值变了就没有比较意义了,而我们不用pretrained model,所以我们要保存第一次初始化的权值

-----------------------------------------------------------------------------------------------

model.save_weights('girl.h5')

第二步:我们先来看看我们的输入数据:

girl = cv2.imread(‘girl.jpg’)

girl.jpg shape= (575,607)

第三步:搭建一个卷积层

girl = cv2.imread('girl.jpg')

model = Sequential()

model.add(Conv2D(3,3,3,input_shape= girl.shape ,name='conv_1')) # filter =3, kernel_size =(3,3)

model.load_weights('girl.h5', by_name=True) # ‘by_name’表示只给和保存模型相同卷积层名字的卷积层导入权值,这里就是把上一步‘conv_1’的权值导入这一步‘conv_1’,当然结构得相同

第四步:数据增维

由于keras 只能按批处理数据,因此需要把单个数据提高一个维度

girl_batch = np.expand_dims(girl,axis=0)

#数据维度由(575,607,3)变为(1,575,607,3)

第五步:查看卷积层输出---特征图

conv_girl = model.predict(girl_batch)

girl_img = np.squeeze(conv_girl,axis=0)

#把图像的像素值大小rescale 到0-255之间

max_img = np.max(img)

min_img = np.min(img)

img = img-(min_img)

img=img/(max_img - min_img)

img = img*255

cv2.imwrite('conv1_output.jpg',girl_img)

conv_1,filter=3,kernel =3x3 ,shape = (573,605)

可以看到图像的一些纹理,边缘,或者颜色信息被一定程度上提取出来了,shape也发生了变化

第七步:加入pooling 层

model = Sequential()

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_1'))

model.add(MaxPooling2D(pool_size=(2,2)))

conv_1, filter=3,kernel =3x3,pool=(3,3) shape=(191,201)

从上图可以明显的看到特征更加明显,并且shape减为三分之一了

第八步 加入激活函数'ReLu'

model = Sequential()

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_1'))

model.add(MaxPooling2D(pool_size=(3,3)))

model.add(Activation('relu'))# 只保留大于0 的值

ReLu

conv_1, filter=3, kernel =3x3, pool=(2,2), activation ='ReLu', shape=(191,201)

可以看到只有一些边缘的特征被保留下来了

第九步 在原来的基础上加入新的卷积层

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

conv_2, filter=3,kernel =3x3,shape=(189,199)

纹理的信息更明显了

第九步 在原来的基础上加入新的采样层

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

model.add(MaxPooling2D(pool_size=(2,2)))

conv_2, filter=3,kernel =3x3,pool=(2,2),shape=(94,99)

第十步:在原来的基础上加入新的激活函数'ReLu’

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Activation('relu')

conv_2, filter=3, kernel =3x3, pool=(2,2), activation =‘relu', shape=(94,99)

番外步:把原来激活函数'relu', 全部改为‘sigmoid’

model = Sequential()

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_1'))

model.add(MaxPooling2D(pool_size=(3,3)))

model.add(Activation('sigmoid'))

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Activation('sigmoid'))

Sigmoid

conv_2, filter=3, kernel =3x3, pool=(2,2), activation =‘sigmoid', shape=(94,99)

番外步:把原来激活函数'Relu',全部改为'tanh’

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_2'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Activation('tanh'))

tanh

conv_2, filter=3, kernel =3x3, pool=(2,2), activation = 'tanh', shape=(94,99)

第十一步 增加两个卷积层和激活函数‘relu’

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_3'))

model.add(Activation('relu'))

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_4'))

model.add(Activation('relu'))

conv_4, filter=3, kernel =3x3, activation = 'relu', shape=(90,95)

第十一步 全连接层输出

model.add(Conv2D(3,3,3,input_shape= girl.shape,name='conv_4'))

model.add(Activation('relu'))

model.add(Flatten())

model.add(Dense(8, activation='relu',name='dens_1'))#分为8类

dens_1, classes = 8 ,shape = (1,8)

番外篇:不同kernel size 之间的对比

这里只用一个卷积层做测试,为了方便比较,所有的weights 值都设为0.12

model = Sequential()

model.add(Conv2D(filter1,ke_width,ke_height,kernel_initializer = keras.initializers.Constant(value=0.12),input_shape= girl.shape,name='conv_1'))

conv_1, filter=3, kernel =3x3, shape=(573,605)

conv_1, filter=3, kernel =12x12, shape=(564,596)

conv_1, filter=3, kernel =24x24, shape=(552,584)

摆代码什么的最轻松了,嘿嘿嘿

喜欢的朋友点个赞再走啊

你的赞是我写下去的动力!!!

Come on!!!!!

全部代码如下:https://github.com/jiangzhubo/cnn_forward_propagation-

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180305G0L0MU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券