【机器学习实战】Datawhale夏令营2:深度学习回顾

#DataWhale夏令营 #ai夏令营

1. 深度学习的定义

1.1 深度学习&图神经网络

首先,我们需要明确深度学习的定义。深度学习是构建多层的神经网络,从而构建起一个大的模型,通过这个模型去学习复杂的特征表示。简单地说,这些层包含输入层、隐含层和输出层(特别像是LSTM),然而像是DCN这样的网络,实际的深度学习模型的层设可能更富创造性。
我认为深度学习可以概括为这样的一个流程:输入就像是神经信号(外部刺激),通过中间的神经元和通路进行加工和处理,最终化为模型(人体)的反应。深度学习正是借鉴了人体神经元处理信号的过程。
在数学意义上,深度学习的全流程至少涉及了所有的大一公共数学课。您需要通过处理权重矩阵和数据向量(线性代数)、梯度下降法计算(微积分)、不确定性计算(概率论)。通常它是这样一个流程:通过确定阈值,将输入加权求和,计算激活函数值,送入多层神经网络;前向传播,多层神经网络继续加权(和偏置)计算;计算损失函数,在输出层,比如通过均方误差(MSE)、交叉熵损失来计算;反向传播,在输出层,基于链式法则计算梯度,送还多层神经网络来调整权重(类似于控制系统的反馈),以便获得更好的结果;对优化器(优化算法)进行改进,比如Baseline用到的Adam优化器;进行正则化,防止过拟合;批处理和迭代,每一批被称为一个epoch;进行超参数调优,比如贝叶斯超参数优化。当然,实际的深度学习模型改进是一个更有趣的过程,也涉及更多的数学过程。

1.2 机器学习和深度学习的关系

机器学习包含深度学习,深度学习是机器学习的一个子方向。它涉及使用神经网络,特别是深度神经网络(即具有多层隐藏层的神经网络)来进行学习和预测。这个子方向处理大量数据和复杂模式识别方面表现出色,尤其在图像识别、自然语言处理和语音识别等领域取得了显著的成果。

2. 深度学习的训练流程

2.1 数学基础

2.1.1 梯度下降法

基本原理

梯度下降法的核心思想是沿着函数的梯度(即函数在各点的方向导数)的反方向,以求找到函数的局部极小值。在机器学习中,我们通常用它来最小化损失函数。
在这里插入图片描述

数学表达

假设我们有一个目标函数 J(θ),其中 θ 是参数向量。梯度下降的更新规则可以表示为:
θ = θ - α∇J(θ)
其中 α 是学习率,∇J(θ) 是 J(θ) 的梯度。

步骤

a) 初始化参数 θ
b) 计算当前参数下的梯度 ∇J(θ)
c) 更新参数: θ = θ - α∇J(θ)
d) 重复步骤 b 和 c,直到收敛或达到预定的迭代次数

学习率 α

学习率决定了每次参数更新的步长。太大可能会导致算法发散,太小则会导致收敛速度过慢。选择合适的学习率是一个重要的超参数调整过程。

梯度下降的变体

a) 批量梯度下降(Batch Gradient Descent): 使用所有训练数据来计算梯度。
b) 随机梯度下降(Stochastic Gradient Descent, SGD): 每次只使用一个样本来计算梯度。
c) 小批量梯度下降(Mini-batch Gradient Descent): 每次使用一小批样本来计算梯度,是前两者的折中。

2.1.2 神经网络与矩阵

网络结构表示

每一层神经元的权重可以表示为一个矩阵。
例如,如果第一层有m个神经元,第二层有n个神经元,那么连接它们的权重可以表示为一个 n × m 的矩阵。

前向传播

使用矩阵乘法可以高效地计算每一层的输出。
如果输入是 X,权重矩阵是 W,偏置是 b,那么输出 Y 可以表示为:Y = WX + b

激活函数

激活函数通常是按元素操作的,可以直接应用于矩阵的每个元素。

反向传播

误差的反向传播也可以用矩阵运算来表示。
梯度的计算涉及到矩阵的转置和矩阵乘法。

批处理

通过将多个输入样本组合成一个矩阵,可以同时处理一批数据。
这大大提高了计算效率,尤其是在GPU上。

卷积操作

在卷积神经网络中,卷积操作可以表示为特殊的矩阵乘法。

参数更新

权重和偏置的更新可以表示为矩阵加法和减法。

优化算法

许多优化算法,如Adam、RMSprop等,都涉及到矩阵操作。

正则化

L1、L2正则化等可以表示为对权重矩阵的操作。

初始化

权重初始化方法(如Xavier、He初始化)通常涉及到对矩阵的操作。

2.2 激活函数

Sigmoid 函数:

公式:f(x) = 1 / (1 + e^(-x))
特点:将输入压缩到 (0, 1) 的范围内,适用于二分类问题,但在深度神经网络中容易出现梯度消失问题。

Tanh 函数:

公式:f(x) = (e^(2x) - 1) / (e^(2x) + 1)
特点:将输入压缩到 (-1, 1) 的范围内,解决了 Sigmoid 函数的零中心问题,但仍存在梯度消失问题。

ReLU 函数 (Rectified Linear Unit):

公式:f(x) = max(0, x)
特点:简单有效,在正区间上是线性函数,在负区间上输出为0,解决了梯度消失问题。但存在神经元死亡问题(输出为0时,梯度为0,权重无法更新)。

Leaky ReLU 函数:

公式:f(x) = max(ax, x),其中 a 是小于1的常数。
特点:解决了 ReLU 函数的神经元死亡问题,允许小的负值通过,但需要额外调整 a 的值。

ELU 函数 (Exponential Linear Unit):

公式:f(x) = x, x >= 0;f(x) = α(e^x - 1), x < 0,其中 α 是大于零的常数。
特点:引入了指数函数,允许负值,解决了 ReLU 的一些问题,但计算量稍大。

Softmax 函数:

公式:f(x_i) = e^(x_i) / Σ(e^(x_k)),其中 i 表示输出层的第 i 个神经元,k 表示所有输出神经元。
特点:通常用于多分类问题,将输出转化为概率分布。

Swish 函数:

公式:f(x) = x · sigmoid(x)
特点:由Google提出,表现良好且易计算。

GELU 函数:

公式:f(x) = x · sigmoid(1.702x)
特点:用于深度神经网络,具有更强的拟合性。

2.3 权重与误差

计算误差

神经网络的目标是通过调整权重来最小化误差。网络的预测输出与真实标签之间的差距通过损失函数计算出来。

误差反向传播:
梯度下降算法利用误差反向传播算法来更新权重:

计算梯度:

误差的梯度是指误差相对于网络中每个权重的变化率。反向传播算法通过链式法则计算每层误差对权重的梯度:
∂ L ∂ w i j \frac{\partial L}{\partial w_{ij}} wijL

更新权重:

使用梯度下降法来调整权重,以最小化损失函数。权重更新公式为:
w i j ( n e w ) = w i j ( o l d ) − α ∂ L ∂ w i j w_{ij}^{(new)} = w_{ij}^{(old)} - \alpha \frac{\partial L}{\partial w_{ij}} wij(new)=wij(old)αwijL
其中, α \alpha α 是学习率。

实例说明

假设我们有一个简单的前馈神经网络:

前向传播

输入: x x x
权重: w w w
输出: y ^ = f ( w ⋅ x + b ) \hat{y} = f(w \cdot x + b) y^=f(wx+b)
计算误差: L ( y , y ^ ) L(y, \hat{y}) L(y,y^)

反向传播

计算误差对输出的梯度: ∂ L ∂ y ^ \frac{\partial L}{\partial \hat{y}} y^L
计算输出对加权输入的梯度: ∂ y ^ ∂ z \frac{\partial \hat{y}}{\partial z} zy^
计算误差对权重的梯度: ∂ L ∂ w = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ z ⋅ ∂ z ∂ w \frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w} wL=y^Lzy^wz
更新权重: w n e w = w o l d − α ⋅ ∂ L ∂ w w_{new} = w_{old} - \alpha \cdot \frac{\partial L}{\partial w} wnew=woldαwL

激活函数对误差和权重计算的影响

不同的激活函数会对误差的计算和权重的更新产生不同的影响:

Sigmoid 和 Tanh: 容易导致梯度消失问题,因为它们的导数在极端值时趋近于零。
ReLU: 提高了梯度的稳定性,但可能会出现神经元死亡的问题。
Leaky ReLU 和 ELU: 解决了 ReLU 的问题,改进了负值的传递。
Softmax: 在分类问题中将输出转换为概率分布,用于多分类任务的损失计算。

2.4 输入层、隐含层和输出层

输入层、隐含层和输出层共同构成了神经网络的基本结构。通过这些层的组合和层与层之间的连接(通过权重和偏置),神经网络能够学习复杂的数据模式并进行有效的预测和分类。每一层的设计和激活函数的选择都会对网络的性能和训练过程产生重要影响。

2.4.1. 输入层 (Input Layer)

定义和功能:

输入层是神经网络的第一层,负责接收原始数据或特征作为输入。
每个输入层节点对应输入数据的一个特征或维度。
输入层的节点数通常由输入数据的特征数确定。
数学表示:

如果输入数据是一个向量 ( x ),则输入层可以表示为 ( x = [x_1, x_2, …, x_n] ),其中 ( n ) 是特征数量。

2.4.2 隐含层 (Hidden Layer)

定义和功能:

隐含层位于输入层和输出层之间,负责处理输入数据并提取其高级特征。
每个隐含层由多个神经元(节点)组成,每个神经元接收来自上一层的输入,并应用激活函数产生输出。
数学表示:

对于第 ( l ) 层的第 ( j ) 个神经元,其输入可以表示为:
[ z_j^{(l)} = \sum_{i} w_{ij}^{(l)} x_i^{(l-1)} + b_j^{(l)} ]
其中 ( w_{ij}^{(l)} ) 是从第 ( l-1 ) 层的第 ( i ) 个神经元到第 ( l ) 层的第 ( j ) 个神经元的权重,( b_j^{(l)} ) 是第 ( l ) 层的第 ( j ) 个神经元的偏置。

2.4.3 输出层 (Output Layer)

定义和功能:

输出层是神经网络的最后一层,负责生成最终的输出。
输出层的节点数通常由任务的要求确定,例如分类任务的类别数量或回归任务的输出维度。
数学表示:

输出层的每个节点对应于神经网络的一个输出值。
在分类问题中,输出层通常会经过 softmax 函数以生成类别概率分布。
在回归问题中,输出层可以直接输出预测的连续值。

3. 图神经网络结构

在这里插入图片描述

3.1 AlexNet

在这里插入图片描述

首先,AlexNet是一个卷积神经网络架构(CNN)。
它包含8个层:5个卷积层和3个全连接层。
使用ReLU(Rectified Linear Unit)激活函数。
采用重叠池化(Overlapping Pooling)。
使用数据增强和Dropout技术来减少过拟合。

它的意义在于首次成功使用GPU进行网络训练,大大加快了训练速度。并引入了Local Response Normalization(LRN)层。

3.2 ResNet

没错,这就是辣个男人的作品,残差网络。
残差网络最重要的突破在于它克服了梯度消失和梯度爆炸问题,这对于使用梯度下降法的传统神经网络是一个非常重要的改进。

3.2.1 核心概念:残差学习

残差学习的核心思想是学习残差函数F(x),而不是直接学习所需的底层映射H(x)。具体来说:

传统方法:直接拟合H(x)
ResNet方法:拟合F(x) = H(x) - x,然后通过F(x) + x 得到H(x)
这种方法使得网络可以更容易学习恒等映射,从而使得非常深的网络也能够有效训练。

3.2.2 残差块(Residual Block)

ResNet 的基本构建块是残差块,其结构如下:

输入 x
经过几层卷积操作(通常是两到三层)
将输出与输入 x 相加(称为跳跃连接或短路连接)
经过 ReLU 激活函数
数学表示:y = F(x, {Wi}) + x

3.2.3 网络架构

ResNet 有多个版本,最常见的有 ResNet-18、ResNet-34、ResNet-50、ResNet-101 和 ResNet-152。以 ResNet-50 为例:

初始卷积层和池化层
4个阶段的残差块堆叠,每个阶段包含多个残差块
全局平均池化
全连接层
Softmax 输出层

3.2.4 主要特点

深度:ResNet 可以训练非常深的网络(如 152 层),而不会出现性能下降。

批量归一化(Batch Normalization):在每个卷积层后使用批量归一化,有助于稳定训练过程。

瓶颈结构:在更深的版本中(如 ResNet-50 及以上),使用了 1x1 卷积的瓶颈结构来减少计算量。

全局平均池化:替代了传统的多层全连接层,减少了参数数量。

参数效率:尽管网络很深,但由于设计巧妙,参数数量并不会过度增加。

3.2.5 ResNet的变体

ResNet 之后出现了许多变体,如:

Wide ResNet:增加了网络的宽度
ResNeXt:引入了分组卷积
DenseNet:在残差连接的基础上进一步增加了密集连接

3.3 EfficientNet

EfficientNet 是由 Google 研究团队在 2019 年提出的一系列卷积神经网络模型,旨在通过平衡网络的宽度、深度和分辨率来提高模型效率。EfficientNet 在保持较低计算成本和参数量的同时,实现了优秀的性能。

3.3.1 核心思想:复合缩放(Compound Scaling)

EfficientNet 的主要创新在于提出了复合缩放方法,同时按照一定比例缩放网络的宽度、深度和分辨率。

网络宽度(Width):增加通道数
网络深度(Depth):增加层数
图像分辨率(Resolution):增加输入图像的尺寸

3.3.2 基础网络:EfficientNet-B0

EfficientNet-B0 是该系列的基础网络,主要由移动倒置瓶颈结构(Mobile Inverted Bottleneck ConvBlock,MBConv)组成,这是从 MobileNetV2 借鉴的结构。

3.3.3 缩放方法

假设总计算量增加 N 倍,EfficientNet 使用如下缩放系数:

深度:d = α^φ
宽度:w = β^φ
分辨率:r = γ^φ
其中 α, β, γ 是通过小网格搜索确定的常数,φ 是用户指定的系数,控制模型大小。

3.3.4 EfficientNet 系列

基于 EfficientNet-B0 和复合缩放方法,研究者提出了 EfficientNet-B1 到 EfficientNet-B7 的一系列模型,每个后续模型都比前一个更大、更强大。

3.3.5 主要特点

高效性:在相同的计算复杂度和参数量下,EfficientNet 系列模型通常能够达到更高的准确率。

可扩展性:复合缩放方法使得模型可以根据可用资源灵活调整大小。

移动友好:基础结构 MBConv 设计轻量,适合在移动设备上部署。

自动搜索:基础网络 EfficientNet-B0 是通过神经架构搜索(NAS)得到的。

注意力机制:使用 Squeeze-and-Excitation(SE)块增强特征表示。

4. 迁移学习

迁移学习是一种机器学习技术,它将已在一个任务上学到的知识(如模型参数、特征表示等)应用到另一个相关任务上。

通常使用在大规模数据集上预训练的模型作为起点,例如在ImageNet数据集上预训练的卷积神经网络(CNN)。
在预训练模型的基础上,使用少量标记数据对模型进行微调,以适应新任务。

在这里插入图片描述
一般我们使用强大的ImageNet来进行数据标记。ImageNet 包含超过1400万张注释过的图像,这些图像分布在超过2.2万个类别中。它的规模之大使得它成为深度学习模型训练和评估的理想数据集。ImageNet 数据集中的图像包含了各种场景、物体、背景和遮挡情况,这为算法提供了极大的挑战。这种多样性使得在 ImageNet 上训练的模型能够学习到鲁棒的特征,从而在现实世界应用中表现良好。

在这里插入图片描述
微调是我们进行迁移学习的主要手段之一。它允许我们利用预训练模型对特定任务进行优化。

其基本原理是,首先在一个大规模的数据集上预训练一个深度学习模型,捕捉通用的特征表示,然后将这个预训练模型作为起点,在目标任务上进行进一步的训练以提升模型的性能。

微调的过程通常开始于选择一个在大型数据集上预训练的模型,这个预训练模型已经学到了丰富的特征表示,这些特征在广泛的领域内都是通用的。接着,我们将这个预训练模型适配到新的目标任务上。适配过程通常涉及以下步骤:

  • 我们会替换模型的输出层,以匹配目标任务的类别数量和类型。例如,如果目标任务是图像分类,而预训练模型原本用于不同的分类任务,我们就需要将模型的最后一层替换成适合新任务类别数的新层。
  • 【可做可不做】我们冻结预训练模型中的大部分层,这样可以防止在微调过程中这些层学到的通用特征被破坏。通常情况下,只对模型的最后一部分层进行解冻,这些层负责学习任务特定的特征。
  • 使用目标任务的数据集对模型进行训练。在这个过程中,我们会用梯度下降等优化算法更新模型的权重,从而使模型能够更好地适应新的任务。训练时,可能会使用比预训练时更低的学习率,以避免过度拟合目标数据集。

在下面代码中,timm.create_model(‘resnet18’, pretrained=True, num_classes=2)这行代码就是加载了一个预训练的ResNet-18模型,其中pretrained=True表示使用在ImageNet数据集上预训练的权重,num_classes=2表示模型的输出层被修改为有2个类别的输出,以适应二分类任务(例如区分真实和Deepfake图像)。通过model = model.cuda()将模型移动到GPU上进行加速。

import timm
model = timm.create_model('resnet18', pretrained=True, num_classes=2)
model = model.cuda()

5. 改进思路

我们可以对视频进行帧提取,面部识别、相似比较这样的手段。

5.1 帧提取

使用openCV能快速进行帧提取:

import cv2

video = cv2.VideoCapture('video.mp4')
success, frame = video.read()
count = 0

while success:
    cv2.imwrite(f"frame{count}.jpg", frame)     # 保存帧为JPEG文件
    success, frame = video.read()
    count += 1

video.release()

或是我们在baseline曾用到的moviePy:

from moviepy.editor import VideoFileClip

clip = VideoFileClip("video.mp4")

for t in range(int(clip.duration)):
    clip.save_frame(f"frame{t}.png", t)

5.2 音频fake

对音频做fake工作,会比对整个视频简单的多,当然,我们之前抽帧也是单独对图像fake的思路:

在这里插入图片描述
这个就是频谱图:
在这里插入图片描述
这个是上次笔记没有见到的梅尔图:
在这里插入图片描述

5.3 特征提取

  • chroma_stft
  • rms
  • spectral_centroid
  • spectral_bandwidth
  • rolloff
  • zero_crossing_rate
  • mfcc
  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城主_全栈开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值