Paddle2.0:浅析并实现 FcaNet 模型

FcaNet通过频率域分析重新审视通道注意力,证明GAP是二维DCT的特例。据此将通道注意力推广到频域,提出多谱通道注意力框架,通过选择更多频率分量引入更多信息。实验显示,其在ImageNet和COCO数据集表现优异,基于ResNet时精度高于SENet,且实现简单。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

paddle2.0:浅析并实现 fcanet 模型 - 创想鸟

引入

注意力机制,尤其是通道注意力,在计算机视觉领域取得了巨大的成功。许多工作专注于如何设计有效的通道注意力机制,同时忽略一个基本问题,即使用全局平均池(GAP)作为毫无疑问的预处理方法。在这项工作中,作者从不同的角度出发,并使用频率域分析(Frequency Analysis)重新考虑通道的注意力。基于频率域分析,作者在数学上证明了传统的 GAP 是离散余弦变化的特例。有了证明,作者自然地在频域上概括了通道注意力机制的预处理,并提出了具有新颖的 Multi-Spectral 通道注意力的 FcaNet(Frequency Channel Attention Networks)。

相关资料

论文:FcaNet: Frequency Channel Attention Networks官方实现:cfzd/FcaNet

主要贡献

证明了 GAP(Global Average Pooling) 是 DCT(Discrete Cosine Transform) 的特例。在此基础上,将通道注意力推广到频域,提出了基于多谱通道注意力(Multi-Spectral Channel Attention)框架的 FcaNet。通过研究不同频率分量数目及其不同组合的影响,提出了频率分量的两步选择准则。大量实验表明,该方法在 lmageNet 和 COCO 数据集上都取得了最新的结果。基于 ResNet 在相同的参数数目和计算代价下,它在 ImageNet 上的 Top1 精度比 SENet 高 1.8%。而且方法简单有效,只需在现有通道注意力实现中更改一行代码即可实现。

通道注意力(Channel Attention)

通道注意力的权重学习如下式所示,它表示输入经过 GAP 处理后由全连接层学习并经过 Sigmoid 激活得到加权的 Mask。

att=sigmoid⁡(fc(gap⁡(X)))att=sigmoid(fc(gap(X)))

然后,Mask 与原始输入经过下式逐通道相乘得到注意力操作后的输出。

X~:,i,:,:=attiX:,i,:,:, s.t. i∈{0,1,⋯ ,C−1}X~:,i,:,:=attiX:,i,:,:, s.t. i∈{0,1,⋯,C−1}

离散余弦变化(DCT)

DCT 是和傅里叶变换很相似,它的基本形式如下:f∈RLf∈RL 为 DCT 的频谱,x∈RLx∈RL 为输入,LL 为输入的长度。

fk=∑i=0L−1xicos⁡(πkL(i+12)), s.t. k∈{0,1,⋯ ,L−1}fk=i=0∑L−1xicos(Lπk(i+21)), s.t. k∈{0,1,⋯,L−1}

进而,推广得到二维 DCT 如下,f2d∈RH×Wf2d∈RH×W 是二维DCT的频谱,x2d∈RH×Wx2d∈RH×W 是输入,HH 和 WW 是输入的高和宽。

fh,w2d=∑i=0H−1∑j=0W−1xi,j2dcos(πhH(i+12))cos(πwW(i+12))⏟DCT weights, s.t. h∈{0,1,⋯ ,H−1},w∈{0,1,⋯ ,W−1}fh,w2d=i=0∑H−1j=0∑W−1xi,j2dDCT weightscos(Hπh(i+21))cos(Wπw(i+21)), s.t. h∈{0,1,⋯,H−1},w∈{0,1,⋯,W−1}

同样,逆 DCT 变换的公式就如下了。

xi,j2d=∑h=0H−1∑w=0W−1fh,w2dcos(πhH(i+12))cos(πwW(i+12))⏟DCT weights, s.t. i∈{0,1,⋯ ,H−1},j∈{0,1,⋯ ,W−1}xi,j2d=h=0∑H−1w=0∑W−1fh,w2dDCT weightscos(Hπh(i+21))cos(Wπw(i+21)), s.t. i∈{0,1,⋯,H−1},j∈{0,1,⋯,W−1}

上面两个式子中,为了简单起见,移除了一些常数标准化约束因子。DCT 变换属于信号处理领域的知识,是 JPEG 图像压缩的核心算法,相当于是对重要信息的聚集。其实从这里可以看出来,DCT 变换其实也是一种对输入的加权求和,式子中的余弦部分就是权重。因此,GAP 这种均值运算可以认为是输入的最简单频谱,这显然是信息不足的,因此作者引出了下面的多谱通道注意力。

多谱注意力(Multi-Spectral Channel Attention)

这里作者首先按证明了 GAP 其实是二维 DCT 的特例,其结果和二维 DCT 的最低频分量成比例。这个证明作者是令 HH 和 WW 都为 0 得到的,其中 f0,02df0,02d 表示二维 DCT 的最低频分量,显然,从结果来看它与 GAP 是成正比。

f0,02d=∑i=0H−1∑j=0W−1xi,j2dcos⁡(0H(i+12))cos⁡(0W(j+12))⏞=1=∑i=0H−1∑j=0W−1xi,j2d=gap⁡(x2d)HWf0,02d=i=0∑H−1j=0∑W−1xi,j2dcos(H0(i+21))cos(W0(j+21))=1=i=0∑H−1j=0∑W−1xi,j2d=gap(x2d)HW

通过上面的结论,自然会想到将其他分量引入通道注意力中,首先,为了叙述方便,将二维 DCT 的基本函数记为:

Bh,wi,j=cos⁡(πhH(i+12))cos⁡(πwW(j+12))Bh,wi,j=cos(Hπh(i+21))cos(Wπw(j+21))

继而将逆二维DCT变换改写如下:

xi,j2d=∑h=0H−1∑w=0W−1fh,w2dcos(πhH(i+12))cos(πwW(j+12))=f0,02dB0,0i,j+f0,12dB0,1i,j+⋯+fH−1.W−12dBH−1,W−1i,j=gap⁡(x2d)HWB0,0i,j+f0,12dB0,1i,j+⋯+fH−1.W−12dBH−1,W−1i,js.t. i∈{0,1,⋯ ,H−1},j∈{0,1,⋯ ,W−1}xi,j2d=h=0∑H−1w=0∑W−1fh,w2dcos(Hπh(i+21))cos(Wπw(j+21))=f0,02dB0,0i,j+f0,12dB0,1i,j+⋯+fH−1.W−12dBH−1,W−1i,j=gap(x2d)HWB0,0i,j+f0,12dB0,1i,j+⋯+fH−1.W−12dBH−1,W−1i,js.t. i∈{0,1,⋯,H−1},j∈{0,1,⋯,W−1}

由这个式子其实不难发现,此前的通道注意力只应用了第一项的最低频分量部分,而没有使用下式表示的后面其他部分,这些信息都被忽略了。

X=gap(X)HWB0,0i,j⏟utilized +f0,12dB0,1i,j+⋯+fH−1,W−12dBH−1,W−1i,j⏟discarded X=utilized gap(X)HWB0,0i,j+discarded f0,12dB0,1i,j+⋯+fH−1,W−12dBH−1,W−1i,j

基于此,作者设计了多谱注意力模块(Multi-Spectral Attention Module),该模块通过推广 GAP 采用更多频率分量从而引入更多的信息。

首先,输入 XX 被沿着通道划分为多块,记为 [X0,X1,⋯ ,Xn−1][X0,X1,⋯,Xn−1],其中每个 Xi∈RC′×H×W,i∈{0,1,⋯ ,n−1},C′=CnXi∈RC′×H×W,i∈{0,1,⋯,n−1},C′=nC,每个块分配一个二维 DCT 分量,那么每一块的输出结果如下式。

Freqi=2DDCTu,v(Xi)=∑h=0H−1∑w=0W−1X:,h,wiBh,wu,vs.t. i∈{0,1,⋯ ,n−1}Freqi=2DDCTu,v(Xi)=h=0∑H−1w=0∑W−1X:,h,wiBh,wu,vs.t. i∈{0,1,⋯,n−1}

上式中的 [u,v][u,v] 表示二维 DCT 的分量下标,这就对每一块采用不同的频率分量了,因此下式得到最终的输出 Freq∈RCFreq∈RC 就是得到的多谱向量,然后再将这个向量送入通道注意力常用的全连接层中进行学习得到注意力图。

 Freq =cat⁡([ Fre q0, Fre q1,⋯ , Freq n−1]) Freq =cat([ Fre q0, Fre q1,⋯, Freq n−1])

ms−att=sigmoid⁡(fc( Freq ))ms−att=sigmoid(fc( Freq ))

以上就是全部的多谱注意力模块的设计了,现在,下图这个FcaNet整体框架中间的一部分就看得明白了,唯一留下的问题就是对分割得到的每个特征图块,如何选择 [u,v][u,v] 呢?事实上,对空间尺寸为 H×WH×W 的特征图,会有 HWHW 个频率分量,由此频率分量的组合共有 CHWCHW 种,遍历显然是非常费时的因此,文中设计了一种启发式的两步准则来选择多谱注意力模块的频率分量,其主要思想是先得到每个频率分量的重要性再确定不同数目频率分量的效果。具体而言,先分别计算通道注意力中采用各个频率分量的结果,然后,根据结果少选出 Top k 个性能最好的分量。

Paddle2.0:浅析并实现 FcaNet 模型 - 创想鸟

代码实现

导入必要的模块

In [ ]

import mathimport paddleimport paddle.nn as nnfrom paddle.vision.models import ResNet

构建多谱注意力层

In [ ]

def get_freq_indices(method):    assert method in [        'top1', 'top2', 'top4', 'top8', 'top16', 'top32', 'bot1', 'bot2',        'bot4', 'bot8', 'bot16', 'bot32', 'low1', 'low2', 'low4', 'low8',        'low16', 'low32'    ]    num_freq = int(method[3:])    if 'top' in method:        all_top_indices_x = [            0, 0, 6, 0, 0, 1, 1, 4, 5, 1, 3, 0, 0, 0, 3, 2, 4, 6, 3, 5, 5, 2,            6, 5, 5, 3, 3, 4, 2, 2, 6, 1        ]        all_top_indices_y = [            0, 1, 0, 5, 2, 0, 2, 0, 0, 6, 0, 4, 6, 3, 5, 2, 6, 3, 3, 3, 5, 1,            1, 2, 4, 2, 1, 1, 3, 0, 5, 3        ]        mapper_x = all_top_indices_x[:num_freq]        mapper_y = all_top_indices_y[:num_freq]    elif 'low' in method:        all_low_indices_x = [            0, 0, 1, 1, 0, 2, 2, 1, 2, 0, 3, 4, 0, 1, 3, 0, 1, 2, 3, 4, 5, 0,            1, 2, 3, 4, 5, 6, 1, 2, 3, 4        ]        all_low_indices_y = [            0, 1, 0, 1, 2, 0, 1, 2, 2, 3, 0, 0, 4, 3, 1, 5, 4, 3, 2, 1, 0, 6,            5, 4, 3, 2, 1, 0, 6, 5, 4, 3        ]        mapper_x = all_low_indices_x[:num_freq]        mapper_y = all_low_indices_y[:num_freq]    elif 'bot' in method:        all_bot_indices_x = [            6, 1, 3, 3, 2, 4, 1, 2, 4, 4, 5, 1, 4, 6, 2, 5, 6, 1, 6, 2, 2, 4,            3, 3, 5, 5, 6, 2, 5, 5, 3, 6        ]        all_bot_indices_y = [            6, 4, 4, 6, 6, 3, 1, 4, 4, 5, 6, 5, 2, 2, 5, 1, 4, 3, 5, 0, 3, 1,            1, 2, 4, 2, 1, 1, 5, 3, 3, 3        ]        mapper_x = all_bot_indices_x[:num_freq]        mapper_y = all_bot_indices_y[:num_freq]    else:        raise NotImplementedError    return mapper_x, mapper_yclass MultiSpectralAttentionLayer(nn.Layer):    def __init__(self,                 channel,                 dct_h,                 dct_w,                 reduction=16,                 freq_sel_method='top16'):        super(MultiSpectralAttentionLayer, self).__init__()        self.reduction = reduction        self.dct_h = dct_h        self.dct_w = dct_w        mapper_x, mapper_y = get_freq_indices(freq_sel_method)        self.num_split = len(mapper_x)        mapper_x = [temp_x * (dct_h // 7) for temp_x in mapper_x]        mapper_y = [temp_y * (dct_w // 7) for temp_y in mapper_y]        # make the frequencies in different sizes are identical to a 7x7 frequency space        # eg, (2,2) in 14x14 is identical to (1,1) in 7x7        self.dct_layer = MultiSpectralDCTLayer(dct_h, dct_w, mapper_x,                                               mapper_y, channel)        self.fc = nn.Sequential(            nn.Linear(channel, channel // reduction, bias_attr=False),            nn.ReLU(), nn.Linear(channel // reduction,                                 channel,                                 bias_attr=False), nn.Sigmoid())    def forward(self, x):        n, c, h, w = x.shape        x_pooled = x        if h != self.dct_h or w != self.dct_w:            x_pooled = nn.functional.adaptive_avg_pool2d(                x, (self.dct_h, self.dct_w))            # If you have concerns about one-line-change, don't worry.   :)            # In the ImageNet models, this line will never be triggered.            # This is for compatibility in instance segmentation and object detection.        y = self.dct_layer(x_pooled)        y = self.fc(y).reshape((n, c, 1, 1))        return x * y.expand_as(x)class MultiSpectralDCTLayer(nn.Layer):    """    Generate dct filters    """    def __init__(self, height, width, mapper_x, mapper_y, channel):        super(MultiSpectralDCTLayer, self).__init__()        assert len(mapper_x) == len(mapper_y)        assert channel % len(mapper_x) == 0        self.num_freq = len(mapper_x)        # fixed DCT init        self.register_buffer(            'weight',            self.get_dct_filter(height, width, mapper_x, mapper_y, channel))        # # fixed random init        # self.register_buffer(        #     'weight',         #     paddle.rand((channel, height, width)))        # # learnable DCT init        # self.register_parameter(        #     'weight',         #     self.get_dct_filter(height, width, mapper_x, mapper_y, channel))                # # learnable random init        # self.register_parameter(        #     'weight',         #     paddle.rand((channel, height, width)))    def forward(self, x):        assert len(x.shape) == 4, 'x must been 4 dimensions, but got ' + str(            len(x.shape))        # n, c, h, w = x.shape        x = x * self.weight        result = paddle.sum(x, axis=[2, 3])        return result    def build_filter(self, pos, freq, POS):        result = math.cos(math.pi * freq * (pos + 0.5) / POS) / math.sqrt(POS)        if freq == 0:            return result        else:            return result * math.sqrt(2)    def get_dct_filter(self, tile_size_x, tile_size_y, mapper_x, mapper_y,                       channel):        dct_filter = paddle.zeros((channel, tile_size_x, tile_size_y))        c_part = channel // len(mapper_x)        for i, (u_x, v_y) in enumerate(zip(mapper_x, mapper_y)):            for t_x in range(tile_size_x):                for t_y in range(tile_size_y):                    dct_filter[i * c_part:(i + 1) * c_part,                               t_x, t_y] = self.build_filter(                                   t_x, u_x, tile_size_x) * self.build_filter(                                       t_y, v_y, tile_size_y)        return dct_filter

构建 FcaNet 模型

基于 ResNet 修改 Bottleneck 为 FcaBottleneckIn [ ]

def conv3x3(in_planes, out_planes, stride=1):    return nn.Conv2D(in_planes,                     out_planes,                     kernel_size=3,                     stride=stride,                     padding=1,                     bias_attr=False)class FcaBottleneck(nn.Layer):    expansion = 4    def __init__(self,                 inplanes,                 planes,                 stride=1,                 downsample=None,                 groups=1,                 base_width=64,                 dilation=1,                 norm_layer=None,                 reduction=16):        global _mapper_x, _mapper_y        super(FcaBottleneck, self).__init__()        # assert fea_h is not None        # assert fea_w is not None        c2wh = dict([(64, 56), (128, 28), (256, 14), (512, 7)])        self.planes = planes        self.conv1 = nn.Conv2D(inplanes,                               planes,                               kernel_size=1,                               bias_attr=False)        self.bn1 = nn.BatchNorm2D(planes)        self.conv2 = nn.Conv2D(planes,                               planes,                               kernel_size=3,                               stride=stride,                               padding=1,                               bias_attr=False)        self.bn2 = nn.BatchNorm2D(planes)        self.conv3 = nn.Conv2D(planes,                               planes * 4,                               kernel_size=1,                               bias_attr=False)        self.bn3 = nn.BatchNorm2D(planes * 4)        self.relu = nn.ReLU()        self.att = MultiSpectralAttentionLayer(planes * 4,                                               c2wh[planes],                                               c2wh[planes],                                               reduction=reduction,                                               freq_sel_method='top16')        self.downsample = downsample        self.stride = stride    def forward(self, x):        residual = x        out = self.conv1(x)        out = self.bn1(out)        out = self.relu(out)        out = self.conv2(out)        out = self.bn2(out)        out = self.relu(out)        out = self.conv3(out)        out = self.bn3(out)        out = self.att(out)        if self.downsample is not None:            residual = self.downsample(x)        out += residual        out = self.relu(out)        return outclass FcaBasicBlock(nn.Layer):    expansion = 1    def __init__(self,                 inplanes,                 planes,                 stride=1,                 downsample=None,                 groups=1,                 base_width=64,                 dilation=1,                 norm_layer=None,                 reduction=16):        global _mapper_x, _mapper_y        super(FcaBasicBlock, self).__init__()        # assert fea_h is not None        # assert fea_w is not None        c2wh = dict([(64, 56), (128, 28), (256, 14), (512, 7)])        self.planes = planes        self.conv1 = nn.Conv2D(inplanes,                               planes,                               kernel_size=3,                               stride=stride,                               padding=1,                               bias_attr=False)        self.bn1 = nn.BatchNorm2D(planes)        self.conv2 = nn.Conv2D(planes,                               planes,                               kernel_size=3,                               padding=1,                               bias_attr=False)        self.bn2 = nn.BatchNorm2D(planes)        self.relu = nn.ReLU()        self.att = MultiSpectralAttentionLayer(planes,                                               c2wh[planes],                                               c2wh[planes],                                               reduction=reduction,                                               freq_sel_method='top16')        self.downsample = downsample        self.stride = stride    def forward(self, x):        residual = x        out = self.conv1(x)        out = self.bn1(out)        out = self.relu(out)        out = self.conv2(out)        out = self.bn2(out)        out = self.att(out)        if self.downsample is not None:            residual = self.downsample(x)        out += residual        out = self.relu(out)        return out
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:26: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations  def convert_to_list(value, n, name, dtype=np.int):

预设模型

In [ ]

def fcanet34(num_classes=1000, pretrained=False):    """Constructs a FcaNet-34 model.    Args:        pretrained (bool): If True, returns a model pre-trained on ImageNet    """    model = ResNet(FcaBasicBlock, 34, num_classes=num_classes)    model.avgpool = nn.AdaptiveAvgPool2D(1)    if pretrained:        params = paddle.load('data/data100873/fca34.pdparams')        model.set_dict(params)    return modeldef fcanet50(num_classes=1000, pretrained=False):    """Constructs a FcaNet-50 model.    Args:        pretrained (bool): If True, returns a model pre-trained on ImageNet    """    model = ResNet(FcaBottleneck, 50, num_classes=num_classes)    model.avgpool = nn.AdaptiveAvgPool2D(1)    if pretrained:        params = paddle.load('data/data100873/fca50.pdparams')        model.set_dict(params)    return modeldef fcanet101(num_classes=1000, pretrained=False):    """Constructs a FcaNet-101 model.    Args:        pretrained (bool): If True, returns a model pre-trained on ImageNet    """    model = ResNet(FcaBottleneck, 101, num_classes=num_classes)    model.avgpool = nn.AdaptiveAvgPool2D(1)    if pretrained:        params = paddle.load('data/data100873/fca101.pdparams')        model.set_dict(params)    return modeldef fcanet152(num_classes=1000, pretrained=False):    """Constructs a FcaNet-101 model.    Args:        pretrained (bool): If True, returns a model pre-trained on ImageNet    """    model = ResNet(FcaBottleneck, 152, num_classes=num_classes)    model.avgpool = nn.AdaptiveAvgPool2D(1)    if pretrained:        params = paddle.load('data/data100873/fca152.pdparams')        model.set_dict(params)    return model

模型测试

In [ ]

model = fcanet34(pretrained=True)x = paddle.randn((1, 3, 224, 224))out = model(x)print(out.shape)model.eval()out = model(x)print(out.shape)
[1, 1000][1, 1000]
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/nn/layer/norm.py:648: UserWarning: When training, we now always track global mean and variance.  "When training, we now always track global mean and variance.")

精度测试

标称精度

Model Reported Evaluation Results

FcaNet3475.0775.02FcaNet5078.5278.57FcaNet10179.6479.63FcaNet15280.0880.02

解压数据集

In [ ]

!mkdir ~/data/ILSVRC2012!tar -xf ~/data/data68594/ILSVRC2012_img_val.tar -C ~/data/ILSVRC2012

模型评估

In [8]

import osimport cv2import numpy as npimport paddleimport paddle.vision.transforms as Tfrom PIL import Image# 构建数据集class ILSVRC2012(paddle.io.Dataset):    def __init__(self, root, label_list, transform, backend='pil'):        self.transform = transform        self.root = root        self.label_list = label_list        self.backend = backend        self.load_datas()    def load_datas(self):        self.imgs = []        self.labels = []        with open(self.label_list, 'r') as f:            for line in f:                img, label = line[:-1].split(' ')                self.imgs.append(os.path.join(self.root, img))                self.labels.append(int(label))    def __getitem__(self, idx):        label = self.labels[idx]        image = self.imgs[idx]        if self.backend=='cv2':            image = cv2.imread(image)        else:            image = Image.open(image).convert('RGB')        image = self.transform(image)        return image.astype('float32'), np.array(label).astype('int64')    def __len__(self):        return len(self.imgs)val_transforms = T.Compose([    T.Resize(256, interpolation='bicubic'),    T.CenterCrop(224),    T.ToTensor(),    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])# 配置模型model = fcanet34(pretrained=True)model = paddle.Model(model)model.prepare(metrics=paddle.metric.Accuracy(topk=(1, 5)))# 配置数据集val_dataset = ILSVRC2012('data/ILSVRC2012', transform=val_transforms, label_list='data/data68594/val_list.txt', backend='pil')# 模型验证acc = model.evaluate(val_dataset, batch_size=8, num_workers=0, verbose=1)print(acc)
{'acc_top1': 0.74838, 'acc_top5': 0.92048}

以上就是Paddle2.0:浅析并实现 FcaNet 模型的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/67556.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
电子签章是什么?概念、作用、主流电子签章软件盘点
上一篇 2025年11月12日 13:05:57
2025年人力资源管理系统排行榜:对比14款人气产品
下一篇 2025年11月12日 13:06:04

相关推荐

  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 利用海象运算符简化条件赋值:Python教程与最佳实践

    本文旨在探讨Python中海象运算符(:=)在条件赋值场景下的应用。通过对比传统if/else语句与海象运算符,以及条件表达式,分析海象运算符在简化代码、提高可读性方面的优势与局限性。并通过具体示例,展示如何在列表推导式等场景下合理使用海象运算符,同时强调其潜在的复杂性及替代方案,帮助开发者更好地掌…

    2026年5月10日
    100
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • RichHandler与Rich Progress集成:解决显示冲突的教程

    在使用rich库的`richhandler`进行日志输出并同时使用`progress`组件时,可能会遇到显示错乱或溢出问题。这通常是由于为`richhandler`和`progress`分别创建了独立的`console`实例导致的。解决方案是确保日志处理器和进度条组件共享同一个`console`实例…

    2026年5月10日
    000
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    100
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000
  • 使用 WebCodecs VideoDecoder 实现精确逐帧回退

    本文档旨在解决在使用 WebCodecs VideoDecoder 进行视频解码时,实现精确逐帧回退的问题。通过比较帧的时间戳与目标帧的时间戳,可以避免渲染中间帧,从而提高用户体验。本文将提供详细的解决方案和示例代码,帮助开发者实现精确的视频帧控制。 在使用 WebCodecs VideoDecod…

    2026年5月10日
    000
  • Debian Copilot的社区活跃度如何

    debian copilot是codeberg社区维护的ai助手,旨在为debian用户提供服务。尽管搜索结果中没有直接提供关于debian copilot社区支持活跃度的具体数据,但我们可以通过debian社区的整体活跃度和特点来推断其活跃性。 Debian社区的一般情况: Debian拥有详尽的…

    2026年5月10日
    000
  • Discord.py 交互按钮超时与持久化解决方案

    本教程旨在解决Discord.py中交互按钮在一段时间后出现“This Interaction Failed”错误的问题。我们将深入探讨视图(View)的超时机制,并提供通过正确设置timeout参数以及利用bot.add_view()方法实现按钮持久化的具体方案,确保您的机器人交互功能稳定可靠,即…

    2026年5月10日
    000
  • Python递归函数追踪与性能考量:以序列打印为例

    本文深入探讨了Python中一种递归打印序列元素的方法,并着重演示了如何通过引入缩进参数来有效追踪递归函数的执行流程和参数变化。通过实际代码示例,文章揭示了递归调用可能带来的潜在性能开销,特别是对调用栈空间的需求,以及Python默认递归深度限制可能导致的错误,为读者提供了理解和优化递归算法的实用见…

    2026年5月10日
    000
  • python中zip函数详解 python多序列压缩zip函数应用场景

    zip函数的应用场景包括:1) 同时遍历多个序列,2) 合并多个列表的数据,3) 数据分析和科学计算中的元素运算,4) 处理csv文件,5) 性能优化。zip函数是一个强大的工具,能够简化代码并提高处理多个序列时的效率。 在Python中,zip函数是一个非常有用的工具,它能够将多个可迭代对象打包成…

    2026年5月10日
    000
  • JavaScript 动态菜单点击高亮效果实现教程

    本教程详细介绍了如何使用 JavaScript 实现动态菜单的点击高亮功能。通过事件委托和状态管理,当用户点击菜单项时,被点击项会高亮显示(绿色),同时其他菜单项恢复默认样式(白色)。这种方法避免了不必要的DOM操作,提高了性能和代码可维护性,确保了无论点击方向如何,功能都能稳定运行。 动态菜单高亮…

    2026年5月10日
    200

发表回复

登录后才能评论
关注微信