深度学习_06_2_神经网络与全连接层_全连接层&输出方式&误差计算

06_2_神经网络与全连接层_全连接层&输出方式&误差计算

全连接层

deep learning最基本的层:全连接层,也就是线性层

Outline

  • Matmul 矩阵形式
  • ->迭代到 Neural Network 神经网络结构
  • ->引入 Deep Learning 概念
  • ->最后实现一个 Multi-Layer

Recap

out = f(X@W+b)

f为非线性因子,一般指relu函数或者SIGMOD函数

X@W+b

h 0 0 = x 0 0 ∗ W 0 0 + x 1 0 ∗ W 0 1 + x 2 0 ∗ W 0 2 h_0^0 = x_0^0*W_0^0 + x_1^0*W_0^1 + x_2^0*W_0^2 h00=x00W00+x10W01+x20W02。相当于下图的连线,还有一个 b 0 b_0 b0没有画出来。

σ \sigma σ符号统指激活函数,左边是输入,右边是输出。

在这里插入图片描述

Black Magic!

上标表示层的概念。

在这里插入图片描述

Layers

输入层、隐藏层、输出层。

一层包括了权值W、偏置b、激活函数 σ \sigma σ等概念。

Here comes Deep Learning!

过去叫Neural Network,一般是3~5层。

在这里插入图片描述

现在大概是1200层,是过去3~5层不停地堆叠。

大概2000年代,更多的是工程paper,很难解释其中的原理机制。目前还是和neural network本质上没有什么区分,更多的是深度的增加。

在这里插入图片描述

Why?

在过去80年代,计算能力弱。

在这里插入图片描述

Heroes

  • BigDATA 大量的图片、音频、视频数据
  • ReLU函数,比较好的解决了梯度离散的现象
  • Dropout
  • BatchNorm
  • ResNet 10~20层->100++的可行性
  • Xavier Initialization 初始化方案
  • Caffe/TensorFlow/PyTorch 深度学习加速库使一般人更方便

Fully connected layer

tf.keras是TensorFlow内部的keras,它是TensorFlow对keras的实现,keras本质上是一种api的协议,TensorFlow对keras有具体的实现,位于tf.keras下。

tf.keras.layers.Dense(512) #512:输出的维度

输入的维度会自动识别,在例子中,W是[784,512],b是[512]

在这里插入图片描述

w和b是通过build创建的,并且可以多次创建。

input_shape=(None,4)。None为batch,4为输入的维度

刚刚上图没有调用build函数,我们在调用net(x)实例的时候,它会自动判断如果没有w和b,会自动调用build函数。

在这里插入图片描述

input的shape和创建的shape不一致的例子:

build的时候输入的维度是20维,喂的是12维,这样会产生error。需要给正确的shape。

现在讲解的是单层的Dense层,也就是一个全连接层,每个输出节点都和每个输入节点相连接,也就是Dense,稠密。

在这里插入图片描述

Multi-Layers

如果要创建多层,我们只需要创建容器:

keras.Sequential([layer1,layer2,layer3])

在这里插入图片描述

具体的实现:

输入是3,变成2维,再变成2维,再变成2维。

这里input_shape是3

model.summary() 其实是print的意思,返回模型的信息。

model.trainable_variables 会返回 w1,b1,w2,b2,w3,b3

在这里插入图片描述

实战:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
from tensorflow import keras

x = tf.random.normal([2,3])

#网络结构
model = keras.Sequential([
    keras.layers.Dense(2,activation='relu'),
    keras.layers.Dense(2,activation='relu'),
    keras.layers.Dense(2)
])
model.build(input_shape=[None,3])
model.summary()
#第一层的8是因为输入为3,输出为2,一共3*2个w,再加上2个b;后面两层类似
# Model: "sequential"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #
# =================================================================
# dense (Dense)                multiple                  8
# _________________________________________________________________
# dense_1 (Dense)              multiple                  6
# _________________________________________________________________
# dense_2 (Dense)              multiple                  6
# =================================================================
# Total params: 20
# Trainable params: 20
# Non-trainable params: 0
# _________________________________________________________________

for p in model.trainable_variables:
    print(p.name,p.shape)
# dense/kernel:0 (3, 2)
# dense/bias:0 (2,)
# dense_1/kernel:0 (2, 2)
# dense_1/bias:0 (2,)
# dense_2/kernel:0 (2, 2)
# dense_2/bias:0 (2,)

输出方式

Outline

原因:因为神经网络是面向不同的应用的,不同的应用有不同的输出的范围的要求

有时候是实数集
有时候是概率的输出
有些概率还要求输出和是1
输出在-1~1

  • y ∈ R d y \in R^d yRd
  • y i ∈ [ 0 , 1 ] y_i \in [0,1] yi[0,1]
  • y i ∈ [ 0 , 1 ] , ∑ i = 0 y y i = 1 y_i \in [0,1], \sum_{i=0}^y y_i = 1 yi[0,1],i=0yyi=1
  • y i ∈ [ − 1 , 1 ] y_i \in [-1,1] yi[1,1]

1. y ∈ R d y \in R^d yRd

linear regression x@w+b,如果要求正数,可以简单地加relu激活函数。一般来说最后一层是不加激活函数的,不加激活函数的输出值叫logits

分类问题,一般是用0~1的输出范围,但是MSE误差的话也可以不加这样范围的约束,直接用它去逼近。

实数集做输出的话,一般来讲不需要做额外的处理。

在这里插入图片描述

2. y i ∈ [ 0 , 1 ] y_i \in [0,1] yi[0,1]

  • 二分类,一般有2种设定,第一种是输出节点只有1个,大于0.5判定为1;小于0.5判定为0。另外一种设定是把二分类也理解为多分类的问题,两个输出节点,P(y=0|x)和P(y=1|x),和其他多分类问题没有什么区别。
  • 图片的生成,rgb是0~255范围压缩到0~1的范围,利于神经网络的优化,所以生成以后也是0~1的输出,表达是灰度或rgb的信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zTNX8I44-1615782848391)(06_2_神经网络与全连接层_全连接层&输出方式&误差计算.assets/image-20210307210845874.png)]

sigmoid函数,它的x范围是整体实数空间,y是从0~1。

通过out' = sigmoid(out),原来out是整个实数范围,变成0~1的范围。它不仅仅是激活函数的功能,更多的是输出值范围压缩的功能。

在这里插入图片描述

sigmoid

具体形式:

f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1

tf.sigmoid

在这里插入图片描述

把很宽的实数空间重映射到0~1的空间去,对于图片,希望能把它压缩到RGB的表示范围,也就是0~1

在这里插入图片描述

3. y i ∈ [ 0 , 1 ] , ∑ i = 0 y y i = 1 y_i \in [0,1], \sum_{i=0}^y y_i = 1 yi[0,1],i=0yyi=1

对MNIST,10分类属于0~9,给出数据集中的任何一张图片,它肯定是0~9之间的1类,同时要求输出之和的 ∑ i ∈ [ 0 , 9 ] P ( y = i ∣ x ) = 1 \sum_{i \in [0,9]} P(y=i|x) = 1 i[0,9]P(y=ix)=1

sigmoid函数并没有实现这个功能。

所有概率之和为1的功能,另外1个函数叫做softmax。

在这里插入图片描述

softmax

一般,没有加激活函数的输出叫Logits。

softmax,把强的变得更强,把弱的变得更弱。在分类中使用的非常广泛,交叉熵也使用了softmax。

在这里插入图片描述

Classification

有个logits,有1个实例,10个分类,值在-2~2之间。

prob = tf.nn.softnax(logits,axis=1)

每个点代表P(y=i|x),因此名字为prob

在这里插入图片描述

4. y i ∈ [ − 1 , 1 ] y_i \in [-1,1] yi[1,1]

tanh:Sigmoid函数通过平移,在y的轴上进行放大,0~2,然后再下移,变成-1~1的空间。

在这里插入图片描述

例子:

在这里插入图片描述

误差计算(损失函数)

Outline

  • MSE 均方差
  • Cross Entropy Loss 专门应对于分类问题的误差计算
  • Hinge Loss 用于SVM支持向量机中Maximum margin多一些

∑ i m a x ( 0 , 1 − y i ∗ h θ ( x i ) \sum_i max(0,1-y_i * h_\theta(x_i) imax(0,1yihθ(xi)

MSE

平方差的和。输出值和真实值的差-的平方-累加,再average( 1 N \frac{1}{N} N1)(可选,一般加)。-》一般来说,加learning rate的目的就是要衰减更新步长,因为我们计算的梯度往往是比较大的数值,所以才需要衰减更新的步长,如果loss计算比较大,梯度往往也比较大,所以有average操作。

N一般指batch,实际上它们往往还会在向量维度上进行average,loss不仅仅除以N,还会除以10(10类、vector length)。也就是说它是求一个sample的输出node的平均的average loss。

batch和10除不除都不是强制的。

2范数(2-norm)和MSE有些相似,在某种程度上是可以相互转换的。

在这里插入图片描述

具体的实例:

三种方式都可以求出MSE

loss1 = tf.reduce_mean(tf.square(y-out)) #按上图的第一个公式
loss2 = tf.square(tf.norm(y-out)) / (5*4) #按第二个公式,利用范数的平方除以(N*类别)
loss3 = tf.reduce_mean(tf.losses.MSE(y-out)) #利用tf.losses.MSE(a,b)求出shape为[b]的Tensor,再利用reduce_mean求出loss

在这里插入图片描述


Entropy(熵)

不确定性,事件发生的概率的确定性和不确定性是比较抽象的概念,同时需要数据来量化不确定度。

E n t r o p y = − ∑ P ( i ) log ⁡ P ( i ) Entropy = - \sum P(i)\log P(i) Entropy=P(i)logP(i)

因此,有以下公式,通过发生的概率P(i)乘以logP(i)求和,加上符号。这个数值用来衡量某个分布的不确定度(惊喜度)。当熵越小的时候,意味着确定度越大,事件发生的确定性更高。

因为概率的数值范围为0~1,logP(i)为负数,P(i)为正数,前面有负号,因此整个的值>=0,再求和。

当猫和狗的概率为0和1,因为熵越低,表示越确定,因此得到的熵接近于0
当猫和狗的概率都为0.5,说明非常不确定,不确定性很高,熵远远大于0

在这里插入图片描述

越有把握,熵越接近于0

Lottery(彩票) - 例子

都是0.25,熵很高
0.1,0.1,0.1,0.7,熵为1.35
0.97,熵为0.24

下面为手写公式计算熵

在这里插入图片描述

Cross Entropy交叉熵

是指两个分布之间信息衡量的标准, H ( p , q ) = − ∑ p ( x ) log ⁡ q ( x ) H(p,q) = -\sum p(x) \log q(x) H(p,q)=p(x)logq(x)

也可以推导成 H ( p , q ) = H ( p ) + D K L ( p ∣ q ) H(p,q) = H(p) + D_{KL} (p|q) H(p,q)=H(p)+DKL(pq),其中 D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq),中文名叫散度,这个是衡量p和q之间的距离。

当p=q, D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq)为0,H(p,q) = H§。

如果p是one-hot encoding,我们知道y一般是one-hot encoding过的,所以y的分布可能是[0,1,0…],它表示label为1的概率是100%,label是其他的概率是0。那么如果把y的分布理解为p,那么对于 h ( p : [ 0 , 1 , 0 ] ) = − 1 l o g 1 = 0 h(p:[0,1,0]) = -1log1 = 0 h(p:[0,1,0])=1log1=0。也就是确定性非常大,对其他的概率是不可能的。

那么再看交叉熵,如果把p当做one-hot encoding放在前面的话,q是我们的output,也就是prob。这样利用公式2, H ( [ 0 , 1 , 0 ] , [ p 0 , p 1 , p 2 ] ) = 0 + D K L ( p ∣ q ) = − 1 l o g q 1 H([0,1,0],[p0,p1,p2]) = 0+D_{KL}(p|q) = -1logq_1 H([0,1,0],[p0,p1,p2])=0+DKL(pq)=1logq1

因此对于one-hot encoding来说,p和q之间的交叉熵其实退化为一个 D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq) D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq)的最小值就是p=q的时候,这也说明了我们为什么使用h(p,q)作为loss的时候是合理的,当针对分类问题来说,我们希望预测的分布q: prob(预测的分布),p: [0,1,0,…](真实的分布),我们希望q能逼近于真实的分布p,那么什么时候能逼近?也就是交叉熵的最小值 D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq)等于0的时候,也就是p和q完全相等的时候,那就意味着如果预测q的分布能够真实的p的分布一样的话,那么这个时候的交叉熵就退化为 D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq),也就退化为0,也是loss取的最小的时候,输出q和真实p是完全一样的,这时候的w参数就是最好的参数。这样我们证明了采用交叉熵作为loss得到的最优化的值刚好是使得 D K L ( p ∣ q ) D_{KL}(p|q) DKL(pq)等于0的时候,也就是p=q的时候。

在这里插入图片描述

具体分类问题的交叉熵的求解方法:

Binary Classification二分类

有两种设计格式:

第1个是把二分类当做多分类求解,比如第1个节点表示P(y=0|x),第2个节点表示P(y=1|x),这个时候和二、三…分类完全一样。

第2个只有一个输出节点,这个节点P(y=1|x),那么P(y=0|x) = 1 - P(y=1|x)。这种方式减少了参数量(没太大关系)。

在这里插入图片描述

Single output(1个节点)

D K L ( p ∣ q ) = − 1 l o g q 1 D_{KL}(p|q) = -1logq_1 DKL(pq)=1logq1的原因:因为 D K L ( p ∣ q ) = − ∑ p i log ⁡ q i D_{KL}(p|q) = -\sum p_i\log q_i DKL(pq)=pilogqi p i p_i pi等于0,那么 p i log ⁡ q i p_i\log q_i pilogqi就等于0, p i p_i pi不等于0的时候,就等于1,10个数字(举例)间只有1个这样的项,因此以上。(p=1时候的q)
l o s s = H ( p , q ) p : o n e − h o t = 0 + D K L ( p ∣ q ) = − 1 log ⁡ q i loss = H(p,q) \quad p:one-hot\\ = 0 + D_{KL}(p|q)\\ = -1\log q_i loss=H(p,q)p:onehot=0+DKL(pq)=1logqi
要最小化loss,就要最大化 q i q_i qi,q表示当前节点的label是i的话,在i号节点输出的概率q,比如说 q ( y = i ∣ x ) q(y=i|x) q(y=ix)越大越好,最大的可能值是1,这个时候就和p完全一样了,因为p的真实节点[0,1,0,…]也在这个下标,若q的预测值是[0,1,0,…],这个时候p和q完全相等,loss等于0。

以上我们推导了对于一个**多分类(上图类型1)**问题的loss的计算方式。

在这里插入图片描述

对于一个**单号节点(上图类型2)**输出的二分类问题的求解:

展开,首先因为对于单分类问题来说,它不是one-hot encoding,因为单一的输出是没有one-hot encoding的,所以,
H ( P , Q ) = − P ( c a t ) log ⁡ Q ( c a t ) − P ( ! c a t ) l o g ( Q ( ! c a t ) ) 因 为 二 分 类 P ( ! c a t ) = 1 − P ( c a t ) , q 同 理 = − P ( c a t ) log ⁡ Q ( c a t ) − ( 1 − P ( c a t ) ) log ⁡ ( 1 − Q ( c a t ) ) = − ( y l o g ( p ) + ( 1 − y ) l o g ( 1 − p ) ) H(P,Q) = -P(cat)\log Q(cat) - P(!cat)log(Q(!cat))\\ 因为二分类 \quad P(!cat)=1-P(cat), q同理\\ =-P(cat)\log Q(cat) - (1-P(cat))\log(1-Q(cat))\\ =-(ylog(p) + (1-y)log(1-p)) H(P,Q)=P(cat)logQ(cat)P(!cat)log(Q(!cat))P(!cat)=1P(cat),q=P(cat)logQ(cat)(1P(cat))log(1Q(cat))=(ylog(p)+(1y)log(1p))
p是神经网络输出节点的概率值,因此对于一个二分类的问题来说,y已知,p已知,我们可以简单的把loss归化为交叉熵H(P,Q)。当y(cat)=1,前项存在,后项不存在,为 − y l o g ( p ) -ylog(p) ylog(p);当y(cat)=0,则相反,为 − ( 1 − y ) l o g ( 1 − p ) -(1-y)log(1-p) (1y)log(1p)

在这里插入图片描述

然后我们看更加通用的多分类,也就是多号输出节点(0,1,2,…9):

Classification

根据二分类中的多分类推导情况,可知:
H ( [ 0 , 1 , 0 ] , [ p 0 , p 1 , p 2 ] ) = 0 + D K L ( p ∣ q ) = − 1 log ⁡ q 1 H([0,1,0],[p_0,p_1,p_2]) = 0 + D_{KL}(p|q)= -1\log q_1 H([0,1,0],[p0,p1,p2])=0+DKL(pq)=1logq1

也就是当前x=1的话,其实概率就为-logP(y=1|x),这个节点的概率希望你越大越好,比如q为 q 1 q_1 q1的时候 log ⁡ q 1 \log q_1 logq1等于0,这时候loss取最小值。

在这里插入图片描述

具体情况:

这里是五分类,真实是一只小狗。图片x=0。

第一种输出 Q 1 = [ 0.4 , 0.3 , 0.05 , 0.05 , 0.2 ] Q_1 = [0.4,0.3,0.05,0.05,0.2] Q1=[0.4,0.3,0.05,0.05,0.2],可以判定预测为狗的概率最大,输出为狗,只是没有很大的置信度。这样网络不算太好,但是预测对了。
这样情况的loss(也是交叉熵),为0.916,loss(交叉熵)较大。

如果输出为[0.98…],这个时候的loss(交叉熵)是0.02,较小。

通过这样的情况,就可以更新参数,直到满足loss足够小。

在这里插入图片描述

更多的计算实例:

Categorical Cross Entropy(分类问题的交叉熵)

tf.losses.categorical_crossentropy([0,1,0,0],[0.25,0.25,0.25,0.25])

第一个参数是y_true(one-hot),第二个是预测值prob(predict)。
四个例子表示不同预测情况与肯定度的交叉熵(loss)值各不相同(正确且肯定的交叉熵小,不确定且肯定的交叉熵大……),也说明了Cross Entropy是合理的。

在这里插入图片描述

例子:

交叉熵有两种形式:

  1. tf.losses.categorical_crossentropy([0,1,0,0],[0.25,0.25,0.25,0.25])是函数形式。
  2. 还有一种类的形式,criteon = tf.keras.losses.CategoricalCrossentropy(),首先声明类,然后对对象进行一个调用(对类实例criteon传入参数[y],[predict])。

第三部分是二分类但是只有1个输入节点的。例子中真实值为1,输出概率为0.1,交叉熵较大。

第四部分是函数的形式,和第三部分类似。

在这里插入图片描述

Why not MSE?

当sigmoid和MSE结合,会出现gradient vanish的现象,因为值大的时候梯度为0,小的时候梯度为0,这样很容易会出现前期更新非常慢,甚至出现loss很大,但是一直没更新的情况。

实践证明cross entropy收敛更加地快,在图中,预测值(概率)比较错误的情况下的梯度,当预测错误时候的概率,在刚开始的时候概率非常大,有助于前期收敛的非常快,这是它作为loss非常好的地方。

(我理解图中的梯度为斜率,这个函数是loss函数,loss函数可以是MSE,也可以是cross entropy,但是cross entropy在初期识别能力弱的时候,也就是predicted prob小的时候,它的梯度-斜率大,在前期能比较快的更新w-参数值,通过函数 w = w − l r ∗ δ l o s s δ w w = w - lr * \frac{\delta loss}{\delta w} w=wlrδwδloss

不过在meta-learning等一些学科,发现MSE更加稳定合理,交叉熵则不稳定,根据实际情况来说。

在这里插入图片描述

分类问题的pipeline:

logits->CrossEntropy

首先是从输入经过一系列网络得到输出(LOGIT)(一般指最后一层没有加激活函数),如果是分类问题,经过softmax,再经过cross entropy得到loss。

如果这么做会发现,有数值不稳定的过程,会出现处理错误error(not a number或infinity),为了处理这个问题,通常利用隔断,将黑色的区域统一在一起作为1个函数,函数内部已经做好了优化,防止出现数据不稳定的过程。

在这里插入图片描述

Numerical Stability(为数据稳定加参数from_logits)

所以做分类问题,不需要先softmax再cross entropy。直接交给TensorFlow稳定处理的函数,这个函数名字为原来的函数,只是加了参数from_logits=True,一般情况都加这个参数。

总结注意两点:

  1. 第四部分的第一个参数必须要one-hot encoding
  2. 设定from_logits

当然,在第三部分经过softmax,第五部分from_logits设置为False,理论上讲和第四部分是一样的,但是不推荐,会出现数值不稳定的问题。

在这里插入图片描述

在PyTorch中,前馈全连接层是**构建神经网络的基本组件之一**。以下是有关PyTorch前馈全连接层的详细介绍: 1. **定义**:前馈全连接层(Feed-Forward Linear Layer)是由多个神经元组成的层,其中每个神经元都与前一层的所有神经元相连接。在这种结构中,信息从输入层流向隐藏层,最后流向输出层,过程中没有回路,即不包含任何形式的反馈或循环。 2. **创建**:在PyTorch中,可以通过`torch.nn.Linear`类来创建一个全连接层。这个类接受两个参数:输入特征的数量和输出特征的数量。例如,`nn.Linear(10, 5)`会创建一个接受10个输入特征并输出5个特征的全连接层。 3. **作用**:全连接层的主要作用是进行特征的线性变换。它通过将输入数据与权重矩阵相乘,并添加一个偏置项来进行计算。这种变换可以帮助网络学习输入输出之间的复杂映射关系。 4. **激活函数**:为了引入非线性特性,通常会在全连接层之后添加激活函数,如ReLU、Sigmoid或Tanh等。这样可以使网络能够捕捉到更加复杂的数据模式。 5. **训练**:在训练过程中,全连接层的权重和偏置会根据反向传播算法和优化器(如SGD、Adam等)来更新,以最小化损失函数,从而提高网络的预测性能。 6. **应用**:前馈全连接层广泛应用于各种类型的神经网络中,无论是用于回归问题还是分类问题,它们都是构建深层网络的基础。 此外,在搭建一个简单的前馈全连接层网络时,通常需要定义网络的架构,包括各层的节点数、激活函数类型等,然后通过数据进行训练,最终得到一个可以用于预测或分类的模型。 总的来说,前馈全连接层神经网络中不可或缺的一部分,它们负责处理信息的传递和转换,是深度学习模型的核心组成部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值