TensorFlow深度学习-第六章

Char6-神经网络neural networks

本章中主要讲解的内容包含:

  • 神经模型的简介

  • 感知机模型

  • 全连接网络

  • 神经网络介绍

  • 常见的激活函数

  • 输出层设计方案

  • 误差类型

  • 神经网络类型

image

机器学习的目的是找到一组良好的参数​,使得其表示的数学模型能够很好地从训练数据集中学到映射关系​

神经元模型

MP-神经模型

神经网络是由具有自适应性的简单单元组成的并行互连的网络。下图是经典的MP-神经元模型。

  • 当前神经元接收来自n个其他的神经元传递过来的输入信号x_i
  • 这些信号带着自己的连接权重w_i一起过来
  • 当前神经元的总输入:\sum^n_{i=1}x_iw_i
  • 将神经元的总输入和阈值\theta进行比较,再通过激活函数进行处理并输出

y = f(\sum^n_{i=1}w_ix_i-\theta)

image

神经网络就是包含了多个参数的数学模型,这个模型就是若干个参数。

y_i = f(\sum_{i=1}w_ix_i-\theta _i)

感知机

感知机简介

简单的两层神经网络,感知机是线性分类判别模型。

  • 输入层接收来自外界的出入信号x=[x_1,…,x_n],传递给输出层
  • 输入信号有自己的权值[w_1,…,w_n]
  • 输出层是MP-神经元模型(也叫阈值逻辑单元)
  • 感知机还有自己的偏置b

z=w_1x_1+w_2x_2+...+w_nx_n+b

image

上式的向量形式为

z=w^T \cdot x+b
上面的z表示感知机的净活性值,加上激活函数之后变成活性值:
a=\sigma(z)=\sigma(w^T \cdot x+b)
激活函数可以是阶跃函数,也可以是符号函数;一般选用的符号函数sign(x)

image

感知机模型

感知机模型就是上文中的

sign(w^Tx+b)=0

image

为了方便,直接将模型改成:
sign(w\cdot x+b)=0
wx+b是一个n维空间中的超平面S,其中w是超平面的法向量,b是超平面的截距,这个超平面将特征空间划分成两部分,位于两部分的点分别被分为正负两类,所以超平面S称为分离超平面。

对于二分类的正确分类有:

  • 正例输出y_i = +1, w\cdot x_i+b>0
  • 负例输出y_i = -1, w\cdot x_i+b<0

那么,输入空间的某个点x_0S的距离为
\frac{1}{||w||}|w\cdot x_0+b|
|wx+b|叫函数间隔,除模长之后叫几何间隔,几何间隔可以认为是物理意义上的实际长度。

对于误分类点有:

  • 输出y_i = -1, w\cdot x_i+b>0
  • 输出y_i = +1, w\cdot x_i+b<0

那么总有:
-y_i(w\cdot x_i+b) > 0

因此误分类点x_i到超平面的距离总是:
-\frac{1}{||w||}y_i(w\cdot x_i+b) > 0
全部的误分类点到超平面的距离是
-\frac{1}{||w||}\sum_{x_i\in M}y_i(w\cdot x_i+b) > 0
不考虑前面的系数,得到感知机sign(w\cdot x)的损失函数
L(w,b)=-\sum_{x_i \in M}y_i(w \cdot x_i+b)

感知机算法

1. 初始化参数w_0,b_0
2. 循环过程:
    3. 在训练集中选取数据(x_i,y_i)
    4. 计算感知机的输出a=sign(w^Tx_i+b)
    5. 如果输出a和真实值y_i不等:
            6. 更新w
            7. 更新b
   8.转至步骤2,直至训练集中没有误分类点
9. 输出w,b

过程解释:如果一个误分类点在超平面的一侧,调整两个参数,使得超平面向着该误分类点移动,以此来减少误分类点的和分离超平面的距离,直至超平面将该点正确分类。

全连接层

感知机模型的不可导限制了它的潜力,全连接层将不连续的阶跃函数换成了平滑连续的激活函数,通过堆叠多层网络实现。

每个输出节点和全部的输出相连接的网络层称之为全连接层

下图中3个输出,2个神经元,2个输出节点。

image

通过矩阵表示上述网络层的运算:
O=X@W+b

image

  • 输入xshape[b,d_{in}],b是样本数量,d_{in}是输入节点数
  • 权值矩阵W,其shape[d_{in}, d_{out}],其中d_{out}是输出节点数
  • 偏置b的shaped_{out}

如果是2个样本参与运算,𝒙^1 = [𝑥^1_1, 𝑥^1_2, 𝑥^1_3],𝒙^2 = [𝑥_1^2, 𝑥^2_2, 𝑥^2_3]

image

输出矩阵O的为

张量实现

定义好权值张量和偏置张量,利用批量矩阵相乘函数`tf.matmul()``

"""
输入X矩阵为𝑏=2个样本(2行,2个样本)
每个样本的输入特征长度为𝑑𝑖𝑛 = 784(784个属性特征)
输出节点数为𝑑𝑜𝑢𝑡 = 256
定义权值矩阵W的shape为[784,256],并采用正态分布初始化W;
偏置向量b的shape定义为[256]
在计算完X@W后相加即可,最终全连接层的输出O的shape为[2,256],即2个样本的特征,每个特征长度为 256。
"""

x = tf.random.normal([2,784])
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
o1 = tf.matmul(x, w1) + b1
o1 = tf.nn.relu(o1)

层方式

通过layers.Dense(units, activation)

import tensorflow as tf
x = tf.random.normal([4, 28*28])
from tf.keras import layers
# 创建全连接层,指定输出节点数和激活函数
fc = layers.Denss(512, activation=tf.nn.relu)  # 激活函数也可以不指定
h1 = fc(x)  # 通过fc完成一次全连接的计算
fc.kernal   # 获取权值矩阵
fc.bias   # 获取Dense类的偏置
fc.trainable_variables   # 返回的是待优化参数的列表
fc.variables  # 返回所有的参数列表

神经网络

保证前一层的输出节点数与当前层的输入节点数匹配,即可堆叠出任意层数的网络。

image

张量实现

# 定义隐藏层1的张量
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))

# 定义隐藏层2的张量
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))

# 定义隐藏层3的张量
w3 = tf.Variable(tf.random.truncated_normal([128,64], stddev=0.1))
b3 = tf.Variable(tf.zeros([64]))

# 输出层张量
w4 = tf.Variable(tf.random.truncated_normal([64,10], stddev=0.1))
b4 = tf.Variable(tf.zeros([10]))

"""
计算时,只需要按照网络层的顺序,将上一层的输出送入当前层的输入即可,重复直至 最后一层,将输出层的输出作为网络的输出:
"""

with tf.GradienTape() as tape:   # 必须将前向计算过程放入tf.GradienTape()环境中,利用 GradientTape 对象的 gradient()方法自动求解参数的梯 度,并利用 optimizers 对象更新参数
  # x: [b, 28*28]
  # 隐藏层 1 前向计算,[b, 28*28] => [b, 256]
  h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0],256])
  h1 = tf.nn.relu(h1)
  
  h2 = h1@w2 + b2
  h2 = tf.nn.relu(h2)
  
  h3 = h2@w3 + b3
  h3 = tf.nn.relu(h3)
  
  # 输出层前向计算,[b, 64] => [b, 10]
  h4 = h3@w4 + b4

层方式

通过layer.Dense类来实现

# 方式1:将每个网络分别建立出来,并且指定激活函数
x = tf.random.normal([4,28*28])
fc1 = layers.Dense(256, activation=tf.nn.relu)
fc2 = layers.Dense(128, activation=tf.nn.relu)
fc3 = layers.Dense(64, activation=tf.nn.relu)
fc4 = layers.Dense(10, activation=None)

# 依次通过各个层
x = tf.random.normal([4,28*28])
h1 = fc1(x)
h2 = fc2(h1)
h3 = fc3(h2)
h4 = fc4(h3)  # 通过输出层得到网络输出

# 通过Sequential容器来进行封装
x = tf.random.normal([4,28*28])
model = layers.Sequential({
  layers.Dense(256, activation=tf.nn.relu),   # 创建隐藏层 1
  layers.Dense(128, activation=tf.nn.relu) , # 创建隐藏层 2
  layers.Dense(64, activation=tf.nn.relu) , # 创建隐藏层 3
  layers.Dense(10, activation=None) , # 创建输出层
})

out = model(x)

激活函数

Sigmoid

Sigmoid 函数也叫Logistic 函数,tf.nn.sigmoid(x)实现
Sigmoid := \frac{1}{1+e^{-x}}
在输入值较大或者较小的时候都是很容易出现梯度弥散现象。

image

ReLU

  • 单边抑制
  • 相对宽松的边界
  • 通过tf.nn.relu实现
image
image

LeakyReLU

ReLU 函数在𝑥 < 0时梯度值恒为 0,也可能会造成梯度弥散现象,为了克服这个问 题,LeakyReLU函数被提出。通过tf.nn.leaky_relu来实现

image
  • ​,上述函数退化为​

  • ​ ,当​能够获得较小的梯度值​

    image

    Tanh

    Tanh函数能够将​的输入压缩到[-1,1]之间,定义为

    tanh 激活函数可通过 Sigmoid 函数缩放平移后实现。通过tf.nn.tanh()实现

    image

输出层设计

四种设计

根据输出值的区间来进行分类:

  • o \in R^d输出属于整个实数区间,如正弦函数曲线预测、年龄的预测、股票的走势预测等
  • o \in [0,1]输出值落在[0,1]之间,如图片的像素归一化到[0,1]之间
  • o \in [0,1], \sum_io_i=1,输出值落在[0,1]之前,且所有的的输出值之和为1。通过添加Softmax函数来实现功能
  • o \in [-1,1]输出值在[-1,1],使用tf.tanh(x)来实现
    image

softmax函数

Dense层类似,Softmax函数还可以作为网络层来使用。通过类layers.Softmax(axis=-1)

输入值较大,会出现溢出现象。同时实现Softmax函数和交叉熵损失函数,接口为tf.keras.losses.categorical_crossentropy(y_true, y_pred, from_logits=False)

  • y_true 代表了one-hot 编码后的真实标签
  • y_pred 表示网络的预测值
    • from_logits = True 时,y_pred 表示须为未经过 Softmax函数的变量 z
    • from_logits = False 时,y_pred 表示为经过Softmax 函数的输出。
z = tf.random.normao([2,10])
y_onehot = tf.constant([1,3])
y_onehot = tf.one_hot(y_onehot, depth=10)
# 输出层未使用Softmax函数,设置成True
loss = keras.losses.categorical_crossentropy(y_onehot,z,from_logits=True)
loss = tf.reduce_mean(loss)

# 可以利用 losses.CategoricalCrossentropy(from_logits)类方式同时实现 Softmax与交叉熵损失函数的计算
ctiteon = keras.losses.CategoricalCrossentropy(from_logits=True)
loss = criteon(y_onehot, z)

误差类型

均方差

均方差MSE,mean squared error:将输出向量和真实向量映射到笛卡尔坐标系上的两个点,计算两点之间的欧式距离(平方)
MSE=\frac{1}{d_{out}}\sum^{d_{out}}_{i=1}(y_i-o_i)^2

  • MSE的值总是大于等于0;当其为0表示输出值等于真实标签
  • 主要用于回归问题
o = tf.random.normal([2,10]) # 构造网络
y_onehot = tf.constant([1,3]) # 真实输出
y_onehot = tf.one_hot(y_onehot, depth=10)
loss = keras.losses.MSE(y_onehot, o)  # 计算均方差,返回的是每个样本的均方差
loss = tf.reduce_mean(loss)  # 计算batch均方差

# 通过类的方式实现
criteon = keras.losses.MeanSquaredError()
loss = criteon(y_onehot, o)

交叉熵

熵是用来衡量信息的不确定性。熵越大,代表不确定越大,信息量越大。

假设数据集D中第k类样本占的比例是p_k(k=1,2,…,K),则D信息熵定义为:
Ent(D)=-\sum^K_{k=1} p_klog_2{p_k}
比如:某个事件发生的结果有3中情形,出现的概率分别是:

结果1 结果2 结果3
\frac{1}{3} \frac{1}{2} \frac{1}{6}

信息熵的计算如下:

Ent=-(\frac{1}{3}log_2\frac{1}{3}+\frac{1}{2}log_2\frac{1}{2}+\frac{1}{6}log_2\frac{1}{6})
交叉熵 Cross Entropy 的定义为
H(p,q)= -\sum_{i=0}p(i)log_2q(i)
通过变换,交叉熵可以分解为 p 的熵𝐻(𝑝)与 p,q 的 KL 散度(Kullback-Leibler Divergence)的和
H(p,q)=H(p)+D_{KL}(p|q)
其中 KL 定义为
𝐷_{𝐾𝐿}(𝑝|𝑞) = ∑_{x\in X} 𝑝(𝑥)𝑙𝑜𝑔 \frac{𝑝(𝑥)}{q(x)}
KL散度是衡量连个分布之间距离的指标。交叉熵和KL散度都是不对称的。
H(p,q) \neq H(q,p) \\D_{KL} (p|q) \neq D_{KL}(q|p)

神经网络类型

  • 卷积神经网络CNN
  • 循环神经网络RNN
  • 注意力网络Transformer
  • 图神经网络GCN
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容