Bilinear CNN:细粒度图像分类网络,对Bilinear CNN中矩阵外积的解释。

这篇具有很好参考价值的文章主要介绍了Bilinear CNN:细粒度图像分类网络,对Bilinear CNN中矩阵外积的解释。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

细粒度图像分类(fine-grained image recognition)的目的是区分类别的子类,如判别一只狗子是哈士奇还是柴犬。细粒度图像分类可以分为基于强监督信息(图像类别、物体标注框、部位标注点等)和基于弱监督信息(只有图像类别),具体可以参考 细粒度图像分类

Bilinear CNN 是2015在论文 《Bilinear CNN Models for Fine-grained Visual Recognition》中提出来的,是一种基于弱监督信息的细粒度图像分类模型。

一、Bilinear CNN 的网络结构

Bilinear CNN 的网络结构如下:
Bilinear CNN:细粒度图像分类网络,对Bilinear CNN中矩阵外积的解释。,# 图像分类,cnn,分类,矩阵
Bilinear CNN 由两个 CNN 特征提取网络组成,它们的输出做外积(outer product)获得双线性向量(可称为图像描述符 image descriptor),再进行分类。

需要注意的是两个 CNN 其实是完全相同的,代码中用的就是一个网络(一般用预训练的 vgg16 或 ResNet18 网络),只是对网络输出值 x 计算了 x 和 xT 的矩阵乘积实现特征交互。
当然也可以使用两个不同的 CNN 网络。

双线性网络用于模拟图像的双因素变化。有一种说法是:网络A的作用是对图像中对象的特征部位进行定位,网络B则是用来对网络A检测到的特征区域进行特征提取。两个网络相互协调作用,实现细粒度图像分类。但如果用一个网络来实现,这种说法也太荒谬了。

由于模型对两个 CNN 的输出的操作是线性的(矩阵相乘是线性运算,因为只有加法和乘法操作),所以网络称为 bilinear CNNs。

二、矩阵外积(outer product)

2.1 外积的计算方式

网上很多博客说 矩阵外积就是克罗内克积,但是Bilinear CNN代码实现中的外积其实就是普通的矩阵相乘(就是线性代数中最常规的矩阵相乘),并非克罗内克积。

代码可见本文第三部分“PyTorch 网络代码实现”。

计算外积的代码为:

x = torch.bmm(x, torch.transpose(x, 1, 2)) / (28 * 28)

这里的 torch.bmm(a,b) 就是普通的矩阵相乘,举个例子证明:

import torch

a = torch.randint(low=0, high=5, size=(1, 2, 2))
b = torch.randint(low=0, high=5, size=(1, 2, 2))
c = torch.bmm(a, b)
print(f"a = {a}")
print(f"b = {b}")
print(f"c = {c}")


"""
a = tensor([[[4, 0],
             [4, 1]]])
b = tensor([[[1, 4],
             [2, 4]]])
c = tensor([[[ 4, 16],         4 = 4 * 1 + 0 * 2, 16 = 4 * 4 + 0 * 4
             [ 6, 20]]])       6 = 4 * 1 + 1 * 2, 20 = 4 * 4 + 1 * 4
"""

如果这个版本的 PyTorch 代码没有错误的话,这里的外积就是普通的矩阵相乘。当然我没有看 Bilinear CNN 的 Matlab 源码,源码地址为 Bilinear CNNs for Fine-grained Visual Recognition,欢迎大家批评指正(对于内积外积我也没分清楚)。

2.2 外积的作用

外积其实只是一种特征融合的方式,其他常用的特征融合方法还有:最大值融合、平均值融合、相加、concat 等。

但外积可以通过矩阵运算捕捉不同通道之间的特征相关性。由于描述向量的不同维度对应卷积特征的不同通道,而不同通道提取了不同的语义特征,因此,通过双线性操作,可以同时捕获输入图像的不同语义特征之间的关系。

三、PyTorch 网络代码实现

基于 vgg16:

import torch
import torch.nn as nn
import torchvision


class BCNN_fc(nn.Module):
    def __init__(self):
        super(BCNN_fc, self).__init__()
        # VGG16的卷积层和池化层
        self.features = torchvision.models.vgg16(pretrained=True).features

        # 去除最后一个 pooling 层
        self.features = nn.Sequential(*list(self.features.children())[:-1])

        # 线性分类层
        self.fc = nn.Linear(512 * 512, 200)

        # 冻结以前的所有层
        for param in self.features.parameters():
            param.requres_grad = False

        # 初始化fc层
        nn.init.kaiming_normal_(self.fc.weight.data)
        if self.fc.bias is not None:
            nn.init.constant_(self.fc.bias.data, val=0)

    def forward(self, x):
        N = x.size()[0]
        assert x.size() == (N, 3, 448, 448)

        # 特征提取
        x = self.features(x)
        assert x.size() == (N, 512, 28, 28)
        x = x.view(N, 512, 28 * 28)

        # 双线性矩阵相乘
        # 对于 c=torch.bmm(a,b),其中 a.shape=[b,m,n], b.shape=[b,n,p], 则 c.shape=[b,m,p]
        # 这里其实是对 x 和 x^T 进行了相乘
        # 除以 28 * 28 是为了防止最后 softmax 的梯度过小
        x = torch.bmm(x, torch.transpose(x, 1, 2)) / (28 * 28)
        assert x.size() == (N, 512, 512)

        # 有符号平方根,y = sign(x) * sqrt(|x|)
        x = torch.sign(x) * torch.sqrt(torch.abs(x) + 1e-10)
        x = x.view(N, 512 * 512)
        assert x.size() == (N, 512 * 512)

        # L2归一化
        x = torch.nn.functional.normalize(x)
        assert x.size() == (N, 512 * 512)

        # 全连接分类层
        x = self.fc(x)
        assert x.size() == (N, 200)
        return x

if __name__ == '__main__':
    input = torch.randn(16, 3, 448, 448)
    model = BCNN_fc()
    output = model(input)
    print(output.shape)   # torch.Size([16, 200])

基于 ResNet18:文章来源地址https://www.toymoban.com/news/detail-684980.html

import torch
import torch.nn as nn
from torchvision.models import resnet18

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.features = nn.Sequential(resnet18().conv1,
                                     resnet18().bn1,
                                     resnet18().relu,
                                     resnet18().maxpool,
                                     resnet18().layer1,
                                     resnet18().layer2,
                                     resnet18().layer3,
                                     resnet18().layer4)
        self.classifiers = nn.Sequential(nn.Linear(512**2,14))
        
    def forward(self,x):
        x=self.features(x)
        batch_size = x.size(0)
        feature_size = x.size(2)*x.size(3)
        x = x.view(batch_size , 512, feature_size)
        x = (torch.bmm(x, torch.transpose(x, 1, 2)) / feature_size).view(batch_size, -1)
        x = torch.nn.functional.normalize(torch.sign(x)*torch.sqrt(torch.abs(x)+1e-10))
        x = self.classifiers(x)
        return x

到了这里,关于Bilinear CNN:细粒度图像分类网络,对Bilinear CNN中矩阵外积的解释。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Pytorch】计算机视觉项目——卷积神经网络CNN模型识别图像分类

    在上一篇笔记《【Pytorch】整体工作流程代码详解(新手入门)》中介绍了Pytorch的整体工作流程,本文继续说明如何使用Pytorch搭建卷积神经网络(CNN模型)来给图像分类。 其他相关文章: 深度学习入门笔记:总结了一些神经网络的基础概念。 TensorFlow专栏:《计算机视觉入门

    2024年02月05日
    浏览(57)
  • 卷积神经网络教程 (CNN) – 使用 TensorFlow 在 Python 中开发图像分类器

    在这篇博客中,让我们讨论什么是卷积神经网络 (CNN) 以及 卷积神经网络背后的 架构 ——旨在 解决   图像识别 系统和 分类 问题。 卷积神经网络在图像和视频识别、推荐系统和 自然语言处理方面有着 广泛的应用 。 目录 计算机如何读取图像? 为什么不是全连接网络?

    2024年02月12日
    浏览(45)
  • 【图像分类】基于LIME的CNN 图像分类研究(Matlab代码实现)

    目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 基于LIME(Local Interpretable Model-Agnostic Explanations)的CNN图像分类研究是一种用于解释CNN模型的方法。LIME是一种解释性模型,旨在提供对黑盒模型(如CNN)预测结果的可解释性。下面是简要的步骤: 1. 数据准备:首

    2024年02月16日
    浏览(39)
  • 【图像分类】CNN + Transformer 结合系列.4

    介绍两篇利用Transformer做图像分类的论文:CoAtNet(NeurIPS2021),ConvMixer(ICLR2022)。CoAtNet结合CNN和Transformer的优点进行改进,ConvMixer则patch的角度来说明划分patch有助于分类。 论文:https://arxiv.org/abs/2106.04803 CoAtNet: Marrying Convolution and Attention for All Data Sizes 代码:https://github.com

    2024年02月13日
    浏览(69)
  • 【图像分类】CNN + Transformer 结合系列.1

    介绍三篇结合使用CNN+Transformer进行学习的论文:CvT(ICCV2021),Mobile-Former(CVPR2022),SegNetr(arXiv2307). 论文:https://arxiv.org/abs/2103.15808 代码:https://github.com/leoxiaobin/CvT 解读:CvT | CNN+Vision Transformer会有什么样的火花呢? - 知乎 (zhihu.com) 读论文之transformer系列-CvT:将卷积引入

    2024年02月15日
    浏览(72)
  • 什么是 CNN? 卷积神经网络? 怎么用 CNN 进行分类?(1)

    先看卷积是啥,url: https://www.bilibili.com/video/BV1JX4y1K7Dr/?spm_id_from=333.337.search-card.all.clickvd_source=7a1a0bc74158c6993c7355c5490fc600 下面这个式子就是卷积 看完了,感觉似懂非懂 下一个参考视频:https://www.youtube.com/watch?v=E5Z7FQp7AQQlist=PLuhqtP7jdD8CD6rOWy20INGM44kULvrHu 视频1:简单介绍卷积神经网络

    2024年02月08日
    浏览(47)
  • 什么是 CNN? 卷积神经网络? 怎么用 CNN 进行分类?(2)

    参考视频:https://www.youtube.com/watch?v=E5Z7FQp7AQQlist=PLuhqtP7jdD8CD6rOWy20INGM44kULvrHu 视频4:CNN 中 stride 的概念 如上图,stride 其实就是 ”步伐“ 的概念。 默认情况下,滑动窗口一次移动一步。而当 stride = 2 时,则一次移动两步,垂直移动和水平移动都是。 当我们提高 stride 的值的时

    2024年02月06日
    浏览(36)
  • 什么是 CNN? 卷积神经网络? 怎么用 CNN 进行分类?(3)

    参考视频:https://www.youtube.com/watch?v=E5Z7FQp7AQQlist=PLuhqtP7jdD8CD6rOWy20INGM44kULvrHu 视频7:CNN 的全局架构 卷积层除了做卷积操作外,还要加上 bias ,再经过非线性的函数,这么做的原因是 “scaled properly” 通常滑动窗口(filter) 不止一个,如下图 如下图是一个 CNN 的全部流程 如上图,

    2024年02月06日
    浏览(39)
  • 《数字图像处理》实验之对图像进行双线性(bilinear)插值缩放

     最近数字图像处理的实验课,老师让我们实现 对图像进行双线性(bilinear)插值缩放 ,以下是原理和代码。 一、双线性插值缩放 1、图像几何变换的一般流程: ①确定变换后新图像的大小 ②对新图像的每一个像素,确定其在旧图像坐标中的对应位置(逆变换) ③确定旧图像

    2024年02月07日
    浏览(95)
  • R语言矩阵、向量操作(矩阵乘法,向量内积、外积(叉乘),矩阵转置,矩阵的逆)

    创建两个四维矩阵 A 与 B,A 按列填充,B 按行填充 : 创建两个 n 维向量 x 和 y : 使用 t(矩阵、向量名) 即可: 输出如下: 使用 %*% 符号即可: 输出如下: 在R语言中,两个矩阵、向量的内积并不只是简单的 * 号就完事了,而是有以下两种求法: 或者 其结果如下: (注意区分

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包