tf.keras搭建神经网络八股:六步法,实践鸢尾花分类、MNIST手写数字识别、Fashion-mnist数据集

keras简介

Keras官方文档html

  • tensorflow2引入的高封装度的框架
  • 用于快速搭建神经网络模型,为支持快速实验而生
  • 深度学习框架之中最终易上手的一个,提供了一致而简洁的API,可以极大地减小通常应用下的工做量,提升代码地封装程度和复用性

学习API:阅读源码和注释

1. 在pycharm集成开发环境中查看框架源码

  • 将鼠标放置在函数上按住Ctrl键,会显示函数的基本信息,包括封装函数的类,函数入口参数,函数功能等;
  • 按住Ctrl键点击函数会跳转到函数的源代码部分,使用者能够根据源码和注释进一步了解函数的实现方法。

2. 在tensorflow官网中查询函数文档

TensorFlow APIpython

tf.keras搭建神经网络“六步法”

第一步:import相关模块

  好比import tensorflow as tfgit

第二步:指定输入网络的训练集和测试集

  告知要喂入的训练集、测试集是什么,如指定训练集的输入x_train和标签y_train,测试集的输入x_test和标签y_test。web

第三步:逐层搭建网络结构

注:tensorflow2.* 之后的版本能够直接使用tf.keras.Sequential()和tf.keras.Model()两个类。不用再使用keras.models的API。api

1. tf.keras.models.Sequential()(顺序结构)

  • 在sequential()中搭建网络结构,逐层描述每层网络,至关于走了一遍前向传播。
  • Sequential函数是一个容器,描述了神经网络的网络结构,在Sequential函数的输入参数中描述从输入层到输出层的网络结构。

拉直层:拉直层能够变换张量的尺寸,把输入特征拉直为一维数组,是不含计算参数的层。数组

tf.keras.layers.Flatten()

全链接层网络

tf.keras.layers.Dense( 神经元个数,
						activation=”激活函数”,
						kernel_regularizer=”正则化方式”)
  • activation:字符串给出,可选'relu''softmax''sigmoid''tanh'等。
  • kernel_regularizer:可选tf.keras.regularizers.l1()tf.keras.regularizers.l2()

卷积层app

tf.keras.layers.Conv2D( filter = 卷积核个数,
						kernel_size = 卷积核尺寸,
						strides = 卷积步长,
						padding = “valid” or “same”)

LSTM层框架

tf.keras.layers.LSTM()

示例:dom

import tensorflow as tf
from tensorflow.keras import layers, models

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

也能够不使用.add方法。直接在Sequntial里放入层列表:

import tensorflow as tf
from tensorflow.keras import layers, models

model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax')
])

2. 使用类/class(非顺序结构)

  使用Sequential()能够快速搭建网络结构,可是若是网络包含跳连等其余复杂网络结构,Sequential()就没法表示了。这就须要使用class来声明网络结构。以下是使用class类封装网络结构的模板:

class MyModel(Model):
	def __init__(self):
		super(MyModel, self).__init__()
		初始化网络结构
	def call(self, x):
		y = self.d1(x)
		return y
  • MyModel表示声明的神经网络的名字,括号中的Model表示建立的类须要继承tensorflow库中的Model类。
  • __init__()函数为类的构造函数用于初始化类的参数,spuer(MyModel,self).__init__()这行表示初始化父类的参数。以后即可初始化网络结构,搭建出神经网络所需的各类网络结构块。
  • call()函数中调用__init__()函数中完成初始化的网络块,实现前向传播并返回推理值。

搭建好网络结构后只须要使用Model=MyModel()构建类的对象,就可使用该模型了。

3. tf.keras.models.Model()

  • 搭建多输入多输出的网络。
  • 流程使用keras.Input定义输入张量shape; 建立网络层,定义每层的输入和输出张量;keras.models.Model肯定输入张量和输出层,keras能够根据每一层的输入输出关系完成整个网络图的建立。
import tensorflow as tf
from tensorflow.keras import layers, models, Input

input_tensor = Input(shape=(32, 32, 3))
x = layers.Conv2D(32, (3, 3), activation='relu')(input_tensor)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
output_tensor1=layers.Flatten()(x)
x = layers.Dense(64, activation='relu')(output_tensor1)
output_tensor2 = layers.Dense(10, activation='softmax')(x)

model = models.Model(inputs=input_tensor, outputs=[output_tensor1, output_tensor2])
model.summary()

TensorFlow2网络结构的搭建方法及共享权重问题

第四步:配置训练方法

  • model.compile()中配置训练方法,选择训练时使用的优化器、损失函数和最终评价指标
Model.compile( optimizer = 优化器,
				loss = 损失函数,
				metrics = [“准确率”])

optimizer 能够是字符串形式给出的优化器名字,也能够是函数形式,使用函数形式能够设置学习率、动量和超参数。

字符串形式 函数形式
‘sgd’ tf.optimizers.SGD( lr=学习率,decay=学习率衰减率,momentum=动量参数)
‘adagrad’ tf.keras.optimizers.Adagrad(lr=学习率,decay=学习率衰减率)
‘adadelta’ tf.keras.optimizers.Adadelta(lr=学习率,decay=学习率衰减率)
‘adam’ tf.keras.optimizers.Adam (lr=学习率,decay=学习率衰减率)

Loss能够是字符串形式给出的损失函数的名字,也能够是函数形式。

字符串形式 函数形式
‘mse’ tf.keras.losses.MeanSquaredError()
‘sparse_categorical_crossentropy’ tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
‘categorical_crossentropy’
‘binary_crossentropy’
‘hinge’
‘squared_hinge’

  损失函数常须要通过softmax等函数将输出转化为几率分布的形式。from_logits则用来标注该损失函数是否须要转换为几率的形式,取False时表示转化为几率分布,取True时表示没有转化为几率分布,直接输出。

Metrics标注网络评测指标。

  • ‘accuracy’:y_和y都是数值,如y_=[1] y=[1]。
  • ‘categorical_accuracy’:y_和y都是以独热码和几率分布表示。如y_=[0, 1, 0], y=[0.256, 0.695, 0.048]。
  • ‘sparse_ categorical_accuracy’:y_是以数值形式给出,y是以独热码形式给出。如y_=[1],y=[0.256, 0.695, 0.048]。
  • *‘accuracy’:准确率

Tensorflow2.0 model.compile详细介绍

第五步:执行训练过程

  • model.fit()中执行训练过程,告知训练集和测试集的输入值和标签、每一个batch的大小(batchsize)和数据集的迭代次数(epoch)
model.fit(训练集的输入特征, 训练集的标签, batch_size, epochs,
			validation_data = (测试集的输入特征,测试集的标签),
			validataion_split = 从测试集划分多少比例给训练集,
			validation_freq = 测试的epoch间隔次数)
  • x_train,y_train分别表示网络的输入特征和标签,
  • batch_size表示一次喂入神经网络的数据量,
  • epochs表示数据集的迭代次数
  • validation_split表示数据集中测试集的划分比例,
  • validation_freq表示每迭代多少次在测试集上测试一次准确率。

第六步:打印网络结构,统计参数数目

  • 使用model.summary()打印网络结构,统计参数数目。

实例

1.iris数据集

tf.keras.models.Sequential()

#-------第一步:import相关模块------
import tensorflow as tf
from sklearn import datasets
import numpy as np

#-------第二步:指定输入网络的训练集和测试集------
#1.测试集的输入特征x_test和标签y_test能够像x_train和y_train同样直接从数据集获取;
#2.在model.fit()中按比例从训练集中划分。
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target

#打乱数据集
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)

#-------第三步:逐层搭建网络结构-------
#本例使用了单层全链接网络
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
])

#-------第四步:配置训练方法-------
#因为神经网络输出使用了softmax激活函数,使得输出是几率分布,而不是原始输出,因此须要将from_logits参数设置为False;
#鸢尾花数据集给的标签是0,1,2这样的数值,而网络前向传播的输出为几率分布,因此metrics须要设置为sparse_categorical_accuracy。
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
     		  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

#-------第五步:在model.fit()中执行训练过程-------
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
#-------第六步:打印网络结构,统计参数数目-------
model.summary()

使用类/class

#-------第一步:import相关模块------
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np

#-------第二步:指定输入网络的训练集和测试集------
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target

np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)

#-------第三步:逐层搭建网络结构-------
class IrisModel(Model):
    def __init__(self):
        super(IrisModel, self).__init__()
        self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())

    def call(self, x):
        y = self.d1(x)
        return y
#实例化
model = IrisModel()

#-------第四步:配置训练方法-------
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

#-------第五步:在model.fit()中执行训练过程-------
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)

#-------第六步:打印网络结构,统计参数数目-------
model.summary()

使用Sequential()方法和class方法的区别:

(1). import中添加了Model模块和Dense层、Flatten层。
(2). 使用class声明网络结构,model = IrisModel()初始化模型对象。

2.MNIST数据集

数据集介绍

  MNIST数据集一共有7万张图片,是28×28像素的0到9手写数字数据集,其中6万张用于训练,1万张用于测试。每张图片包括 784 28 × 28 784(28\times28) 个像素点,使用全链接网络时可将784个像素点组成长度为784的一维数组,做为输入特征。数据集图片以下所示。

导入、查看数据集

导入数据集

import tensorflow as tf
from matplotlib import pyplot as plt
#keras函数库中提供了使用mnist数据集的接口
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

使用plt库中的两个函数可视化训练集中的图片

# 可视化训练集输入特征的第一个元素
plt.imshow(x_train[0], cmap='gray')  # 绘制灰度图
plt.show()

使用print打印出训练集中第一个样本以二位数组的形式打印出来

# 打印出训练集输入特征的第一个元素
print("x_train[0]:\n", x_train[0])
# 打印出训练集标签的第一个元素
print("y_train[0]:\n", y_train[0])

打印出测试集样本的形状,共有10000个28行28列的三维数据

# 打印出整个训练集输入特征形状
print("x_train.shape:\n", x_train.shape)
# 打印出整个训练集标签的形状
print("y_train.shape:\n", y_train.shape)
# 打印出整个测试集输入特征的形状
print("x_test.shape:\n", x_test.shape)
# 打印出整个测试集标签的形状
print("y_test.shape:\n", y_test.shape)

训练MNIST数据集

使用Sequential实现手写数字识别

import tensorflow as tf

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()

使用class实现手写数字识别

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

class MnistModel(Model):
    def __init__(self):
        super(MnistModel, self).__init__()
        self.flatten = Flatten()
        self.d1 = Dense(128, activation='relu')
        self.d2 = Dense(10, activation='softmax')

    def call(self, x):
        x = self.flatten(x)
        x = self.d1(x)
        y = self.d2(x)
        return y


model = MnistModel()

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()

值得注意的是训练时须要将输入特征的灰度值归一化到[0,1]区间,这可使网络更快收敛。
在这里插入图片描述
训练时每一个step给出的是训练集accuracy不具备参考价值,有实际评判价值的是validation_freq中设置的隔若干轮输出的测试集accuracy。
在这里插入图片描述

3.Fashion-mnist数据集

  Fashion_mnist数据集具备mnist近乎全部的特征,包括60000张训练图片和10000张测试图片,图片被分为十类,每张图像为28×28的分辨率。

import tensorflow as tf

fashion = tf.keras.datasets.fashion_mnist
(x_train, y_train),(x_test, y_test) = fashion.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model

fashion = tf.keras.datasets.fashion_mnist
(x_train, y_train),(x_test, y_test) = fashion.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


class MnistModel(Model):
    def __init__(self):
        super(MnistModel, self).__init__()
        self.flatten = Flatten()
        self.d1 = Dense(128, activation='relu')
        self.d2 = Dense(10, activation='softmax')

    def call(self, x):
        x = self.flatten(x)
        x = self.d1(x)
        y = self.d2(x)
        return y


model = MnistModel()

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()

北大人工智能实践:Tensorflow笔记