【深度学习】各种卷积—卷积、反卷积、空洞卷积、可分离卷积、分组卷积

news2024/12/1 3:16:37

        在全连接神经网络中,每个神经元都和上一层的所有神经元彼此连接,这会导致网络的参数量非常大,难以实现复杂数据的处理。为了改善这种情况,卷积神经网络应运而生。

一、卷积

        在信号处理中,卷积被定义为一个函数经过翻转和移动后与另一个函数的乘积的积分。

        那卷积具体卷了什么呢?我们用f函数表示进食,g函数表示消化。如果我们不考虑消化的话,如果想求14点的时候我们胃里面剩什么,只需要将f(t)在0点到14点求积分。但现在问题是,我们的胃是一直消化的。

         假如,我们在12点的时候吃进去一碗米饭,而在14点的时候消化的已经剩一半了,这时候我们就需要用到消化函数g(t)。

        g(t)代表消化曲线,最大值为1,在12点吃进去一碗米饭,在14点米饭还剩 f (12)·g (14 - 12),即 f (x)·g (t - x) 。那么14点之前吃进去的食物就可以进行求积分 \int_{0}^{14}f(x)g(14-x)dx.

        从上述来看,我们可以把卷积理解为,一个系统的输入不稳定(在某时刻吃的东西多少不一定)、输出稳定(衰减/变化都符合g(t)函数),用卷积求系统存量。

2D卷积

        在图像卷积中,过滤函数是不经过翻转的。卷积便是看很多像素点对某一个像素点如何产生的影响。2D卷积指的是在卷积操作过程中,卷积核只有两个维度——宽和高。卷积核与输入矩阵中对齐的区域,如下图灰色框所示。在对齐的区域里,输入矩阵与卷积核对应位置的元素值相乘,所有乘积再相加,得到一个标量值,为输出区域(0,0)位置的数值。接着卷积核向右平移,平移的距离由步长stride决定(stride为1,则向右平移一步),重复以上计算。

        

        执行卷积的目的是从输入中提取有用的特征。在图像处理中,执行卷积操作有不同的过滤函数可供选择,每一种都有助于从输入图像中提取不同的方面或特征,如水平/垂直/对角边等。类似地,卷积神经网络通过卷积在训练期间使用自动学习权重的函数来提取特征。所有这些提取出来的特征,之后会被组合在一起做出决策。同时,卷积操作还具有权重共享(weights sharing)和平移不变性(translation invariant),可以考虑像素空间的关系。

        一个输入图像在连续经过几次卷积操作之后,输出的图像就变得很小了。当输出尺寸变成1x1的时候,就无法进行卷积运算了,这样的话我们难以构建较深的神经网络。况且,在某些场景当中,例如图像分割,我们并不希望图像每次在经过特征提取之后都变小。此外,卷积运算并没有充分利用边缘处的信息,边缘处的像素点只会参与一次卷积运算,影响一个输出结果;但中间区域的像素点会参与多次卷积运算,影响多个输出结果。而填充操作padding就会解决这些问题,当padding=1时,图像周围会填充1个像素,例如一个5x5的图像经过填充后会变成7x7的图像。

        卷积计算后的图像输出尺寸大小计算公式如下:

多通道卷积(空间卷积)

        在2D卷积的例子中,输入时单通道的二维数据。而对于实际的图片,输入数据往往是多通道的,比如RGB三通道的。多通道的卷积操作与单通道的类似,只是在构造卷积核时需要注意卷积核的通道个数要与输入数据通道数相同。而对于卷积层而言,也是如此,一个卷积层往往也是多个通道组成的,每个通道描述一个方面的特征。

        生成一个输出通道,就需要将每一个卷积核应用到前一层的输出通道上,这是一个卷积核级别的操作过程。对所有的卷积核都重复这个过程以生成多通道,之后,这些通道组合在一起共同形成一个单输出通道。设输入层是一个 5 x 5 x 3 矩阵,它有 3 个通道。过滤器则是一个 3 x 3 x 3 矩阵。首先,过滤器中的每个卷积核都应用到输入层的 3 个通道,执行 3 次卷积后得到了尺寸为 3 x 3 的 3 个通道。如下图所示:

        之后,这 3 个通道都合并到一起(元素级别的加法)组成了一个大小为 3 x 3 x 1 的单通道。这个通道是输入层(5 x 5 x 3 矩阵)使用了过滤器(3 x 3 x 3 矩阵)后得到的结果。

        同样,我们也可以将这个过程视作将一个 3D 过滤器矩阵滑动通过输入层,这个输入层和过滤器的深度都是相同的,即通道数=卷积核数。这个 3D 过滤器仅沿着 2 个方向(图像的高和宽)移动,这也是为什么 3D 过滤器即使通常用于处理 3D 体积数据,但这样的操作还是被称为 2D 卷积。假设,输入图像和卷积核的通道数为3,卷积核尺寸为3x3x3(宽x高x通道数),这时候将一个3D过滤器矩阵对图像沿着高和宽作卷积,通道数为1的卷积核是进行9个像素点的计算,而通道数为3的卷积核是进行27个像素点的计算。

多卷积核卷积

        在实际神经网络中,每一层都会有多个卷积核参与运算。每个卷积核分别于输入卷积得到一个单通道的输出,最后多个单通道的输出拼在一起得到多通道输出。

        单个卷积核只能提取单一特征,要想利用卷积核提取更多的特征,需要增加卷积核数量。r如果需要提取100个特征,卷积层需要100个卷积核,假设卷积核大小为4,则共需要4*100个参数。 

        如何进行多通道图的多核卷积呢? 对多通道图进行一个核一个核地卷积,最后生成n个特征图,将这些特征图拼接在一起最终可以得到2x2xn的特征图。

3D卷积

        上一节中最后一张图虽然实现了空间卷积,但是本质上它还是2D卷积。而在 3D 卷积与2D卷积相比,多了一个时间的维度。而且3D卷积的过滤器深度要比输入层深度小,即卷积核大小<通道大小。这样做的结果是,3D 过滤器可以沿着所有 3 个方向移动,即高、宽及图像通道。

        每个位置经过元素级别的乘法和算法都得出一个数值。由于过滤器滑动通过 3D 空间,输出的数值同样也以 3D 空间的形式呈现,最终输出一个 3D 数据。如下图所示:

1x1卷积

        1x1卷积核通常会拿来对输入数据的通道做约简,每个1x1卷积核想当于在输入数据的通道上做一个降维(经过一个神经元个数为1的全连接层),从而相当于大幅度降低了特征图的数量,但不影响特征图的结构。1x1卷积表面上好像只是feature map每个值乘了一个数,但实际上不仅仅如此,由于会经过激活层,所以实际上是进行了非线性映射,其次就是可以改变feature 的channel数目。

        经过大小为 1 x 1 x D 的过滤器的 1 x 1 卷积,输出通道的维度为 H x W x 1。如果我们执行 N 次这样的 1 x 1 卷积,然后将这些结果结合起来,我们能得到一个维度为 H x W x N 的输出层。在执行计算昂贵的 3 x 3 卷积和 5 x 5 卷积前,往往会使用 1 x 1 卷积来减少计算量。此外,它们也可以利用调整后的线性激活函数来实现双重用途。

二、 反卷积(转置卷积 Transposed Convolutions)

        卷积不会增大输入的高和宽,通常要么不变、要么减半。但是在语义分割这种任务上,仅仅使用卷积无法进行像素级的输出,这时候就可以用到转置卷积来增大输入高和宽。反卷积是卷积的逆操作。

        在反卷积进行的时候,也需要滑动操作。将输入图像上的0、1、2、3分别与卷积核进行相乘操作,得到结果后在与输出图像相同尺寸的框图上进行滑动,最终将这些结果进行相加。


        为什么反卷积又叫做转置卷积呢?对于一个卷积操作Y=X*W,可以构造一个V使得卷积等价于矩阵乘法Y^{'}=VX^{'},其中Y^{'}X^{'}Y X对应的向量版本。转置卷积则是将卷积操作Y=X*W等价于Y^{'}=V^{T}X^{'},如果Y^{'}的尺寸为1xm,X^{'}的尺寸为1xn,则V的尺寸为mxn。如果卷积将输入从(h,w)变成了(h^{'},w^{'}),同样超参数的转置卷积则从(h^{'},w^{'})变成了(h,w),卷积一般是做下采样,转置卷积通常用作上采样。需要注意的是,虽然转置卷积可以增加特征图的空间尺寸,但是它不等同于传统意义上的上采样或者插值,因为它引入了非线性,转置卷积层在增加特征图尺寸的同时,通过学习卷积核的权重,能够保留或增加信息内容。

        转置卷积也是一种卷积。当填充为0,步幅为1时,将输入填充k-1(k是核窗口),将核矩阵上下、左右翻转,然后做正常卷积(填充0、步幅1),可以得到结果等价于转置卷积。

         当填充为p,步幅为1时,将输入填充k-p-1(k是核窗口),将核矩阵上下、左右翻转,然后做正常卷积(填充0、步幅1),可以得到结果等价于转置卷积。

        当填充为p,步幅为s时,在行和列之间插入s-1行或列,将输入填充k-p-1(k是核窗口),将核矩阵上下、左右翻转,然后做正常卷积(填充0、步幅1),可以得到结果等价于转置卷积。

        转置卷积输出特征图尺寸计算公式如下:

三、 分组卷积(Group convolution)

        Group convolution 分组卷积,最早在AlexNet中出现,由于当时的硬件资源有限,训练AlexNet时卷积操作不能全部放在同一个GPU处理,因此作者把feature maps分给多个GPU分别进行处理,最后把多个GPU的结果进行融合。

        在传统的 2D 卷积中,通过应用 128 个过滤器(每个过滤器的大小为 3 x 3 x 3),大小为 7 x 7 x 3 的输入层被转换为大小为 5 x 5 x 128 的输出层。针对通用情况,可概括为通过应用 Dout 个卷积核(每个卷积核的大小为 h x w x Din),可将大小为 Hin x Win x Din 的输入层转换为大小为 Hout x Wout x Dout 的输出层。

        而在分组卷积中,过滤器被拆分为不同的组,每一个组都负责具有一定深度的传统 2D 卷积的工作。一个过滤器被拆分为 2 个过滤器组的分组卷积。在每个过滤器组中,其深度仅为名义上的 2D 卷积的一半(Din / 2),而每个过滤器组都包含 Dout /2 个过滤器。第一个过滤器组(红色)对输入层的前半部分做卷积([:, :, 0:Din/2]),第二个过滤器组(蓝色)对输入层的后半部分做卷积([:, :, Din/2:Din])。最终,每个过滤器组都输出了 Dout/2 个通道。整体上,两个组输出的通道数为 2 x Dout/2 = Dout。之后,我们再将这些通道堆叠到输出层中,输出层就有了 Dout 个通道。

四、扩张卷积(空洞卷积 Dilated Convolutions)

        空洞卷积又叫扩张卷积,是一种特殊的卷积运算。与标准卷积不同的是,在卷积核尺寸、步长、填充之外,又引入另一个卷积层的参数——扩张率(膨胀率)。膨胀率定义了内核中值之间的间距。扩张速率为2的3x3内核将具有与5x5内核相同的视野,而只使用9个参数。 使用5x5内核并删除每个间隔的行和列,如下图所示:

        为什么要增加采样间隔呢?空洞卷积最初被提出时,是为了解决图像分割中一些特定的问题,特别是语义分割。图像分割做的是像素级的预测,模型需要精确地预测出图像中地每个像素所属的类别,这就需要模型具有较大的感受野,以便捕捉到图像中上下文信息。同时,图像分割需要保持高分辨率的输出,传统的神经网络需要经过卷积层和池化层降低图像分辨率,然后再经过上采样操作还原输入尺寸,这个过程增大了感受野但也会导致细节丢失。空洞卷积便可缓解这个问题,增大感受野的同时,保持特征图的尺寸不变,通过膨胀率卷积核可以在不增加参数数量和计算量的条件下覆盖更大的感受野,这样网络就可以捕捉到图像中的长距离依赖关系,同时又可以保持较高的空间分辨率。

        直观上,空洞卷积通过在卷积核部分之间插入空间让卷积核“膨胀”。这个增加的参数 (空洞率)表明了我们想要将卷积核放宽到多大。当 膨胀率为1,2,4 时的卷积核大小,其中当膨胀率为1时,空洞卷积就变成了一个标准的卷积。

        在图像中,3 x 3 的红点表明经过卷积后的输出图像的像素是 3 x 3。虽然三次空洞卷积都得出了相同维度的输出图像,但是模型观察到的感受野是不同的。膨胀率为1时,感受野为 3 x 3;膨胀率为2时,感受野是 7 x 7;膨胀率为3时,感受野增至 15x15。伴随这些操作的参数数量本质上是相同的,不需要增加参数运算成本就能观察大的感受野。因此,空洞卷积常被用以低成本地增加输出单元上的感受野,同时还不需要增加卷积核大小,当多个空洞卷积一个接一个堆叠在一起时,这样是有效的。

五、可分离卷积

空间可分离卷积(separable convolution)

        空间可分离卷积就是再空间维度对卷积核进行拆分,将一个标准卷积核拆为一个个小卷积核,最终一个标准的卷积运算可以转换为多个顺序执行的卷积运算。

        例如,一个矩阵A可以拆分为B和C的外积。那么,用A作为卷积核对图像作卷积就等价于先用B作为卷积核对图像作卷积,然后再用C作为卷积核对图像作卷积。

        一般而言,在一个可分离卷积中,我们可以将内核操作拆分成多个步骤。我们用y = conv(x,k)表示卷积,其中y是输出图像,x是输入图像,k是内核。这一步很简单。接下来,我们假设k可以由下面这个等式计算得出:k = k1.dot(k2)。这将使它成为一个可分离的卷积,因为我们可以通过对k1和k2做2个一维卷积来取得相同的结果,而不是用k做二维卷积。

        以通常用于图像处理的Sobel内核为例。你可以通过乘以向量[1,0,-1]和[1,2,1] .T获得相同的内核。在执行相同的操作时,你只需要6个而不是9个参数。(如下所示,其实有点类似矩阵的分解,在线性系统的时候学过类似的)

        比起卷积,空间可分离卷积要执行的矩阵乘法运算也更少。假设我们现在在 m x m 卷积核、卷积步长=1 、填充=0 的 N x N 图像上做卷积。传统的卷积需要进行 (N-2) x (N-2) x m x m 次乘法运算,而空间可分离卷积只需要进行 N x (N-2) x m + (N-2) x (N-2) x m = (2N-2) x (N-2) x m 次乘法运算。空间可分离卷积与标准的卷积的计算成本之比为:

深度可分离卷积(depthwise separable convolution)

        深度可分离卷积和空间可分离卷积类似,也是将标准卷积运算拆分为多个卷积运算,深度维度指的是通道维度,深度可分离卷积是在通道维度上对标准卷积进行拆分处理。一个大小为 w x h x c的输入,经过co个wk x hk x c的卷积核进行标准卷积运算,假设得到大小为a x b x co的输出,整个运算过程中的运算量等于wk x hk x c x co。

         同样大小的输入和输出,换做深度可分离卷积是如何做的呢?首先,对输入逐通道卷积,分别提取输入的每个通道上的特征。

        但此时,各通道上的特征是独立的,还没有得到融合因此需要逐点卷积,使用一个1 x 1 x c的卷积核对深度卷积得到的特征图进行卷积运算,可以得到一个1 x a x b的输出,此时的输出已经融合了c个通道的输出。

        如果用co个1 x 1 x c的卷积核对特征图进行卷积运算,此时的输出特征图变为a x b x co。整个过程的参数量为 wk x hk x 1 x c + 1 x 1 x c x co, 大大缩减了计算量和参数量。

参考资料:

7.5多通道多卷积核_哔哩哔哩_bilibiliicon-default.png?t=O83Ahttps://www.bilibili.com/video/BV1q34y1V7p4/?spm_id_from=333.337.search-card.all.click&vd_source=0dc0c2075537732f2b9a894b24578eed各种卷积层的理解(深度可分离卷积、分组卷积、扩张卷积、反卷积)_分层卷积-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/gwplovekimi/article/details/89890510【深度学习 搞笑教程】22 卷积运算过程(单通道 多通道 多卷积核)| 草履虫都能听懂 零基础入门 | 持续更新_哔哩哔哩_bilibiliicon-default.png?t=O83Ahttps://www.bilibili.com/video/BV1de411H7s8/?spm_id_from=333.337.search-card.all.click&vd_source=0dc0c2075537732f2b9a894b24578eed卷积神经网络原理 - 12 - 有趣的1x1卷积核_哔哩哔哩_bilibiliicon-default.png?t=O83Ahttps://www.bilibili.com/video/BV1Q5411d7hz?spm_id_from=333.788.videopod.sections&vd_source=0dc0c2075537732f2b9a894b24578eed【深度学习 搞笑教程】26 反卷积 空洞卷积 可分离卷积 | 草履虫都能听懂 零基础入门 | 持续更新_哔哩哔哩_bilibiliicon-default.png?t=O83Ahttps://www.bilibili.com/video/BV19x4y1E7yA/?spm_id_from=333.337.search-card.all.click&vd_source=0dc0c2075537732f2b9a894b24578eed47 转置卷积【动手学深度学习v2】_哔哩哔哩_bilibiliicon-default.png?t=O83Ahttps://www.bilibili.com/video/BV17o4y1X7Jn/?spm_id_from=333.337.search-card.all.click&vd_source=0dc0c2075537732f2b9a894b24578eed

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

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

相关文章

VOLO实战:使用VOLO实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

GPU 服务器厂家:怎样铸就卓越 AI 算力?

文章来源于百家号&#xff1a;GPU服务器厂家 今天咱来聊聊 GPU 服务器厂家那些事儿&#xff0c;而这其中衡量 AI 算力的因素可是关键所在哦。 先讲讲计算速度这一块。咱都知道 AI 那复杂的活儿&#xff0c;像训练超厉害的图像识别模型&#xff0c;得处理海量图像数据&#x…

DroneCAN 最新开发进展,Andrew在Ardupilot开发者大会2024的演讲

本文是Andrew演讲的中文翻译&#xff0c;你可以直接观看视频了解演讲的全部内容&#xff0c;此演讲视频的中文版本已经发布在Ardupilot社区的Blog板块&#xff0c;你可以在 Arudpilot官网&#xff08;https://ardupilot.org) 获取该视频&#xff1a; 你也可以直接通过Bilibili链…

USB Type-C一线通扩展屏:多场景应用,重塑高效办公与极致娱乐体验

在追求高效与便捷的时代&#xff0c;启明智显USB Type-C一线通扩展屏方案正以其独特的优势&#xff0c;成为众多职场人士、娱乐爱好者和游戏玩家的首选。这款扩展屏不仅具备卓越的性能和广泛的兼容性&#xff0c;更能在多个应用场景中发挥出其独特的价值。 USB2.0显卡&#xff…

Android 混淆问题

我的安卓混淆只需要在gradle里面开启就行了。 buildTypes {release {minifyEnabled trueshrinkResources truezipAlignEnabled trueproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro}} minifyEnabled true 这个就是开启方法&#xf…

《硬件架构的艺术》笔记(九):电磁兼容性能设计指南

简介 电子线路易于接收来自其他发射器的辐射信号&#xff0c;这些EMI&#xff08;电磁干扰&#xff09;使得设备内毗邻的元件不能同时工作。这就有必要进行电磁兼容设计以避免系统内有害的电磁干扰。 确保设备不产生多余的辐射&#xff0c;设备也不易受到射频辐射的干扰&…

MR30分布式 IO 模块在冷却水泵系统中的卓越应用

在当今各类工业生产以及大型设施运行的场景中&#xff0c;冷却水泵系统起着至关重要的作用&#xff0c;它犹如保障整个运转体系顺畅运行的 “血液循环系统”&#xff0c;维持着设备适宜的温度环境&#xff0c;确保其稳定、高效地工作。而随着科技的不断发展&#xff0c;明达技术…

【数据分析】布朗运动(维纳过程)

文章目录 一、概述二、数学布朗运动2.1 数学定义2.2 布朗运动的数学模型2.21 标准布朗运动2.22 布朗运动的路径2.23 布朗运动的方程 三、布朗运动在金融学中的应用四、数学构造&#xff08;以傅里叶级数为例&#xff09;4.1 傅里叶级数的基本思想4.2 构造布朗运动 一、概述 布…

3.22【机器学习】决策树作业代码实现

4.1由于决策树只在样本同属于一类或者所有特征值都用完或缺失时生成叶节点&#xff0c;同一节点的样本&#xff0c;在路径上的特征值都相同&#xff0c;而训练集中又没有冲突数据&#xff0c;所以必定存在训练误差为0的决策树 4.2使用最小训练误差会导致过拟合&#xff0c;使得…

数字IC后端实现之PR工具中如何避免出现一倍filler的缝隙?

在数字IC后端实现中&#xff0c;由于有的工艺foundary不提供Filler1&#xff0c;所以PR工具Innovus和ICC2在做标准单元摆放时需要避免出现两个标准单元之间的缝隙间距是Filler1。为了实现这个目的&#xff0c;我们需要给PR工具施加一些特殊的placement constraint&#xff08;典…

群控系统服务端开发模式-应用开发-前端短信配置开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下sms文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;"><el…

111.有效单词

class Solution {public boolean isValid(String word) {if(word.length()<3){return false;}int countV0,countC0;//分别统计原音和辅音for(int i0;i<word.length();i){if(Character.isLetterOrDigit(word.charAt(i))){if(word.charAt(i)a||word.charAt(i)e||word.charA…

python图像彩色数字化

效果展示&#xff1a; 目录结构&#xff1a; alphabets.py GENERAL {"simple": "%#*-:. ","complex": "$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_~<>i!lI;:,\"^. " } # Full list could be found here…

欧科云链研究院:比特币还能“燃”多久?

出品&#xff5c; OKG Research 作者&#xff5c;Hedy Bi 本周二&#xff0c;隔夜“特朗普交易” 的逆转趋势波及到比特币市场。比特币价格一度冲高至约99,000美元后迅速回落至93,000美元以下&#xff0c;最大跌幅超6%。这是由于有关以色列和黎巴嫩有望达成停火协议的传闻引发…

Unity之一键创建自定义Package包

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之一键创建自定义Package包 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01; …

E2、UML类图顺序图状态图实训

一、实验目的 在面向对象的设计里面&#xff0c;可维护性复用都是以面向对象设计原则为基础的&#xff0c;这些设计原则首先都是复用的原则&#xff0c;遵循这些设计原则可以有效地提高系统的复用性&#xff0c;同时提高系统的可维护性。在掌握面向对象七个设计原则基础上&…

【Java基础入门篇】一、变量、数据类型和运算符

Java基础入门篇 一、变量、数据类型和运算符 1.1 变量 计算机中的数据表示方式是&#xff1a;“二进制(0/1)”&#xff0c;但是同时也可以兼容其他进制&#xff0c;例如八进制、十进制、十六进制等。 Java变量的本质是&#xff1a;存储在固定空间的内容&#xff0c;变量名是…

前端学习笔记之文件下载(1.0)

因为要用到这样一个场景&#xff0c;需要下载系统的使用教程&#xff0c;所以在前端项目中就提供了一个能够下载系统教程的一个按钮&#xff0c;供使用者进行下载。 所以就试着写一下这个功能&#xff0c;以一个demo的形式进行演示&#xff0c;在学习的过程中也发现了中文路径…

【力扣】387.字符串中的第一个唯一字符

问题描述 思路解析 对于这种个数有限的问题&#xff0c;我的第一想法是使用桶排序来解决因为s中只有小写英文单词&#xff0c;所以我只需要一个26个单位的数组就好了通过 charAt() 来提取单个字符&#xff0c;然后通过 -‘a’ 来将其映射到 0~25&#xff0c;不然数组长度就被超…

数据采集中,除了IP池的IP被封,还有哪些常见问题?

在数据采集的过程中&#xff0c;代理IP池的使用无疑为我们打开了一扇通往信息宝库的大门。然而&#xff0c;除了IP被封禁这一常见问题外&#xff0c;还有许多其他问题可能影响数据采集的效果。本文将探讨在数据采集中&#xff0c;除了IP被封之外&#xff0c;还可能遇到的一些常…