keras搭建神经网络

it2024-06-19  44

Keras是一个神经网络开发的高级API,用Python编写,底层调用神经网络开发库TensorFlow、CNTK或Theano。 Keras的目标是简化神经网络应用开发过程,快速实现想法。

Keras 后端

Keras 是一个模型级库,为开发深度学习模型提供了高层次的构建模块。它不处理诸如张量乘积和卷积等低级操作。 相反,它依赖于一个专门的、优化的张量操作库来完成这个操作,它可以作为 Keras 的「后端引擎」。 相比单独地选择一个张量库,而将 Keras 的实现与该库相关联,Keras 以模块方式处理这个问题,并且可以将几个不同的后端引擎无缝嵌入到 Keras 中。 目前,Keras 有三个后端实现可用: TensorFlow 后端,Theano 后端,CNTK 后端。 可通过修改Keras 配置文件,将字段 backend 更改为 theano,tensorflow 或 cntk, Keras 将在下次运行 Keras 代码时使用新的配置。

Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),

函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。

a)序贯模型(Sequential):

单输入单输出,一条路通到底,层与层之间只有相邻关系,没有跨层连接。 这种模型编译速度快,操作也比较简单。

b)函数式模型(Model):

多输入多输出,层与层之间任意连接。这种模型编译速度慢。

Keras 导入库与模块

从导入numpy开始,并为计算机的伪随机数生成器设置一个种子,相同种子可以产生同系列的随机数。

import numpy as np np.random.seed(123) # 种子相同,随机数产生可以重现

接下来,将从Keras导入Sequential模型类型。

这是一个简单的线性神经网络层的栈,它非常适合本教程将构建的前馈CNN(卷积神经网络)类型。 一般需要:前三个是Sequential内置函数 1、model.add,添加层; 2、model.compile,模型训练的BP模式设置; 3、model.fit,模型训练参数设置 + 训练; 4、模型评估 5、模型预测

from keras.models import Sequential

从Keras导入核心层,

这些层是在任何神经网络中都要使用的层: Dense,全连接层 Dropout, Dropout层 Activation,激活层 Flatten Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。

from keras.layers import Dense, Dropout, Activation, Flatten

然后,将从Keras导入CNN层

,这些卷积层将帮助我们有效地训练图像数据:

from keras.layers import Convolution2D, MaxPooling2D

导入一些实用程序,用于转换数据:

CustomObjectScope 提供定制类的作用域 HDF5Matrix 使用HDF5数据集代替Numpy数组的方法 Sequence 序列数据的基类,例如一个数据集。 to_categorical 将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵 normalize 对numpy数组规范化,返回规范化后的数组

from keras.utils import np_utils

导入backend,获取底层实现库的信息,

例如可以获取支持的图像格式:

from keras import backend as K

keras加载minst手写数字集

Keras库已经包含了这个数据集,可以从Keras库中加载:

from keras.callbacks import Callback from keras.datasets import mnist # 将预打乱的MNIST数据加载到训练和测试集中 (X_train, y_train), (X_test, y_test) = mnist.load_data() print (X_train.shape)#训练集中有60000个样本,每个图像都是28像素x28像素。 (60000, 28, 28) import matplotlib.pyplot as plt plt.imshow(X_train[1]) plt.show()

Keras 预处理数据

查看原始数据集的形状shape:

X_train.shape (60000, 28, 28)

MNIST是灰度图像,位深为1,为单通道,我们将数据集从形状 (n,宽度,高度)转换为(n,位深,宽度,高度)。 所谓通道就是每个像素中包含的颜色个数,经典的就是三通道:BGR; 四通道就是:BGRA(A是指Alpha值,主要控制图片的透明度) 所谓位深就是一个像素中每种颜色的位数

if K.image_data_format() == 'channels_first': X_train = X_train.reshape(X_train.shape[0], 1, 28, 28) X_test = X_test.reshape(X_test.shape[0], 1, 28, 28) input_shape = (1, 28, 28) else: X_train = X_train.reshape(X_train.shape[0], 28, 28, 1) X_test = X_test.reshape(X_test.shape[0], 28, 28, 1) input_shape = (28, 28, 1)

Keras的底层实现库可能是TensorFlow或Theano,它们对数据集的形状要求是不一样的, TensorFlow要求通道在前channels_first,Theano相反(channels_last)。 彩色图像一般会有Width, Height, Channels,而“channels_first”或“channels_last”,则代表数据的通道维的位置。 该参数是Keras 1.x中的image_dim_ordering,“channels_last”对应原本的“tf”,“channels_first”对应原本的“th”。 以128x128x128的数据为例,“channels_first”应将数据组织为(3,128,128,128),而“channels_last”应将数据组织为(128,128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channels_last”。 此处,我们使用TensorFlow的格式。 重新打印X_train的形状:

print (X_train.shape) (60000, 28, 28, 1)

接下来,输入数据预处理步骤是将数据类型转换为float32, 并将数据值归一化到[0,1]范围内。

X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255

Keras 预处理分类标签

让我们看看分类标签数据:

print (y_train.shape) # (60000,) print (y_train[:10]) #y_train前面10个值是: (60000,) [5 0 4 1 9 2 1 3 1 4]

在Keras中,模型训练时,需要把分类标签数据转换为类似位图的矩阵, 可以使用to_categorical来转换标签数据。ONE-HOT编码 将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵, 用于应用到以categorical_crossentropy为目标函数的模型中. 参数 y: 类别向量 num_classes:总共类别数

# 将一维类数组转换为10维分类矩阵 Y_train = np_utils.to_categorical(y_train, 10) Y_test = np_utils.to_categorical(y_test, 10) # 打印Y_train矩阵的形状、内容 print (Y_train.shape) print (Y_train[:10]) # [[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.] # 5 对应位置标为1 # [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.] # 0 # [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.] # 4 # [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] # 1 # [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] # 9 以此类推 # [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] # [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] # [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] # [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] # [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]] (60000, 10) [[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.] [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]]

定义神经网络模型架构。 首先声明一个Sequential模型格式:

model = Sequential()

接下来,声明输入层:

model.add(Convolution2D(32, 3, 3, activation='relu', input_shape=input_shape)) D:\Anaconda\envs\tensorflow\lib\site-packages\ipykernel_launcher.py:1: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(32, (3, 3), activation="relu", input_shape=(28, 28, 1...)` """Entry point for launching an IPython kernel.

input_shape参数应为1个样本的形状。在本例中,与每个数字图像的(深度、宽度、高度)对应的是相同的(1,28,28)。 前3个参数分别对应于要使用的卷积滤波器的数量(32)、每个卷积核中的行数和列数(3,3)。

# 我们可以通过打印当前模型输出的形状来确认: print (model.output_shape) (None, 26, 26, 32)

可以简单地在模型中添加更多层,就像搭积木一样

# 接下来,可以简单地在模型中添加更多层,就像搭积木一样: model.add(Convolution2D(32, 3, 3, activation='relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) D:\Anaconda\envs\tensorflow\lib\site-packages\ipykernel_launcher.py:2: UserWarning: Update your `Conv2D` call to the Keras 2 API: `Conv2D(32, (3, 3), activation="relu")`

MaxPooling2D层是池化层,进一步降低数据量提取特征,Dropout层的作用是防止过拟合。activation='relu’是relu激活函数 到目前为止,对于模型参数,已经添加了2个卷积层。为完成CNN模型架构,还需添加一个全连接层和输出层:

model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax'))# 输出层用到softmax分类激活函数 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # model.compile(optimizer = 优化器, # loss = 损失函数, # metrics = ["准确率”]) WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:3295: The name tf.log is deprecated. Please use tf.math.log instead.

接下来编译模型。在编译模型时,设置损失函数与优化器。 categorical_crossentropy损失函数,Adam 优化器。

损失函数 binary_crossentropy 交叉熵损失函数:适用于多分类问题,并使用softmax作为输出层的激活函数的情况。 categorical_crossentropy 平方差

优化算法: BGD 批量梯度下降 所谓的梯度下降方法是无约束条件中最常用的方法。假设f(x)是具有一阶连续偏导的函数,现在的目标是要求取最小的f(x) : min f(x) 核心思想:负梯度方向是使函数值下降最快的方向,在迭代的每一步根据负梯度的方向更新x的值,从而求得最小的f(x)。因此我们的目标就转变为求取f(x)的梯度。当f(x)是凸函数的时候,用梯度下降的方法取得的最小值是全局最优解。 SGD 随机梯度下降 随机梯度下降算法和批量梯度下降的不同点在于其梯度是根据随机选取的训练集样本来决定的,其每次对theta的更新,都是针对单个样本数据,并没有遍历完整的参数。当样本数据很大时,可能到迭代完成,也只不过遍历了样本中的一小部分。因此,其速度较快,但是其每次的优化方向不一定是全局最优的,但最终的结果是在全局最优解的附近。 需要:学习速率 ϵ, 初始参数 θ 每步迭代过程:

从训练集中的随机抽取一批容量为m的样本{x1,…,xm},以及相关的输出yi计算梯度和误差并更新参数 虽然BGD可以让参数达到全局最低点并且停止,而SGD可能会让参数达到局部最优,但是仍然会波动,甚至在训练过程中让参数会朝一个更好的更有潜力的方向更新。但是众多的实验表明,当我们逐渐减少学习速率时,SGD和BGD会达到一样的全局最优点。 MBGD小批量梯度下降 为了综合上述两种方法,提出了小批量梯度下降。它:(1)降低在SGD中高方差的问题,能使得收敛更加稳定;(2)可以利用深度学习中最先进的库进行矩阵优化的操作,加速操作;(3)一般的小批量介于50~256,但是当适用很小的批量时,有时也统称为SGD。 核心思想:在每次迭代时考虑一小部分样本,比如考虑10个样本,同时计算在这10个样本点上的每个参数的偏导数,对于每个优化参数,将该参数在这10个样本点的偏导数求和。 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit( x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, # validation_split=0.0, validation_data=None, shuffle=True, # class_weight=None, sample_weight=None, initial_epoch=0) # model.fit( 训练集的输入特征, # 训练集的标签, # batch_size, #每一个batch的大小 # epochs, #迭代次数 # validation_data = (测试集的输入特征,测试集的标签), # validation_split = 从测试集中划分多少比例给训练集, # validation_freq = 测试的epoch间隔数) model.fit(X_train, Y_train, batch_size=32, nb_epoch=10, verbose=1) D:\Anaconda\envs\tensorflow\lib\site-packages\ipykernel_launcher.py:2: UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\tensorflow_core\python\ops\math_grad.py:1424: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version. Instructions for updating: Use tf.where in 2.0, which has the same broadcast rule as np.where WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:986: The name tf.assign_add is deprecated. Please use tf.compat.v1.assign_add instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:973: The name tf.assign is deprecated. Please use tf.compat.v1.assign instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:2741: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead. Epoch 1/10 WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:174: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:181: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:190: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:199: The name tf.is_variable_initialized is deprecated. Please use tf.compat.v1.is_variable_initialized instead. WARNING:tensorflow:From D:\Anaconda\envs\tensorflow\lib\site-packages\keras\backend\tensorflow_backend.py:206: The name tf.variables_initializer is deprecated. Please use tf.compat.v1.variables_initializer instead. 60000/60000 [==============================] - 92s 2ms/step - loss: 0.2213 - acc: 0.9326 Epoch 2/10 60000/60000 [==============================] - 74s 1ms/step - loss: 0.0910 - acc: 0.9729 Epoch 3/10 60000/60000 [==============================] - 92s 2ms/step - loss: 0.0694 - acc: 0.9790 Epoch 4/10 60000/60000 [==============================] - 88s 1ms/step - loss: 0.0584 - acc: 0.9826 Epoch 5/10 60000/60000 [==============================] - 86s 1ms/step - loss: 0.0480 - acc: 0.9852 Epoch 6/10 60000/60000 [==============================] - 81s 1ms/step - loss: 0.0441 - acc: 0.9864 Epoch 7/10 60000/60000 [==============================] - 83s 1ms/step - loss: 0.0383 - acc: 0.9876 Epoch 8/10 60000/60000 [==============================] - 84s 1ms/step - loss: 0.0351 - acc: 0.9892 Epoch 9/10 60000/60000 [==============================] - 81s 1ms/step - loss: 0.0305 - acc: 0.9906 Epoch 10/10 60000/60000 [==============================] - 83s 1ms/step - loss: 0.0293 - acc: 0.9910 <keras.callbacks.History at 0x2aeb9316088>

模型评估model.evaluate和model.predict区别

model.evaluate 输入数据和标签,输出损失和精确度. # 评估模型,不输出预测结果 loss,accuracy = model.evaluate(X_test,Y_test) print(’\ntest loss’,loss) print(‘accuracy’,accuracy) model.predict 输入测试数据,输出预测结果 (通常用在需要得到预测结果的时候) #模型预测,输入测试集,输出预测结果 y_pred = model.predict(X_test,batch_size = 1) 两者差异 输入输出不同 model.evaluate输入数据(data)和金标准(label),然后将预测结果与真实标签相比较,得到两者误差并输出. model.predict输入数据(data),输出预测结果 是否需要真实标签 model.evaluate需要,因为需要比较预测结果与真实标签的误差 model.predict不需要,只是单纯输出预测结果,全程不需要真实标签的参与.

loss,accuracy = model.evaluate(X_test, Y_test, verbose=0)#返回loss 和accuracy print('\ntest loss',loss) print('accuracy',accuracy) test loss 0.030404101986087607 accuracy 0.9916
最新回复(0)