【Python · PyTorch】卷积神经网络(基础概念)
【Python · PyTorch】卷积神经网络 CNN(基础概念)
- 0. 生物学相似性
- 1. 概念
- 1.1 定义
- 1.2 优势
- 1.2.1 权重共享
- 1.2.2 局部连接
- 1.2.3 层次结构
- 1.3 结构
- 1.4 数据预处理
- 1.4.1 标签编码
- ① One-Hot编码 / 独热编码
- ② Word Embedding / 词嵌入
- 1.4.2 归一化
- ① Min-Max归一化(最大最小归一化)
- ② Z-Score归一化(标准化 Standardization)
- 2. 基础概念
- 2.2.1 卷积层
- ① 一维卷积
- ② 二维卷积
- 单通道单卷积核
- 单通道多卷积核
- 多通道单卷积核
- 多通道多卷积核
- ③ 互相关
- 2.2.2 辅助操作
- ① 卷积步长
- ② 零填充
- 2.2.3 池化层 / 汇聚层
- ① 最大池化
- ② 平均池化 / 均值池化
- 2.2.4 感受野
- 2.2.5 空洞卷积 / 膨胀卷积
- ① Gridding Effect 现象
- ② 如何设计膨胀系数?
- 2.2.6 可分离卷积
- ① 空间可分离卷积
- ② 深度可分离卷积
- 2.2.7 扁平卷积
- 2.2.8 分组卷积
- 2.2.9 混洗分组卷积
- 2.2.10 上采样 vs 下采样
- ① 上采样
- ② 下采样
- 2.2.11 上采样
- ① 转置卷积
- 微步卷积
- ② 插值
- 最近邻插值
- 双线性插值
- 双三次插值
- ③ 反池化
- 反最大池化
- 反平均池化
- 3. 评估方法
- 3.1 混淆矩阵
- 3.2 精确度
- 3.3 其他指标
0. 生物学相似性
卷积神经网络从猫视觉皮层电生理研究中获得启发,通过仿造生物的视知觉机制来构建模型。卷积网络中卷积核的设定就对应着视觉神经系统中视觉皮层对视觉空间的组织。
视觉皮层细胞从视网膜上的光感受器接收信号,但单个视觉皮层细胞不会接收光感受器的所有信号,而是只接受其所支配的刺激区域,即感受野内的信号。只有感受野内的刺激才能够激活该神经元。多个视觉皮层细胞通过系统地将感受野叠加,完整接收视网膜传递的信号并建立视觉空间 。
卷积神经网络中基于感受野设定的稀疏连接有明确对应的神经科学过程——视觉神经系统中视觉皮层(visual cortex)对视觉空间(visual space)的组织 。视觉皮层细胞从视网膜上的光感受器接收信号,但单个视觉皮层细胞不会接收光感受器的所有信号,而是只接受其所支配的刺激区域,即感受野内的信号。只有感受野内的刺激才能够激活该神经元。多个视觉皮层细胞通过系统地将感受野叠加完整接收视网膜传递的信号并建立视觉空间。
事实上机器学习的“感受野”一词即来自其对应的生物学研究。卷积神经网络中的权重共享的性质在生物学中没有明确证据,但在对与大脑学习密切相关的目标传播(target-propagation, TP)和反馈调整(feedback alignment, FA) 机制的研究中,权重共享提升了学习效果 。
1. 概念
1.1 定义
卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一 。
卷积神经网络具有表征学习(representation learning)能力,能够按其阶层结构对输入信息进行平移不变分类(shift-invariant classification),因此也被称为“平移不变人工神经网络(Shift-Invariant Artificial Neural Networks, SIANN)” 。
应用领域:计算机视觉、音频识别
1.2 优势
1.2.1 权重共享
使用相同的权重参数对输入数据进行处理,从而减少模型的参数数量,降低计算复杂度,并提高模型的泛化能力;在卷积神经网络中主要体现在卷积核 (过滤器)。
在卷积神经网络中,权值共享是指在卷积层中,同一个卷积核在不同位置上的权值是相同的,这样可以大大减少模型参数,提高模型泛化能力。
权值/权重独立与CNN的权重共享不同:
1.2.2 局部连接
在卷积神经网络中,局部连接是指在卷积层中,每个卷积核只与输入数据的一部分进行卷积运算,而不是与整个输入数据进行卷积运算,这样可以提取出局部特征,增强模型的特征提取能力。
用类比卷积神经网络的方式描述全连接:
1.2.3 层次结构
卷积神经网络是一种包含卷积计算且具有深度结构的前馈神经网络,其所包含的层次结构如下:
输入层:接收原始图像数据或其他类型的网格结构数据。
卷积层:卷积层是CNN的核心,通过卷积操作提取输入数据的局部特征。每个卷积核可以提取一种特定的特征,多个卷积核可以并行工作以提取不同类型的特征。卷积操作通过滤波器对局部输入数据进行内积计算,滤波器在数据窗口上滑动,计算每个局部数据的输出。
激活层:激活层用于提升网络的非线性能力,通常跟在卷积层之后,其能够解决梯度消失问题、加快收敛速度。
池化层:池化层对卷积层的输出进行下采样 (降维),以减少参数数量并提高计算效率。
全连接层:全连接层负责将前面层提取的特征综合起来,用于分类或回归等任务。全连接层的每个神经元都与前一层的所有神经元相连。
BatchNorm层:BN层通过规范化手段将每层神经网络的输入值的分布强行拉回到均值为0,方差为1的标准正态分布,以加快训练速度并减小图像之间的绝对差异。
1.3 结构
输入层:输入接收数据集,处理原始图像数据。
卷积层:通过卷积操作提取图像特征,卷积操作使用滤波器 (卷积核) 对图像的局部区域进行内积运算,提取特征。
激活层:对卷积层的输出应用非线性激活函数,引入非线性以增强网络的表达能力。
池化层:通过下采样减少数据的维度和参数数量,通常有两种方式:最大池化和平均池化。
全连接层:在网络的最后部分,将前面的特征图展平后进行分类/回归任务。
1.4 数据预处理
1.4.1 标签编码
① One-Hot编码 / 独热编码
One-Hot编码 / 独热编码:一种常用于机器学习中的特征编码方式,主要用于处理分类数据。它的基本思想是将分类变量转换为机器学习算法易于处理的形式。
-
例如:MNIST数据集共有10个分类结果,若利用独热编码其可表示为:
↓ 编码下标 \ 分类结果 → 0 1 2 3 4 5 6 7 8 9 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 4 0 0 0 0 1 0 0 0 0 0 5 0 0 0 0 0 1 0 0 0 0 6 0 0 0 0 0 0 1 0 0 0 7 0 0 0 0 0 0 0 1 0 0 8 0 0 0 0 0 0 0 0 1 0 9 0 0 0 0 0 0 0 0 0 1
用途
- 更易于表示分类
- 适用于多种算法
② Word Embedding / 词嵌入
Word Embedding / 词嵌入:一种自然语言处理机器学习任务中常用的特征编码方式,便于机器学习算法读取文本信息并理解相关内容。通过词嵌入将单词转变为在预定义的向量空间中的实数向量,每个单词都映射到一个向量。
目的:通过数字替代字母,从而便于程序进行运算,还可完成词语间相似度、词语间关联等计算。而独热编码无法胜任此项工作,故利用词嵌入实现。
常见的词嵌入模型:EmbeddingLayer算法、Word2Vec模型、Glove模型、FastText模型
举例:“猫”对应的向量为 a ⃗ = [ 0.1 0.2 0.3 ] \vec{a}=\begin{bmatrix}0.1\\0.2 \\ 0.3\end{bmatrix} a= 0.10.20.3 ,“虎”对应的向量为 b ⃗ = [ 0.2 0.2 0.4 ] \vec{b}=\begin{bmatrix}0.2\\0.2\\0.4\end{bmatrix} b= 0.20.20.4 ,“鹰”对应的映射为 c ⃗ = [ − 0.4 − 0.5 − 0.2 ] \vec{c}=\begin{bmatrix}-0.4\\-0.5\\ -0.2\end{bmatrix} c= −0.4−0.5−0.2
计算 猫&虎、猫&鹰 间的余弦相似度,余弦相似度公式如下:
c o s < a ⃗ , b ⃗ > = a ⃗ ⋅ b ⃗ ∣ ∣ a ⃗ ∣ ∣ ∣ ∣ b ⃗ ∣ ∣ cos\left<\vec{a},\vec{b}\right>=\frac{\vec{a}\cdot\vec{b}}{||\vec{a}||\space||\vec{b}||} cos⟨a,b⟩=∣∣a∣∣ ∣∣b∣∣a⋅b
余弦相似度的取值范围为 [ − 1 , 1 ] [-1,1] [−1,1],当两个向量的夹角为180°时,余弦相似度为-1。
余弦相似度衡量的是两个向量之间的夹角,其值的符号表示向量之间的方向关系,数值的大小表示它们的相似程度。
当两个向量的夹角为0度时,即完全重合,余弦相似度为1;当两个向量的夹角为90度时,即正交或无关,余弦相似度为0;当两个向量的夹角为180度时,即完全相反,余弦相似度为-1。
计算过程:
import torch
import torch.nn as nna = torch.tensor([0.1, 0.2, 0.3], dtype=torch.float)
b = torch.tensor([0.2, 0.2, 0.4], dtype=torch.float)
c = torch.tensor([-0.4, -0.5, -0.2], dtype=torch.float)# 计算两个余弦值的余弦相似度
cos = nn.CosineSimilarity(dim=0, eps=1e-6)output1 = cos(a, b)
output2 = cos(a, c)
output1, output2
计算结果:
(tensor(0.9820), tensor(-0.7968))
由此可得出结论:猫与虎更接近,猫与鹰完全相反。
1.4.2 归一化
归一化:归一化是一种常见的数据预处理技术,用于将数据转换为统一的比例范围,以消除不同变量之间的量纲差异
用途
- 消除量纲差异:消除单位差异
- 避免权重不平衡:避免因数值范围差异大引起的权重不平衡问题
- 加速模型收敛
① Min-Max归一化(最大最小归一化)
将数据线性地映射至一个区间(例如:[0,1] 或 [-1,1])
x ∗ = x − M i n ( x ) M a x ( x ) − M i n ( x ) x^*=\frac{x-Min(x)}{Max(x)-Min(x)} x∗=Max(x)−Min(x)x−Min(x)
其中, x x x是原始数据, x ∗ x^* x∗是归一化后数据。
x # 评估器导入
from sklearn.preprocessing import MinMaxScaler#评估器实例化
scaler = MinMaxScaler() # 评估器实例化:默认映射[0.1]区间
scaler = scaler.fit(data) # 计算min(x)、max(x)
# scaler = MinMaxScaler(feature_range=[5,10]) # 映射至除[0.1]其他区间
result = scaler.transform(data)
② Z-Score归一化(标准化 Standardization)
将数据映射至 均值为0 标准差为1 的标准正态分布的一个区间。
x ∗ = x − μ σ x^*=\frac{x-\mu}{\sigma} x∗=σx−μ
其中, x x x是原始数据, x ∗ x^* x∗是标准化后的数据, μ \mu μ是原始数据的均值, σ \sigma σ是原始数据的标准差。
# 评估器导入
from sklearn.preprocessing import StandardScaler# 评估器实例化
scaler = StandardScaler()
scaler.fit(data)
scaler.transform(X)
2. 基础概念
2.2.1 卷积层
卷积(Convolution),分析数学中的一种运算。在信号或图像处理中,经常使用一维或二维卷积。
卷积运算是卷积神经网络的核心,它通过在音频/图像上滑动卷积核,计算核与图像的局部区域的点积,从而形成 特征图(Feature Map)。
卷积运算捕捉了图像的局部关联并保留了图像的空间关系,卷积神经网络依靠卷积运算实现图像平移不变性。
卷积意义
卷积数学公式:
∫ 0 t f ( x ) g ( t − x ) d x \int^t_0f(x)g(t-x)dx ∫0tf(x)g(t−x)dx
在卷积运算中,可理解为 瞬时行为的持续性后果,可类比蝴蝶效应。
在图像识别领域中, f ( ⋅ ) f(·) f(⋅)等同于图像, g ( ⋅ ) g(·) g(⋅)等同于卷积核,通过卷积运算可求得周围像素对中间像素的影响程度,或被扫描区域对卷积核/过滤器过滤的响应程度。滑动过程中所遇两者外形越相似,则卷积得到的响应越高。卷积神经网络中,卷积核实际上在提取某种局部特征,图片中与该卷积核过滤所需 越相似的区域响应越高。
卷积 三种意义:
- 一个系统 + 输入不稳定 + 输出稳定 + 用卷积求系统存量
- 输入不稳定:输入数据存在差异(如 x x x和 x \mathscr{x} x)
- 输出稳定:变化趋势稳定
- 用卷积求系统存量:求变化后的系统总存量,这一过程持续故采用积分形式
- 周围像素点如何影响中间像素点
- 周围像素点与中间像素点共同构成局部特征
- 通过神经网络对局部特征进行归纳识别从而得出分类/预测结果
- 对周围位置的试探
- 过滤器过滤保留有用特征,交由神经网络判断结果
在图像识别领域中,像素为离散点,故将积分更换为求和,两种维度卷积情况如后文所示。
① 一维卷积
一维卷积一般用于 音频/时序数据 的处理,一维卷积公式如下:
y t = ∑ k = 1 K w k x t − k + 1 y_t=\sum^{K}_{k=1}w_kx_{t-k+1} yt=k=1∑Kwkxt−k+1
其中: x t − k + 1 x_{t-k+1} xt−k+1表示输入的信号序列, w k w_k wk表示 滤波器 (卷积核), y t y_t yt表示输出。
向量形式:
y = w ∗ x \boldsymbol{y}=\boldsymbol{w} \ast \boldsymbol{x} y=w∗x
其中: w \boldsymbol{w} w和 x \boldsymbol{x} x分别为滤波器和输入信号的向量形式, ∗ \ast ∗表示卷积运算, y \boldsymbol{y} y表示输出。
② 二维卷积
二维卷积一般用于 图像/视频数据 的处理,二维卷积公式如下:
y i j = ∑ u = 1 U ∑ v = 1 V w u v x i − u + 1 , j − v + 1 y_{ij}=\sum^{U}_{u=1}\sum^{V}_{v=1}w_{uv}x_{i-u+1,j-v+1} yij=u=1∑Uv=1∑Vwuvxi−u+1,j−v+1
矩阵形式:
Y = W ∗ X \boldsymbol{Y}=\boldsymbol{W} \ast \boldsymbol{X} Y=W∗X
其中: W \boldsymbol{W} W和 X \boldsymbol{X} X分别为滤波器和输入信号的矩阵形式, ∗ \ast ∗表示卷积运算, Y \boldsymbol{Y} Y表示输出。
单通道单卷积核
卷积也可以拥有偏置,这种单一卷积核的情况称为单通道单卷积核。
单通道多卷积核
某些情况下,可使用多个卷积核完成不同类型特征的提取。
卷积核可以认为是具有识别某一类元素(特征)的能力,而对于一些复杂结构的数据来说仅仅只是通过一类特征来进行辨识往往是不够的,因此,通常来说我们都会通过多个不同的卷积核来对输入进行特征提取得到多个特征图,然再输入到后续的网络中进行后续任务。
多通道单卷积核
多通道的单卷积核天生针对每个通道进行操作,所以实际上还是视作单个卷积核。
RGB合成示意图
多通道多卷积核
多通道也可以利用多卷积核针对不同通道分别提取多种不同种类的特征。
③ 互相关
**互相关 (Cross-Correlation) **→ 不翻转卷积:用滑动窗口的点积 → 衡量两个序列的相关性
它与卷积的区别仅仅在于是否翻转:翻转指所有维度颠倒次序 → 即旋转180°(二维 → 上下颠倒+左右颠倒)
y i j = ∑ u = 1 U ∑ v = 1 V w u v x i + u − 1 , j + v − 1 y_{ij}=\sum^{U}_{u=1}\sum^{V}_{v=1}w_{uv}x_{i+u-1,j+v-1} yij=u=1∑Uv=1∑Vwuvxi+u−1,j+v−1
矩阵形式:
Y = W ⊗ X = r o t 180 ( W ) ∗ X \begin{equation} \begin{aligned} Y &= \boldsymbol{W} \otimes \boldsymbol{X} \\ &= rot180(\boldsymbol{W}) \ast \boldsymbol{X} \end{aligned} \end{equation} Y=W⊗X=rot180(W)∗X
2.2.2 辅助操作
① 卷积步长
卷积步长:卷积核每次扫描间距,一般用字母 k k k或 K K K表示。
一维情况
卷积步长 s = 2 s=2 s=2
二维情况
卷积步长 s = 2 s=2 s=2
② 零填充
零填充:为原始输入特征周围填充若干圈零元素,一般用字母 p p p或P表示。
卷积类型:
- 窄卷积 (Narrow Convolution):步长 s = 1 s=1 s=1,两端不补零 p = 0 p=0 p=0,卷积后输出长度为 m − k + 1 m-k+1 m−k+1。
- 宽卷积 (Wide Convolution):步长 s = 1 s=1 s=1,两端补零 p = k − 1 p=k-1 p=k−1,卷积后输出长度为 m + k − 1 m+k-1 m+k−1。
- 等宽卷积 (Equal-Width Convolution):步长 s = 1 s=1 s=1,两端补零 p = k − 1 2 ,卷积后输出长度为 p=\frac{k-1}{2},卷积后输出长度为 p=2k−1,卷积后输出长度为m。
2.2.3 池化层 / 汇聚层
池化层 (Pooling Layer):又称汇聚层
**池化 (Pooling):**属于下采样(Down Sampling)
作用:特征筛选 → 减少特征数量 → 减少后续层参数数量
① 最大池化
最大池化 (Maximum Pooling):取区域内所有神经元最大激活值
② 平均池化 / 均值池化
平均池化 (Mean Pooling):取区域内所有神经元激活值均值
2.2.4 感受野
感受野 (Receptive Field):卷积神经网络每一层输出的特征图 (Feature Map) 上的像素点在输入图片上映射的区域大小。
生物学 - 感受野 :视觉皮层细胞从视网膜上的光感受器接收信号,但单个视觉皮层细胞不会接收光感受器的所有信号,而是只接受其所支配的刺激区域,即感受野内的信号。只有感受野内的刺激才能够激活该神经元。多个视觉皮层细胞通过系统地将感受野叠加,完整接收视网膜传递的信号并建立视觉空间 。
感受野计算公式:
l k = l k − 1 + [ ( f k − 1 ) ∗ ∏ i = 0 k − 1 s i ] l_k=l_{k-1}+[(f_k-1) \ast \prod^{k-1}_{i=0}s_i] lk=lk−1+[(fk−1)∗i=0∏k−1si]
其中 , l k − 1 l_{k-1} lk−1为第 k − 1 k − 1 k−1层对应的感受野大小, f k f_k fk为第 k k k层卷积层的卷积核大小 / 第 k k k层池化层的池化尺寸大小, s i s_i si为步长stride。
感受野绘制工具 (开源)(作者:WZMIAOMIAO)
该工具代码如下:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormapdef dilated_conv_one_pixel(center: (int, int),feature_map: np.ndarray,k: int = 3,r: int = 1,v: int = 1):"""膨胀卷积核中心在指定坐标center处时,统计哪些像素被利用到,并在利用到的像素位置处加上增量vArgs:center: 膨胀卷积核中心的坐标feature_map: 记录每个像素使用次数的特征图k: 膨胀卷积核的kernel大小r: 膨胀卷积的dilation ratev: 使用次数增量"""assert divmod(3, 2)[1] == 1# left-top: (x, y)left_top = (center[0] - ((k - 1) // 2) * r, center[1] - ((k - 1) // 2) * r)for i in range(k):for j in range(k):feature_map[left_top[1] + i * r][left_top[0] + j * r] += vdef dilated_conv_all_map(dilated_map: np.ndarray,k: int = 3,r: int = 1):"""根据输出特征矩阵中哪些像素被使用以及使用次数,配合膨胀卷积k和r计算输入特征矩阵哪些像素被使用以及使用次数Args:dilated_map: 记录输出特征矩阵中每个像素被使用次数的特征图k: 膨胀卷积核的kernel大小r: 膨胀卷积的dilation rate"""new_map = np.zeros_like(dilated_map)for i in range(dilated_map.shape[0]):for j in range(dilated_map.shape[1]):if dilated_map[i][j] > 0:dilated_conv_one_pixel((j, i), new_map, k=k, r=r, v=dilated_map[i][j])return new_mapdef plot_map(matrix: np.ndarray):plt.figure()c_list = ['white', 'blue', 'red']new_cmp = LinearSegmentedColormap.from_list('chaos', c_list)plt.imshow(matrix, cmap=new_cmp)ax = plt.gca()ax.set_xticks(np.arange(-0.5, matrix.shape[1], 1), minor=True)ax.set_yticks(np.arange(-0.5, matrix.shape[0], 1), minor=True)# 显示color barplt.colorbar()# 在图中标注数量thresh = 5for x in range(matrix.shape[1]):for y in range(matrix.shape[0]):# 注意这里的matrix[y, x]不是matrix[x, y]info = int(matrix[y, x])ax.text(x, y, info,verticalalignment='center',horizontalalignment='center',color="white" if info > thresh else "black")ax.grid(which='minor', color='black', linestyle='-', linewidth=1.5)plt.show()plt.close()def main():# bottom to topdilated_rates = [1, 2, 3]# init feature mapsize = 31m = np.zeros(shape=(size, size), dtype=np.int32)center = size // 2m[center][center] = 1# print(m)# plot_map(m)for index, dilated_r in enumerate(dilated_rates[::-1]):new_map = dilated_conv_all_map(m, r=dilated_r)m = new_mapprint(m)plot_map(m)if __name__ == '__main__':main()
2.2.5 空洞卷积 / 膨胀卷积
空洞卷积 (Atrous Convolution) / 膨胀卷积 (Dilated Convolution)
作用:增大感受野、保持原输入特征图W、H(Padding后)
卷积神经网络 - 4个核心参数:
- 卷积间隙 (膨胀因子 / 膨胀系数) r r r
- 卷积核大小 k k k
- 填充 p p p
- 步长 s s s
空洞卷积 在语义分割中的应用:
- 图片下采样提取后再上采样还原尺寸
- 下采样倍率不能过大,VGG maxpooling丢失细节信息/目标,上采样无法还原
- maxpooling层去除得到特征图感受野变小,影响后面的卷积层
- 此时需要用到膨胀卷积:既能增加感受野、输入输出矩阵高宽不发生改变
① Gridding Effect 现象
Gridding Effect 现象:感受野间存在不连续间隔
实验一
r 1 = 2 , r 2 = 2 , r 3 = 2 ; k = 3 r_1=2,\space r_2=2,\space r_3=2;\space k=3 r1=2, r2=2, r3=2; k=3
像素利用热度:累加计算L4利用L1像素的次数
r r r相同 → 连续堆叠3层:L4利用L1像素数据并非连续 / 存在间隔 → 丢失细节信息 → 出现 Grid Effect
实验二
r 1 = 1 , r 2 = 1 , r 3 = 1 ; k = 3 r_1=1,\space r_2=1,\space r_3=1;\space k=3 r1=1, r2=1, r3=1; k=3
感受野:累加计算 L4 利用 L1(原始图像) 像素的次数,即为其连续时所能覆盖的大小
该实验中 感受野大小: R F ( R e c e p t i v e F i e l d ) = 7 × 7 RF(Receptive Field) = 7 \times 7 RF(ReceptiveField)=7×7
普通卷积: r = 1 r=1 r=1相同 → 连续堆叠3层:L4利用L1像素数据连续 → 感受野较小
实验三
r 1 = 1 , r 2 = 2 , r 3 = 3 ; k = 3 r_1=1,\space r_2=2,\space r_3=3;\space k=3 r1=1, r2=2, r3=3; k=3
该实验中 感受野大小: R F ( R e c e p t i v e F i e l d ) = 13 × 13 RF(Receptive Field) = 13 \times 13 RF(ReceptiveField)=13×13
r r r相异 → 连续堆叠3层:L4利用L1像素数据连续 → 避免 Grid Effect → 感受野大
结论:当卷积核大小相同时,为空洞卷积设置合适的膨胀系数可增大感受野。
② 如何设计膨胀系数?
论文链接
将上述选取 r r r值过程连续,假设连续堆叠 n n n 个 k × k k \times k k×k 膨胀卷积。
Hybrid Dilated Convolution (HDC) 问题目标:通过一系列堆叠膨胀卷积,最终形成覆盖底层无孔洞方形区域;最终目标 M 2 ≤ K M_2 \le K M2≤K。
若给出待验证的膨胀系数 r ⃗ = [ r 1 , r 2 , … , r n ] \vec{r}=[r_1,r_2,\dots,r_n] r=[r1,r2,…,rn],令 M n = r n M_n=r_n Mn=rn,则从第 n n n层系数一次计算至第 1 1 1层:
M i = m a x [ M i + 1 − 2 r i , M i + 1 − 2 ( M i + 1 − r i ) , r i ] M_i=max[M_{i+1}-2r_i,M_{i+1}-2(M_{i+1}-r_i),r_i] Mi=max[Mi+1−2ri,Mi+1−2(Mi+1−ri),ri]
其中: M M M为第 i i i层两非零元素距离最大值, r i r_i ri为需验证的第 i i i层膨胀系数。
选值一
r 1 = 1 , r 2 = 2 , r 3 = 5 ; k = 3 r_1=1,\space r_2=2,\space r_3=5;\space k=3 r1=1, r2=2, r3=5; k=3
令 M 3 = r 3 = 5 M_3=r_3=5 M3=r3=5,则:
M 2 = m a x [ 5 − 4 , 5 − 2 ( 5 − 2 ) , 2 ] = 2 M 1 = m a x [ 2 − 2 , 2 − 2 ( 2 − 2 ) , 1 ] = 1 \begin{equation} \begin{aligned} M_2 &= max[5-4,5-2(5-2),2]=2 \\ M_1 &= max[2-2,2-2(2-2),1]=1 \end{aligned} \end{equation} M2M1=max[5−4,5−2(5−2),2]=2=max[2−2,2−2(2−2),1]=1
此时:满足条件 M 2 ≤ k M_2 \le k M2≤k,故不存在Grid Effect现象。
选值二
r 1 = 1 , r 2 = 2 , r 3 = 9 ; k = 3 r_1=1,\space r_2=2,\space r_3=9;\space k=3 r1=1, r2=2, r3=9; k=3
令 M 3 = r 3 = 9 M_3=r_3=9 M3=r3=9,则:
M 2 = m a x [ 9 − 4 , 9 − 2 ( 9 − 2 ) , 2 ] = 5 M 1 = m a x [ 5 − 2 , 5 − 2 ( 5 − 2 ) , 1 ] = 3 \begin{equation} \begin{aligned} M_2 &= max[9-4,9-2(9-2),2]=5 \\ M_1 &= max[5-2,5-2(5-2),1]=3 \end{aligned} \end{equation} M2M1=max[9−4,9−2(9−2),2]=5=max[5−2,5−2(5−2),1]=3
此时:不满足条件 M 2 ≤ k M_2 \le k M2≤k,故存在Grid Effect现象。
原因:我们希望高层特征图利用底层所有像素, M 1 M_1 M1在 M 2 − 2 r 1 M_2-2r_1 M2−2r1、 M 2 − 2 ( M 2 − r 1 ) M_2-2(M_2-r_1) M2−2(M2−r1)和 r 1 r_1 r1中取最大,第1层 M 1 = 1 M_1=1 M1=1时无间隙,则 r 1 r_1 r1必须 = 1 =1 =1,倘若 r 1 > 1 r_1>1 r1>1,则 M 1 > 1 M_1>1 M1>1 会出现间隙。
公约数大于1,也会出现 Grid Effect问题,即每层的利用区域未能实现 “交错”。
结论:公约数不能大于1,否则会出现 Grid Effect问题。
选值三(公约数2大于1)
r 1 = 2 , r 2 = 4 , r 3 = 8 ; k = 3 r_1=2,\space r_2=4,\space r_3=8;\space k=3 r1=2, r2=4, r3=8; k=3
令 M 3 = r 3 = 8 M_3=r_3=8 M3=r3=8,则:
M 2 = m a x [ 8 − 8 , 8 − 2 ( 8 − 4 ) , 8 ] = 8 M 1 = m a x [ 4 − 2 , 4 − 2 ( 4 − 2 ) , 2 ] = 2 \begin{equation} \begin{aligned} M_2 &= max[8-8,8-2(8-4),8]=8 \\ M_1 &= max[4-2,4-2(4-2),2]=2 \end{aligned} \end{equation} M2M1=max[8−8,8−2(8−4),8]=8=max[4−2,4−2(4−2),2]=2
此时:不满足条件 M 2 ≤ k M_2 \le k M2≤k,故存在Grid Effect现象。
文章推荐可使用诸如 [ 1 , 2 , 3 , 1 , 2 , 3 ] [1,2,3,1,2,3] [1,2,3,1,2,3]的锯齿结构设计。下图是是否使用准则训练效果的对比情况,可以看出使用准则效果明显优于未使用准则。
2.2.6 可分离卷积
可分离卷积 (Separable Convolutions):包括 空间可分离卷积(Spatially Separable Convolutions) 和 深度可分离卷积(depthwise separable convolution)。
① 空间可分离卷积
空间可分离卷积 (Spatially Separable Convolutions):将卷积核分解为两项独立的核分别进行操作。
利用向量乘法,将3×3卷积核分解为如下两个小卷积核:
[ − 1 0 1 − 2 0 2 − 1 0 1 ] = [ 1 2 1 ] ⋅ [ − 1 0 1 ] \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \\ \end{bmatrix}= \begin{bmatrix} 1 \\ 2 \\ 1 \\ \end{bmatrix} \cdot \begin{bmatrix} -1 & 0 & 1 \end{bmatrix} −1−2−1000121 = 121 ⋅[−101]
计算流程:先用 3 × 1 3\times1 3×1的卷积核作横向扫描计算,再用 1 × 3 1\times3 1×3的卷积核作纵向扫描计算,最后得到结果,其计算量相较于标准卷积更小。
② 深度可分离卷积
深度可分离卷积 (Depthwise Separable Convolutions):由深度卷积和 1 × 1 1\times1 1×1卷积组成。
深度可分卷积(depthwise separable convolution)是卷积神经网络中对标准的卷积计算进行改进所得到的算法,其通过拆分空间维度和通道(深度)维度的相关性,减少了卷积计算所需要的参数个数,并在一些研究中被证实提升了卷积核参数的使用效率。
深度可分卷积的原型可认为来自于卷积神经网络中的Inception模块,其卷积计算分为两部分,首先对通道(深度)分别进行空间卷积(depthwise convolution),并对输出进行拼接,随后使用单位卷积核进行通道卷积(pointwise convolution)以得到特征图。
在应用方面,深度可分卷积被用于微型神经网络的搭建,也被用于大规模卷积神经网络的结构优化。使用深度可分卷积的深度学习算法包括Xception和MobileNet。
第一步:深度卷积
以彩色图像为例,使用3个卷积核分别对输入层的3个通道作卷积计算,再堆叠在一起。
第二步: 1 × 1 1\times1 1×1卷积
1 × 1 1\times1 1×1卷积可以得到只有1个通道的结果,将 1 × 1 1\times1 1×1卷积过程重复多次。
2.2.7 扁平卷积
扁平卷积 (Flattened convolutions):将标准卷积核拆分为3个 1 × 1 1\times1 1×1的卷积核,再分别对输入层进行卷积计算。
2.2.8 分组卷积
分组卷积 (Grouped Convolution):2012年AlexNet论文中最先提出的概念,当时以解决GPU显存不足问题为目的,将卷积分组后放到两个GPU并行执行。
在分组卷积中,卷积核被分成不同的组,每组负责对相应的输入层进行卷积计算,最后再进行合并。
2.2.9 混洗分组卷积
在分组卷积中,卷积核被分成多个组后,输入层卷积计算的结果仍按照原先的顺序进行合并组合,这就阻碍了模型在训练期间特征信息在通道组之间流动,同时还削弱了特征表示。
而 混洗分组卷积 (Shuffled Grouped Convolution) 将分组卷积后的计算结果混合交叉在一起输出。
如下图,在第一层分组卷积 (GConv1) 计算后,得到的特征图先进行拆组,再混合交叉,形成新的结果输入到第二层分组卷积 (GConv2)中。
2.2.10 上采样 vs 下采样
① 上采样
上采样:将低分辨率的图像或特征图放大到原始分辨率的过程。
计算机视觉中,上采样用于图像分割、目标检测和图像生成等任务,可帮助提高模型的准确性和性能。
常见的上采样方法:转置卷积、双线性插值/最近邻插值等。
其中:双线性插值/最近邻插值是较简单的上采样方法,转置卷积则专用于卷积神经网络。
② 下采样
下采样:将高分辨率的图像或特征图缩小到较低分辨率的过程。
计算机视觉中,下采样用于图像分类、目标检测和图像分割等任务,可帮助减少计算量和内存消耗,加快模型训练及推理速度。
作用:一是减少计算量,防止过拟合
二是增大感受野,使得后面的卷积核能够学到更加全局的信息。
常见的下采样方法:卷积操作、平均池化/最大池化等。
其中:池化操作是一种常用的下采样方法,卷积操作也可实现下采样 ( 步长卷积 / 空洞卷积 )
2.2.11 上采样
常见的上采样方法:转置卷积、双线性插值/最近邻插值等。
① 转置卷积
转置卷积 (Transposed Convolution):即 分数步长卷积 (Fractionally-strided Convolution) / 反卷积 (Deconvolution),一种上采样方法,可增大图像的尺寸。转置卷积不是卷积的逆运算,而是通过特定的操作来恢复图像的原始尺寸。
微步卷积
微步卷积 (Fractionally-Strided Convolution): “步长” < 1 <1 <1 的 转置卷积
实现方式:间隙填充 → 在输入特征间插入0 → 间接减少步长
转置卷积默认参数 s = 1 s=1 s=1,参数 s > 1 s > 1 s>1时则转置卷积称为步长为 1 s \frac{1}{s} s1微步卷积,需在输入特征间插入 s − 1 s − 1 s−1行列的0元素使其移动速度变慢。
运算步骤:
- 间隙 填充:在输入特征图元素间填充 s − 1 s-1 s−1行、 s − 1 s-1 s−1列的 0元素
- 四周 填充:在输入特征图四周填充 k − p − 1 k-p-1 k−p−1行、 k − p − 1 k-p-1 k−p−1列的 0元素
- 转置卷积核:将卷积核参数 上下+左右翻转
- 卷积操作:做正常卷积运算
参数一
当 s = 1 , p = 0 , k = 3 s=1,\space p=0,\space k=3 s=1, p=0, k=3 时,执行如下图所示的 转置卷积。
经计算 s − 1 = 0 s-1=0 s−1=0、 k − p − 1 = 2 k-p-1=2 k−p−1=2,故间隙不填充0元素,四周填充2行列0元素。
随后将卷积核参数上下左右翻转,在此基础继续作 步长1 且 填充0 的 正常卷积运算。
参数二
当 s = 2 , p = 0 , k = 3 s=2,\space p=0,\space k=3 s=2, p=0, k=3 时,执行如下图所示的 微步卷积。
经计算 s − 1 = 1 s-1=1 s−1=1、 k − p − 1 = 2 k-p-1=2 k−p−1=2,故间隙填充1行列0元素,四周填充2行列0元素。
随后将卷积核参数上下左右翻转,在此基础继续作 步长1 且 填充0 的 正常卷积运算。
参数三
当 s = 2 , p = 1 , k = 3 s=2,\space p=1,\space k=3 s=2, p=1, k=3 时,执行如下图所示的 微步卷积。
经计算 s − 1 = 1 s-1=1 s−1=1、 k − p − 1 = 1 k-p-1=1 k−p−1=1,故间隙填充1行列0元素,四周填充1行列0元素。
随后将卷积核参数上下左右翻转,在此基础继续作 步长1 且 填充0 的 正常卷积运算。
Pytorch 中 2D转置卷积 实现:
import tortch.nn as nn# 函数参数:in_channels, out_channels, kernel_size, stride, padding, output_padding, dilation, groups
# in_channels: 输入图像特征尺寸
# out_channels: 转置卷积后输出图像特征尺寸
# kernel_size: 转置卷积核尺寸
# stride: 步长 默认值1
# padding: 填充 默认值0 【dilation * (kernel_size - 1) - padding zero-padding will be added to both sides of each dimension in the input. Default: 0】
# bias: 偏置 默认值True
# dilation: 膨胀卷积
nn.ConvTranspose2d()
转置卷积的应用场景
- 无监督学习:用于找到一组核和特征图,以重建图片。
- CNN可视化:将CNN中的特征图还原到像素空间,观察特定的特征图对哪些图案敏感。
- 上采样:在像素级预测任务中,如图像分割和图像生成中,通过上采样还原到原始图片尺寸。
由下图可见,转置卷积增大了图像的尺寸。
② 插值
插值:利用已知数据估计未知位置数值。
最近邻插值
最近邻插值 (Nearest Neighbor Interpolation):对于未知位置,直接采用与它最邻近的像素点的值为其赋值,即缩放前后等比填充。
前提假设:在一个连续变量的空间中,一个点的值可以由离它最近的已知点来估计,其在图像处理中被应用于图像的缩放。
双线性插值
双线性插值 (Bilinear Interpolation):不仅可实现图像缩放;其本质是利用参考周围元素按坐标进行双向线性计算后插值。
坐标转换公式:
s r c X = d s t X ∗ ( s r c W i d t h / d s t W i d t h ) s r c Y = d s t Y ∗ ( s r c H e i g h t / d s t H e i g h t ) srcX=dstX* (srcWidth/dstWidth) \\ srcY = dstY * (srcHeight/dstHeight) srcX=dstX∗(srcWidth/dstWidth)srcY=dstY∗(srcHeight/dstHeight)
其中, s r c X srcX srcX表示原图插值临时坐标, d s t X dstX dstX表示新图坐标, s r c H e i g h t srcHeight srcHeight、 s r c W i d t h srcWidth srcWidth 分别表示原图长宽, d s t H e i g h t dstHeight dstHeight、 d s t W i d t h dstWidth dstWidth 分别表示目标长宽。
双线性插值就是做两次线性变换,先在X轴上做一次线性变换,求出每一行的R点, f ( ⋅ ) f(·) f(⋅)表示对应坐标所在数值:
f ( R 1 ) ≈ x 2 − x x 2 − x 1 f ( Q 11 ) + x − x 1 x 2 − x 1 f ( Q 12 ) W h e r e R 1 = f ( x , y 1 ) f ( R 2 ) ≈ x 2 − x x 2 − x 1 f ( Q 12 ) + x − x 1 x 2 − x 1 f ( Q 22 ) W h e r e R 1 = f ( x , y 2 ) f(R_1) \approx \frac{x_2-x}{x_2-x_1}f(Q_{11})+\frac{x-x_1}{x_2-x_1}f(Q_{12}) \space\space\space\space Where \space R_1=f(x,y_1) \\ f(R_2) \approx \frac{x_2-x}{x_2-x_1}f(Q_{12})+\frac{x-x_1}{x_2-x_1}f(Q_{22}) \space\space\space\space Where \space R_1=f(x,y_2) f(R1)≈x2−x1x2−xf(Q11)+x2−x1x−x1f(Q12) Where R1=f(x,y1)f(R2)≈x2−x1x2−xf(Q12)+x2−x1x−x1f(Q22) Where R1=f(x,y2)
再通过一次线性变换求出在该区域中的P点:
f ( P ) ≈ y 2 − y y 2 − y 1 f ( R 1 ) + y − y 1 y 2 − y 1 f ( R 2 ) f(P) \approx \frac{y_2-y}{y_2-y_1}f(R_1)+\frac{y-y_1}{y_2-y_1}f(R_2) f(P)≈y2−y1y2−yf(R1)+y2−y1y−y1f(R2)
整合所有公式,可得以下计算公式:
f ( x , y ) ≈ ( x 2 − x ) ( y 2 − y ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 11 ) + ( x − x 1 ) ( y 2 − y ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 21 ) + ( x 2 − x ) ( y − y 1 ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 12 ) + ( x − x 1 ) ( y − y 1 ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 22 ) f(x,y) \approx \frac{(x_2-x)(y_2-y)}{(x_2-x_1)(y_2-y_1)}f(Q_{11})+\frac{(x-x_1)(y_2-y)}{(x_2-x_1)(y_2-y_1)}f(Q_{21})+\frac{(x_2-x)(y-y_1)}{(x_2-x_1)(y_2-y_1)}f(Q_{12})+\frac{(x-x_1)(y-y_1)}{(x_2-x_1)(y_2-y_1)}f(Q_{22}) f(x,y)≈(x2−x1)(y2−y1)(x2−x)(y2−y)f(Q11)+(x2−x1)(y2−y1)(x−x1)(y2−y)f(Q21)+(x2−x1)(y2−y1)(x2−x)(y−y1)f(Q12)+(x2−x1)(y2−y1)(x−x1)(y−y1)f(Q22)
如果计算出的点在f中是边缘点,则使用单线性插值,如果不是边缘点,则使用双线性插值。
双三次插值
双三次插值 (Bicubic Interpolation)
Bicubic函数公式:
W ( d ) = { ( a + 2 ) ∣ d ∣ 3 − ( a + 3 ) ∣ d ∣ 2 + 1 f o r ∣ d ∣ ≤ 1 a ∣ d ∣ 3 − 5 a ∣ d ∣ 2 + 8 a ∣ d ∣ − 4 a f o r 1 < ∣ d ∣ < 2 0 o t h e r w i s e W(d)= \begin{equation} \left\{ \begin{array}{ll} (a+2)|d|^3-(a+3)|d|^2+1 & for \space |d| \le 1 \\ a|d|^3-5a|d|^2+8a|d|-4a & for \space 1 \lt|d| \lt 2 \\ 0 & otherwise \end{array} \right. \end{equation} W(d)=⎩ ⎨ ⎧(a+2)∣d∣3−(a+3)∣d∣2+1a∣d∣3−5a∣d∣2+8a∣d∣−4a0for ∣d∣≤1for 1<∣d∣<2otherwise
函数图像如下所示:
假设存在以下图像,需在 P P P点插值。
根据坐标转换公式,求得点P坐标,并将其分割为整数部分和小数部分。
假设 P P P的坐标为 P ( x + u , y + v ) P(x+u,y+v) P(x+u,y+v),其中 x , y x,y x,y分别表示整数部分, u , v u,v u,v分别表示小数部分。
可得到如图所示的最近16个像素的位置,用 a ( i , j ) ( i , j = 0 , 1 , 2 , 3 ) a(i,j)\space \space(i,j=0,1,2,3) a(i,j) (i,j=0,1,2,3) 来表示。
求出BiCubic函数中的参数d,从而获得上面所说的16个像素所对应的权重W(d)。
BiCubic基函数是一元函数,而图像是二维图像,故将像素点的行与列分开计算。
BiCubic函数中的参数 d d d表示该像素点到 P P P点的距离。
例如: ( 0 , 0 ) (0,0) (0,0)距离 P ( x + u , y + v ) P(x+u,y+v) P(x+u,y+v)的距离为 ( 1 + u , 1 + v ) (1+u,1+v) (1+u,1+v),因此a00的横坐标权重 i 0 = W ( 1 + u ) i_0=W(1+u) i0=W(1+u),纵坐标权重 j 0 = W ( 1 + v ) j_0=W(1+v) j0=W(1+v), ( 0 , 0 ) (0,0) (0,0)对 B ( X , Y ) B(X,Y) B(X,Y)的贡献值为: Q 00 ∗ i 0 ∗ j 0 Q_{00} * i_0* j_0 Q00∗i0∗j0。
因此,横坐标权重分别为 W ( 1 + u ) W(1+u) W(1+u), W ( u ) W(u) W(u), W ( 1 − u ) W(1-u) W(1−u), W ( 2 − u ) W(2-u) W(2−u);纵坐标权重分别为 W ( 1 + v ) W(1+v) W(1+v), W ( v ) W(v) W(v), W ( 1 − v ) W(1-v) W(1−v), W ( 2 − v ) W(2-v) W(2−v)。
B ( X , Y ) B(X,Y) B(X,Y)像素值为:
B ( X , Y ) = ∑ i = 0 3 ∑ j = 0 3 a i j × W ( i ) × W ( j ) B(X,Y)=\sum^{3}_{i=0}\sum^{3}_{j=0}a_{ij}\times W(i)\times W(j) B(X,Y)=i=0∑3j=0∑3aij×W(i)×W(j)
③ 反池化
反池化 (Unpooling):池化 (Pooling) 的逆操作,包括 反最大池化 和 反平均池化。
在池化过程中,数据被压缩以减少维度,而在反池化过程中,数据通过恢复被压缩的数据来增加维度。
反池化并不能完全恢复原始数据,它只恢复主要信息,并舍去部分信息。
反最大池化
在池化过程中记录最大激活值的坐标位置,最大反池化时,将最大激活值所在位置坐标值激活,其他的值设置为0。
反平均池化
先还原成原来的大小,再将池化结果中的每个值都填入其对应原始数据区域中相应位置即可。
3. 评估方法
3.1 混淆矩阵
展示模型在各个类别上的预测正确与预测错误的数量,非常直观地反映模型在各类别上的性能,以帮助改进模型。
3.2 精确度
总的正确预测数除以总的预测数。
- 注意:在类别不平衡的情况下,精确度不是唯一的评估标准。
3.3 其他指标
- 召回率 (Recall)
- 精确率 (Precision)
- F1 分数 (F1 Score):精确率和召回率的调和平均。
相关文章:

【Python · PyTorch】卷积神经网络(基础概念)
【Python PyTorch】卷积神经网络 CNN(基础概念) 0. 生物学相似性1. 概念1.1 定义1.2 优势1.2.1 权重共享1.2.2 局部连接1.2.3 层次结构 1.3 结构1.4 数据预处理1.4.1 标签编码① One-Hot编码 / 独热编码② Word Embedding / 词嵌入 1.4.2 归一化① Min-…...
深入描述dts和dtsi的区别
QA:dts和dtsi的区别 在嵌入式 Linux 系统中,DTS(Device Tree Source)和 DTSI(Device Tree Source Include)是描述硬件设备树的文件格式。它们本质上是同一种语法的文件,但在使用上有一定区别。…...
京准时钟:一种北斗卫星校时器的结构设计
京准时钟:一种北斗卫星校时器的结构设计 京准时钟:一种北斗卫星校时器的结构设计 1、有关时间的一些基本概念: 时间与频率之间互为倒数关系,两者密不可分,时间标准的基础是频率标准,由晶体振荡器决定时间…...

【WiFi】ubuntu20.4 WiFi6 无线抓包环境搭建及使用
环境说明 笔记本电脑,无线网卡AX200,安装ubuntu20.04 安装无线网卡工具aircrack-ng sudo apt-get install aircrack-ng 安装wireshark sudo add-apt-repository ppa:wireshark-dev/stable sudo apt update sudo apt -y install wireshark sudo apt -…...

《Java核心技术 卷I》用户界面AWT事件继承层次
AWT事件继承层次 EventObject类有一个子类AWTEvent,它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象,都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件:表示用户的动作事件&…...
蓝牙 HFP 协议详解及 Android 实现
文章目录 前言一、什么是蓝牙 HFP 协议?HFP 的核心功能HFP 的核心功能HFP 在 Android 中的典型应用场景 二、HFP 协议的工作流程HFP 的连接流程 三、HFP 在 Android 的实现1. 检查蓝牙适配器状态2. 发现并检测支持 HFP 的设备3. 获取 BluetoothHeadset 服务4. 连接设…...

sqli-labs靶场17-20关(每日四关)持续更新!!!
Less-17 打开靶场,发现页面比之前多了一行字 翻译过来就是,密码重置,大家肯定会想到,自己平时在日常生活中怎么密码重置,肯定是输入自己的用户名,输入旧密码,输入新密码就可以了,但…...

动态规划-完全背包问题——518.零钱兑换II
1.题目解析 建议先看 322.零钱兑换可以 更加轻松的理解本题 题目来源 518.零钱兑换——力扣 测试用例 2.算法原理 1.状态表示 本题要求返回所有情况,所以dp值就代表所有的方法数,即 dp[i][j]:在[1,i]个硬币中选择不同面值的硬币,…...
[模板总结] - 单向链表LinkedList操作
题目汇总 Leetcode 21, 82, 160, 206, 237, 268 Leetcode 21. 合并两个有序链表 归并排序的思路,创建一个哨兵节点从两个链表中按大小插入即可。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(…...

fastadmin多个表crud连表操作步骤
1、crud命令 php think crud -t xq_user_credential -u 1 -c credential -i voucher_type,nickname,user_id,voucher_url,status,time --forcetrue2、修改控制器controller文件 <?phpnamespace app\admin\controller;use app\common\controller\Backend;/*** 凭证信息…...

山西省网络建设与运维第十八届职业院校技能大赛(样题)
集团计划把部分业务由原有的 X86 架构服务器 上迁移到 ARM 架构服务器上,同时根据目前的部分业务需求进行了部分 调整和优化。 一、 X86 架构计算机安装与管理 1、PC1系统为 ubuntu-desktop-amd64 系统,登录用户为 xiao,密码为 Key-1122。在对…...

服务端高并发分布式结构进阶之路
序言 在技术求知的旅途中,鉴于多数读者缺乏在中大型系统实践中的亲身体验,难以从宏观角度把握某些概念,因此,本文特选取“电子商务应用”作为实例,详细阐述从百级至千万级并发场景下服务端架构的逐步演变历程。同时&am…...
分布式微服务项目,同一个controller不同方法间的转发导致cookie丢失,报错null pointer异常
源码: /***添加商品进入购物车*/ GetMapping("/addToCart") public String addToCart(RequestParam("num") Integer num, RequestParam("skuId") Long skuId, RedirectAttributes redirectAttributes) {System.out.println("nu…...

STM32 ADC --- 任意单通道采样
STM32 ADC — 单通道采样 文章目录 STM32 ADC --- 单通道采样cubeMX配置代码修改:应用 使用cubeMX生成HAL工程 需求:有多个通道需要进行ADC采样,实现每次采样只采样一个通道,且可以随时采样不同通道的功能。 cubeMX配置 这里我们…...

vscode中执行git合并操作需要输入合并commit信息,打开的nano小型文本编辑器说明-
1.前提: VScode中的git组件执行任何合并动作的时候需要提交远程合并的commit信息,然后编辑器自动打开的是nano文本编辑器 2.nano编辑器说明: 1.保存文件:按 Ctrl O,然后按 Enter 来保存文件。 2.退出编辑器…...

蓝桥杯每日真题 - 第7天
题目:(爬山) 题目描述(X届 C&C B组X题) 解题思路: 前缀和构造:为了高效地计算子数组的和,我们可以先构造前缀和数组 a,其中 a[i] 表示从第 1 个元素到第 i 个元素的…...
【Git】Git Clone 指定自定义文件夹名称:详尽指南
目录 引言一、git clone 基本语法二、默认行为:没有指定文件夹名称时三、如何指定自定义文件夹名称四、高级使用技巧:动态文件夹名称4.1 基于日期命名文件夹4.2 基于版本标签(Tag)动态命名文件夹4.1 基于日期命名文件夹4.2 基于版…...
终端快捷键学习笔记
以下是优化润色后的内容: 终端快捷键学习笔记 前言 终端(Terminal)是开发者、系统管理员以及技术人员常用的重要工具,它为我们提供了直接与操作系统交互的方式。不同操作系统中的终端使用体验存在差异,尤其在 Linux、…...
Go语言24小时极速学习教程(四)MySQL数据库的增删改查
通过前几篇想必你已经知道该如何使用Go语言写一些简单的程序了,那么从这一篇开始,我们开始探究如何用go语言能够写真正的企业级应用。第一步我们实现先能让程序对数据库进行增删改查,这里以MySQL为例。 1. 导入必要的包 首先需要导入databa…...

04 - Clickhouse-21.7.3.14-2单机版安装
目录 一、准备工作 1、确定防火墙处于关闭状态 2、CentOS 取消打开文件数限制 3、安装依赖 4、CentOS取消SELINUX 二、单机安装 2.1、下载安装 2.2、安装这4个rpm包 2.3、修改配置文件 2.4、启动服务 2.5、关闭开机自启 2.6、使用Client连接server 一、准备工作 1…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...