本文内容参考以下文章并做知识汇总:
http://www.cnblogs.com/lc1217/p/7132364.html
https://keras-cn.readthedocs.io/en/latest/
1)简介
Keras是由纯python编写的基于theano/tensorflow的深度学习框架。
Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras:
a)简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
b)支持CNN和RNN,或二者的结合
c)无缝CPU和GPU切换
2)设计原则
a)用户友好:Keras是为人类而不是天顶星人设计的API。用户的使用体验始终是我们考虑的首要和中心内容。Keras遵循减少认知困难的最佳实践:Keras提供一致而简洁的API, 能够极大减少一般应用下用户的工作量,同时,Keras提供清晰和具有实践意义的bug反馈。
b)模块性:模型可理解为一个层的序列或数据的运算图,完全可配置的模块可以用最少的代价自由组合在一起。具体而言,网络层、损失函数、优化器、初始化策略、激活函数、正则化方法都是独立的模块,你可以使用它们来构建自己的模型。
c)易扩展性:添加新模块超级容易,只需要仿照现有的模块编写新的类或函数即可。创建新模块的便利性使得Keras更适合于先进的研究工作。
d)与Python协作:Keras没有单独的模型配置文件类型(作为对比,caffe有),模型由python代码描述,使其更紧凑和更易debug,并提供了扩展的便利性。
以简单的Sequential模型举例:
(1)先创建模型实例:
from keras.models import Sequential
model = Sequential()
(2)将一些网络层通过.add()堆叠起来,就构成了一个模型:
from keras.layers import Dense, Activation
model.add(Dense(units=64, input_dim=100))
model.add(Activation("relu"))
model.add(Dense(units=10))
model.add(Activation("softmax"))
(3)完成模型的搭建后,我们需要使用.compile()方法来编译模型(编译模型时必须指明损失函数和优化器):
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
用户可以根据自己的需要定制自己的模型、网络层,甚至修改源代码:
from keras.optimizers import SGD
model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True))
(4)完成模型编译后,我们在训练数据上按batch进行一定次数的迭代来训练网络
model.fit(x_train, y_train, epochs=5, batch_size=32)
(5)对模型进行评估,看看模型的指标是否满足要求:
loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128)
(6)使用训练好的模型,对测试集数据进行预测:
classes = model.predict(x_test, batch_size=128)
1)符号计算
Keras的底层库使用Theano或TensorFlow,这两个库也称为Keras的后端(backend)。无论是Theano还是TensorFlow,都是一个“符号式”的库。符号计算首先定义各种变量,然后建立一个“计算图”,计算图规定了各个变量之间的计算关系。
符号计算也叫数据流图,其过程如下(数据是按图中黑色带箭头的线流动的):
2)张量
张量(tensor),可以看作是向量、矩阵的自然推广,用来表示广泛的数据类型。张量的阶数也叫维度。
0阶张量,即标量,是一个数。
1阶张量,即向量,一组有序排列的数
2阶张量,即矩阵,一组向量有序的排列起来
3阶张量,即立方体,一组矩阵上下排列起来
4阶张量…
依次类推, 重点:关于维度的理解
假如有一个10长度的列表,那么我们横向看有10个数字,也可以叫做10维度,纵向看只能看到1个数字,那么就叫1维度。注意这个区别有助于理解Keras或者神经网络中计算时出现的维度问题。
3)数据格式(data_format)
目前主要有两种方式来表示张量:
a) th模式或channels_first模式,Theano和caffe使用此模式。
b)tf模式或channels_last模式,TensorFlow使用此模式。
下面举例说明两种模式的区别:
对于100张RGB3通道的16×32(高为16宽为32)彩色图,
th表示方式:(100,3,16,32)
tf表示方式:(100,16,32,3)
唯一的区别就是表示通道个数3的位置不一样。
4)模型
Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。
a)序贯模型(Sequential):单输入单输出,一条路通到底,层与层之间只有相邻关系,没有跨层连接。这种模型编译速度快,操作也比较简单
b)函数式模型(Model):多输入多输出,层与层之间任意连接。这种模型编译速度慢。
(1)手写数字的识别(全连接神经网络)
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy
'''
第一步:选择模型(同样以序贯式模型为例)
'''
model = Sequential()
'''
第二步:构建网络层
'''
model.add(Dense(500,input_shape=(784,))) # 输入层,28*28=784
# Dense为全连接层,;
# 500表示输出的维度,完整的输出表示:(*,500):即输出任意个500维的数据流;
# input_shape(784,) 表示输入维度是784,完整的输入表示:(*,784):即输入N个784维度的数据
model.add(Activation('tanh')) # 激活层Activation,激活函数是tanh
model.add(Dropout(0.5)) # 采用50%的dropout,在训练过程中每次更新参数时随机断开一定百分比(rate)的输入神经元,防止过拟合。
model.add(Dense(500)) # 隐藏层节点500个
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(10)) # 输出结果是10个类别,十个输出节点,所以维度是10
model.add(Activation('softmax')) # 最后一层用softmax作为激活函数
'''
第三步:编译
'''
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) # 优化函数,设定学习率(lr)等参数
model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode='categorical') # 使用交叉熵作为loss函数
'''
第四步:训练
.fit的一些参数
batch_size:对总的样本数进行分组,每组包含的样本数量
epochs :训练次数
shuffle:是否把数据随机打乱之后再进行训练
validation_split:拿出百分之多少用来做交叉验证
verbose:屏显模式 0:不输出 1:输出进度 2:输出每次的训练结果
'''
(X_train, y_train), (X_test, y_test) = mnist.load_data() # 使用Keras自带的mnist工具读取数据(第一次需要联网)
# 由于mist的输入数据维度是(num, 28, 28),这里需要把后面的维度直接拼起来变成784维
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2])
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])
Y_train = (numpy.arange(10) == y_train[:, None]).astype(int)
Y_test = (numpy.arange(10) == y_test[:, None]).astype(int)
# label的one_hot
model.fit(X_train,Y_train,batch_size=200,epochs=50,shuffle=True,verbose=0,validation_split=0.3)
model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
'''
第五步:输出
'''
print("test set")
scores = model.evaluate(X_test,Y_test,batch_size=200,verbose=0)
print("")
print("The test loss is %f" % scores)
result = model.predict(X_test,batch_size=200,verbose=0)
result_max = numpy.argmax(result, axis = 1)
test_max = numpy.argmax(Y_test, axis = 1)
result_bool = numpy.equal(result_max, test_max)
true_num = numpy.sum(result_bool)
print("")
print("The accuracy of the model is %f" % (true_num/len(result_bool)))
(2)卷积神经网络
PS:Convolution2D 前最好加ZeroPadding2D;采用的是用Tensorflow做后端,所以采用“channels_last”数据格式
model = Sequential() # 创建序贯式模型实例
model.add(ZeroPadding2D((1, 1), batch_input_shape=(1, 4, 4, 1))) # ZeroPadding层,输入1张1通道(或特征映射)的4*4的数据
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(3,3), activation='relu', name='conv1_1')) # filters = 1为1个通道(或特征映射),kernel_size = (3,3)为参数核是3*3的矩阵, striders = (3,3)表示步长
model.layers[1].get_weights() # 第一层的参数
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(filters=1,kernel_size=(2,3),strides=(2,3), activation='relu', name='conv1_2'))
model.layers[2].get_weights()
备注:
filter要与输入数据类型相同(float32或float64),四个参数为[filter_height, filter_width, in_channels, out_channels]
,即卷积核的高/宽/输入通道数/输出通道数(feature map),如:[5, 5, NUM_CHANNELS, 32], # 5x5, filter_depth ,.filter_num
上图说明了Keras中参数filter的表示方式
当权重是二维矩阵(n*n)时:
(1)[[[…]]]内的元素个数:表示横轴的个数,即filter的高度;
(2)[[…]]内的元素个数:表示纵轴的数目,即filter的宽度;
(3)[…]内的元素个数:表示通道的数目,即filter的深度。
(5) [[[[…]]]]内元素的个数:表示filter的个数
实战代码:
from PIL import Image
import numpy as np
from keras.models import Sequential
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.optimizers import SGD
'''
第一步:读取图片数据
说明:这个过程需要安装pillow模块:pip install pillow # python的图像处理库
'''
##1张1通道的256*256的灰度图片
##data[0,0,0,0]:表示第一张图片的第一个通道的坐标为(0,0)的像素值
img_width, img_height = 256, 256
data = np.empty((1,1,img_width,img_height),dtype="float32")
##打开图片
img = Image.open("D:\\keras\\lena.jpg")
##把图片转换成数组形式
arr = np.asarray(img,dtype="float32")
data[0,:,:,:] = arr
'''
第二步:设置权重
说明:注意最外围是5个方括号
'''
weights = [[[[[-1]],[[0]],[[1]]],[[[-2]],[[0]],[[2]]],[[[-1]],[[0]],[[1]]]]]
weights =np.array(weights)
'''
第三步:组织卷积神经网络
说明:
1.因为实验采用的是默认的tensorflow后端,而输入图像是channels_first模式,所以注意data_format参数的设置
2.为了实验的效果,所以strides、pool_size等参数设置成了1
'''
##第一次卷积
model = Sequential()
model.add(ZeroPadding2D(padding=(2, 2), data_format='channels_first', batch_input_shape=(1, 1,img_width, img_height))) # Zeropadding层
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(1,1), activation='relu', name='conv1_1', data_format='channels_first')) # 卷积层
model.set_weights(weights) # 初始化卷积核的参数
##第二次卷积
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(1,1), activation='relu', name='conv1_2',data_format='channels_first'))
model.set_weights(weights)
##池化操作
model.add(ZeroPadding2D((0, 0)))
model.add(MaxPooling2D(pool_size=1, strides=None,data_format='channels_first'))
'''
第四步: 设置优化参数并编译网络
'''
# 优化函数,设定学习率(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')
'''
第五步:预测结果
'''
result = model.predict(data,batch_size=1,verbose=0)
'''
第六步:保存结果到图片
'''
img_new=Image.fromarray(result[0][0]).convert('L')
img_new.save("D:\\keras\\tt123.jpg")