人工智能——CNN基础:卷积和池化

一、CNN入门介绍

1、卷积神经网络(Convolutional Neural Network,简称 CNN)是一种专门为处理具有网格结构数据(如图像、音频)而设计的深度学习模型。

在传统的全连接神经网络(FNN)中,输入的每个神经元都与下一层的所有神经元相连,这会导致参数数量随着输入维度的增加而急剧增长,并且无法有效利用数据的空间结构信息。(更多的只是关注了全局的特征)

而 CNN 则通过卷积层、池化层等特殊结构,大大减少了模型的参数数量,同时能够自动提取数据中的局部特征,并且对平移、缩放等变换具有一定的不变性。。在图像识别、目标检测、语义分割等计算机视觉任务广泛运用

2、卷积的思想

在之前的OpenCv的学习中,我们接触到了很多的算子,比如Roberts算子,拉普拉斯算子等等,这些都是运用卷积的思想,对图像操作进行边缘提取。

可以把卷积理解为一种 “特征提取器”。想象你有一张藏宝图(图像),上面隐藏着各种宝藏线索(特征),但是线索分布比较杂乱。而卷积操作就像是一个带有不同形状 “放大镜”(卷积核)的寻宝工具。

每个 “放大镜” 都有自己特定的形状和功能,比如有的专门找直线形状的线索(检测边缘),有的找圆形的线索(检测类似眼睛的部件) 。当我们拿着这些 “放大镜” 在藏宝图上一格一格地移动(卷积核在图像上滑动),去观察每个小区域(感受野),就可以把对应的线索找出来,也就是提取出了图像的局部特征

二、卷积层

1、卷积核

卷积核其实是一个小矩阵,在定义时需要考虑以下几方面的内容:

  • 卷积核的个数:卷积核(过滤器)的个数决定了其输出特征矩阵的通道数。每一个卷积核对应一个通道数,也就对应一张特征图

  • 卷积核的值:卷积核的值是初始化好的,后续进行更新。

  • 卷积核的大小:常见的卷积核有1×1、3×3、5×5等,一般都是奇数 × 奇数

2、卷积计算过程:

卷积的过程是将卷积核在图像上进行滑动计算,每次滑动到一个新的位置时,卷积核和图像进行点对点的计算,并将其求和得到一个新的值,然后将这个新的值加入到特征图中,最终得到一个新的特征图

  1. input 表示输入的图像

  2. filter 表示卷积核, 也叫做滤波器

  3. input 经过 filter 的得到输出为最右侧的图像,该图叫做特征图,所有的特征图的数量就是输出通道数,在代码中通常用out_channels(其实就是特征图的数量)

代码:了解卷积

from matplotlib import pyplot as plt
import torch.nn as nn
import os
import torchimage_path= os.path.relpath('../data/彩色.png')
img_data = plt.imread(image_path)
#shape是(高,宽,通道)(H, W, C),要转变为(N, C, H, W)---->先转为(C, H, W),再转(N, C, H, W)
print(img_data.shape)img_data =torch.tensor(img_data.transpose(2,0,1)).unsqueeze(0)print(img_data.shape)#卷积层
conv = nn.Conv2d(in_channels=4,  #输入通道数out_channels=1,  #输出通道数(卷积核个数,对应输出的特征个数)kernel_size=3, #卷积核大小stride=1,  #步长
)
#conv传入的参数是(N, C, H, W)
output = conv(img_data)#输出(N, C, H, W)
print(output.shape)#还原成图片
out = output.squeeze(0).data.numpy()#去掉batch维度,转成numpy数组
out = out.transpose(1,2,0)
#绘图
plt.imshow(out)
plt.show()

正常图片输入的shape是(高,宽,通道)(H, W, C),进行卷积的API:nn.Conv2d(),输入的数据格式应该是四维的:(N, C, H, W),在传入img_data前需要经过转换,先用transpose方法转为(C, H, W)再用unqueeze在0维上升维,转为(N, C, H, W)

Conv2d的使用

conv = nn.Conv2d(

    in_channels=4,  #输入通道数

    out_channels=1,  #输出通道数(卷积核个数,对应输出的特征个数)

    kernel_size=3, #卷积核大小

    stride=1,  #步长

)

        我们需要去理解,这里的in_channels和out_channels到底是什么,在进行多层卷积神经网络时才能正确传入参数。

        其中in_channels,输入的通道数,也就是(N, C, H, W)里面的C,对于初始我们给的图像而言,常常就是单通道(1),三通道(3),四通道(4)

        但是经过卷积操作后,这里的out_channels输出通道就不再是简单的图像上颜色对应的通道了,而是特征通道(经过每个卷积核操作后生成的特征图个数,也就是卷积核个数)

        例如:   

  • 第一层卷积conv1in_channels=1(输入是单通道灰度图),out_channels=16
    这意味着卷积层会创建16 个不同的 3×3 卷积核,每个卷积核专门检测一种局部特征(如:

    • 第 1 个卷积核:检测水平边缘
    • 第 2 个卷积核:检测垂直边缘
    • 第 3 个卷积核:检测 45° 角纹理
    • ...
    • 第 16 个卷积核:检测特定的斑点 / 明暗变化)

    每个卷积核与输入图像卷积后,会输出一张 “特征图”(通道),16 个卷积核就得到 16 个通道,每个通道的数值表示 “该位置是否包含对应特征” 以及 “特征强度”。

3、边缘填充

在上面的图像中可以看出,经过卷积计算后特征图的尺寸会比原始图像尺寸小,这是由于在卷积过程中边缘的像素值计算后放在卷积核中心去了,如果想要保持图像大小不变, 可在原图周围添加padding来实现(边缘填充)。

在代码中,就是在conv = nn.Conv2d方法中加入参数padding=n,其中n表示用什么来填充,一般默认是0

4、步长
一般步长是根据图像的大小而定,在图像尺寸很小时,例如只有20*20,总共一行都没多少个像素值,所以步长肯定不宜过大。当图像比较大时,也可以适当的设置为2、3等等。需要去实验

stride太小:重复计算较多,计算量大,训练效率降低;

stride太大:会造成信息遗漏,无法有效提炼数据背后的特征;

5、多通道卷积计算

  1. 当输入有多个通道(Channel), 例如RGB三通道, 此时要求卷积核需要有相同的通道数。

  2. 卷积核通道与对应的输入图像通道进行卷积。

  3. 将每个通道的卷积结果按位相加得到最终的特征图

如图:

6、多卷积核计算

实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取,通过多个卷积核从输入数据中提取多种类型的特征

其实就是上面讲Conv2d方法中提到的out_channels

用 “团队分工” 类比多卷积核

假设你需要分析一张动物图片:

  • 有人负责观察 “边缘”(比如动物的轮廓)
  • 有人负责观察 “纹理”(比如毛发的粗细)
  • 有人负责观察 “颜色块”(比如是否有黑白条纹)
  • 每个人专注于一种特征,最后汇总所有观察结果,才能全面判断这是猫、狗还是老虎

7、特征图大小

  1. size: 卷积核/过滤器大小,一般会选择为奇数,比如有 1×1, 3×3, 5×5

  2. Padding: 零填充的方式

  3. Stride: 步长

那计算方法如下图所示:

  1. 输入图像大小: W x W

  2. 卷积核大小: F x F

  3. Stride: S

  4. Padding: P

  5. 输出图像大小: N x N

8、局部特征提取——多层多通道卷积核进行特征提取

本质是通过层级化的特征组合,从原始数据中逐步提炼出从简单到复杂、从局部到全局的特征

用 “拼图游戏” 类比多层特征提取

想象你在拼一幅复杂的动物拼图:

  • 第一层(浅层):你先找所有带 “直边”“曲边” 的拼图块(对应低级特征:边缘、纹理)。
  • 第二层(中层):你把 “直边 + 曲边” 组合成 “耳朵”“爪子” 等部件(对应中级特征:局部部件)。
  • 第三层(深层):你把 “耳朵 + 爪子 + 身体” 组合成完整的 “猫”(对应高级特征:整体物体)。

每一层基于上一层的特征,通过多通道卷积核进行 “特征组合”,逐步构建更抽象、更有意义的表示

示例:

我们以 “RGB 图像(3 通道)→ 3 层卷积” 为例,详细拆解每一层的输入、卷积核作用和输出特征

1. 输入层:原始图像(物理通道)

输入是一张 \(224 \times 224 \times 3\) 的 RGB 图像

        这些是最原始的像素信息,没有经过任何特征提取

2. 第一层卷积(提取低级特征)
  • 输入通道:3(RGB 三通道)
  • 卷积核设置:16 个卷积核,每个尺寸为 \(3 \times 3 \times 3\)(深度 = 输入通道数 3,确保能覆盖所有颜色通道)
  • 操作逻辑:每个卷积核在输入图像上滑动,对 3 个颜色通道的对应区域同时计算(每个通道与卷积核的对应切片做点积,再求和),输出 1 个特征图。16 个卷积核共输出 16 个通道。
  • 输出特征:16 个 \(222 \times 222\) 的特征图(假设 stride=1,padding=0),每个通道对应一种低级特征:
    • 通道 0:检测 “水平红色边缘”
    • 通道 1:检测 “45° 绿色纹理”
    • 通道 2:检测 “垂直蓝色边缘”
    • ...(16 种不同的边缘、纹理、颜色块特征)这些特征我们也无法确认,是计算机自行去计算,我们也不需要去搞懂到底提取了哪些特征
3. 第二层卷积(组合低级特征为中级特征)
  • 输入通道:16(第一层输出的 16 种低级特征)
  • 卷积核设置:32 个卷积核,每个尺寸为 \(3 \times 3 \times 16\)(深度 = 输入通道数 16,能覆盖所有低级特征)
  • 操作逻辑:每个卷积核滑动时,会同时 “观察” 第一层的 16 个特征通道(比如:“水平边缘通道” 的响应 +“垂直边缘通道” 的响应),通过权重加权求和,输出 1 个新的特征图。32 个卷积核输出 32 个通道。
  • 输出特征:32 个 \(220 \times 220\) 的特征图,每个通道对应中级特征
4. 第三层卷积(组合中级特征为高级特征)
  • 输入通道:32(第二层输出的 32 种中级特征)
  • 卷积核设置:64 个卷积核,每个尺寸为 \(3 \times 3 \times 32\)
  • 操作逻辑:每个卷积核整合 32 种中级特征(比如:“角点 + 斑点 + 短线条” 的特定组合),输出代表更复杂模式的特征图。
  • 输出特征:64 个 \(218 \times 218\) 的特征图,每个通道对应高级特征:
    • 通道 0:“眼睛”(圆形斑点 + 周围的边缘轮廓)
    • 通道 1:“车轮”(圆形纹理 + 辐射状线条)
    • 通道 2:“文字笔画”(特定方向的线条组合)
    • ...(64 种接近 “物体部件” 的特征)

多层多通道的核心机制:特征的 “层级抽象” 与 “通道协同”

  1. 层级抽象
    浅层(1-2 层)→ 低级特征(边缘、纹理、颜色)
    中层(3-4 层)→ 中级特征(角点、斑点、局部部件)
    深层(5 层以上)→ 高级特征(物体部件、整体轮廓)
    每一层的特征都是上一层特征的 “组合与抽象”,就像从 “字母” 到 “单词” 再到 “句子” 的过程。

  2. 通道协同
    每个卷积核的深度 = 输入通道数,意味着它能 “同时关注多个输入特征”。例如,检测 “眼睛” 的卷积核会重点关注:

    • 输入通道中 “圆形纹理” 的高响应区域
    • 输入通道中 “边缘轮廓” 的闭合区域
    • 输入通道中 “肤色(特定颜色)” 的区域
      这种多通道协同,让网络能学习 “特征之间的关联”(比如 “圆形 + 闭合边缘 + 肤色 = 眼睛”)。
  3. 感受野扩大
    深层卷积的 “感受野”(能影响输出的输入区域)比浅层大。例如:

    • 第一层 3×3 卷积的感受野是 3×3(只看 3×3 像素)
    • 第二层 3×3 卷积的感受野是 5×5(因为它的输入是第一层的 3×3 区域,对应原始图像 5×5)
    • 第三层 3×3 卷积的感受野是 7×7
      这使得深层特征能捕捉更大范围的局部信息,为组合高级特征提供基础。

        什么是感受野:

感受野(Receptive Field) 是指输出特征图上的一个像素点,对应输入图像(或前层特征图)上的区域大小

用 “望远镜视野” 类比感受野

想象你用望远镜观察风景:

  • 当你用低倍镜(类似 CNN 浅层卷积)时,视野小(感受野小),只能看清眼前的细节(如一片树叶的纹理)。
  • 当你换高倍镜(类似 CNN 深层卷积)时,视野大(感受野大),能看到更大范围的场景(如整棵树的轮廓)。

CNN 中:

  • 浅层卷积层的感受野小,只能 “看到” 输入图像的局部区域(如几个像素组成的边缘)。
  • 深层卷积层的感受野大,能 “看到” 输入图像的更大范围(如多个局部特征组合成的部件)。

感受野的意义:

  1. 特征层级与感受野的关系

    • 浅层(感受野小):捕捉边缘、纹理等局部特征(如眼睛的轮廓、毛发的纹理)。
    • 深层(感受野大):捕捉部件、整体等全局特征(如人脸的整体结构、汽车的轮廓)。

    例如,在识别 “猫” 的任务中:

    • 第 1 层可能检测 “胡须的边缘”(感受野 3×3)。
    • 第 3 层可能检测 “眼睛的形状”(感受野 7×7)。
    • 第 5 层可能检测 “整个猫脸”(感受野 21×21)。

多层卷积代码示例:

from matplotlib import pyplot as plt
import torch.nn as nn
import os
import torchimage_path= os.path.relpath('../data/彩色.png')
img_data = plt.imread(image_path)
#shape是(高,宽,通道)(H, W, C),要转变为(N, C, H, W)---->先转为(C, H, W),再转(N, C, H, W)
print(img_data.shape)img_data =torch.tensor(img_data.transpose(2,0,1)).unsqueeze(0)print(img_data.shape)#卷积层
#进入时的形状:(1,4,501,500)
conv1 = nn.Conv2d(in_channels=4,#输入通道数(N,C, H, W)out_channels=16,kernel_size=3,stride=1,
)
#conv1输出的形状:(1,16,499,498)conv2 = nn.Conv2d(in_channels=16,out_channels=32,kernel_size=3,stride=1,
)
#conv2输出的形状:(1,32,497,496)conv3 = nn.Conv2d(in_channels=32,out_channels=1,kernel_size=3,stride=1,
)
#conv3输出的形状:(1,1,495,494)#conv传入的参数是(N, C, H, W)
output = conv1(img_data)#输出(N, C, H, W)
output = conv2(output)
output = conv3(output)
# print(output.shape)#还原成图片
out = output.squeeze(0).data.numpy()#去掉batch维度,转成numpy数组
out = out.transpose(1,2,0)
#绘图
plt.imshow(out)
plt.show()

三、池化层

1、池化层的概述

池化层的核心思想是“下采样”,通过对卷积层输出的特征图进行局部区域的聚合操作(如取最大值、平均值),在保留关键特征的同时,降低特征图的尺寸和数据量。

可以把池化层类比为 “信息压缩器”:卷积层提取的特征图往往包含冗余信息(比如相邻像素的特征响应很相似),池化层就像给特征图 “降分辨率”,只保留每个局部区域中最关键的信息(如最强响应、平均响应)

常见的池化方式有两种:

  • 最大池化(Max Pooling):取局部区域的最大值(最常用)。
  • 平均池化(Average Pooling):取局部区域的平均值。

2、池化层的计算:

池化的计算逻辑与卷积类似:用一个固定大小的 “池化窗口” 在特征图上按指定步长滑动,对窗口内的元素进行聚合操作,生成下采样后的特征图

和卷积一样也有步长Stride、Padding

另外注意:在处理多通道输入数据时,池化层对每个输入通道分别池化,而不是像卷积层那样将各个通道的输入相加。这意味着池化层的输出和输入的通道数是相等。

3、池化层的作用

池化操作的优势有:

  1. 通过降低特征图的尺寸,池化层能够减少计算量,从而提升模型的运行效率。

  2. 池化操作可以带来特征的平移、旋转等不变性,这有助于提高模型对输入数据的鲁棒性。

  3. 池化层通常是非线性操作,例如最大值池化,这样可以增强网络的表达能力,进一步提升模型的性能。

但是池化也有缺点:

  1. 池化操作会丢失一些信息,这是它最大的缺点;

import torch
import torch.nn as nndef test01():#设置随机种子input_map = torch.randn(1, 1, 7, 7)print(input_map)print("-"* 50)pool1 = nn.MaxPool2d(kernel_size=2,stride=1,return_indices=True#是否返回索引)output,indices = pool1(input_map)print(output,indices)print("-"*50)def test02():input_map = torch.randn(1, 1, 7, 7)pool1 = nn.AvgPool2d(kernel_size=2,stride=1,)output = pool1(input_map)print(output.shape)def test03():input_map = torch.randn(1, 1, 7, 7)pool1 = nn.AdaptiveMaxPool2d(output_size=(3,3))if __name__ == '__main__':test01()test02()

运行结果:

对于最大值池化。其返回值有两个:output,indices

1. output(输出特征图)

池化操作后的结果,即每个池化窗口中选出的最大值(对于最大池化)或平均值(对于平均池化)

2. indices(索引)

在最大池化中,记录每个池化窗口中最大值在原特征图中的位置索引

四、自定义网络

思路:

1、自定义网络就是写一个模型的类,首先定义一个类继承于父类nn.Module

2、进行卷积操作,提取特征。定义三层卷积层,每一层进行一次池化和激活(经过池化后要算清楚输出的图像尺寸变化)

3、进行全连接,计算经过卷积池化操作后,总的像素点。这是全连接层特征的输入值

4、前向传播

5、调用模型

import torch
import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()#第一卷积层self.conv1 = nn.Conv2d(in_channels=1,#输入的通道数out_channels= 16,#输出的通道数,其实就是输出多少张特征图kernel_size=3,stride=1,padding=1)#激活函数self.relu = nn.ReLU()#池化层self.pool = nn.AdaptiveMaxPool2d(output_size=(22,22),)#第二卷积层self.conv2 = nn.Conv2d(in_channels=16,out_channels=32,kernel_size=3,stride=1,padding=1)self.pool2 = nn.AdaptiveMaxPool2d(output_size=(16,16),)#全连接层(要判断输入特征就是计算像素点)self.fc1 = nn.Linear(in_features=32*16*16,out_features=10  #输出类别数)def forward(self, x):#x(1,16,26,26)x =self.conv1(x)#x(1,16,22,22)x = self.pool(x)#x(1,32,20,20)x = self.conv2(x)#x(1,32,16,16)x = self.pool2(x)out = self.fc1(x.view(-1,x.size(1)*x.size(2)*x.size(3)))return outif __name__ == '__main__':input_data = torch.randn(1, 1, 28, 28)model = MyModel()output = model(input_data)print(output.shape)

代码讲解:

此处的out_channels前面已经讲过,就是卷积核的个数,经过卷积后输出多少张特征图

单纯的卷积后,函数也还是线性关系,所以i需要激活函数

选用自适应池化

第一步经过卷积后,图像的尺寸变成了(原图像大小是28*28)26*26。

经过池化后,图像的特征减少(也就是像素减少),尺寸就变成了22*22

第二层卷积与第一层类似

全连接层,用nn.Linear,其中输入的特征值,其实就是经过卷积池化后,此时图像的像素值(通道数*高*宽)

而输出特征呢?因为我们目标是做10分类,所以最后训练出来输出的特征值就应该是10个类别

前向传播,每次卷积和池化后,其x的形状会发生改变,追踪每次的改变。

为什么这么做:因为卷积神经网络里,conv(卷积)、pool(池化)层输出的是 4 维张量 (N, C, H, W) (N 批大小、C 通道、H 高、W 宽 ),但全连接层(nn.Linear )要求输入是 2 维张量 (N, feature_num) (feature_num 是一维特征数量 )。所以必须用 view 把 (N, C, H, W) 转成 (N, C*H*W) ,才能让全连接层处理

  • -1 的含义
    让 PyTorch 自动计算该维度的大小。比如 x.view(-1, A*B*C) ,-1 所在维度会被自动填充为 总元素数 / (A*B*C) ,保证元素总数不变。

  • 具体到代码
    假设卷积、池化后,x 的形状是 (N, C, H, W) (N 是 batch 数、C 是通道数、H 高、W 宽 )。
    执行 x.view(-1, x.size(1)*x.size(2)*x.size(3)) 后:

    • 第一个维度填 -1 ,PyTorch 会自动算出是 N(因为总元素数是 N*C*H*W ,第二个维度是 C*H*W ,所以 N = 总元素数 / (C*H*W) )。
    • 第二个维度是 C*H*W ,把每个样本的 (C, H, W) 三维特征图,压成 长度为 C*H*W 的一维向量 。

举个实际例子:
如果 x 是 (2, 16, 22, 22) (2 个样本、16 通道、22 高、22 宽 ),执行 x.view(-1, 16*22*22) :

  • 第一个维度自动算成 2(总元素数 2*16*22*22 = 15488 ,16*22*22=7744 ,15488 / 7744=2 )。
  • 第二个维度是 7744 ,最终形状变成 (2, 7744) 

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

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

相关文章

适用监测农作物长势和病虫害的高光谱/多光谱相机有哪些?

面对农作物长势分析和病虫害监测,光谱技术在农业中得到了有效的应用。本篇文章给大家介绍下适合监测农作物长势和病虫害的高光谱/多光谱相机。农作物在遭受病虫害侵袭时,其叶片的细胞结构、水分含量、色素组成会发生变化,从而导致农作物对不同…

深度学习——03 神经网络(4)-正则化方法价格分类案例

4 正则化 4.1 概述模型拟合的3种状态左边(Underfitting 欠拟合):模型太简单,没抓住数据规律。比如用直线硬套弯曲的数据,预测效果差,训练误差和测试误差都大;中间(Just right 拟合合…

java16学习笔记

Java16是一个重要的特性发布,它为JAVA带来了许多JVM特定的更改和语言特定的更改。它遵循了自JavaJava10以来引入的Java发布步调,并于2021年3月发布,仅在Java15发布后的六个月内发布。 Java 16是一个非LTS版本。 338:Vector API (Incubator)…

useCallback 的陷阱:当 React Hooks 反而拖了后腿

我有一支技术全面、经验丰富的小型团队,专注高效交付中等规模外包项目,有需要外包项目的可以联系我很多代码库到处都是 useCallback / useMemo。初衷是好的:减少不必要的重新渲染、稳定引用、提速。然而,用错场景或铺天盖地地包一…

【IntelliJ IDEA】如何在pom.xml中去除maven中未使用的依赖

pom.xml中去除maven中未使用的依赖主要解决的问题一、怎么做?二、重点依赖类型解析说明三、什么时候做?四、有什么风险要注意的?五、补充一个快捷方法使用六、IDEA的terminal中如何才能使用命令mvn呢?主要解决的问题 你的项目中p…

安卓9.0系统修改定制化____关于自启脚本的规律、编写与实战示例 推荐收藏【二】

在定制化ROM服务中,许多功能都需要通过自启脚本来实现。上期博文详细解析了脚本编写的规律、权限设置以及常见错误踩坑的排查与修复方法,并逐行解释了脚本代码的含义。掌握这些基础知识后,这期再以实例演示的过程来使我们使用更得心应手。。 通过博文了解💝💝💝 1�…

选择gpt-5还是claude-4-sonnect

了解我的朋友都知道,我是一个伪全栈工程师,一个人加AI编程工具打天下。 最近,gpt-5已经出来有一段时间了,cursor第一时间就支持了gpt-5模型,我第一时间就尝试了gpt-5效果。说实话,gpt-5和claude-4-sonnect都…

自动化运维实验(二)---自动识别设备,并导出配置

目录 一、实验拓扑 二、实验目的 三、实验步骤 实验思路: 代码部分: 四、实验结果: 一、实验拓扑 二、实验目的 ssh远程登录后,识别设备类型(华三、华为、锐捷、山石、飞塔、深信服等),再…

Matlab(4)初阶绘图

一、Basic plotting1.plot()plot(x,y) :x图片中点的横坐标,y图片中点的纵坐标plot(y) :y图片中点的纵坐标,x图片中点的横坐标默认为1,2,3,4,5........plot(co…

服务器硬件电路设计之 I2C 问答(五):I2C 总线数据传输方向如何确定、信号线上的串联电阻有什么作用?

在服务器硬件电路设计中,I2C 总线作为常用的串行通信总线,其数据传输方向的确定和信号线上串联电阻的作用是关键知识点。​I2C 总线数据传输方向由主设备和从设备的角色以及读写位共同确定。主设备是发起通信的一方,从设备则是被寻址的对象。…

OpenBMC中C++策略模式架构、原理与应用

1. 策略模式概述 策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时动态选择算法或行为,而无需修改客户端代码。 核心思想:封装可互换的算法族,使它们可以独立于使用它们的客户端变化。 1.…

【python实用小脚本-187】Python一键批量改PDF文字:拖进来秒出新文件——再也不用Acrobat来回导

Python一键批量改PDF文字:拖进来秒出新文件——再也不用Acrobat来回导 PDF文字替换, 批量导出, 零依赖转档, 一键完成, 瑞士军刀 故事开场:一把瑞士军刀救了周五下班的你 周五 18:00,老板甩来 50 份合同 PDF: “把里面的‘2023’全…

汽车后雾灯色度难达标?OAS 软件精准解决破瓶颈

汽车后雾灯案例分析简介汽车后雾灯是车辆在能见度较低的雾、雨、雪等恶劣天气条件下行驶时,向后方车辆传递警示信号的重要装置,其性能直接关系到车辆的后方安全。根据规定,红色信号灯需符合 CIE1931 标准,其色度坐标 X 值应在 0.6…

[系统架构设计师]架构设计专业知识(二)

[系统架构设计师]架构设计专业知识(二) 一.信息系统基础知识 1.信息系统概述 信息系统功能:输入,存储,处理,输出,控制 理查德.诺兰: 初始,传播,控制&#xff…

如果用ApiFox调用Kubernetes API,需要怎么设置证书?

针对Docker Desktop中Kubernetes访问报SSL/TLS信任关系错误的问题,以下是综合解决方案:要在Postman中调用Kubernetes API并设置证书,需按以下步骤操作:🔐 证书设置步骤‌提取证书文件‌从kubeconfig文件(~/…

nodejs 路由/请求

//导入模块 const express require(express); //创建应用 const app express();//设置路由 app.get(/,(req,resp)>{//输出响应console.log(request coming.............);resp.json(req.headers); });app.get(/user/:id, (req, res) > {const userId req.params.id; …

Python 数据可视化:柱状图/热力图绘制实例解析

Python 数据可视化:柱状图绘制实例解析 一、引言 数据可视化是数据分析中至关重要的环节,它能将复杂的数据以直观的图形方式呈现,帮助我们更好地理解数据特征和规律。Python 拥有丰富的可视化库,其中 Matplotlib 是最常用的基础库…

API生命周期10阶段

一、策略规划(Strategy Planning) 核心任务:业务价值对齐、技术路线设计关键产出: API产品蓝图:定义业务领域边界(如支付API域、用户API域)治理规范:《API安全标准》《版本管理策略》…

UGUI源码剖析(9):布局的实现——LayoutGroup的算法与实践

UGUI源码剖析(第九章):布局的实现——LayoutGroup的算法与实践 在前一章中,我们剖析了LayoutRebuilder是如何调度布局重建的。现在,我们将深入到布局核心,去看看那些具体的组件——LayoutGroup系列组件是如…

GitHub PR 提交流程

step1 在 GitHub 上 fork 目标仓库&#xff08;手动操作&#xff09; step2 将 fork 的目标仓库克隆到本地 git clone https://github.com/<your-username>/<repo-name>.git cd <repo-name>step3 与上游目标仓库建立链接 git remote add upstream https://gi…