深度学习 其一 图像识别算法

深度学习笔记:

深度学习的输出结果通常是数据(例如概率、分类标签、数值等),这些结果可以用来判断数据集中是否符合某个要求。

1.虚拟环境创建:

1
2
3
# 在项目目录中创建名为 "myenv" 的虚拟环境
python -m venv myenv#用git bash,cmd也行

1
2
3
4
.\myenv\Scripts\activate.bat
#用cmd风格的shell命令
#或者直接在cmd中激活
venv\Scripts\activate
1
2
3
#进入myenv(不进也行)打开git bash
pip install numpy tensorflow
#等待...
pip Python 的包管理工具,名字是 “Pip Installs Packages” 的缩写,用来安装、升级、卸载 Python 包
tensorflow 是一个开源的机器学习框架,Google 开发的,用于构建和训练神经网络模型
install 表示你想安装某个或多个包
numpy 是一个用于科学计算的库,提供多维数组、高效矩阵计算等功能,是深度学习常用的基础库之一
1
2
3
4
#还可以这样:
pip install numpy==1.24.3 tensorflow>=2.10
#== 指定版本
#>= 表示最小版本要求

虚拟环境五步:

1.创建虚拟环境

2.激活

3.安装包

4.使用一下

5.然后清理掉(防止忘了哪里留了残余文件)

1
2
deactivate
#暂时不用这个虚拟环境了,退出一下,回到系统默认的 Python 环境。这个操作不会删除任何东西,只是退出激活状态。

删除虚拟环境(把环境包括文件彻底删除掉)

1
2
#在git bash里面
rm -rf myenv

2.深度学习各函数:

3.图像识别算法实验:

1.用CNN实现图像分类:

CNN:卷积神经网络(图像处理方面)

应用领域 例子
图像识别 猫狗识别、手写数字识别(MNIST)、人脸识别
图像分割 医学图像分割、道路分割
视频分析 安全监控、动作识别
自然语言处理 文本分类(比如情感分析)

CNN的大致结构:

输入图像 → 卷积层 → 激活层(ReLU) → 池化层 → 卷积层 → 池化层 → 全连接层 → 输出

1. 卷积层(Convolution Layer)

  • 使用小的滤波器(kernel)在图像上滑动,提取边缘、纹理、角点等特征。
  • 类似人类用眼睛扫视一个图像局部。

2. 激活函数(通常是 ReLU)

  • 非线性转换,帮助网络学到复杂的特征。

3. 池化层(Pooling Layer)

  • 用来降低图像尺寸,减少计算量,防止过拟合。
  • 常用的是最大池化(MaxPooling)。

4. 全连接层(Fully Connected Layer)

  • 最后用全连接层(类似普通神经网络)进行分类输出。

2.安装所需库

1
2
#git bash
pip install tensorflow keras numpy matplotlib

3.从 TensorFlow 内置的 MNIST 数据集中加载训练集和测试集,分为图像数据和对应的标签。

1
2
3
from tensorflow.keras.datasets import mnist#表示从 TensorFlow 中引入一个自带的数据模块 —— mnist。
(x_train, y_train), (x_test, y_test) = mnist.load_data()#这是调用加载函数,返回 一个元组,里面嵌套两个子元组:
#
1
2
D:\0001深度学习\porject01\myenv\Scripts\activate
#一定要激活,可以就在编译器的终端激活

4.最后跑完会生成一个模型文件cnn_model.h5

神经网络:

1.神经网络基本架构:

绝大多数的神经网络基本都可分为8大部分:

1.输入层

2.隐藏层

3.输出层

4.连接方式

5.向前传播

6.损失函数

7.反向传播

8.优化器

结构上:

按顺序来分为 输入层->隐藏层->输出层 这三部分

连接方式(各层之间的连接细节):

连接方式

一轮训练中的流程:

向前传播:即从输入层到隐藏层,最后到输出层这样一个传播过程,最后得到一个预测结果,这一步说白了就是进行一遍结构初始的三部分,然后进入下面3个流程(那这个预测结果后面会被保存用来参与模型的形成吗

1.预测结果本身不会保存模型里面,会用来和真实数据对比,计算损失(那每轮训练都是根据数据集里面的一个数据来吗,下一轮是不是就进入下一个数据集?这个真实标签是我们自己输入的吗,我们能自己输入这个真实标签吗,还是说只能用数据集提供好的,数据集都会提供一个真实标签吗
1.训练的时候一般有3种:逐个样本(SGD),小批量(mini-batch),全量(batch),最常用的是min-batch小批量。每一轮会遍历整个数据集,每个样本都会用到(这每一轮是什么意思,是执行这8个步骤的一个循环吗,那这一轮就用到了整个数据集的每个样本,下一轮怎么办,重复吗,有什么意义?

1.每一轮通常指一个epoch,一个epoch里面进行多个小批量的循环训练,在一轮中训练了所有的样本,下一轮通常为了更好地泛化,会打乱所有样本的数据,多轮学习可以让模型不断学习,而不只是只记住了死的数据而没有学会规律(这个轮次是我们手动定义的吗?)

2.数据集真实标签通常由数据集提供自带,大部分公开数据集(如MINST,CIFAR-10)都自带有标签,如果我们自己做数据集,也可以自己输入真实标签(比如一张图片-》图片文件名,文件夹名,Excel表名)(那我们使用这些数据集的时候怎么调用这些标签呢?

损失函数:用输出层的预测结果和实际标签来计算损失(那这个实际标签怎么来定呢?这个预测结果如果不符合标签,但是确实是正确的,那该怎么办?错误的预测结果又有什么用?如果有损失,那这个损失又有什么用?

1.标签通常在数据集里面,比如说猫和狗这个类别,通常是人工标注或已有数据集给出(怎么标注?数据集不是一张张图片吗
最简单的:为每张图配一个图片当做标签,如猫狗(是创建一个图片的文件吗?),标注也可以用文件夹进行分类,如cat/xxx.jpg(就是把数据集放在一个标签如cat命名的文件夹里吗,然后编译器会自动识别文件名作为标签?)复杂任务如目标检测和分割时,会用专门的标注工具如LabelImg、LabelMe生成xml、json等标注文件,记录每个目标的位置和类别
2.如果预测结果不符合实际标签但又没有错,那标签是错的,要更改真实标签
3.错误的预测结果的损失较大,模型会知道自己哪里有问题,并在会在后续训练中调整参数,减少类似错误(这个知道并调整的过程是怎么实现的?是通过某个损失的大小来对参数做更改吗?,那模型训练过程中是不是还要加上一个逻辑,使每次训练的时候让模型的参数往损失小的方向改变?那如果是这样,改变的大小幅度是多少?大吗?
1.每次通过反向传播用根据前向传播计算的损失计算出每个参数的梯度,根据梯度往损失小的方向调整参数,参数改变的幅度由学习率决定,学习率大,参数改变幅度大,反之小,学习率要选择适当,不然改变会过大或者过小(即参数损失函数的导数)(那梯度是不是对损失函数求导,然后对应参数带入导数中就是梯度?学习率是我们自己选择的吗?我们怎么选择?
4.损失越大,模型预测结果就越差,就要优化,损失函数就是引导模型不断地优化

反向传播:根据损失函数用输出层的预测结果计算出的损失来计算每个参数对损失的影响(计算每个参数对损失的影响有什么作用?这是怎么计算的?那计算的影响的波动就是梯度吗?这梯度有什么意义

1.反向传播就是要知道如果每个参数变大一点或者变小一点,损失会怎么变化,好针对调整(这个检测变化的过程是在当前训练中进行,那每次对一个参数已经检测后会把所有结果存储一起在下一轮开始时调整还是一个个检测一个个调整?
1.反向传播是一次性批量地对参数进行计算梯度,然后优化器再一次性对参数进行调整
2.计算每个参数对损失的影响是用链式法则(微积分),自动求导工具(如pytorch,TensorFlow)自动完成(这个过程就是损失函数的运行操作吗?具体来说pytorch和TensorFlow是怎么实现这个操作的?我应该怎么做?
1.pytorch和TensorFlow都支持自动求导(autograd),只需定义网络结构和损失函数,框架会自动追踪计算图,自动完成反向传播和梯度计算(这里网络结构和损失函数是怎么定义的?有固定的模版吗??定义之后又是怎么调用的?
2.以pytorch为例,调用求导:(这就是这几步的所有内容吗?
1
2
3
4
loss=loss_fn(pre,label) #计算损失(这参数又是什么意思?)
loss.backward() #自动反向传播,计算所有参数的梯度
optimizer.step() #优化器更新参数
optimizer.zero_gard() #优化清零,准备下一次迭代
3.梯度就是损失函数对每个参数的导数,表示参数每变化一点,损失会怎么变,梯度的方向指向损失增加最快的方向,我们要反梯度方向调整参数,让损失变小(那损失函数就是对每个参数求导,然后看参数的变化率吗?再和真实标签进行比较?那参数实际是函数里面的一个自变量吗所以才能求导?
1.是的,参数就是损失函数的自变量,所以可以对其进行求导,损失函数就是对每个参数求导,说白了就是对损失函数求导,对应梯度就是对应的参数带入导函数

优化器:利用反向传播计算出的度,更新网络中的参数,使模型表现更好(这就是说现在还是处于模型训练阶段对吧,怎么能通过梯度来更新网络中的参数?实际是根据每个参数损失函数大小来定的吗?那第一次训练的参数是怎么形成的?是自己输入的吗?

1.是的,优化器是用于训练阶段的
2.通过梯度来更新参数的具体操作是:新参数=旧参数-学习率*梯度(这个学习率又是什么,为什么通过这个公式就能更新参数,具体的原理是什么?
1.学习率是一个超参数,用来控制每次参数更新的步长,即变化幅度,学习率过大,会导致训练结果不稳定,学习率过小,会导致训练过慢,导致结果可能最终陷入局部最优(始终在某一块局部训练)
2.更新参考公式:
  • $$
    θnew=θold−η*⋅∂θ/∂L
    $$

  • θ:模型参数(如权重、偏置)

  • η:学习率

  • ∂θ/∂L:损失函数对参数的梯度

  • 其实就是上面那个 新参数=旧参数-学习率*梯度

3.参数是根据梯度来定,而不是损失本身(参数的导数?那计算梯度是不是反向传播的作用实际只是用来反向遍历一遍每个参数,然后损失函数对梯度的计算起决定作用?
1.是的,反向传播的核心是利用损失函数对每个参数求导求出梯度,损失函数的形式决定了梯度的计算方式和数值,梯度的大小和方向直接影响参数的更新(那这样损失又有什么用?直接求梯度不就行了,根据梯度来进行优化,损失函数的形式怎么定义,有哪些?
4.第一次训练的参数一般是随机初始化的,由深度学习框架自动生成一组初始参数(通常是很小的随机数)(这是怎么生成的?既然有参数,那应该也有导入参数的变量吧,那变量在哪里,是怎么用的?)
1.框架会自动为每一层参数分配变量,并用特定的方法(如高斯分布、均匀分布、Xavier、He初始化等)生成初始值,这样是让网络一开始就有多样性,避免所有神经元学到一样的东西(这里神经元是什么?为什么要避免所有神经元学到一样的东西?
2.只需定义网络结构,框架就会自动初始化参数