机器学习之监督学习(三)神经网络

机器学习之监督学习(三)神经网络基础

  • 0. 文章传送
  • 1. 深度学习 Deep Learning
    • 深度学习的关键特点
    • 深度学习VS传统机器学习
  • 2. 生物神经网络 Biological Neural Network
  • 3. 神经网络模型基本结构
    • 模块一:TensorFlow搭建神经网络
  • 4. 反向传播梯度下降 Back Propagation Gradient Descent
    • 模块二:激活函数 activation function
    • 模块三:优化方法 optimizatoin method
      • Adam优化器
      • 正则化
  • 5. 多分类问题 Multiclass Classification
    • softmax激活函数
    • from_logits=True
  • 6. 数据增强 Data Augmentation
  • 实战篇——手写数字识别

0. 文章传送

机器学习之监督学习(一)线性回归、多项式回归、算法优化[巨详细笔记]
机器学习之监督学习(二)二元逻辑回归
机器学习之实战篇——预测二手房房价(线性回归)
机器学习实战篇——肿瘤良性/恶性分类器(二元逻辑回归)

1. 深度学习 Deep Learning

神经网络是深度学习算法的基础。在监督学习板块中,前面我们学习了线性回归模型和逻辑回归模型,这些被称为传统机器学习模型。何为深度学习?和传统机器学习模型相比又有什么优势?

深度学习是机器学习的一个子领域,它主要通过使用深层神经网络(即具有多个隐含层的神经网络)来学习和提取数据中的复杂模式和特征

深度学习的关键特点

多层结构:深度学习模型通常由多个层级组成,包括输入层、多个隐含层和输出层。每一层都可以提取不同级别的特征。

非线性激活函数:通过使用非线性激活函数(如ReLU、Sigmoid、Tanh等),深度学习模型能够学习复杂的非线性关系。

自动特征学习:深度学习能够自动从原始数据中提取特征,减少了对人工特征工程的需求。

大数据处理:深度学习在大规模数据集上表现优异,能够从中学习出有用的信息和模式。

端到端学习:深度学习模型可以直接从原始输入学习到最终输出,无需中间的特征处理步骤。

迁移学习能力:已经在一个任务上训练的深度学习模型可以被迁移到其他相关任务上,充分利用已有的知识。

深度学习VS传统机器学习

  1. 复杂数据表示
    图像处理:深度学习能够自动从原始像素中提取特征,识别复杂模式,如图像分类和目标检测,而传统机器学习依赖手动特征提取,难以处理高维度和复杂结构。
    自然语言处理:深度学习模型(如循环神经网络、Transformer)能够处理序列数据,捕捉上下文信息,适用于机器翻译和文本生成等任务。
  2. 大规模数据处理
    大数据应用:深度学习在处理大规模数据集(如图像、视频和文本)时表现突出,能够利用数据的复杂性和多样性进行学习,而传统方法在数据量庞大时可能面临过拟合等问题。
  3. 多模态学习
    结合多种数据类型:深度学习能够同时处理图像、文本和音频等多种信息,适用于多模态任务,如图像描述生成和视频分析,而传统机器学习通常不具备这种能力。
  4. 生成模型
    内容生成:深度学习能够生成新的数据样本,如GANs生成高度逼真的图像或音频,传统机器学习方法在这方面的能力相对有限。
  5. 实时处理与反馈
    快速决策:深度学习在实时应用(如自动驾驶、实时语音识别)中,能够处理大量数据并迅速做出决策,而传统模型可能无法满足实时性要求。
  6. 复杂的非线性关系建模
    高维非线性映射:深度学习能够有效地捕捉复杂的非线性关系,适用于高度复杂的应用场景,而传统机器学习方法如线性回归、决策树在处理这些问题时会受到限制。
  7. 迁移学习
    知识迁移:深度学习允许模型在一个任务上训练后迁移到另一个相关任务,利用已有知识优化新任务的学习,而传统机器学习往往需要从头开始训练。

2. 生物神经网络 Biological Neural Network

神经网络可以分为生物神经网络和人工神经网络:

(1)生物神经网络,指的是生物脑内的神经元、突触等构成的神经网络,可以使生物体产生意识,并协助生物体思考、行动和管理各机体活动。

(2)人工神经网络,是目前热门的深度学习的研究基础。目前对人工神经网络的定义多种多样,采用TKohonen1988年在NeuralNetworks 创刊号上给出的定义,即:“人工神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它能够模拟生物神经系统对真实世界物体所做出的交互反应”(Kohonen,1988)

先回顾一下高中生物所学的神经元:
在这里插入图片描述
回忆生物神经元的结构,细胞体作为神经元的主体,由细胞体向外延伸的多个突起神经纤维称为树突,树突作为细胞体的输入端,轴突为细胞体向外延伸最长的突起,末端由很多细的分支被称为神经末梢,每一条神经末梢相当于细胞体的输出端。每个神经元通过轴突的神经末梢与其他神经元的细胞体或树突相连接,这种连接称为突触。

细胞体的细胞膜在正常状态下形成内负外正的膜电位,当神经元突触与上千个其他神经元连接时,接受不同输入对神经元点位的影响也不用(视为不同输入具有权重),当膜电位升高到一个阈值时,就会产生一个脉冲。突触也可以分为兴奋性和抑制性两种,兴奋性的突触可能引起下一个神经元兴奋,抑制性的突出会抑制下一个神经元的兴奋。

前面所说的逻辑回归模型可视为最简单的神经网络结构(单个神经元模型),输入的各个特征相当于神经元树突接收的各个信号,不同特征乘以不同权重相当于不同输入对神经元具有不同影响,最后将线性组合的结果通过激活函数(逻辑回归中用的是sigmoid函数)作用后输出。

引入激活函数的原因是引入非线性,如果神经网络中没有激活函数(只使用线性激活函数),那无论层次结构多复杂,总体来看还是一个线性回归模型。

单个神经元的数学表达式:

z = ∑ i = 1 d w i x i + b = w ⃗ ⋅ x ⃗ + b a = f ( z ) z=\sum_{i=1}^{d}{w_ix_i}+b=\vec{w}\cdot\vec{x}+b\\a=f(z) z=i=1dwixi+b=w x +ba=f(z)

在这里插入图片描述

3. 神经网络模型基本结构

了解了单个神经元的基本功能后,我们开始探讨由多个神经元构成的神经网络结构的基本组成。

假设我们想要制作一个模型判断服装产品是否能畅销,考虑的特征有价格、运费、营销力度和制作材料。
对于一件产品,输入层(input layer)输入这四个特征。进一步考虑,价格和运费联系到客户可购买能力,营销力度联系到客户对产品了解程度,材料和价格涉及到客户对产品质量感知,用这三个新特征构造一个隐层(hidden layer),下图中黄色箭头指示了哪些特征输入相应的隐层神经元。隐层的三个神经元接收输入后,进行线性运算,激活后输出,三个输出数值再传入最后一个神经元(即输出层 output layer),输出最终结果,用来预测服装畅销的概率。在这个案例中,我们通过对初级特征的提炼总结构造了一层新特征,提升了模型的复杂性,有利于更充分挖掘原始特征,取得更好的预测效果。

在这里插入图片描述

这种引入了隐层的神经网络,也称为多层感知机(multiple perception)。值得注意的是在上图中,由于我们人为地对原始特征进行了一定归纳,每个隐层神经元都只与特点的部分输入特征连接。但事实上神经网络具备自主提炼特征的能力,一般神经网络结构都采用全连接的形式,全连接层(Dense layer)是神经网络中的一种基本层类型,它的特点是每个神经元(节点)与前一层的所有神经元都有连接。可以认为在层层递进过程中,神经元逐渐学习到越来越复杂的特征表示,很难定义每一层神经元具体表示什么特征(比较抽象),举人脸识别的案例来说:在这里插入图片描述
图片转化为像素向量输入(卷积)神经网络,经过三层隐层后输出,可以看到第一层学习到了图像的边缘/线条特征,第二层用边缘特征组合出更复杂的几何图形结构,表示人的眼睛、鼻子等区域,第三层几乎提炼出了整个面部结构,然后模型输出人脸对应某人的概率,实现人脸识别。这个过程体现了深度学习的核心优势:自动特征提取。相比传统的计算机视觉方法需要手动设计特征提取器,深度学习模型能够自动学习到从低级到高级的特征层次结构。

在讲解了几个案例后,相信大家已经领会到了神经网络的魅力,接下来从数学上进行定量描述。

在这里插入图片描述

下面定义:
n [ i ] : 第 i 层神经元数量 x ⃗ : 输入特征向量 a ⃗ [ i ] : 第 i 层输出向量 z j [ i ] : 第 i 层第 j 个神经元线性组合值 a j [ i ] : 第 i 层第 j 个神经元输出值 W [ i ] : 第 i 层权重矩阵 w ⃗ j [ i ] : 第 i 层第 j 个神经元权重向量 b ⃗ [ i ] : 第 i 层偏置向量 b j [ i ] : 第 i 层第 j 个神经元偏置值 y ⃗ :输出目标向量 n^{[i]}:第i层神经元数量\\ \vec{x}:输入特征向量\\ \vec{a}^{[i]}:第i层输出向量\\ z_j^{[i]}:第i层第j个神经元线性组合值\\ a_j^{[i]}:第i层第j个神经元输出值\\ W^{[i]}:第i层权重矩阵\\ \vec{w}_{j}^{[i]}:第i层第j个神经元权重向量 \\ \vec{b}^{[i]}:第i层偏置向量\\ b^{[i]}_j:第i层第j个神经元偏置值\\ \vec{y}:输出目标向量\\ n[i]:i层神经元数量x :输入特征向量a [i]:i层输出向量zj[i]:i层第j个神经元线性组合值aj[i]:i层第j个神经元输出值W[i]:i层权重矩阵w j[i]:i层第j个神经元权重向量b [i]:i层偏置向量bj[i]:i层第j个神经元偏置值y :输出目标向量
对于第i层第j个神经元,其数学表达式为:
输入向量 : i n p u t ⃗ [ i ] = a ⃗ [ i − 1 ] ( i n p u t ⃗ [ 1 ] = x ⃗ ) 输入向量 :\vec{input}^{[i]}=\vec{a}^{[i-1]}(\vec{input}^{[1]}=\vec{x}) 输入向量:input [i]=a [i1](input [1]=x )
线性组合: z j [ i ] = w ⃗ j [ i ] ⋅ i n p u t ⃗ [ i ] + b j [ i ] 线性组合:z_j^{[i]}=\vec{w}_{j}^{[i]}\cdot\vec{input}^{[i]}+ b^{[i]}_j 线性组合:zj[i]=w j[i]input [i]+bj[i]
激活(激活函数 g ): a j [ i ] = g ( z j [ i ] ) 激活(激活函数g):a_j^{[i]}=g(z_j^{[i]}) 激活(激活函数g):aj[i]=g(zj[i])

如上图的神经网络,有一个输入层,输入特征数量为4,有两个隐层,第一隐层有5个神经元,第二隐藏有3个神经元;还有一个输出层,包含一个神经元。

Q1 这个神经网络总共包含多少参数(包含权重和偏置)?我们来进行简单计算:

第一层(不考虑输入层)输入向量长度为4,每一个神经元参数包含长度为4的权重向量和一个偏置值,共5*(4+1)=25个参数,由此可总结规律:第i层有 n i n_i ni个神经元,上一层有 n i − 1 n_{i-1} ni1个神经元(或输出),则该层参数数量计算公式为 n i ∗ ( n i − 1 + 1 ) n_i*(n_{i-1}+1) ni(ni1+1)
由于四层大小分别为4、5、3、1,参数总数为
5 × ( 4 + 1 ) + 3 × ( 5 + 1 ) + 1 × ( 3 + 1 ) = 25 + 18 + 4 = 47 5×(4+1)+3×(5+1)+1×(3+1)=25+18+4=47 5×4+1+3×5+1+1×3+1=25+18+4=47

Q2 从前往后写出每个神经元的数学表达式:
了解了神经网络中符号表示和单个神经元的数学表达式后,我们不难写出这个神经网络中所有神经元的数学表达式,初步入门的读者可以自行练习,熟悉神经网络这个前向传播(forward propagation)的过程。

注意:当输入多个数据时,输入神经网络的为特征矩阵

模块一:TensorFlow搭建神经网络

在前面的线性回归、逻辑回归中,我们都自己编写了实现代码,在神经网络中,由于模型结构比较复杂(特别是后面说的反向传播梯度下降),个人觉得编写代码难度很高。因此个人建议把神经网络模型的基本数学原理了解清楚后,推荐借助python强大的机器学习库例如TensorFlow、pytorch来构建神经网络。

这里主要先介绍TensorFlow。TensorFlow 是一个开源的机器学习框架,由 Google Brain 团队开发。它被广泛用于深度学习、神经网络和其他机器学习任务。

TensorFlow 的核心数据结构是张量,可以看作是多维数组。所有的数据在 TensorFlow 中都是以张量的形式表示的,支持标量、向量、矩阵和更高维的数据结构。TensorFlow 使用计算图来表示计算过程。计算图由节点(操作)和边(数据流)组成,便于进行并行计算和优化。

Keras 是一个高级神经网络 API,旨在简化深度学习模型的构建和训练过程。它提供了简洁且易于使用的接口,使得用户可以快速构建和实验各种神经网络架构。 从 TensorFlow 2.x 开始,Keras 被作为 TensorFlow 的官方高层 API 集成。这意味着用户可以直接通过 TensorFlow 使用 Keras,享受两者的优势。如遇到两个模块不兼容的情况,解决方案参照传送门。在机器学习入门阶段,经常会遇到numpy、pandas、matplotlib、scipy、scikit-learn、TensorFlow等等这些数据分析、机器学习基本模块不兼容的情况,建议这时候重新创建新的虚拟环境,按照上面教程推荐的顺序和版本去安装各个库,使无后患之忧。有时在jupyter notebook中遇到不兼容错误,重启pycharm后可能会解决问题。

下面代码演示用TensorFlow搭建上图的神经网络:
第一步:导入tensorflow和相应模块

import tensorflow as tf
from tensorflow.keras.layers import Normalization,Input,Dense#(Input:输入层,Dense:全连接层,Normalization:标准化层)
from tensorflow.keras.models import Sequential #Sequential:联系各层,构造完整的神经网络
from tensorflow.keras.activations import sigmoid,relu,linear #激活函数:sigmoid、relu、linear
from tensorflow.keras.losses import BinaryCrossentropy,MeanSquaredError #损失函数,二元交叉熵损失函数、平均平方损失函数

第二步:可先用Normalizatoin模块对输入特征矩阵标准化

Norm_l=Normalization()
Norm_l.adapt(X)
Xn=Norm_l(X)

第三步:使用Sequential搭建神经网络模型

model=Sequential([ Input(shape=(4,)),  #标明输入每一个特征向量的长度,即特征数Dense(units=5,activation='sigmoid',name='1'),  #第一层,5个神经元,使用sigmoid激活函数Dense(units=3,activation='sigmoid',name='L2'),  #第二层,3个神经元,使用sigmoid激活函数Dense(units=1,activation='sigmoid',name='L_out') #输出层,1个神经元,使用sigmoid激活函数]
)

第四步:查看模型结构

model.summary()
Model: "model1"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================L1 (Dense)                  (None, 5)                 25        L2 (Dense)                  (None, 3)                 18        L_out (Dense)               (None, 1)                 4         =================================================================
Total params: 47
Trainable params: 47
Non-trainable params: 0

第五步:编译模型,指定损失函数

#分类模型:二元交叉熵损失函数
model.compile(loss=BinaryCrossentropy())
#回归模型:平均平方损失函数
model.compile(loss=MeanSquaredError())

第六步:拟合数据,开始训练

model.fit(Xn,y,epochs=100)  #epochs:迭代次数

第七步:应用模型进行预测,返回值是numpy对象,在分类问题中返回的是预测概率向量,需要通过设置阈值后转换为预测类别向量

y_pred=model.predict(X_pred)

查看训练后每层的参数:

layer_1=model.get_layer(name='L1')
w_1,b_1=layer_1.get_weights()
print(f'第一层参数w:{w_1},b:{b_1}')

在机器学习实战篇——肿瘤良性/恶性分类器(二元逻辑回归)中,我们使用逻辑回归模型取得了准确率高于95%的预测效果,而读者可以尝试使用神经网络模型训练,准确率可以达到100%,足见神经网络模型的强大。

4. 反向传播梯度下降 Back Propagation Gradient Descent

上面我们已经学习了如何使用tensorflow搭建神经网络,可以看到不需要对内部原理有多少认识,就足以搭建出一个强大的机器学习模型。我们不满足于此,希望了解神经网络模型是如何发挥魔力的。其具体训练机制是什么?学习了线性回归模型和逻辑回归模型后,我们能直接猜出答案:使用梯度下降算法迭代训练各个参数。但问题是,神经网络模型结构相当复杂,定义了代价函数后,计算偏导异常困难。在神经网络模型中,计算偏导的策略是反向传播(Back Propagation),为什么叫"反向"呢,因为梯度的计算是从网络的输出层开始,逐层向输入层传播,与数据的前向传播方向相反。反向传播依赖于微积分中的链式法则。这允许我们将复杂的复合函数的导数分解为更简单的部分。由于这部分涉及比较复杂的数学运算,如果我们的学习目标并非是从0手撕神经网络,那不必过分纠结,可以只了解其主要思想。

关于损失函数,在机器学习系列前两篇文章中已有详细解读,这里不再赘述,回归问题中通常采用平均平方损失函数,二元分类问题中通常采用二元交叉熵损失函数(对数损失函数)。梯度下降每一次迭代过程中都需要计算代价函数对各个参数的偏导,并更新各个参数。

关于反向传播的具体细节,参照笔者的两张图片笔记,可以算是最容易理解的推导版本:
在这里插入图片描述

在这里插入图片描述
在tensorflow神经网络模型中,默认采用批量梯度下降进行训练,可以在model.fit()中通过batch_size设置单次训练批量,默认值32,关于批量梯度下降之前已经进行过详细介绍,迁移到神经网络中,工作流程如下:

  1. 数据打乱:在每个训练周期(称为 epoch)开始时,通常会对整个训练数据集进行打乱,以确保每个 mini-batch 都是随机抽取的数据。
  2. 分批次处理:将训练数据按预定的批次大小(batch size)进行分割,每个批次的数据将被用来进行一次前向传播和反向传播。
  3. 梯度计算:在每个批次上计算损失函数的梯度。
  4. 参数更新:使用计算出的梯度更新模型参数。
  5. 重复:重复上述步骤,直到遍历完整个数据集(完成一个 epoch),然后开始下一个 epoch。

在训练过程中,可以看到每次迭代的相关信息,1875表示训练批次数,8s表示每次迭代所用时间,loss表示迭代后损失值。
在这里插入图片描述

模块二:激活函数 activation function

在逻辑回归章节中,我们介绍了Sigmoid激活函数,在这里对常用的几种激活函数进行总结。

线性激活函数 linear activation function
线性激活函数即
g ( z ) = z g(z)=z g(z)=z
可以看出相当于无激活输出,输出范围为 ( − ∞ , + ∞ ) (-\infty,+\infty) (,+),回归问题输出连续数值,因此神经网络回归模型输出层采用线性激活函数。

Sigmoid激活函数 sigmoid activation function
S型生长曲线是一类在自然和社会现象中常出现的曲线形状,它由三个阶段组成:起始阶段、加速阶段和饱和阶段。在起始阶段,增长速度较慢;在加速阶段,增长速度逐渐加快;在饱和阶段,增长速度逐渐减缓。
在这里插入图片描述
在数学上,描述S型曲线的函数称为sigmoid函数,表达式为:
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+ez1
(为了和模型表达式一致,将函数用g表示,输入变量用z表示)
1、函数图像,单调递增,奇函数
在这里插入图片描述
2、值域:g ∈ \in (0,1),由于输出范围在0到1之间,Sigmoid函数可以将任意实数映射到一个有限的范围内,适合处理概率问题,这使它成为了机器学习模型中常用的激活函数。
3、导数:
①sigmoid函数处处连续可微
②sigmoid函数的导数很容易计算,可以直接由求导处函数值经简单计算得出:
g ′ ( z ) = g ( z ) ( 1 − g ( z ) ) g'(z)=g(z)(1-g(z)) g(z)=g(z)(1g(z))
(导数计算并不复杂,读者可以自行动笔进行计算)

ReLU激活函数 ReLU activation function

  • 数学表达式:

    f ( x ) = max ⁡ ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x)

  • 输出范围: [ 0 , + ∞ ) [0, +\infty) [0,+)

  • 非线性:ReLU 是一个分段线性的非线性函数。

  • 导数:ReLU 的导数要么是 0,要么是 1,这取决于输入是负数还是正数。

  • 图像:

  • 在这里插入图片描述
    在神经网络隐层中,通常采用ReLU激活函数,因为相比sigmoid激活函数它具备几点优势:
    ①导数容易计算,计算开销小,加快了训练的速度
    ②见下图,ReLU在正区间的梯度始终为1,这有助于缓解梯度消失的问题。在深层网络中,使用ReLU可以使得梯度更有效地传播,从而加快训练速度和提高模型性能
    在这里插入图片描述
    ③ReLU激活函数会将负值输出为零,这意味着在任意给定的输入数据点上,只有一部分神经元会被激活(即输出非零值)。这种稀疏性特性可以使模型在计算上更加高效,并减少过拟合的风险。
    ④虽然ReLU本身是分段线性的,但它引入的非线性特性使得网络能够更好地拟合复杂数据,实验表明,使用ReLU作为隐层激活函数的网络通常能取得更好的性能。

模块三:优化方法 optimizatoin method

Adam优化器

作用:Adam是一种自适应学习率的优化算法,对不同参数设置不同学习率,根据梯度下降的情况调节学习率,加速梯度下降,提高运行效率
在这里插入图片描述
在TensorFlow中,在编译模型时设置优化参数为Adam:

from tensorflow.keras.optimizers import Adam
model.compile(optimizer=Adam(learning_rate=1e-3)) #设置初始学习率

正则化

在前面的文章中,我们详细讨论过欠拟合,过拟合和偏差,方差的问题并提出了机器学习模型的优化方案。神经网络模型中,随着模型复杂程度增大,也容易出现过拟合的情况,因此正则化仍然能派上用场,但使用正则化未必一定能提升模型的性能(甚至可能降低模型性能),所以需要结合实际情况灵活运用。一般来说,当模型复杂度较高或数据集规模较小时,容易出现过拟合,这时候推荐使用正则化;而当数据集规模足够大时或模型较简单时,不必使用正则化。关于正则化系数,也需灵活设置。

有这样一个结论:神经网络只要合理正则化,模型越大,训练误差越小。

下面是典型的神经网络训练思路:
①训练,如果训练集误差大(high bias)->增大神经网络规模->满意的训练效果
②验证,如果验证集误差大(high variance)->增大数据量
重复①②直到模型满足low bias and low variance->输出最终模型

常见的正则化方法有:

  1. L2正则化(权重衰减):在损失函数中添加权重参数的平方和的乘积,鼓励模型的权重更小。

    Loss = Original Loss + λ ∑ i w i 2 \text{Loss} = \text{Original Loss} + \lambda \sum_{i} w_i^2 Loss=Original Loss+λiwi2

  2. L1正则化:在损失函数中添加权重参数的绝对值和的乘积,鼓励稀疏模型(即大多数权重为零)。

    Loss = Original Loss + λ ∑ i ∣ w i ∣ \text{Loss} = \text{Original Loss} + \lambda \sum_{i} |w_i| Loss=Original Loss+λiwi

  3. Dropout:在训练过程中随机丢弃一部分神经元,以减少神经元之间的共适应性。
    在训练时:每次迭代,随机选择一部分神经元(Dropout率)设置为0。
    前向传播和反向传播都只在保留的神经元上进行。
    在测试时:所有神经元都被保留。但是输出需要乘以保留率(1-Dropout率)来平衡训练和测试时的期望输出。
    选择合适的Dropout率需要根据具体问题和网络结构进行实验。通常,较小的网络使用较小的Dropout率(如0.1-0.3),而较大的网络可能使用较大的Dropout率(如0.3-0.5)。

在TensorFlow中,实现正则化很简单,L1、L2正则化在创建层的时候设置:

from tensorflow.keras.regularizers import l2...
Dense(...,kernel_regularizer=l2(0.01)) #设置正则化系数为
...

引入Dropout层示例代码,可以在隐层之后设置Dropout层,并设置Dropout率:

from tensorflow.keras.layers import Dropoutmodel = Sequential([Input(shape=(n,)),Dense(units=25, activation='sigmoid', name='L1'),Dropout(0.2),Dense(units=15, activation='sigmoid', name='L2'),Dropout(0.2),Dense(units=1, activation='sigmoid', name='L_out')
])

推荐:

对于小型数据集或简单模型,L2正则化通常是一个好的起点。

对于大型、复杂的深度学习模型,Dropout往往更有效。

5. 多分类问题 Multiclass Classification

前面我们讨论的分类问题都属于二元分类问题,输出为1或0,表示阳(阴)性或正(负)性。当输出类别大于二时,例如手写数字0~9识别(输出10个类别),这时候称之为多分类问题(multiclass classification)。

在解决多分类问题的神经网络模型中,输出层神经元数量不再是1个,而是输出类别数,每个输出值表示样本对应该类别的概率,例如手写数字0-9识别案例中,若输出概率向量为 [ 0.10 0.10 0.09 0.11 0.30 0.06 0.09 0.01 0.07 0.07 ] [0.10~ 0.10~0.09~0.11~0.30~0.06~0.09~0.01~0.07~0.07] [0.10 0.10 0.09 0.11 0.30 0.06 0.09 0.01 0.07 0.07],则表示该手写图片对应数字4的概率最大,因此模型将其识别为4。

在多分类问题中,需引入新的激活函数softmax激活函数:

softmax激活函数

假设输出层有N个神经元,输入向量为 x ⃗ \vec{x} x ,每个神经元的权重向量是 w j ⃗ \vec{w_j} wj ( j = 1 、 2 、 . . . 、 N ) (j=1、2、...、N) (j=12...N),线性组合输出值为 z j z_j zj,激活输出值为 a j a_j aj,则
z j = w j ⃗ ⋅ x ⃗ + b j ( j = 1 、 2 、 . . . 、 N ) z_j=\vec{w_j}\cdot{\vec{x}}+b_j(j=1、2、...、N) zj=wj x +bj(j=12...N)
softmax函数可表达为:
a j = e z j ∑ i = 1 N e z j = P ( y = j ∣ x ⃗ ) a_j=\frac{e^{z_j}}{\sum_{i=1}^Ne^{z_j}}=P(y=j|\vec{x}) aj=i=1Nezjezj=P(y=jx )
N=4时:在这里插入图片描述
可以看到所有激活输出值范围均在0~1之间,且和为1,满足所有类别预测概率之和为1的基本规律。

由于指数运算输出值庞大,为了避免溢出问题,通常将softmax函数进行优化。将指数全减去指数中最大值,这样一个指数值为1,其他指数值都小于1,这样有些避免了指数溢出,增强算法的健壮性。下面是手写参考代码:

def my_softmax_ns(z):"""numerically stablility improved"""bigz = np.max(z)ez = np.exp(z-bigz)              # minimize exponentsm = ez/np.sum(ez)return(sm)

tensorflow提供了内置sigmoid函数:

import tensorflow as tf
tf.nn.softmax()#softmax激活函数

多分类问题中目标输出值采用独热(one-hot)编码,即对应类别输出为1,其他类别输出为0。

与soft激活函数配合使用的损失函数是分类交叉熵损失函数(Categorical Cross-Entropy Loss Function),可简单表示为:
l o s s = − l o g ( a j ) i f y = j loss=-log(a_j)~if~y=j loss=log(aj) if y=j
更一般的表达式是:
l o s s = − ∑ j = 1 N y j l o g ( a j ) loss=-\sum_{j=1}^{N}{y_jlog(a_j)} loss=j=1Nyjlog(aj)
由于输出值 a j a_j aj可能取0,而0log0无意义,解决方案有两种:
1、在代码中定义0log0=0
2、将损失函数修改为
l o s s = − ∑ j = 1 N y j l o g ( m a x ( a j , ϵ ) ) ( ϵ 取极小值 ) loss=-\sum_{j=1}^{N}{y_jlog(max(a_j,\epsilon))}(\epsilon取极小值) loss=j=1Nyjlog(max(aj,ϵ))(ϵ取极小值)

在TensorFlow中,分类交叉熵损失函数用 SparseCategoricalCrossentropy 表示,

‘Sparse’ 的含义
“Sparse” 在这里指的是标签的编码方式,而不是数据的稀疏性。
它表示真实标签是以整数形式给出的,而不是one-hot编码。
例如,对于三类分类问题:
Sparse标签:[0, 2, 1]
非Sparse(one-hot)标签:[[1,0,0], [0,0,1], [0,1,0]]

如果标签已经是one-hot编码,则应使用CategoricalCrossentropy

from tensorflow.keras.losses import SparseCategoricalCrossentropy #分类交叉熵损失函数

from_logits=True

神经网络分类模型在使用交叉熵函数时,另一个优化方法是通过设置from_logits参数。Logits 是模型最后一层线性输出的原始值,还没有被转换成概率。

from_logits=True 表示模型的最后一层输出的是原始的、未经过 softmax 处理的值(称为 logits)。
from_logits=False(默认值)表示模型的最后一层已经应用了 softmax 函数,输出的是概率分布。

如下图,在二元分类模型中,将输出层激活函数由’sigmoid’修改为‘linear’,即将Logits直接输出,而编译模型时在损失函数参数中设置from_logits=True,即损失函数直接使用Logits而不是激活后的值进行计算。

loss=BinaryCrossEntropy(from_logits=True)

在这里插入图片描述

对于分类交叉熵损失函数,同样可以设置from_logits=True。由于模型输出Logits,因此需要手动通过激活函数后输出预测概率向量。

在这里插入图片描述

为什么将激活函数和损失函数合二为一,能优化模型?在计算损失函数时,直接在 logits 上计算(一步到位)通常比先将 logits 转换为概率再计算损失(分步计算)更稳定和精确。这涉及到计算机数值精度的问题,参照下图示例:

上面的一步到位计算相比下面的分步计算,结果精度更高。from_logits优化即是为了消除分布计算积累的误差,提高模型预测的精确度。
在这里插入图片描述

6. 数据增强 Data Augmentation

在ai训练过程中,除了构建和完善一个强大的机器学习模型之外,充分大并且全面的数据集也是必不可少。前面说过,在面临过拟合问题时,一个有效的应对思路就是增大训练数据规模,以此降低方差,提高模型的泛化能力。下面讨论机器学习过程中如何针对性地添加数据,并且如何从原有数据集中衍生新数据。
在这里插入图片描述

在机器学习训练过程的评估过程中,我们在进行误差分析后,如果发现模型在某一类数据上表现不佳,便可以有针对性的增加某一类数据规模。例如,假设你正在训练一个图像分类模型,在评估过程中发现模型在识别某一类图像(比如狗)的准确率较低。这可能是由于训练数据中这一类图像的数量相对较少,导致模型无法充分学习该类图像的特征。

解决方法是收集更多该类图像的训练数据,并将其添加到训练集中。这可以通过网上搜索、自行拍摄等方式获得。除此外,可以采用数据增强(Data Augmentation)技术,对图像训练数据进行变形比如随机旋转、缩放、裁剪等,进一步扩充该类图像的数量和多样性。

在这里插入图片描述

对于音频数据,可以通过给原始音频加上背景音实现数据增强。例如在训练语音识别模型时,为了让模型在各种场景中都能取得较好的识别效果,可以给原始训练音频加上嘈杂背景音(例如引入打电话声音、汽车声音或模拟信号断续的状况)。

下面用代码展示如何实现图像数据增强:

import tensorflow as tf
import matplotlib.pyplot as plt# 加载MNIST数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()# 数据增强的transforms,对图像进行随机旋转、随机缩放、随机对比度调整
data_augmentation = tf.keras.Sequential([tf.keras.layers.RandomRotation(0.1),tf.keras.layers.RandomZoom(0.1),tf.keras.layers.RandomContrast(0.1),
])# 可视化部分训练数据
fig, axes = plt.subplots(2, 5, figsize=(12, 6))
for i, ax in enumerate(axes.flat):ax.imshow(x_train[i], cmap='gray')ax.axis('off')
plt.suptitle('Original MNIST Training Data')
plt.show()# 应用数据增强
#expand_dims (10,28,28)->(10,28,28,1) #最后一个维度表示通道(灰色)
augmented_images = data_augmentation(tf.expand_dims(x_train[:10], axis=-1), training=True)# 可视化增强后的数据
fig, axes = plt.subplots(2, 5, figsize=(12, 6))
for i, ax in enumerate(axes.flat):ax.imshow(augmented_images[i, ..., 0], cmap='gray') #这里的0表示选取最后一个维度(通道维度)的第0个通道,也就是灰度通道ax.axis('off')
plt.suptitle('Augmented MNIST Training Data')
plt.show()

实战篇——手写数字识别

机器学习之实战篇——手写数字0~9识别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/53772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源的 Windows 12 网页体验版!精美的 UI 设计、丰富流畅的动画

大家周二好呀!博主今天给小伙伴们分享一款炫酷的 Windows 12 体验版,网页效果拉满,非常值得我们去尝试! 如果你对未来的Windows操作系统充满期待,那么这款开源的Windows 12 网页体验版绝对不容错过!这不仅…

consul配置ACL安全认证

文章目录 前言一、漏洞详情二、漏洞处理1.ACL相关介绍2.开启ACL3.创建令牌4.修改acl文件5.修改单节点consul启动配置文件6.重启consul 三、漏洞处理结果验证 前言 因为现阶段属于护网期,因此公司对服务器、业务的安全都很关注,只要再次期间被漏扫出来的漏洞,都需要…

tomcat是不是已经被Springboot集成了?

Tomcat 确实已经被 Spring Boot 集成。Spring Boot 通过其独特的“starter”模块(如spring-boot-starter-web)实现了对Tomcat的自动配置。当在Spring Boot项目中引入这个starter时,会自动引入相关的依赖,包括tomcat-embed-core、t…

C语言补习课——文件篇

来源:黑马程序员 第157讲 C语言操作文件概述 读取文件:输入流 写文件:输出流 读写的方向判断取决与参照,一般我们站在程序的角度判断读写方向。 第158讲 路径 基本概念 路径就是指文件在电脑中的位置,eg&#xf…

阿里旗下土耳其电商Trendyol计划进军欧洲市场

阿里旗下土耳其电商Trendyol计划进军欧洲市场 近年来,阿里巴巴集团在全球电商领域的布局持续深化,其旗下土耳其电商巨头Trendyol更是凭借其出色的市场表现和强劲的增长势头,成为了备受瞩目的焦点。近日,Trendyol宣布了一项重要战…

Java初步

背景 名字 Oak(橡树)改到一个岛(疑似盛产咖啡) Java之父 詹姆斯高斯林(James Gosling) sun公司研发 现在属于Oracle公司 把它称为甲骨文公司 应用 企业级应用开发 重点学习JavaSE(Standa…

线性代数 第六讲 特征值和特征向量_相似对角化_实对称矩阵_重点题型总结详细解析

文章目录 1.特征值和特征向量1.1 特征值和特征向量的定义1.2 特征值和特征向量的求法1.3 特征值特征向量的主要结论 2.相似2.1 相似的定义2.2 相似的性质2.3 相似的结论 3.相似对角化4.实对称矩阵4.1 实对称矩阵的基本性质4.2 施密特正交化 5.重难点题型总结5.1 判断矩阵能否相…

JavaScript高级——函数中的this

1、this是什么? ① 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是 window 。 ② 所有函数内部都有一个变量 this 。 ③ 它的值是调用函数的当前对象。 2、如何确定 this 的值? ① test()&#xff…

如何进行DAP-seq的数据挖掘,筛选验证位点

从样本准备到寄送公司,每一天都在“祈祷”有个心仪的分析结果,终于在这天随着邮件提示音的响起,收到了分析结果...... 分析前工作 爱基在进行数据分析之前,会有两次质控报告反馈给老师们。第一个,基因组DNA的提取质控…

springBoot 集成https

springBoot 集成https 1、springBoot默认的证书格式 pring Boot 需要 .p12 或 .jks 格式的证书。如果你只有 .pem 和 .key 文件,可以使用 openssl 工具将它们转换成 .p12 文件 2、转换.p12 我的证书文件如下,需要转换 2.1 下载openssl https://slpr…

苹果手机铃声怎么设置自己的歌?3个方法自定义手机铃声

苹果手机内部的手机铃声库只有固定的几首铃声,且都是纯音乐,比较单调,并不是所有用户都喜欢这些铃声。那么,苹果手机铃声怎么设置自己的歌呢?小编这里有3个方法,可以教大家如何将手机铃声设置成自己喜欢的歌…

Java 入门指南:Java 并发编程 —— 同步工具类 Semephore(信号量)

文章目录 同步工具类Semephore核心功能限制并发访问量公平与非公平策略灵活性与适应性 常用方法使用示例 同步工具类 JUC(Java.util.concurrent)是 Java 提供的用于并发编程的工具类库,其中包含了一些通信工具类,用于在多个线程之…

C语言-综合案例:通讯录

传送门:C语言-第九章-加餐:文件位置指示器与二进制读写 目录 第一节:思路整理 第二节:代码编写 2-1.通讯录初始化 2-2.功能选择 2-3.增加 和 扩容 2-4.查看 2-5.查找 2-6.删除 2-7.修改 2-8.退出 第三节:测试 下期…

【单片机开发】单片机常用开发工具

【前言】 在嵌入式系统领域,单片机(Microcontroller, MCU)作为核心组件,广泛应用于智能家居、工业控制、汽车电子等众多领域。而单片机开发工具,则是开发者们实现创意、解决问题的重要助手。本文主要讲述目前主流的单…

港科夜闻 | 叶玉如校长出席2024科技+新质生产力高峰论坛发表专题演讲,贡献国家科技强国战略...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、叶玉如校长出席“2024科技新质生产力高峰论坛”,做了题为“三个创新:培育和发展新质生产力、贡献国家科技强国战略”的主题演讲。该论坛于9月2日在香港召开。论坛围绕夯实基础科研、推动源头创新、…

axure判断

在auxre中我们也可以实现判断的功能,当目标等于什么内容时则执行下方的功能。 一、判断输入框中是否有值 画布添加一个输入框、一个文本标签删除其中内容,添加一个按钮,输入框命名为【文本显示】文本标签命名为【提示】 给按钮新增一个交互…

单向链表概述

文章目录 🍊自我介绍🍊单向链表概述数据域和指针域数据类型设计 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞关注评论收藏(一键四连)哦~ 🍊自我介绍 Hello,大家好,我是小珑也要…

(计算机网络)应用层

1.为什么需要应用层 应用层提供使用tcp,udp使用的方式 协议就是制定的规则 2.域名服务器概述 域名是唯一的 新增域名,大家都要修改这个文本文件,所以要进行集中管理这个文本文件,而不是使用本地的hosts文件 hosts文件在Windows系统…

Java | Leetcode Java题解之第397题整数替换

题目: 题解: class Solution {public int integerReplacement(int n) {int ans 0;while (n ! 1) {if (n % 2 0) {ans;n / 2;} else if (n % 4 1) {ans 2;n / 2;} else {if (n 3) {ans 2;n 1;} else {ans 2;n n / 2 1;}}}return ans;} }

部署定时任务每2天清理一次表

1、创建存储过程 create or replace procedure truct authid current_user ---使用“authid Current_user”将存储过程转化为调用者权限 as begin execute immediate truncate table rep.tmp_s_st_busi_send_arc; end; / 2、创建定时任务 begin dbms_scheduler.create…