Keras入门之二:Hello Keras on CNN with Lena

这是第二个Keras的例子。是介绍了如何使用Keras构建一个卷积神经网络。
通过这个例子,我之前在图像处理上固有的观念导致对卷积网络的工作原理有了稍微的误差,从而修正过来了。

这种错误主要是对卷积之后网络变厚的理解,之前我总以为一个卷积核将3通道的图像卷积后仍然是3个通道。这是以前做图像处理的时候固有的想法,而不是神经网络工作的模式。神经网络的卷积实际上更多的是要从网络连接上来考虑这种卷积实现。
时间关系先上代码,以后再修改
#=================== Test 2    Hello Keras on CNN ==============================================================================
# 这是一个简单的卷积神经网络的例子。

from PIL import Image
from keras.models import Sequential  # 采用贯序模型
from keras.layers import Input, Dense, Dropout, Activation
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.models import Model
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy as np
import matplotlib.pyplot as plt  # 显示图片

tBatchSize = 128

def Kernels2Weight(Kernels, chl):
    weight_Num = Kernels.shape[0]
    weight_row = Kernels.shape[1]
    weight_col = Kernels.shape[2]

    ConvKernels = []
    for r in range(0,weight_row):
        CK_CHL= [] # 通道
        CKRow = []
        for c in  range(0,weight_col):
            CK_Item = []
            CK_Item2= []
            for n in range(0, weight_Num):
                CK_Item2.append(Kernels[n][r][c])
            for ch in range(0, chl):
                CK_Item.append(CK_Item2)  # 每个通道都是一样的
            CKRow.append(CK_Item)
        ConvKernels.append(CKRow)
    ConvKernels2 = []
    ConvKernels2.append(ConvKernels)
    return ConvKernels2

'''第1步:准备数据'''
##打开图片
img = Image.open("Z:/Lenna.jpg",)
imgChl = 3
# img= img.convert("L")  # 转为灰度图像
# imgChl = 1

(img_width, img_height) = img.size
print("image Size = ",img_width, img_height)

##把图片转换成数组形式
arr = np.asarray(img,dtype="float32") #RGB:(w, h, 3)   Gray:(w,h)
if imgChl == 3:
    arr = np.rollaxis(arr, 2, 0)  #输入数据的维度轴转换次序
data = np.empty((1,imgChl, img_width,img_height),dtype="float32") # 'channels_last' for TF
data[0,:,:,:] = arr

'''第2步:构建模型'''
model = Sequential() # 采用贯序模型

'''构建权重(卷积核)'''
#增加一个横向的sobel卷积核 一个纵向的sobel卷积核
Kernels = []
sobel_h = [[-1,0,1], [-2, 0, 2], [-1, 0, 1]]
sobel_v = [[-1,-2,-1], [0, 0, 0], [1, 2, 1]]
Kernels.append(sobel_h)
Kernels.append(sobel_v)
Kernels = np.asarray(Kernels)


weights = Kernels2Weight(Kernels, chl=imgChl)
# 显示权重结构
# print('Kernels2Weight:\r\n',weights)

'''##第一次卷积'''
# ZeroPadding2D 的作用:对2D输入(如图片)的边界填充0,以控制卷积以后特征图的大小
# “channels_last”对应原本的“tf”,“channels_first”对应原本的“th”
#        ‘channels_first’模式下,形如(samples,channels,first_axis_to_pad,second_axis_to_pad)的4D张量
#        ‘channels_last’模式下,形如(samples,first_axis_to_pad,second_axis_to_pad, channels)的4D张量
strFormat = 'channels_first'  # 这里应该是因为data的初始化维度用的th
model.add(ZeroPadding2D(padding=(0,0), data_format = strFormat, batch_input_shape=(1,imgChl, img_width, img_height)))
#  filters:卷积核的数目(即输出的维度)  ### 是该卷积层输出的厚度,而不是输入图像的通道数*卷积核数。 一定要与图像处理区分开
#  kernel_size:整数或由单个整数构成的list/tuple,卷积核的空域或时域窗长度
#  strides:整数或由单个整数构成的list/tuple,为卷积的步长。任何不为1的strides均与任何不为1的dilation_rate均不兼容
#  padding:补0策略,为“valid”(缩小), “same” 或“causal”(膨胀) 缩小或膨胀卷积核的一半
#  activation:激活函数 卷积激活常用的是'relu' 参考 http://keras-cn.readthedocs.io/en/latest/other/activations/
model.add(Convolution2D(filters=2,kernel_size=(3,3),strides=(1,1), padding='same', activation='relu', name='conv1_1', data_format = strFormat))
model.set_weights(weights)  # 这相当于设置了卷积核

# 显示权重结构
# w = model.layers[1].get_weights() #返回该层的权重
# print('weight:\r\n', w)

'''##第二次卷积(这是继续卷积的实现。为了看提取边缘的效果,所以先注释了)'''
# model.add(ZeroPadding2D((0, 0)))
# model.add(Convolution2D(filters=2,kernel_size=(3,3),strides=(1,1), activation='relu', name='conv1_2',data_format = strFormat))
# w = model.layers[3].get_weights() #返回该层的权重
# print('weight:\r\n', w)
# model.set_weights(weights)

##池化操作
model.add(ZeroPadding2D((0, 0)))
model.add(MaxPooling2D(pool_size=(2,2), strides=None, data_format = strFormat))


'''第3步:设置优化参数,编译网络(本例中并没有训练)'''
# 优化函数,设定学习率(lr)等参数
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
# 使用mse作为loss函数
model.compile(loss='mse', optimizer=sgd) #class_mode='categorical'


'''第4步:执行结果'''
'''这里只进行了卷积/池化,并没有分类等'''

print('data-shape = ', data.shape)
result = model.predict(data,batch_size=3,verbose=0)
print('result shape = ', result.shape)

'''显示图片,卷积的结果'''
fig = plt.figure()
img_new1 = Image.fromarray(result[0][0]).convert('L')
print(img_new1.size)
ax0 = fig.add_subplot(121)
ax0.imshow(img_new1)

img_new2 = Image.fromarray(result[0][1]).convert('L')
print(img_new2.size)
ax0 = fig.add_subplot(122)
ax0.imshow(img_new2)
plt.show()


原图是迷人的Lena,就不用贴了。512x512的尺寸。
两个sobel卷积核,结果是纵向边缘和横向边缘。经过池化之后,为256大小的图像。
这里是进行了固定权重(卷积核)进行的图像处理,下一步就可以将卷积网络连上数据去训练了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值