【Keras篇】---Keras初始,两种模型构造方法,利用keras实现手写数字体识别
一、前述
Keras 适合快速体验 ,keras的设计是把大量内部运算都隐藏了,用户始终可以用theano或tensorflow的语句来写扩展功能并和keras结合使用。
二、安装
Pip install --upgrade keras
三、Keras模型之序列模型
序列模型属于通用模型的一种,因为很常见,所以这里单独列出来进行介绍,这种模型各层之间是依次顺序的线性关系,在第k层和第k+1层之间可以加上各种元素来构造神经网络
这些元素可以通过一个列表来制定,然后作为参数传递给序列模型来生成相应的模型。
第一种方式
from keras.models import Sequential from keras.layers import Dense from keras.layers import Activation # Dense相当于构建一个全连接层,32指的是全连接层上面神经元的个数 layers = [Dense(32, input_shape=(784,)), Activation('relu'), Dense(10), Activation('softmax')] model = Sequential(layers) model.summary()
第二种方式:
from keras.models import Sequential from keras.layers import Dense from keras.layers import Activation model = Sequential() model.add(Dense(32, input_shape=(784,))) model.add(Activation('relu')) model.add(Dense(10)) model.add(Activation('softmax'))
结果:
四、Keras模型之通用模型
通用模型可以用来设计非常复杂、任意拓扑结构的神经网络,例如有向无环图网络类似于序列模型,通用模型通过函数化的应用接口来定义模型使用函数化的应用接口有好多好处,比如:决定函数执行结果的唯一要素是其返回值,而决定返回值的唯一要素则是其参数,这大大减轻了代码测试的工作量
在通用模型中,定义的时候,从输入的多维矩阵开始,然后定义各层及其要素,最后定义输出层将输入层和输出层作为参数纳入通用模型中就可以定义一个模型对象
代码:
# 通用模型 # 通用模型可以用来设计非常复杂、任意拓扑结构的神经网络,例如有向无环图网络 # 类似于序列模型,通用模型通过函数化的应用接口来定义模型 # 使用函数化的应用接口有好多好处,比如:决定函数执行结果的唯一要素是其返回值,而决定 # 返回值的唯一要素则是其参数,这大大减轻了代码测试的工作量 # 在通用模型中,定义的时候,从输入的多维矩阵开始,然后定义各层及其要素,最后定义输出层 # 将输入层和输出层作为参数纳入通用模型中就可以定义一个模型对象 from keras.layers import Input from keras.layers import Dense from keras.models import Model # 定义输入层 input = Input(shape=(784,)) # 定义各个连接层,假设从输入层开始,定义两个隐含层,都有64个神经元,都使用relu激活函数 x = Dense(64, activation='relu')(input)#把上一层输出结果给下一层的输入 x = Dense(64, activation='relu')(x) # 定义输出层,使用最近的隐含层作为参数 y = Dense(10, activation='softmax')(x)#整个逻辑从输入到输出全都在y里面了 # 所有要素都齐备以后,就可以定义模型对象了,参数很简单,分别是输入和输出,其中包含了 # 中间的各种信息 model = Model(inputs=input, outputs=y) # 当模型对象定义完成之后,就可以进行编译(定义损失函数,通过什么方式优化(优化器),等等)了,并对数据进行拟合,拟合的时候也有两个参数 # 分别对应于输入和输出 model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) model.fit(data, labels)#data是输入数据的X labels是Y
五、Keras实现手写识别体案例
import numpy as np from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D #Conv2D 图片是3通道 Conv1D 单声道或者双声道 # 先读入数据 (X_train, y_train), (X_test, y_test) = mnist.load_data("../test_data_home") # 看一下数据集的样子 print(X_train[0].shape)#X_train是很多张图片[0]是第一张 print(y_train[0]) # 下面把训练集中的手写黑白字体变成标准的四维张量形式,即(样本数量,长,宽,1) # 1是channel通道 # 并把像素值变成浮点格式 # X_train.shape[0]取得是行的数量 X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32') X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype('float32') # 由于每个像素值都介于0到255,所以这里统一除以255,把像素值控制在0-1范围 X_train /= 255 #X_train是一个矩阵 这里相当于里面每个数都除以255 X_test /= 255 # 由于输入层需要10个节点,所以最好把目标数字0-9做成One Hot编码的形式 def tran_y(y):#自己定义的One_hot编码格式 先定义10个零 然后在对应个数上填1 y_ohe = np.zeros(10) y_ohe[y] = 1 return y_ohe # 把标签用One Hot编码重新表示一下 y_train_ohe = np.array([tran_y(y_train[i]) for i in range(len(y_train))])#列表生成器 y_test_ohe = np.array([tran_y(y_test[i]) for i in range(len(y_test))]) # 搭建卷积神经网络 model = Sequential() # 添加一层卷积层,构造64个过滤器(卷积核),每个过滤器(卷积核)覆盖范围是3*3*1 # 过滤器步长为1,图像四周补一圈0,并用relu进行非线性变化 model.add(Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1), padding='same', input_shape=(28, 28, 1), activation='relu'))#activation如果不设置,就是线性的 # 添加一层最大池化层 model.add(MaxPooling2D(pool_size=(2, 2)))#默认Strides是和池化维度一样 这里是2*2 池化默认一般不做padding # 设立Dropout层,Dropout的概率为0.5 model.add(Dropout(0.5)) # 重复构造,搭建深度网络 model.add(Conv2D(128, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.5)) model.add(Conv2D(256, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.5)) # 把当前层节点展平 model.add(Flatten()) # 构造全连接层神经网络层 model.add(Dense(128, activation='relu')) model.add(Dense(64, activation='relu')) model.add(Dense(32, activation='relu')) model.add(Dense(10, activation='softmax')) # 定义损失函数,一般来说分类问题的损失函数都选择采用交叉熵 # adagrad自适应的调整学习率的随机梯度下降算法 因为自适应所以会比较耗时间 model.compile(loss='categorical_crossentropy', optimizer='adagrad', metrics=['accuracy']) # 放入批量样本,进行训练 model.fit(X_train, y_train_ohe, validation_data=(X_test, y_test_ohe)#验证集作用边训练边测试 在每一个step中都会验证 , epochs=20, batch_size=128) #epochs是迭代多少轮次 学完一轮是整个数据集/128 这里面有20轮 # 在测试集上评价模型的准确率 # verbose : 进度表示方式。0表示不显示数据,1表示显示进度条 scores = model.evaluate(X_test, y_test_ohe, verbose=0)#evaluate就是评估准确率
延伸结论:
最后一个卷积层到第一个全连接层的参数是最多的
结果: