一文搞定deeplearning_入门_理论基础_手撕代码

01.TensorFlow简介

1.1 TensorFlow和Keras简介

1.使用tf.data加载数据。

使用tf.data实例化读取训练数据和测试数据

2.模型的建立与调试

使用动态图模式Eager Execution 和著名的神经网络高级API框架Keras。结合可视化工具TensorBoard,简易、快速地建立和调试模型

3.模型的训练:

支持CPU、单GPU、单机多卡GPU、多机集群、TPU训练模型

4.预训练模型部署

通过Tensorflow Hub,可以方便的调用预训练完毕的医用成熟模型

5.模型的部署

通过TensorFlow Serving /TensorFlow Lite /TensorFlow.js等组件,可以将TensorFlow模型部署

1.2 TensorFlow安装

GPU版本的安装

pip install tensoeflow-gpu==2.2.0 -i http://pypi.douban.com/simple

1.3 张量及其操作

1.3.1 张量Tensor

print('hello world')
import tensorflow as tf
import numpy as np

首先创建基础的张量:

# 创建int32类型的0维张量
rank_0_tensor = tf.constant(4)
print(rank_0_tensor)
# 创建flout32类型的1维张量
rank_1_tensor = tf.constant([2.0, 3.0 4.0])
print(rank_1_tensor)
# 创建flout16类型的2维张量
rank_2_tensor = tf.constant([[1,2],
                            [3,4],
                            [5,6]], dtype=tf.flout16)
print(rank_2_tensor)

输出结果为:

tf.Tensor(4, shape=(), dtype=flout32)    # 标量scalar
tf.Tensor([2. 3. 4.],shape=(3,), dtype=flout32)   # 向量 vector
tf.Tensor([[1. 2.]
           [3. 4.]
           [5. 6.]], shape=(3,2), dtype=flout16)  # 矩阵 metrix

2.转换成numpy

  • np.array

    # 将张量转换成array形式
    tensor1 =tf.constant([1,2,3,4,5])
    np.array(tensor1)
    

3.常用函数

# 定义张量a和b
a = tf.constant([[1,2],[3,4]])
b = tf.conatant([[1,1],[1,1]])
# 加法
tf.add(a,b)
# 元素相乘
tf.multiply(a,b)
# 矩阵乘法
tf.matmul(a,b)
# 最大值
tf.reduce_max(a)
# 最大值索引
tf.argmax(a)

4.变量

特殊张量,形状不可变,但可以更改其中的参数

my_variable = tf.Variable([[1,2],[3,4]])
my_variable.shape
my_variable.dtype

1.4 tf.Keras介绍

tensor2.0的高阶API接口

1.4.1 常用模块

activations 激活函数

applications 预训练网络模块

datasets

layers

losses

metrics

models

optimizers

1.4.2 常用方法

  1. 数据获取
  2. 数据处理
  3. 模型创建于训练
  4. 模型测试与评估
  5. 模型预测
1.导入tf.keras
import tensorflow
from tensorflow import keras
2.数据输入
3. 模型构建
4.训练与评估
model.compile()
model.fit()
5.回调函数(callbacks)
6.模型的保存和恢复
  • 只保存参数(save weights)
  • 保存整个模型(save model.h5)

1.4.3 快速入门模型

# 导入相关的库
# 绘图
import tensorflow
import seaborn as sns
# 机器学习
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegressionCV
# 深度学习:tf.keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras import utils
'数据处理’
# 读取数据
iris = sns.load_dataset('iris')
# 将数据之间的关系可视化
sns.pairplot(iris, hue='species')
# 花瓣和花萼的数据(获取数据集的特征值和目标值)
X = iris.values[:,:4]
Y = iris.values[:,4]
# 数据集划分
train_x,test_x,train_y,test_y = train_teat_split(X,Y, test_size=0.5,random_states=0)
# tf.keras 实现
# 数据处理:目标值的进行热编码
def one_hot_encode(arr):
    # 获取目标值中的所有类别,并进行热编码
    uniques,ids = np.unique(arr,return_inverse=True)
    return utils.to_categorical(ids,len(uniques))
# 对目标值进行编码
train_y_ohe = one_hot_encode(train_y)
test_y_ohe = one_hot_encode(test_y)
# 模型搭建
# 利用Sequential方式构建模型
model = Sequential([
    # 隐藏层
    Dense(10, activation = "relu", input_shape = (4,)),
    # 隐藏层
    Dense(10, activation ="relu" ),
    # 输出层
    Dense(3, activation = "softmax")
])
------------------------------------------------------------------
model.summary() # 查看网络结构
utils.plot_model(model, show_shapes=True)  # 查看网络结构图
------------------------------------------------------------------
# 模型训练与评估
# 设置模型的相关参数:优化器、(交叉熵)损失函数和评价标准
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 类型转换
train_x = np.array(train_x, dtype=np.float32)
test_x = np.array(test_x, dtype=np.float32)

# 模型训练;epochs,训练样本送入网络的次数;batch_size:每次训练的送入网络中的样本个数
model.fit(train_x,train_y_ohe,epochs=10,batch_size=1,verbose=1)

# 模型评估:计算模型的损失与准确率
loss, accuracy = model.evaluate(test_x, test_y_ohe,verbose=1)

2.1 Deep_learning简介

神经网络简介

1.什么是神经网络 ANN

Input layer —>> Hidden layers —>> Output layer

f ( b + ∑ i = 1 n x i w i ) f(b+\sum_{i=1}^{n}x_iw_i) f(b+i=1nxiwi)

2.激活函数

  • sigmoid/logistics函数

    • import tensorflow as tf
      import tensorflow.keras as keras
      import matplotlib.pyplot as plt
      x=np.linspace(-10,10,1000)
      y=tf.nn.sigmoid(x)
      plt.plot(x,y)
      plt.grid()
      
  • tanh(双曲正切)

    • import tensorflow as tf
      import tensorflow.keras as keras
      import matplotlib.pyplot as plt
      x=np.linspace(-10,10,1000)
      y=tf.nn.tanh(x)
      plt.plot(x,y)
      plt.grid()
      
  • RELU

    • # Relu是一部分神经元输出为0,造成网络的稀疏性,减少过拟合
      import tensorflow as tf
      import tensorflow.keras as keras
      import matplotlib.pyplot as plt
      x=np.linspace(-10,10,1000)
      y=tf.nn.relu(x)
      plt.plot(x,y)
      plt.grid()
      
  • LeakRelu

    f ( x ) = m a x ( 0.1 x , x ) f(x) = max(0.1x,x) f(x)=max(0.1x,x)

    • import tensorflow as tf
      import matplotlib.pyplot as plt
      import tensorflow.keras as keras
      x = np.linspace(-10,10,1000)
      y=tf.nn.leak_relu(x)
      plt.plot(x,y)
      plt.grid()
      
  • Softmax

    • s o f t m a x ( z i ) = e ( z i ) ∑ j e ( z j ) softmax(z_i) = \frac{e^(z_i)}{\sum_j e^(z_j)} softmax(zi)=je(zj)e(zi)

    • 就是将网络输出的logits通过softmax函数映射成(0,1)的值,这些值的累计和为1

    • import tensorflow as tf
      import matplotlib.pyplot as plt
      import tensorflow.keras as keras
      import numpy as np
      # 数字中的score
      x = tf.constant([0.2,0.02,0.15,1.3,0.5,0.06,1.1,0.05,3.75])
      # 将其送入到softmax中计算分类结果
      y = tf.nn.softmax(x)
      # 将结果进行打印
      print(y)
      
  • 其它激活函数

    • identity function
    • binary step
    • Logistic
    • PRelu
    • RRelu
    • ELU

隐藏层:优先使用RELU激活函数,效果不好时可以考虑Leaky_relu,需要注意Dead Relu问题

输出层:二分类sigmoid 多分类softmax函数 回归identity

  1. 参数初始化

    • 随机初始化:高斯分布取样

    • 标准初始化:均匀随机取值

      以下两种使用最多

    • Xavier初始化

    基本思想:各层的激活值和梯度的方差在传播过程中保持一致,也叫作Glorot初始化

    # Xavizer初始化
    iport tensorflow as tf
    # 1. 正态分布的
    # 进行实例化
    initializer = tf.keras.initializers.glorot_normal()
    # 采样得到权重
    values = initializers((9,1))
    
    # 2. 标准化:均匀分布的
    # 进行实例化
    initializer = tf.keras.initializers.glorot_uniform()
    # 采样得到权重
    values = initializers(shape=(9,1))
    print(values)
    
    • He初始化

    正向传播时,激活值的方差保持不变;反向传播时。关于状态值的梯度的方差保持不变

    # He初始化
    iport tensorflow as tf
    # 1. 正态分布
    # 实例化
    initializer = tf.keras.initializers.he_normal()
    # 采样得到权重
    values = initializers(shape=(9,1))
    print(values)
    
    # 2. 均匀分布
    # 实例化
    initializer = tf.keras.initializers.he_uniform()
    # 采样得到权重
    values = initializers(shape=(9,1))
    print(values)
    
  2. 神经网络的搭建

一种使用Sequential构建 一种通过model类进行构建(函数式编程或继承model类)

4.1 通过Sequential构建

'神经网络的搭建'
# 导入相关的工具包
import tensorflow as tf
import tensorflow.keras as keras 
import tensorflow.keras.layers as layers
# 定义model,构建模型、
model = keras.Sequential([
    # 第一个隐层
    layers.Dense(3,activation='relu',kernel_initializer='he_normal',name = "layer1", input_shape=(3,)),
    # 第二个隐层
    layers.Dense(2,activation='relu',kernel_initializer='he_normal',name = "layer2"),
    # 输出层
    layer.Dense(2,activation='sigmoid',kernel_initializer='he_normal',name = "layer3")]
                name="sequential"
               )

# model.summary()
# keras.untils.plot_model(model)

4.2 通过functional API构建

将层作为可调用的对象并返回张量,并将输入向量和输出向量提供给’tf.keras.Model’的’inputs’和’outputs’参数,实现方法如下:

# 导入工具包
import tensorflow as tf
import tensorflow.keras as keras 
import tensorflow.keras.layers as layers
# 定义模型的输入
inputs = keras.Input(shape=(3,), name="input")
# 第一层:激活函数为relu,其它默认
x = layers.Dense(3, activation='relu',name = 'layer1')(inputs)
# 第二层:激活函数为relu,其它默认
x = layers.Dense(2, activation='relu',name = 'layer2')(x)
# 第三层(输出层):激活函数为sigmoid
outputs = layers.Dense(2, activation='sigmoid',name = 'output')(x)
# 使用model来创建模型,指明输入和输出
model = keras.Model(inputs=inputs, outputs=outputs, name="Functional_API_model")

---------------------------------------------------
model.summary()
keras.untils.plot_model(model,show_shapes=True)

4.3 通过model的子类进行构建

通过model的子类进行构建,此时需要在—init—中定义神经网络的层,在call方法中定义网络的前向传播过程,实现方法如下:

# 导入工具包
import tensorflow as tf
import tensorflow.keras as keras 
import tensorflow.keras.layers as layers
# 定义一个model的子类
class MyModel(keras.Model):
    # 在init方法中定义网络的层结构
    def __init__(self):
        super(MyModel, self).__init__()
        # 第一层:激活函数为relu,权值初始化为he_normal
        self.layer1 = layers.Dense(3,activation="relu", name="layer1")
        # 第二个隐层
        self.layer2 = layers.Dense(2,activation="relu", name="layer2")
        # 输出层
        self.layer3 = layers.Dense(2,activation="sigmoid", name="layer3")
    # 定义网络的前向传播
    def class(self,inputs):
        x = self.layer1(inputs)
        x = self.layer2(x)
        outputs = self.layer3(x)
        return outputs
                                   
# 实例化模型
model = MyModel()
# 设置输入
x = tf.ones((1,3))
y = model(x)                                                       
  1. 神经网络的优缺点

    • 优点:可以接近任意非线性函数了,大量框架和库可使用;

    • 缺点:黑箱,没办法了解怎么工作的,训练时间长,需要大量计算力,网络结构复杂,需要调整超参数,小数据集容易过拟合。

常见的损失函数

衡量模型参数的函数 Loss/cost/objective/error Function

分类任务

  • 多分类任务

    softmax损失: L = − ∑ i − 1 n y i l o g ( S ( f Θ ( X i ) ) ) L=-\sum_{i-1}^{n} y_ilog(S(f_\Theta(X_i))) L=i1nyilog(S(fΘ(Xi)))

# 交叉熵损失函数
import tensorflow as tf
import tensorflow.keras as keras 

# 设置真实值和预测值
y_true = [[0,1,0],[0,0,1]]
y_pred = [[0.05,0.9,0.05],[0.3,0.2,0.5]]
# 实例化交叉熵损失
cce = keras.losses.CategoricalCrossentropy()
# 计算损失结果
cce(y_true,y_pred)
  • 二分类任务

    L = − y l o g y ^ − ( 1 − y ) l o g ( 1 − y ^ ) L=-ylog\hat{y} - (1-y)log(1-\hat{y}) L=ylogy^(1y)log(1y^) 使用sigmoid激活函数

    # 二分类的交叉熵损失函数
    import tensorflow as tf
    import tensorflow.keras as keras 
    
    # 设置真实值和预测值
    y_true = [[0],[1]]
    y_pred = [[0.9],[0.5]]
    # 实例化交叉熵损失
    cce = keras.losses.BinaryCrossentropy()
    # 计算损失结果
    cce(y_true,y_pred)
    
  • 回归任务

    1. MAE 损失

    2. MSE 损失

    3. smooth L1 损失 s m o o t h L 1 ( x ) = { 0.5 x 2 i f ∣ x ∣ < 1 ∣ x ∣ − 0.5 o t h e r w i s e smooth_{L_1} (x) = \begin{cases} 0.5x^2 \quad &if |x|<1 \\|x| - 0.5 \quad &otherwise \end{cases} smoothL1(x)={0.5x2x0.5ifx<1otherwise

      h = tf.keras.lossses.Huber()
      
深度学习的优化方法
  • 梯度下降算法

    • W i j n e w = W i j o l d − η ∂ E ∂ W i j W_{ij}^{new} = W_{ij}^{old} - \eta\frac{\partial{E}}{\partial{W_{ij}}} Wijnew=WijoldηWijE

    • η \eta η 为学习率

    • BGD SGD MBGD(小批量梯度下降)

      # 梯度下降算法
      # 导入工具包
      import tensorflow as tf
      import tensorflow.keras as keras
      # 实例化
      opt = tf.keras.optimizers.SGD(learning_rate=0.1)
      # 定义要更新的参数
      var = tf.Variable(1.0)
      # 定义损失函数
      loss = lambda:(var**2)/2.0
      # 计算梯度损失,并进行参数更新
      opt.minimize(loss,[var]).numpy()
      # 参数更新结果
      var.numpy()
      

      Epoch / Batch / Iteration

    • epoch:一代训练

    • batch:一批数据

    • iteration:一个batch一次参数更新,一次训练

      梯度下降方式Training Set SizeBatch SizeNumber of Batches
      BGDNN1
      SGDN1N
      Mini-BatchNBN/B +1(针对未整除的情况)
  • 反向传播算法(BP算法)

    该方法与梯度下降算法相结合

    在网络训练过程中,前向传播中的最终结果跟真实值之间存在一定误差,要减小误差,从后往前,依次求各个参数的偏导,就是反向传播。( 复合函数求偏导

    σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1+e^{-z}} σ(z)=1+ez1 求导为: σ ( z ) ( 1 − σ ( z ) ) \sigma(z)(1-\sigma(z)) σ(z)(1σ(z))

  • 计算损失函数 并进行反向传播

  • 计算梯度值

  • 参数更新

  • 更新输出层、隐藏层权重 ;偏置更新

  • until神经网络模型在验证集上的错误率不在下降

  1. 梯度下降优化算法
  • 动量算法(Momentum)

指数加权平均

  • 动量梯度下降算法

计算梯度的指数加权平均数,并利用该值来修改权重

在kears中使用Momentum算法仍使用功能SGD方法,但要设置momentum参数,实现过程如下:

Momentum算法实现

# 导入相应的包
import tensorflow as tf
# 实例化优化方法:SGD指定参数beta=0.9
opt = tf.keras.optimizers.SGD(learning_rate=0.1, momentum=0.9)
# 定义要调整的参数,初始值
var = tf.Variable(1.0)
val0 = var.value()
# 定义损失函数(L2损失函数)
loss = lambda: (var**2)/2.0
# 第一次更新:计算梯度,并对参数进行更新,步长为'- learning_rate * grad'
opt.minimize(loss, [var]).numpy()
val1 = var.value()
# 第二次更新:计算梯度,并对参数进行更新,因为加入了momentum,步长会增加
opt.minimize(loss, [var]).numpy()
val2 = var.value()
# 打印两次更新的步长
print("第一次更新步长={}".format((val0 - val1).numpy()))
print("第二次更新步长={}".format((val1 - val2).numpy()))
-------------------------------运行结果----------------------------------
'''
使用了Momentum梯度下降算法,两次步长逐渐增加
val0-val1=0.10024
val1-val2=0.18001
'''
  • AdaGrad算法

使用一个小批量随机梯度g_t按元素平方的累加变量St.

s t ← s t − 1 + g t ⨀ g t s_t \leftarrow s_{t-1} + g_t\bigodot g_t stst1+gtgt

w t ← w t − 1 − η s t + ϵ ⨀ g t w_t \leftarrow w_{t-1} - \frac{\eta}{\sqrt{s_t+\epsilon}}\bigodot g_t wtwt1st+ϵ ηgt ,其中 η \eta η 是学习率, ϵ \epsilon ϵ 是为了维持稳定性而添加的常数,如 1 0 − 6 10^{-6} 106

# 导入相应的包
import tensorflow as tf
# 实例化优化方法:SGD
opt = tf.keras.optimizers.Adagrad(learning_rate=0.1, initial_accumulator_value=0.1, epsilon=1e-06)
# 定义要调整的参数,初始值
var = tf.Variable(1.0)
# 定义损失函数(L2损失函数)
def loss():
    return(var**2)/2.0
# 计算梯度,并对参数进行更新
opt.minimize(loss, [var]).numpy()
--------------------------------------
print(var)
  • RMSprop算法

对Adagrad算法进行了一点小小修改,将梯度按元素平方做指数加权移动平均

# 导入相应的包
import tensorflow as tf
# 实例化优化方法
opt = tf.keras.optimizers.RMSprop(learning_rate=0.1, rho=0.9)
# 定义要调整的参数,初始值
var = tf.Variable(1.0)
# 定义损失函数(L2损失函数)
def loss():
    return(var**2)/2.0
# 对参数进行更新
opt.minimize(loss, [var]).numpy()
--------------------------------------
print(var.numpy())
  • Adam算法(自适应矩估计) 使用较多(首选)

在RMSprop算法基础上对小批量随机梯度做了指数加权移动平均

参数更新:学习率:需要尝试

​ \beta1=0.9

​ \beta2=0.999

​ \epsilon默认1e-8

# 导入相应的包
import tensorflow as tf
# 实例化优化方法
opt = tf.keras.optimizers.Adam(learning_rate=0.1) # 其它参数使用默认设置
# 定义要调整的参数,初始值
var = tf.Variable(1.0)
# 定义损失函数(L2损失函数)
def loss():
    return(var**2)/2.0
# 对参数进行更新
opt.minimize(loss, [var]).numpy()
-------------------------------------------------
print(var.numpy())

学习率退火

  • 分段常数衰减
  • 指数衰减
  • 1/t 衰减
深度学习的正则化

通过对算法的修改减少泛化误差

  1. L1与L2正则化

L1 对压缩模型很有用,其它情况一般选用L2正则化(直接在LAYERS中指明正则化类型和超参数即可)

  1. Dropout正则化

可以看成机器学习中的集成学习。一般由于单一模型,可以捕获更多的随机性,dropout使得神经网络模型优于正常的模型

rate: 每一个神经元被丢弃的概率

# Dorpout
# 导入相关的包
import tensorflow as tf
import numpy as np
# 定义dropout层
layer = tf.keras.layers.Dropout(0.2, input_shape=(2,)) # dropout层失活概率为0.2
# 定义输入数据
data = np.arange(1,11).reshape(5,2).astype(np.float32)
print(data)

# 对输入数据进行随机失活
outputs = layer(data,training=True)  # 如果设置为false时dropout层不起作用
print(outputs)
  1. 提前停止

在tf.kears中,我们使用callbacks函数实现早期停止:

monitor参数表示监测量;patience参数表示epochs数量,当在这个过程中性能无提升时会停止训练。即虚线后patience个epoch,模型将停止训练,因此没有进一步的改善。

# 提前停止
# 导入相关的包
import tensorflow as tf
import numpy as np
# 定义回调函数
callback = tf.keras.callbacks.EarlyStopping(monitor="loss",patience=3)
# 定义一层的网络
model = tf.keras.models.Sequential([tf.keras.layers.Dense(10)])
# 模型编译
model.compile(tf.keras.optimizers.SGD(),loss='mse')
# 模型训练
history = model.fit(np.arange(100).reshape(5,20),np.array([0,1,0,1,0]), epochs=10, batch_size=1, callbacks=[callback], verbose=1)  # verbose=1代表选择打印日志

h=len(history['loss'])
print(h)
  1. 批标准化

批标准化(BN层,Batch Normalization)

对某一批次数据的神经元的输出进行标准化(均值、方差、标准化),然后再使用变换重构,引入可学习参数$ \gamma / \beta$ 对标准化的结果进行下一步处理:

z ~ ( i ) = γ z n o r m ( i ) + β \tilde{z}^{(i)} = \gamma z_{norm}^{(i)} + \beta z~(i)=γznorm(i)+β

神经网络案例(MNIST案例)

案例实现流程

  • 数据加载
  • 数据处理
  • 模型构建
  • 模型训练
  • 模型测试
  • 模型保存

unit8: 图像专用特殊的数据类型(8位无符号整数),以此方式存储的图像称作8位图像。

案例代码实现

# 导入所需的工具包
import numpy as np
import matplotlib.pyplot as plt
# tf中使用的工具包
import tensorflow as tf
# 构建模型
from tensorflow.kears.models import Sequentiual
# 相关的网络层
from tensorflow.keras.layers import Dense,Dropout,Activation,BatchNormalization
# 导入辅助工具包
from tensorflow.keras import utils
# 正则化
from tensorflow.keras import regularizers

1.数据加载

# 加载数据集
(x_train,y_train),(x_test,y_test) = mnist.load_data()
# 显示数据
plt.figure()
plt.imshow(x_train[1], camp='gray')  #显示索引为1的图片

2.数据处理

# 调整数据维度:每一个数字转换成一个向量
x_train = x_train.reshape(60000,784)
x_test = x_test.reshape(10000,784)

#数据类型调整
x_train = x_train.astype('float32')
x_test=x_test.astype('float32')

# 归一化
x_train = x_train/255
x_test = x_test/255

# 将目标值转换成热编码的形式
y_train = utils.to_categorical(y_train,10)
y_test = utils.to_categorical(y_test,10)

3.模型构建

# 三层全连接网络构建(序列模型)
model = Sequential()
# sequential方式 定义一个空元组 进行一步步a
# 全连接层、两个隐藏层、一个输出层
# 第一个隐层:512个神经元,先激活后BN,随机失活
model.add(Dense(512,activation='relu', input_shape=(784,)))
model.add(BatchNormalization)
model.add(Dropout(0.2))
# 第二个隐层:512个神经元,先BN后激活,随机失活
model.add(Dense(512, kernel_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization)
model.add(Activation='relu')
model.add(Dropout(0.2))
# 输出层
model.add(Dense(10),activation='softmax')

# 展示模型架构
# model.summary()
# utils.plot_model(model)

4.模型编译

设置模型训练使用的损失函数(交叉熵损失)和优化方法(adam),损失函数用来衡量预测值和真实值之间的差异,优化器用来使损失函数达到最优

# 模型编译,指明:损失函数。优化器和评估指标
model.compile(loss= tf.keras.losses.categorical_crossentropy, optimizer = tf.keras.optimizers.Adam(),
             metrics=tf.keras.metrics.Accuracy())

5.模型训练

# 使用fit, 指定训练集, epochs, batch_size, val, verbose
history = model.fit(x_train,y_train,epochs=4,batch_size=128,validation_data=(x_test,y_test),verbose=1)

# 绘制损失函数
plt.figure()
plt.plot(history.history['loss'],lable="train")
plt.plot(history.history['val_loss'],lable="val")
plt.legend()
plt.grid()

# 准确率
plt.figure()
plt.plot(history.history['accuracy'],lable="train")
plt.plot(history.history['val_accuracy'],lable="val")
plt.legend()
plt.grid()

通过tensorboard 监控训练过程:

# 回调函数
tensorboard = tf.keras.callbacks.TensorBoard(log_dir = "./graph")
# 训练
history = model.fit(x_train,y_train,epochs=4,validation_data=(x_test,y_test),batch_size=128,verbose=1,
                    callbacks=[tensorboard])
----------------------------------------------------------------
在终端中打开指定文件夹的目录,运行一下命令:
tensorboard --logdir="./"

6.模型评估与保存

# 模型评估
model.evaluate(x_test,y_test,verbose=1)

# 模型保存
model.save("model.h5")

# 加载模型
loadmodel = tf.keras.models.load_model("model.h5")
loadmodel.evaluate(x_test,y_test,verbose=1)

2.6 卷积神经网络

全连接网络的问题:
  • 需要处理的数据量大,效率低下,耗资源
  • 维度调整过程中,很难保留原有的特征,导致图像处理的准确率不高

CNN网络的构成

卷积层池化层全连接层
提取图像特征降维、防止过拟合输出结果

卷积层

卷积层

核心模块 目的是提取图像特征

I n p u t → F i l t e r → O u t p u t ( F e a t u r e − m a p ) Input \rightarrow Filter \rightarrow Output(Feature-map) InputFilterOutput(Featuremap)

padding

保证卷积过程中特征图大小不变,在原图像周围用0来进行padding

stride

卷积步长 自行设置 移动卷积核

多通道卷积

实际图像都是多通道组成的

input imageFilterFeature Map
5 ∗ 5 ∗ 3 5*5*3 553 3 ∗ 3 ∗ 3 3*3*3 333 3 ∗ 3 3*3 33

多卷积核卷积

每个卷积核学习不同的特征,对应产生多个channelFeature Map

有多少个卷积核,就产生有多少个通道的特征图

特征图大小

输入体积大小 H 1 ∗ W 1 ∗ D 1 H_1*W_1*D_1 H1W1D1

四个超参数:卷积核数K 卷积核大小F 步长S 零填充大小P

输出体积大小 H 2 ∗ W 2 ∗ D 2 H_2*W_2*D_2 H2W2D2

  • H 2 = ( H 1 − F + 2 P ) / S + 1 H_2 = (H_1-F+2P)/S+1 H2=(H1F+2P)/S+1
  • W 2 = ( W 1 − F + 2 P ) / S + 1 W_2 = (W_1-F+2P)/S+1 W2=(W1F+2P)/S+1
  • D 2 = K D_2=K D2=K

在tf.keras中卷积核的实现:

tf.keras.layers.Conv2D(
		filters, kernel_size, strides=(1, 1), padding='valid',activation=None)

主要参数说明如下:

参数描述
filters卷积过滤器的数量,对应输出特征图的通道数
kernel_size过滤器filter的大小
strides步长
paddingvalid:在输入周围不进行padding; same: padding后使输出特征图和输入特征图形状相同
activation激活函数

池化层(Pooling)

降低后续输入维度,缩减模型大小,提高计算速度,防止过拟合主要对特征图进行下采样(subsampling)操作

  • 最大池化 (取窗口中的最大值作为输出)

    tf.keras.layers.MaxPool2D()
    
  • 平均池化 (取窗口中的均值作为输出)

    tf.keras.layers.AveragePooling2D()
    

全连接层

位于CNN网络的末端,进行分类或回归的操作。

在tf.keras中使用 tf.keras.dense实现。

卷积神经网络的构建

LeNet-5处理mnist数据集

输入二维图像,经过两次卷积池化,经过全连接,最后softmax分类

# 导入相关包
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.datasets import mnist

# 数据集加载
(train_images,train_lables),(test_images,test_lables) = mnist.load_data()

# 数据处理(图像个数、高、宽、通道数)
# 维度调整
train_images = tf.reshape(train_images,		(train_images.shape[0],train_images.shape[1],
     
                                             train_images.shape[2],1))  # Tensorshape ([60000,28,28,1])
-----------------------------------------------------------------------------------------


# 模型构建
net = keras.models.Sequential([
    # 卷积层:6个5*5的卷积 sigmoid
    keras.layers.Conv2D(filters=6, kernel_size=5, activation='sigmoid',input_shape=(28,28,1)),
    # maxpooling
    keras.layers.MaxPool2D(pool_size=2, strides=2),
    # 卷积层:16个5*5的卷积核 sigmoid
    keras.layers.Conv2D(filters=16, kernel_size=5, activation='sigmoid'),
    # maxpooling
    keras.layers.MaxPool2D(pool_size=2,strides=2),
    # 维度调整
    keras.layers.Flatten()
    # 全连接层, sigmoid
    keras.layers.Dense(120,activation='sigmoid')
    # 全连接层, sigmoid
    keras.layers.Dense(84,activation='sigmoid')
    # 输出层 softmax
    keras.layers.Dense(10,activation='softmax')
])
-------------------------------------
net.summary()  # 查看网络结构
keras.utils.plot_model(net)
-------------------------------------


# 模型编译
# 设置优化器、损失函数、评价指标
net.compile(optimizer=keras.optimizers.SGD(learning_rate = 0.9),
            loss=keras.losses.sparse_categorical_crossentropy,metrics=['accuracy'])
				# 未进行热编码的时候,就选用sparse交叉熵损失函数

# 模型训练
net.fit(train_images,train_lables, epochs=5, batch_size=128, verbose=1)


#模型评估
net.evaluate(test_images,test_lables, verbose=1)

残差网络ResNet

随着网络层数的增加,优化效果反而越差,测试数据和训练数据的准确率反而降低了,针对这一问题,何恺明提出残差网络

构建残差块

# 导入工具包
import tensorflow as tf
from tensorflow.keras import layers,activations

# 残差块
class Residual(keras.Model):
    # 定义网络结构
    def __init__(self,num_channels,use_1x1conv=False,strides=1):
        super(Residual,self).__init__()
        # 卷积层
        self.conv1 = layers.Conv2D(num_channels, padding='same', kernel_size=3, strides=strides)
        # 卷积层
        self.conv2 = layers.Conv2D(num_channels, kernel_size=3, strides=strides)
        # 是否使用1x1卷积
        if use_1x1conv:
            self.conv3 = layers.Conv2D(num_channels, kernel_size=1, strides=strides)
        else:
            self.conv3 = None
        #BN层
        self.bn1 = layers.BatchNoramlization()
        self.bn2 = layers.BatchNoramlization()
    # 定义前向传播过程
    def call(self,x):
        Y = activations.relu(self.bn1(self.conv1(x)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            x = self.conv3(x)
        output = activations.relu(Y+x)
        return outputs

Resnet-18实现

# 残差模块
class ResnetBlock(tf.keras.layers.Layer):
    # 定义所需的网络结构
    def __init__(self,num_channels, num_res, first_block=Flase):
        super(ResnetBlock,self).__init__()
        # 存储残差块
        self.listLayers=[]
        # 遍历所有的残差数目生成模块
        for i in range(num_res):
            # 如果是第一个残差块,而且不是第一个模块时,
            if i == 0 and not first_block:
                self.listLayers.append(Residual(num_cahnnels,use_1x1conv=True, strides=2))
            else:
                self.listLayers.append(Residual(num_cahnnels))
    # 定义前向传播过程:
    def call(self,X):
        for layer in self.listLayers.layers:
            X = layer(X)
        return X
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值