【U-Net验证】逐元素乘积将特征投射到极高维隐式特征空间的能力

写在前面:本博客仅作记录学习之用,部分图片来自网络,如需使用请注明出处,同时如有侵犯您的权益,请联系删除!


文章目录

  • 前言
  • 网络结构
    • 编码结构
    • 解码结构
    • 代码
  • 实验
    • 实验设置
    • w/o-ReLU的性能比较
    • with-ReLU的性能比较
  • 总结
  • 致谢
  • 参考


前言

在深度学习领域,网络架构的创新和性能的提升一直是研究的热点。在传统的神经网络设计中,激活函数扮演着至关重要的角色,它们为网络引入了非线性,使得网络能够学习和表示复杂的模式和结构。

近年来,逐元素乘积作为一种简单的操作,在各类神经网络中展现出惊人的潜力。它不仅能够有效融合不同来源的信息。在博客【CVPR_2024】:逐元素乘积为什么会产生如此令人满意的结果? 揭示了逐元素乘积具有将特征投射到极高维隐式特征空间的能力,为设计紧凑和高效网络提供了思路。简言之,网络缺少激活函数,也可基于逐元素乘积为网络提供非线性。

为了验证逐元素乘积在神经网络中的性能,本文以眼底视网膜血管分割任务为例进行了实验。视网膜血管分割是医学图像处理中的一个重要任务,它对于眼科疾病的诊断和治疗具有重要意义。本文选择U-Net作为基础网络架构,并在其中引入逐元素乘积操作,以验证其在缺少激活函数时的网络性能。

网络结构

在这里插入图片描述

编码结构

U-Net的编码结构(Encoder)是一种专为图像分割任务设计的深度卷积神经网络的重要组成部分。U-Net的编码结构采用了一种典型的卷积神经网络(CNN)架构,其主要目的是从输入图像中提取有用的特征信息。该结构通常由多个重复的卷积块组成,每个卷积块包含卷积层、BN、激活函数和池化层。

区别于传统的unet,本文去除了编码阶段所有激活函数,即编码部分只包含卷积、BN和池化层,结构如下图。具体组成:

卷积层:卷积核大小为3x3,步长(stride)为1,填充(padding)为1。
池化层:池化窗口的大小通常为2x2,步长为2。

在这里插入图片描述

解码结构

U-Net的解码结构是U-Net网络中的关键部分,主要用于从编码器提取的特征中恢复图像的空间分辨率和细节。解码器通过上采样操作逐步恢复图像尺寸,并与编码器中的对应层通过跳跃连接进行特征融合,以恢复丢失的空间信息。

区别于传统的unet,本文去除了解码阶段所有激活函数,即解码部分只包含卷积、BN和上采样层,结构如下图。具体组成:

上采样层:最邻近插值法。
卷积层:卷积核大小为3x3,步长(stride)为1,填充(padding)为1。

在这里插入图片描述

代码

需要注意的是,本文为说明逐元素乘积的性能,将解码阶段中特征图拼接换为了sum/star,使得网络的参数进一步减少,网络更加紧凑。

同时,网络传入参数,设置了narrow,channel_multiplier参数用于控制网络通道以实现对网络参数的控制,return_feats参数则用于选择是否需要深度监督。

# ==============================U_Net—without ReLU====================================
class encode_block_wo_relu(nn.Module):def __init__(self, ch_in, ch_out):super(encode_block_wo_relu, self).__init__()self.conv = nn.Sequential(nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1, bias=True),NormLayer(ch_out, 'bn'),nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1, bias=True),NormLayer(ch_out, 'bn'),)self.down = nn.MaxPool2d(kernel_size=2, stride=2)def forward(self, x):skip = self.conv(x)x = self.down(skip)return x, skipclass decode_block_wo_relu(nn.Module):def __init__(self, ch_in, ch_out):super(decode_block_wo_relu, self).__init__()self.conv = nn.Sequential(nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1, bias=True),NormLayer(ch_out, 'bn'),nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1, bias=True),NormLayer(ch_out, 'bn'),UpsampleLayer())def forward(self, x):x = self.conv(x)return xclass U_Net_wo_relu(nn.Module):def __init__(self, img_ch=3, output_ch=1, narrow=0.5, channel_multiplier=1, return_feats=False):super(U_Net_wo_relu, self).__init__()channels = {'32': int(32 * channel_multiplier * narrow),'64': int(64 * channel_multiplier * narrow),'128': int(128 * channel_multiplier * narrow),'256': int(256 * channel_multiplier * narrow),'512': int(512 * channel_multiplier * narrow),'1024': int(1024 * channel_multiplier * narrow),'2048': int(2048 * channel_multiplier * narrow),'4096': int(4096 * channel_multiplier * narrow),}self.return_feats = return_featsself.up = UpsampleLayer()self.encoder = nn.ModuleList()self.decoder = nn.ModuleList()self.encoder.append(encode_block_wo_relu(img_ch, channels['64']))for i in range(0, 3):self.encoder.append(encode_block_wo_relu(channels[f'{64 * 2 ** i}'], channels[f'{64 * 2 ** (i + 1)}']))self.decoder.append(decode_block_wo_relu(channels[f'512'], channels[F'512']))for i in range(3, 0, -1):self.decoder.append(decode_block_wo_relu(channels[f'{int(64 * 2 ** i)}'], channels[f'{int(64 * 2 ** (i-1))}']))self.out = nn.Conv2d(channels['64'], output_ch, kernel_size=1)def forward(self, x):skips = []feats = []# encodefor enc in self.encoder:x, skip = enc(x)skips.append(skip)skips = skips[::-1]# decodefor i, dec in enumerate(self.decoder):x = dec(x)# print(x.shape, skips[i].shape)if i < len(self.decoder) - 1:# x = x + skips[i]x = x * skips[i]if self.return_feats:feats.append(x)out = self.out(x)pre = F.softmax(out, dim=1)return pre, feats

实验

实验设置

实验的设置如下:

随机种子验证集比例批大小早停学习率优化器图像大小数据集
20240.28100.0005adam96x96STARE

所有方法均在相同的设置下进行实验,保证实验的公平性,网络参数为2.94M,均选择在验证集上表现最优的权重进行测试。

w/o-ReLU的性能比较

下图给了sum和star两种方法的性能对比:

sum-w/o-ReLU-ROC曲线
sum-w/o-ReLU-PR曲线
star-w/o-ReLU-ROC曲线
star-w/o-ReLU-PR曲线
操作类型ROCPRF1AccSESPpre
sum-w/o-ReLU0.90390.71390.65300.92710.59390.97060.7251
star-w/o-ReLU0.93120.74070.68350.93300.62710.97290.7511
提升 ↑ 2.73 % \textcolor{red}{\uparrow 2.73\%} 2.73% ↑ 2.68 % \textcolor{red}{\uparrow 2.68\%} 2.68% ↑ 3.05 % \textcolor{red}{\uparrow 3.05\%} 3.05% ↑ 0.59 % \textcolor{red}{\uparrow 0.59\%} 0.59% ↑ 3.32 % \textcolor{red}{\uparrow 3.32\%} 3.32% ↑ 0.23 % \textcolor{red}{\uparrow 0.23\%} 0.23% ↑ 2.60 % \textcolor{red}{\uparrow 2.60\%} 2.60%
sum-w/o-ReLU
star-w/o-ReLU

如上所示,star操作在各个指标上均取得了更佳的性能,分别获得了0.2%到3%不等的提升,从定性的图像中来看,网络似乎对较大的血管具有更好的分割效果,同时血管分割的结果也更加光滑。

with-ReLU的性能比较

下图给了sum和star两种方法的性能对比:

sum-with-ReLU-ROC曲线
sum-with-ReLU-PR曲线
star-with-ReLU-ROC曲线
star-with-ReLU-PR曲线
操作类型ROCPRF1AccSESPpre
sum-with-ReLU0.97430.87320.78460.95000.78880.97100.7805
star-with-ReLU0.97060.86130.77500.94830.77150.97130.7786
提升 ↓ 0.37 % \textcolor{blue}{\downarrow 0.37\%} 0.37% ↓ 1.19 % \textcolor{blue}{\downarrow 1.19\%} 1.19% ↓ 0.96 % \textcolor{blue}{\downarrow 0.96\%} 0.96% ↓ 0.17 % \textcolor{blue}{\downarrow 0.17\%} 0.17% ↓ 1.73 % \textcolor{blue}{\downarrow 1.73\%} 1.73% ↑ 0.03 % \textcolor{red}{\uparrow 0.03\%} 0.03% ↓ 0.19 % \textcolor{blue}{\downarrow 0.19\%} 0.19%
sum-with-ReLU
star-with-ReLU

如上所示,star操作在各个指标上均有不同程度的下降,总体来说,两者的性能差不多,从定性的图像中来看,star操作对血管连续上有较差的表现。

总结

本文将U-Net解码中的特征拼接修改为逐元素求和和逐元素乘积,并针对血管分割任务进行了性能评估。实验结果显示,在无激活函数时,逐元素乘积在多个关键指标上均优于逐元素求和,性能提升幅度在0.2%至3%之间,表明逐元素乘积确实能在一定程度上提供更高维度的隐式空间。从分割结果来看,逐元素乘积似乎对较大的血管具有更好的分割效果,能够更准确地捕捉血管的轮廓和细节。同时,star网络的分割结果也表现出更高的光滑性和一致性,减少了噪声和伪影的干扰,从而提高了分割结果的可靠性和可读性。在使用激活函数时,逐元素乘积在多个关键指标上均低于于逐元素求和,表明逐元素乘积的优势会倍激活函数所湮没。总言之,网络中要摒弃激活函数还有很长的路要走。

致谢

欲尽善本文,因所视短浅,怎奈所书皆是瞽言蒭议。行文至此,诚向予助与余者致以谢意。

参考

  1. 【CVPR_2024】:逐元素乘积为什么会产生如此令人满意的结果?
  2. GitHub-SkelCon

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

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

相关文章

【Kotlin】简单介绍与使用kotlin

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Kotlin ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 特点 变量和常量 数据类型和类型推断 函数 字符串模板 条件表达式 空安全 when 表达式 循环 我的其他博客 前言 Kotlin是…

适合技术小白学习的项目1840java swing社团管理系统myeclipse开发Mysql数据库CS结构java编程

一、源码特点 java swing社团管理系统 是一套完善的窗体设计系统&#xff0c;对理解SWING java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;&#xff0c;系统主要采用C/S模式开发。 应用技术&#xff1a;javamysql 开发工具&#xff1a;Myecl…

Flutter开发效率提升1000%,Flutter Quick教程之对被遮挡的组件进行编辑

1&#xff0c;有些时候&#xff0c;有的widget会被其他widget所遮挡&#xff0c;那么&#xff0c;我们如何选中被遮挡的Widget?如下面这张图。上面是一个Text&#xff0c;外面包裹着一个Container&#xff0c;这时候点击事件会被Text所拦截&#xff0c;那么&#xff0c;如何选…

零基础画师文创运营变现课,从0基础到入门一步步提升(46节课)

课程下载&#xff1a;零基础画师文创运营变现课&#xff0c;从0基础到入门一步步提升&#xff08;46节课&#xff09;-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 01 我的二十五年,mp4 02 古法裁剪与新古法裁剪,mp4 …

动规算法-地下城游戏

在刷题练习专栏中&#xff0c;已经写了两篇文章实现对动态规划入门题目的讲解了&#xff0c;动态规划这类题目很难很好的掌握&#xff0c;今天给大家带来稍微深入的题目&#xff0c;帮助大家更好的理解动态规划的算法思想&#xff0c;加深对该算法的理解&#xff0c;建议看每道…

操作系统|进程和线程的上下文以及他们的上下文切换具体流程?

进程和线程已经是老生常谈的问题了&#xff0c;现在那么他们是如何进行切换的呢&#xff1f;他们之间的切换有什么区别呢&#xff1f;如果你不懂的话&#xff0c;就让我们一起来探讨一下吧&#xff01; 进程上下文切换(context switch) 进程到底由哪些部分组成&#xff1f; …

GPT-4o vs. GPT-4 vs. Gemini 1.5 性能评测,谁更胜一筹!

OpenAI 最近推出了 GPT-4o&#xff0c;OpenAI有一次火爆了&#xff0c;其图像、音频、视频的处理能力非常强。 最令人印象深刻的是&#xff0c;它支持用户与 ChatGPT 实时互动&#xff0c;并且能够处理对话中断。 而且&#xff0c;OpenAI 免费开放了 GPT-4o API 的访问权限。…

finebi或者finereport发邮件

我们二次开发中&#xff0c;如果想利用产品自带的发邮件的功能&#xff0c;来发送自己的邮件内容。 首先 决策系统中邮件相关信息要配置好之后&#xff1a; 这里配好了发件人&#xff0c;以及默认发件人后&#xff0c; private void sendEmail(String content,String subject)…

云计算如何助力金融科技企业实现高效运营

一、引言 随着信息技术的飞速发展,云计算作为一种新兴的计算模式,正在逐渐改变着传统金融行业的运营模式。金融科技企业作为金融行业的重要组成部分,面临着日益增长的业务需求和技术挑战。在这一背景下,云计算凭借其弹性扩展、高可用性、低成本等优势,成为金融科技企业实…

163.二叉树:二叉树的最小深度(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

海南省三支一扶报名照上传失败?别忘了这

一、海南三支一扶报名照上传失败的2个原因 1.未按要求使用浏览器&#xff1a;请使用IE浏览器&#xff08;IE8以上版本&#xff09;、Chrome(谷歌浏览器&#xff09;或 Firefox&#xff08;火狐&#xff09;浏览器 来使用本系统&#xff0c;360浏览器等其他浏览器请使用极速模式…

数电课设:电动机转速测量控制电路

电动机转速测量控制电路设计 摘要 本文设计的电动机转速测量控制电路通过数字电路核心实现对电机转速的测量和显示。与市面上基于单片机的电机转速测量相比&#xff0c;该电路无需要注重复杂的软件设计&#xff0c;功耗小&#xff0c;稳定性高&#xff0c;实现了更好的底层封装…

如何组织我的 Python 代码

编写代码更像是一门艺术&#xff0c;而不是一门科学。编写精炼、合乎逻辑且强大的工程解决方案对于解决问题非常重要。然而&#xff0c;似乎存在一个重大挑战&#xff1a;让这些解决方案全面且易读。 本文的重点是如何最好地组织 Python 类&#xff0c;使其既可读又整洁。Pyth…

pdf文件太大如何变小,苹果电脑压缩pdf文件大小工具软件

压缩PDF文件是我们在日常办公和学习中经常会遇到的需求。PDF文件由于其跨平台、保持格式不变的特点&#xff0c;被广泛应用于各种场合。然而&#xff0c;有时候我们收到的PDF文件可能过大&#xff0c;不便于传输和存储&#xff0c;这时候就需要对PDF文件进行压缩。下面&#xf…

针对硅基氮化镓高电子迁移率晶体管(GaN-HEMT)的准物理等效电路模型,包含基板中射频漏电流的温度依赖性

来源&#xff1a;Quasi-Physical Equivalent Circuit Model of RF Leakage Current in Substrate Including Temperature Dependence for GaN-HEMT on Si&#xff08;TMTT 23年&#xff09; 摘要 该文章提出了一种针对硅基氮化镓高电子迁移率晶体管&#xff08;GaN-HEMT&…

【Java数据结构】详解LinkedList与链表(四)

&#x1f512;文章目录&#xff1a; 1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2.什么是LinkedList 3.LinkedList的使用 3.1LinkedList的构造方法 3.2LinkedList的其他常用方法介绍 addAll方法 subList方法 LinkedList的常用方法总使…

网络I/O模型

网络I/O模型 同步I/O阻塞I/O非阻塞I/OI/O多路复用select函数接口示例 poll函数接口示例 poll 和 select 的区别epoll原理&#xff1a;示例 Reactor单 Reactor 单进程 / 线程&#xff1b;单 Reactor 多线程 / 进程&#xff1b;多 Reactor 多进程 / 线程&#xff1b; 异步I/O 同步…

【吊打面试官系列】Java高并发篇 - 什么是自旋 ?

大家好&#xff0c;我是锋哥。今天分享关于 【什么是自旋 &#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 什么是自旋 &#xff1f; 很多 synchronized 里面的代码只是一些很简单的代码&#xff0c;执行时间非常快&#xff0c;此时等待的线程都加锁可能是一种不…

CCIG学术论坛|文档解析技术加速大模型训练与应用

目录 前言一、大模型训练和应用过程的关键环节面临的问题1、数据2、算力3、语料4、训练时间5、模型规模与复杂度6、部署和推理效率7、安全和隐私 二、高精准、高效率的文档解析三、文档解析技术难点四、TextIn文档解析1、算法Pipeline2、文档图像预处理算法效果3、版面分析算法…

关于单链表——数组

1.单链表统计负数个数 要求实现一个函数&#xff0c;返回带头结点的单链表中负整数的个数。 函数接口定义&#xff1a; int NegativeInt(LinkList L); L是带头结点的单链表的头指针&#xff0c;函数NegativeInt返回L中负整数的个数。如果单链表为空&#xff0c;返回0。 其中Lin…