29

我们能比卷积神经网络做得更好吗?

 4 years ago
source link: https://www.tuicool.com/articles/QRryqq3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
bu6Rfuz.jpg!web

作者|Boris Knyazev

译者 | Jhonson

来源 | Medium

英国机器视觉会议(BMVC)大约两周前在英国卡迪夫结束,是计算机视觉和模式识别领域的顶级会议之一,具有28%的竞争接受率。 与其他人相比,这是一个小活动,所以你有足够的时间在会议上走来走去,和论文讲述者一对一的交流,我觉得这大有裨益。

我在会议上展示了一份关于分层多图网络图像分类的工作,在林晓、穆罕默德·艾默尔(主页)和我的博士顾问格雷厄姆·泰勒的监督下,我在SRI国际公司实习期间主要在上面工作。

在本文中,我们基本上试图回答以下问题: “我们能比卷积神经网络做得更好吗? ”。 在这里,我讨论这个问题,并通过结果支持我的论点。 我还将引导您使用PyTorch从PASCAL VOC 2012的整个管道前进,获取单个图像。

这篇文章的完整代码在我的 Github笔记本( https://github.com/bknyaz/bmvc_2019 上。应该很容易地对其进行调整,以对整个PASCAL数据集进行训练和验证。

那么,为什么我们要比ConvNets做得更好? 他们在许多任务上都胜过人类吗?

例如,您可以说图像分类是解决的任务。 好吧,就ImageNet而言,是的。 但是,尽管ImageNet做出了巨大贡献,但这是一个奇怪的任务。 您为什么要区分数百种狗? 因此,结果是我们成功地建立了模型,但是无法区分稍微旋转的狗和猫。 幸运的是,我们现在有了ImageNet-C和其他类似的基准,表明我们离解决它还很遥远。

eeURZz6.png!web

相关任务(例如对象检测)中出现的另一个未解决的问题是在非常大的图像(例如4000×3000)上进行训练,例如Katharopoulos&Fleuret(ICML,2019)和Ramapuram等人解决了这个问题。 (BMVC,2019)。 多亏了后者,我现在知道如果海报的背景是黑色的,那么很有可能来自Apple。 我也应该保留一些颜色!

因此,也许我们需要不同于卷积神经网络的东西? 也许我们应该从一开始就使用具有更好属性的模型,而不是不断修补其错误.

我们认为这种模型可以是图神经网络(GNN):一种可以从图结构数据中学习的神经网络。 GNN具有一些吸引人的属性。 例如,与ConvNets相比,GNN本质上是旋转和平移不变的,因为在图形中根本没有旋转或平移的概念,即没有左右,在某种意义上只有“邻居”(Khasanova和Frossard, ICML,2017)。 因此,人们多年来一直试图解决的使ConvNet更好地推广到不同的轮换的问题可以通过GNN自动解决!

关于从大图像中学习,如何从图像中提取超像素并将低维输入输入到GNN而不是将下采样(例如224×224)图像输入到ConvNet? 与双线性插值相比,超像素似乎是对图像进行下采样的一种更好的方法,因为超像素通常通过保持对象之间的边界来保留很多语义。 借助ConvNet,我们无法直接从这种输入中学习,但是,有一些很好的提议建议利用它们(Kwak等人,AAAI,2017)。

因此,GNN听起来很棒! 让我们看看它在实践中的表现。

但是不好了! 基于(Kipf&Welling,ICLR,2017)的基准GNN在PASCAL上仅达到19.2%(平均平均精度或mAP),而在每一层中具有相同数量的层和滤波器的ConvNet为32.7%

我们提出了一些改进措施,最终击败了ConvNet!

1. 层次图

在ConvNets中,图像的层次结构是通过池化层隐式建模的。 在GNN中,您至少可以通过两种方式实现这一目标。 首先,您可以使用类似于ConvNets的池化方法,但是对于图而言,定义一种快速且良好的池化方法确实具有挑战性。 相反,我们可以计算多个比例的超像素,并通过将它们与较大的父超像素对应来合并超像素。 但是,由于某些原因,这种合并在我们的案例中效果不佳(我仍然认为效果很好)。 因此,我们改为在输入级别对层次结构建模。 特别是,我们将所有比例的超像素组合成一个集合,并基于语义分割中常用的基于联合的交集(IoU)计算层次关系。

A3iMfqJ.jpg!web

基于该原理,我在下面的代码中构建了层次图。 我还构建了空间图的多尺度版本,但它仅编码空间关系,而IoU应该更好地编码分层关系。 例如,使用IoU,我们可以在远程子节点之间创建快捷方式,即连接两个空间上相距较远但属于同一父节点(例如汽车)的小超像素(例如车轮),如上图所示。

实际上,层次图将mAP提升到31.7%,使其比ConvNet仅低1%,而可训练参数却减少了4倍! 如果仅使用空间多尺度图,则结果将比本文中探讨的要差得多。

def compute_iou_binary(seg1, seg2):
    inters = float(np.count_nonzero(seg1 & seg2))
    #区域可以预先计算
    seg1_area = float(np.count_nonzero(seg1))
    seg2_area = float(np.count_nonzero(seg2))
    return inters / (seg1_area + seg2_area - inters)

def hierarchical_graph(masks_multiscale, n_sp_actual, knn_graph=32):
    n_sp_total = np.sum(n_sp_actual)
    A = np.zeros((n_sp_total, n_sp_total))
    for level1, masks1 in enumerate(masks_multiscale):
        for level2, masks2 in enumerate(masks_multiscale[level1+1:]):
            for i, mask1 in enumerate(masks1):
                for j, mask2 in enumerate(masks2):
                    A[np.sum(n_sp_actual[:level1], dtype=np.int) + i, 
                    np.sum(n_sp_actual[:level2+level1+1], dtype=np.int) + j] = compute_iou_binary(mask1, mask2)
    sparsify_graph(A, knn_graph)
    return A + A.T

n_sp_actual = []
avg_values_multiscale, coord_multiscale, masks_multiscale = [], [], []

# Scales [1000, 300, 150, 75, 21, 7] ]在论文中
for i, (name, sp) in enumerate(zip(['children', 'parents', 'grandparents'], [1000, 300, 21])):
    superpixels = slic(img, n_segments=sp)
    n_sp_actual.append(len(np.unique(superpixels)))
    avg_values_, coord_, masks_ = superpixel_features(img, superpixels)
    avg_values_multiscale.append(avg_values_)
    coord_multiscale.append(coord_)
    masks_multiscale.append(masks_)

A_spatial_multiscale = spatial_graph(np.concatenate(coord_multiscale), img.shape[:2], knn_graph=knn_graph)
A_hier = hierarchical_graph(masks_multiscale, n_sp_actual, knn_graph=None)

很棒! 我们还可以做些什么来进一步改善结果?

2.易学的关系

到目前为止,如果我们可视化滤波器,它们将看起来非常原始(就像高斯一样)。有关更多详细信息,请参见我的 GNN教程( https://medium.com/@BorisAKnyazev/tutorial-on-graph-neural-networks-for-computer-vision-and-beyond-part-1-3d9fada3b80d 。我们想学习一些类似于ConvNets的边缘检测器,因为效果很好。但是事实证明,使用GNN来学习它们非常困难。为此,我们基本上需要根据坐标之间的差异在超像素之间生成边缘。这样,我们将使GNN能够理解坐标系(旋转,平移)。我们将使用在PyTorch中定义的2层神经网络,如下所示:

``python
class GraphLayerFusion(GraphLayerMultiscale):
def __init__(self,
in_features,
out_features,
K,
fusion='pc',
n_hidden=64,
bnorm=True,
activation=nn.ReLU(True),
n_relations=1)
:

super(GraphLayerFusion, self).__init__(in_features, out_features, K, bnorm, activation, n_relations)
self.fusion = fusion
if self.fusion == 'cp':
fc = [nn.Linear(in_features * K * n_relations, n_hidden),
nn.ReLU(True),
nn.Linear(n_hidden, out_features)]
else:
if self.fusion == 'pc':
fc = [nn.Linear(n_hidden * n_relations, out_features)]
elif self.fusion == 'sum':
fc = [nn.Linear(n_hidden, out_features)]
else:
raise NotImplementedError('cp, pc or sum is expected. Use GraphLayer for the baseline concatenation fusion')
self.proj = nn.ModuleList([nn.Sequential(nn.Linear(in_features * K, n_hidden), nn.Tanh())
for rel in range(n_relations)]) # projection layers followed by nonlinearity
if bnorm:
fc.append(BatchNorm1d_GNN(out_features))
if activation is not None:
fc.append(activation)
self.fc = nn.Sequential(*fc)

def relation_fusion(self, x, A):
B, N = x.shape[:2]
for rel in range(self.n_relations):
y = self.chebyshev_basis(A[:, :, :, rel], x, self.K).view(B, N, -1) # B,N,K,C
if self.fusion in ['pc', 'sum']:
y = self.proj[rel](y) # projection
if self.fusion == 'sum':
y_out = y if rel == 0 else y_out + y
continue
# for CP and PC
if rel == 0:
y_out = []
y_out.append(y)

y = self.fc(y_out if self.fusion == 'sum' else (torch.cat(y_out, 2))) # B,N,F
return y
```


结语

事实证明,有了多关系图网络和一些技巧,我们可以比卷积神经网络做得更好!

不幸的是,在改进GNN的过程中,我们逐渐失去了不变性。例如,旋转图像后,超像素的形状可能会发生变化,而我们用于节点特征以改善模型的超像素坐标也使其健壮性降低。

尽管如此,我们的工作只是迈向更好的图像推理模型的一小步,并且我们证明了GNN可以为一个有希望的方向铺平道路。

有关实现的详细信息,请参阅我在Github上的 笔记本:( https://github.com/bknyaz/bmvc_2019

我还高度推荐Matthias Fey的硕士论文,其中包含与非常相关的主题相关的 代码:( https://github.com/rusty1s/embedded_gcnn

你也许还想

Python Seaborn综合指南,成为数据可视化专家

       使用Python创建自己的Instagram滤镜|视觉实战

    图像质量评估|调研

欢迎扫码关注:

J3aYnyj.jpg!web

 点击下方  |   |  了解更多


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK