目录

摘要

一、介绍

二、相关工作

2.1 现代 CNN 架构

2.2 多路和特征图注意力

2.3 神经架构搜索

三、原理 (Split-Attention Networks)

3.1 Feature-Map Group

3.2 Split Attention in Cardinal Groups

3.3 ResNeSt Block

3.4 Instantiation, Acceleration, and Computational Costs

3.5 Relation to Existing Attention Methods

四、网络和训练

4.1 Large Mini-batch Distributed Training

4.2 Label Smooth

4.3 Auto Augmentation

4.4 Mixup Training

4.5 Large Crop Size

4.6 Regularization

五、结论

六、代码

6.1 Split Attention

6.2 ResNest BottleNeck

6.3 ResNeSt


  • 论文:https://arxiv.org/abs/2004.08955
  • 代码:GitHub - zhanghang1989/ResNeSt: ResNeSt: Split-Attention Networks
  • timm:pytorch-image-models/resnest.py at master · rwightman/pytorch-image-models · GitHub

摘要

虽然图像分类模型最近不断发展,但由于其简单和模块化的结构,大多数下游应用程序 (如目标检测和语义分割) 仍使用 ResNet 变体作为主干网络。 我们提出了一个模块化的 Split-Attention Block,可以跨特征图组执行注意力。通过堆叠 ResNet 风格的 Split-Attention Block,我们获得了一个新的 ResNet 变体 —— ResNeSt。我们的网络保留了整个 ResNet 结构以直接用于下游任务,而不会引入额外的计算成本。


一、介绍

图像分类是计算机视觉研究中的一项基本任务。为图像分类训练的网络通常作为为其他应用设计的神经网络的支柱,例如目标检测、语义分割和姿态估计。最近的工作通过大规模神经架构搜索 (NAS) 显着提高了图像分类精度。尽管它们具有 SOTA 性能,但这些源自 NAS 的模型通常并未针对通用/商业处理硬件 (CPU/GPU) 上的训练效率或内存使用进行优化。由于内存消耗过多,这些模型的一些较大版本甚至无法在具有适当的 batch size 的 GPU 上训练。这限制了 NAS 衍生模型在其他应用中的采用,尤其是涉及密集预测的任务,例如分割。

下游应用的最新工作仍然使用 ResNet 或其变体作为主干 CNN,其简单的模块化设计可轻松适应各种任务。然而,由于 ResNet 模型最初是为图像分类而设计的,由于有限的感受野和跨通道交互的缺乏,它们可能不适合各种下游应用。 这意味着提高给定计算机视觉任务的性能需要 “网络手术” 来修改 ResNet,使其对特定任务更有效。例如,一些方法添加金字塔模块、引入长程连接 或 使用跨通道特征图注意力。 虽然这些方法确实提高了某些任务的迁移学习性能,但它们提出了一个问题:能否创建一个具有普遍改善特征表示的多功能主干,从而同时提高多个任务的性能?跨通道信息已在下游应用中取得成功,而最近的图像分类网络更多地关注按组或深度卷积。尽管它们在分类任务中具有出色的计算量和准确率权衡,但这些模型不能很好地迁移到其他任务,因为它们的孤立表示无法捕获跨通道关系。 因此,需要具有跨通道表示的网络。

作为本文的第一个贡献,我们探索了 ResNet 的简单架构修改,在单个网络块中结合了 feature split attention。更具体地,我们的每个块 (沿通道维度) 将特征图划分为几个组 和 细粒度的子组 或 splits,其中每个组的特征表示 是通过其 splits 的表示的加权组合来确定的 (使用基于全局上下文信息选择的权重)。我们将生成的单元称为 Split-Attention Block,它保持简单和模块化。通过堆叠多个 Split-Attention Block,我们创建了一个类似于 ResNet 的网络,称为 ResNeSt (S 代表 “split”)。 我们的架构无需比现有 ResNet 变体更多的计算,并且很容易被用作其他视觉任务的主干。

本文的第二个贡献是图像分类和迁移学习应用的大规模基准测试。我们发现使用 ResNeSt 主干的模型能够在多个任务上达到 SOTA 性能,即:图像分类、目标检测、实例分割 和 语义分割。所提出的 ResNeSt 优于所有现有的 ResNet 变体,并且具有相同的计算效率,甚至比通过 NAS 生成的 SOTA CNN 模型实现了更好的速度-准确度权衡,如表 1 所示。使用 ResNeSt-101 主干的 Cascade-RCNN 模型在 MS-COCO 实例分割上实现了 48.3% 的 box mAP 和 41.56% 的 mask mAP。我们的单个 DeepLabV3 模型再次使用 ResNeSt-101 主干,在 ADE20K 场景解析验证集上实现了 46.9% 的 mIoU,比之前的 SOTA 结果高出 1% 以上的 mIoU。其他结果可在第 5 节和第 6 节中找到。


二、相关工作

2.1 现代 CNN 架构

AlexNet 以来,深度 CNN 主导了图像分类。随着这一趋势,研究已经从工程手工特征转向工程网络架构。NIN 首先使用全局平均池化层代替重全连接层,并采用 1×1 卷积层学习特征图通道的非线性组合,这是第一种特征图注意力机制。VGG-Net 提出了一种模块化网络设计策略,重复堆叠相同类型的网络块,简化了下游应用的网络设计和迁移学习的工作流程。Highway Network 引入了 highway 连接,使得信息可以跨多层无衰减地流动,并有助于网络收敛。在开创性工作的成功基础上,ResNet 引入了 identity 跳跃连接,减轻了深度神经网络中梯度消失的困难,并允许网络学习更深层次的特征表示。ResNet 已成为最成功的 CNN 架构之一,已被各种计算机视觉应用采用。


2.2 多路和特征图注意力

多路表示 GoogleNet 中取得了成功,其每个网络块由不同的卷积核组成。ResNeXt 在 ResNet Bottle Block 中采用分组卷积,将多路结构转换为统一操作。SE-Net 通过自适应地重新校准通道特征响应来引入通道注意机制。SK-Net 将特征图注意力带到两个网络分支上。受先前方法的启发,我们的网络将通道注意力推广到特征图组表示中,可以使用统一的 CNN 算子进行模块化和加速。


2.3 神经架构搜索

随着计算能力的增加,人们的兴趣已经开始从手动设计的架构转移到针对特定任务自适应定制的系统搜索架构。最近的神经架构搜索算法自适应地生成了实现最先进分类性能的 CNN 架构,例如:Amoe baNetMNASNetEfficientNet。 尽管它们在图像分类方面取得了巨大成功,但元网络结构彼此不同,这使得下游模型难以建立。 相反,我们的模型保留了 ResNet 元结构,可以直接应用于许多现有的下游模型。 我们的方法还可以增加神经架构搜索的搜索空间,并有可能提高整体性能,这可以在未来的工作中进行研究。


三、原理 (Split-Attention Networks)

我们的 Split-Attention Block 是一个计算单元,由 Feature-Map GroupSplit-Attention 操作组成。图 1 (右) 展示了 Split-Attention Block。


3.1 Feature-Map Group

在 ResNeXt 块中,特征可按通道维度  分为若干组,特征图组的数量 由 基数 (cardinality) 超参数 给出。我们将得到的 特征图组 称为 基数组 (cardinal groups) (一次划分)。我们引入了一个新的 基数 (radix) 超参数 ,它表示 基数组 (cardinal groups) 内进一步划分的 splits 数 (二次划分)。因此,特征组的总数 。可以对每个单独的 split 应用一系列变换 ,那么每个 split 的中间表示便是 ,因为


3.2 Split Attention in Cardinal Groups

可通过融合 将 若干基数组构成一个组合表示,即 跨多个 splits 按元素求和。第  个基数组表示是  (第  组的  个 splits  之和),其中  且  为块输出特征图的形状。可通过跨空间维度  的 全局平均池化 来集合具有嵌入通道统计数据的全局上下文信息。此处第  个基数组的第 个分量 (split) 计算如下:

基数组表示 的加权融合 是 通过 按通道软注意力 聚合的,其中每个特征图通道是使用 splits 上的加权组合产生的。第 个通道计算如下:

其中  表示 (软) 分配权重:

映射  根据全局上下文表示  确定第  个通道的每个 splits 的权重。


3.3 ResNeSt Block

然后将基数组表示沿通道维度拼接起来:。与标准残差块一样,若输入和输出特征图形状相同,则 Split-Attention Block 的最终输出 由残差连接生成:。对于具有跨步 (stride) 的块,将适当的变换  应用于残差连接以对齐输出形状:。例如, 可以是跨步卷积或卷积和池化的组合。


3.4 Instantiation, Acceleration, and Computational Costs

图 1 (右) 展示了实例化的 Split-Attention Block,其中组转换 是 1×1 卷积后接 3×3 卷积 (灰色色块),并且注意力权重函数  使用两个 ReLU 激活的全连接层进行参数化。我们在基数主视图中绘制此图 (具有相同基数索引的特征图组彼此相邻),以便于描述整体逻辑。 通过将布局切换到基数主视图,可以使用标准 CNN 层 (例如组卷积、组全连接层和 softmax 操作) 轻松加速该块,我们将在补充材料中详细描述。Split-Attention 块的参数数量和 FLOPS 与具有相同基数和通道数的残差块大致相同。


3.5 Relation to Existing Attention Methods

      Squeeze-and-attention 的想法在 SE-Net 中被首次引入 (原文称为 excitation),其利用全局上下文来预测按通道顺序的注意力因子。当基数为 1 时,Split-Attention Block 对每个基数组应用 squeeze-and-attention 操作,而 SE-Net 在整个 Block 上运行而不论有多少组。像 SK-Net 这样的先前的模型在两个网络分支间引入了特征注意,但它们的操作并未针对训练效率和扩展到大型神经网络进行优化。 我们的方法在基数组设置中概括了先前关于特征图注意力的工作,并且其实现仍具有计算效率。图 1 展示了与 SE-Net 和 SK-Net 块的总体比较。


四、网络和训练

我们现在描述实验中使用的网络设计和训练策略。 首先,我们详细介绍了一些进一步提高性能的调整,其中一些已经在 《Bag of tricks to train convolutional neural networks for image classifification》中得到了经验验证。

4.1 Large Mini-batch Distributed Training

根据先前的工作,我们用 8 个服务器 (共 64 个 GPUs) 并行训练模型。

学习率根据余弦策略调整。我们遵循基于小 batch size 大小线性扩展初始学习率的常见做法。初始学习率由  给出,其中 是小 batch size 大小,我们使用 作为基础学习率。这种 warm-up 策略应用于前 5 个 epochs,逐渐将学习率从 0 线性增加到余弦策略的初始值。

按照大 batch size 训练的建议,BN 的放缩参数 (Scale Parameter)  在每个块最后的 BN 操作中初始化为 0。


4.2 Label Smooth

标签平滑最初被用于改进 Inception-V2 的训练。回想一下,我们网络的预测类别概率 引起的交叉熵损失是根据真实值 计算的:

其中  是类别总数, 是第 个类别的真实概率, 是网络对第  个类别的预测概率。与标准图像分类一样,我们定义: probs ,其中  是网络输出层产生的 logits。当提供的标签是类别而非类别概率 (硬标签) 时,如果 等于真实类别 ,则 ,否则 。因此在此设置中:。在训练的最后阶段,对于 ,logits 往往非常小,而 被推到其最佳值 ,这会导致过拟合。标签平滑不将硬标签指定为目标,而用平滑的真实概率。

小常数 。这减轻了网络过度自信和过拟合。


4.3 Auto Augmentation

Auto-Augment 是一种使用变换后的图像来增强训练数据的策略,其中变换是自适应地学习的 (而非人工/手动设置的)。本文引入了 16 种不同类型的图像抖动 (jittering) 变换,其中一种基于移位、旋转和颜色抖动等两个连续变换的 24 种不同组合来增强数据。每个变换的程度可用一个相对参数来控制 (例如 旋转角度),并且变换有概率被略过 ()。尝试各种候选增强策略的搜索会返回最佳的 24 个最佳组合。然后在训练期间随机选择这 24 个策略之一并应用于每个样本图像。最初的 Auto-Augment 实现使用强化学习来搜索这些超参数,将它们视为离散搜索空间中的分类值。对于连续搜索空间,它在搜索最佳值之前首先离散化可能的值。


4.4 Mixup Training

Mixup 是另一种数据增强策略,它 从训练数据中生成随机图像对的加权组合。给定两个图像及其真实标签:,合成训练示例  生成自:

其中, 独立采样自各经增强的样本。


4.5 Large Crop Size

图像分类研究通常比较在共享相同裁剪大小的图像上运行的不同网络的性能。ResNet 变体通常使用固定的训练裁剪大小 224,而 Inception-Net 系列使用的训练裁剪大小为 299。最近,EffifficientNet 方法已经证明 为更深、更宽的网络增加输入图像大小可能会更好地权衡精度与 FLOPS。为公平比较,我们在比较 ResNeSt 与 ResNet 变体时使用 224 的裁剪大小,与其他方法比较时使用 256 的裁剪大小。


4.6 Regularization

即使对于大型数据集,非常深的神经网络也往往会过拟合。为防止这种情况,dropout 正则化在训练期间 (但不是在推理期间) 随机屏蔽一些神经元,以形成隐式网络集成。在最终的全连接层前,将失活概率为 0.2 的 dropout 层应用于超过 200 层的网络。

我们还在网络的最后两个阶段将 DropBlock 层应用于卷积层。作为 dropout 的一种结构化变体,DropBlock 随机屏蔽了局部块区域,在特定正则化卷积层方面比 dropout 更有效。

最后,我们还应用了 权重衰减 (L2 正则化),这也有助于 稳定训练。先前关于大型小 batch size 训练的工作表明,权重衰减应仅应用于卷积层和全连接层的权重。我们不使任何其他网络参数受到权重衰减,包括 BN 层中的偏差单元、


五、结论

这项工作提出了具有新颖 Split-Attention Block 的 ResNeSt 架构,该架构普遍改进了学习的特征表示,以提高图像分类、目标检测、实例分割和语义分割的性能。在后面的下游任务中,通过简单地将主干网络切换到我们的 ResNeSt 所产生的经验改进明显优于应用于标准主干 (如 ResNet) 的任务特定修改。我们的 Split-Attention Block 易于使用且计算效率高,因此应该广泛适用于视觉任务。


六、代码

6.1 Split Attention

""" Split Attention Conv2d (for ResNeSt Models)
Paper: `ResNeSt: Split-Attention Networks` - /https://arxiv.org/abs/2004.08955
Adapted from original PyTorch impl at https://github.com/zhanghang1989/ResNeSt
Modified for torchscript compat, performance, and consistency with timm by Ross Wightman
"""
import torch
import torch.nn.functional as F
from torch import nnfrom .helpers import make_divisibleclass RadixSoftmax(nn.Module):def __init__(self, radix, cardinality):super(RadixSoftmax, self).__init__()self.radix = radix  # 每个基数组 (cardinality) 下划分的 splits 数 Rself.cardinality = cardinality  # 基数组数 Kdef forward(self, x):# x.shape = (B, group_width) = (B, c)batch = x.size(0)if self.radix > 1:  # (B, c) -> (B, K, R, c/(KR)) -> (B, R, K, c/(KR))x = x.view(batch, self.cardinality, self.radix, -1).transpose(1, 2)# 沿 splits 维度 R 计算 Softmax 用于为各 splits 加权x = F.softmax(x, dim=1)x = x.reshape(batch, -1)else:x = torch.sigmoid(x)return xclass SplitAttn(nn.Module):"""Split-Attention (aka Splat)"""def __init__(self, in_channels, out_channels=None, kernel_size=3, stride=1, padding=None,dilation=1, groups=1, bias=False, radix=2, rd_ratio=0.25, rd_channels=None, rd_divisor=8,act_layer=nn.ReLU, norm_layer=None, drop_block=None, **kwargs):super(SplitAttn, self).__init__()out_channels = out_channels or in_channels  # group_widthself.radix = radix  # 每个基数组 (cardinality) 下划分的 splits 数 Rself.drop_block = drop_block# 因为 in_channels = out_channels = group_width# 所以 mid_chs = group_width * R # 表示每个 cardinal group 有 R 个 splits, 共有 mid_chs 个通道mid_chs = out_channels * radix  if rd_channels is None:attn_chs = make_divisible(in_channels * radix * rd_ratio, min_value=32, divisor=rd_divisor)else:attn_chs = rd_channels * radixpadding = kernel_size // 2 if padding is None else paddingself.conv = nn.Conv2d(in_channels, mid_chs, kernel_size, stride, padding, dilation,groups=groups * radix, bias=bias, **kwargs)self.bn0 = norm_layer(mid_chs) if norm_layer else nn.Identity()self.act0 = act_layer(inplace=True)self.fc1 = nn.Conv2d(out_channels, attn_chs, 1, groups=groups)self.bn1 = norm_layer(attn_chs) if norm_layer else nn.Identity()self.act1 = act_layer(inplace=True)self.fc2 = nn.Conv2d(attn_chs, mid_chs, 1, groups=groups)  # 通道数 c' -> cself.rsoftmax = RadixSoftmax(radix, groups)def forward(self, x):# 特征图 x 包含了各 splitsx = self.conv(x)x = self.bn0(x)if self.drop_block is not None:x = self.drop_block(x)x = self.act0(x)B, RC, H, W = x.shape  # RC = mid_chs = group_width (c) * self.radix (R) if self.radix > 1:# x.shape = (B, self.radix, group_width, H, W) 可见 x 是 R 个 splits 的集合x = x.reshape((B, self.radix, RC // self.radix, H, W))# 沿 radix 维对各 splits 按元素求和x_gap = x.sum(dim=1)  # x_gap.shape = (B, group_width, H, W)else:x_gap = x# 对 H, W 维取均值 (相当于全局平均池化)x_gap = x_gap.mean((2, 3), keepdim=True)  # x_gap.shape = (B, group_width) = (B, c)# Dense c' + BN + ReLUx_gap = self.fc1(x_gap)  # x_gap.shape = (B, attn_chs) = (B, c')x_gap = self.bn1(x_gap)x_gap = self.act1(x_gap)# Dense cx_attn = self.fc2(x_gap)  # x_gap.shape = (B, group_width) = (B, c)# r-Softmaxx_attn = self.rsoftmax(x_attn).view(B, -1, 1, 1)# 按元素相乘计算各 splits 的注意力if self.radix > 1:# 此时 x.shape = (B, self.radix, RC // self.radix, H, W)out = (x * x_attn.reshape((B, self.radix, RC // self.radix, 1, 1))).sum(dim=1)else:out = x * x_attnreturn out.contiguous()

6.2 ResNest BottleNeck

class ResNestBottleneck(nn.Module):"""ResNet Bottleneck"""# pylint: disable=unused-argumentexpansion = 4def __init__(self, inplanes, planes, stride=1, downsample=None,radix=1, cardinality=1, base_width=64, avd=False, avd_first=False, is_first=False,reduce_first=1, dilation=1, first_dilation=None, act_layer=nn.ReLU, norm_layer=nn.BatchNorm2d,attn_layer=None, aa_layer=None, drop_block=None, drop_path=None):super(ResNestBottleneck, self).__init__()assert reduce_first == 1   # not supportedassert attn_layer is None  # not supportedassert aa_layer is None    # TODO not yet supportedassert drop_path is None   # TODO not yet supported# group_width = planes * cardinality (K)group_width = int(planes * (base_width / 64.)) * cardinalityfirst_dilation = first_dilation or dilationif avd and (stride > 1 or is_first):avd_stride = stridestride = 1else:avd_stride = 0self.radix = radix  # 每个基数组 (cardinality) 下的 splits 数 Rself.drop_block = drop_blockself.conv1 = nn.Conv2d(inplanes, group_width, kernel_size=1, bias=False)self.bn1 = norm_layer(group_width)self.act1 = act_layer(inplace=True)self.avd_first = nn.AvgPool2d(3, avd_stride, padding=1) if avd_stride > 0 and avd_first else None# 每个基数组 (cardinality) 下的 splits 数 Rif self.radix >= 1:self.conv2 = SplitAttn(group_width, group_width, kernel_size=3, stride=stride, padding=first_dilation,dilation=first_dilation, groups=cardinality, radix=radix, norm_layer=norm_layer, drop_block=drop_block)self.bn2 = nn.Identity()self.act2 = nn.Identity()else:self.conv2 = nn.Conv2d(group_width, group_width, kernel_size=3, stride=stride, padding=first_dilation,dilation=first_dilation, groups=cardinality, bias=False)self.bn2 = norm_layer(group_width)self.act2 = act_layer(inplace=True)self.avd_last = nn.AvgPool2d(3, avd_stride, padding=1) if avd_stride > 0 and not avd_first else Noneself.conv3 = nn.Conv2d(group_width, planes * 4, kernel_size=1, bias=False)self.bn3 = norm_layer(planes*4)self.act3 = act_layer(inplace=True)self.downsample = downsampledef zero_init_last_bn(self):nn.init.zeros_(self.bn3.weight)def forward(self, x):shortcut = x  # 跳跃/残差连接# Conv + BN + ReLUout = self.conv1(x)out = self.bn1(out)if self.drop_block is not None:out = self.drop_block(out)out = self.act1(out)# AvgPoolif self.avd_first is not None:out = self.avd_first(out)# SplitAttn + BN + ReLUout = self.conv2(out)out = self.bn2(out)if self.drop_block is not None:out = self.drop_block(out)out = self.act2(out)# AvgPoolif self.avd_last is not None:out = self.avd_last(out)# Conv + BNout = self.conv3(out)out = self.bn3(out)if self.drop_block is not None:out = self.drop_block(out)if self.downsample is not None:shortcut = self.downsample(x)# Resout += shortcutout = self.act3(out)return out

6.3 ResNeSt

def _create_resnest(variant, pretrained=False, **kwargs):return build_model_with_cfg(ResNet, variant, pretrained,default_cfg=default_cfgs[variant],**kwargs)@register_model
def resnest101e(pretrained=False, **kwargs):""" ResNeSt-101e model. Matches paper ResNeSt-101 model, https://arxiv.org/abs/2004.08955Since this codebase supports all possible variations, 'e' for deep stem, stem_width 64, avg in downsample."""model_kwargs = dict(block=ResNestBottleneck, layers=[3, 4, 23, 3],stem_type='deep', stem_width=64, avg_down=True, base_width=64, cardinality=1,block_args=dict(radix=2, avd=True, avd_first=False), **kwargs)return _create_resnest('resnest101e', pretrained=pretrained, **model_kwargs)

【机器学习】详解 ResNeSt相关推荐

  1. 二分类最优阈值确定_机器学习 | 详解GBDT在分类场景中的应用原理与公式推导...

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第31篇文章,我们一起继续来聊聊GBDT模型. 在上一篇文章当中,我们学习了GBDT这个模型在回归问题当中的原理.GBD ...

  2. 强的离谱, Transformer 模型与联邦机器学习详解!

    Transformer 作为一种基于注意力的编码器 - 解码器架构,不仅彻底改变了自然语言处理(NLP)领域,还在计算机视觉(CV)领域做出了一些开创性的工作.与卷积神经网络(CNN)相比,视觉 Tr ...

  3. 机器学习--详解基于梯度下降的Logistic回归算法原理

    先给出Logistic回归的sigmod函数数学表达式: 很简单的表达式,再看看它的性质,当时,,因此 当时,,因此 Logistic回归之所以称为Logistic是因为只有两个状态即0和1,这也是数 ...

  4. 机器学习——详解KD-Tree原理

    今天是机器学习的第15篇文章,之前的文章当中讲了Kmeans的相关优化,还讲了大名鼎鼎的EM算法.有些小伙伴表示喜欢看这些硬核的,于是今天上点硬菜,我们来看一个机器学习领域经常用到的数据结构--KD- ...

  5. 机器学习--详解贝叶斯公式、朴素贝叶斯的来龙去脉(附上多方式代码实现)

    贝叶斯公式: 提到贝叶斯公式,首先需要从条件概率说起,因为他们都是基于条件概率发展而来的,既然条件概率那么重要,那么什么是条件概率呢? 条件概率是概率论中的一个重要而时用的概念,生活中我们总是无意识的 ...

  6. 机器学习--详解人脸对齐算法SDM-LBF

    https://www.cnblogs.com/Anita9002/p/7095380.html 引自:http://blog.csdn.net/taily_duan/article/details/ ...

  7. 【机器学习详解】SVM解回归问题

    转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/51121767 CSDN−勿在浮沙筑高台 \color{Blue}{CSDN-勿 ...

  8. SLAM学习笔记(二十)LIO-SAM流程及代码详解(最全)

    写在前面 关于安装配置,博客LIO_SAM实测运行,论文学习及代码注释[附对应google driver数据] 我觉得已经写的比较完善了.但是我觉得在注释方面,这位博主写的还不够完善,因此在学习以后, ...

  9. 详解SVM支持向量机算法(四:坐标上升和SMO算法)

    作者:RayChiu_Labloy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 目录 背景 坐标上升算法 定义 过程 举个求解的栗子 基于坐标上升的SMO算法 SMO ...

最新文章

  1. 每日一皮:产品经理的黑化,你听过几个?
  2. 基于FPGA的OLED屏幕开发
  3. u盘文件看得见却打不开_U盘中病毒,文件看得见,但是打不开,文件要怎么修复,求解答?...
  4. 创建安卓app的30个经验教训
  5. 防止多重启动之调用Api [收集2005090201]
  6. iOS buttonWithType:101 苹果私有api
  7. 监督学习 | 线性分类 之Logistic回归原理及Sklearn实现
  8. maven导入模块后重新导入有两个一样的_Testng在Maven中配置Reportng中文乱码解决及笔记记录...
  9. python MultipartEncoder
  10. 我的世界中国版服务器存档位置,我的世界中国版如何自己上传本地的mod和存档...
  11. 台大李宏毅Machine Learning 2017Fall学习笔记 (4)Gradient Descent
  12. java单链表选票_Hackerrank Practice
  13. 在同一个公司死磕5-10年,到底值不值得?
  14. 计算机网络和internet选项,internet选项在哪
  15. Typescript1-基本语法
  16. php如何根据条件删除二维数组中的元素
  17. U8接口开发-五大方式对比与剖析
  18. HighSpeedCharting简单的使用
  19. Word恢复文本转换器-修复损坏的WORD文件
  20. simulink/psim电力电子仿真的一些问题

热门文章

  1. 20170118Capstone训练营
  2. Matlab三相变两相公式,交流电机三相两相坐标互换及MATLAB仿真
  3. htmlcss复习笔记-4
  4. 2022年钴酸锂、三元材料行业重点企业市场竞争规模份额占比分析及投资发展战略咨询预测
  5. 谷歌安装JSON格式插件
  6. 2023西南大学907考研,西南大学计算机考研情况
  7. 通电导体在磁场中运动大型实验电磁铁设备
  8. 应届生嵌入式软件岗笔面试经验总结
  9. python之父头发对比图_【发型前后对比】2021剪头发图鉴,换发型简直就是换一张脸!...
  10. 强化学习3——基于强化学习的四足机器人运动控制