UNet详解(附图文和代码实现)

卷积神经网络被大规模的应用在分类任务中,输出的结果是整个图像的类标签。但是UNet是像素级分类,输出的则是每个像素点的类别,且不同类别的像素会显示不同颜色,UNet常常用在生物医学图像上,而该任务中图片数据往往较少。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:(1)输出结果可以定位出目标类别的位置;(2)由于输入的训练数据是patches,这样就相当于进行了数据增强,从而解决了生物医学图像数量少的问题。但是,

大家好,又见面了,我是你们的朋友全栈君。

卷积神经网络被大规模的应用在分类任务中,输出的结果是整个图像的类标签。但是UNet是像素级分类,输出的则是每个像素点的类别,且不同类别的像素会显示不同颜色,UNet常常用在生物医学图像上,而该任务中图片数据往往较少。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:(1)输出结果可以定位出目标类别的位置;(2)由于输入的训练数据是patches,这样就相当于进行了数据增强,从而解决了生物医学图像数量少的问题。

但是,采用该方法的神经网络也有两个很明显的缺点:(1)它很慢,因为这个网络必须训练每个patch,并且因为patch之间的重叠有很多冗余,这样会导致同样特征被多次训练,造成资源的浪费,导致训练时间的加长且效率也会有所降低,也有人会问神经网络经过多次训练这个特征后,会对这个特征的印象加深,从而准确率也会上升,但是举个例子一个图片复制50张,用这50张图片去训练网络,虽说数据集增大了,可是导致的后果是神经网络会出现过拟合,也就是说神经网络对训练图片很熟悉,可是换了一张图片,神经网络就有可能分辨不出来了。(2)定位准确性和获取上下文信息不可兼得,大的patches需要更多的max-pooling,这样会减少定位准确性,因为最大池化会丢失目标像素和周围像素之间的空间关系,而小patches只能看到很小的局部信息,包含的背景信息不够。

UNet主要贡献是在U型结构上,该结构可以使它使用更少的训练图片的同时,且分割的准确度也不会差,UNet的网络结构如下图:

在这里插入图片描述
(1)UNet采用全卷积神经网络。
(2)左边网络为特征提取网络:使用conv和pooling
(3)右边网络为特征融合网络:使用上采样产生的特征图与左侧特征图进行concatenate操作。(pooling层会丢失图像信息和降低图像分辨率且是永久性的,对于图像分割任务有一些影响,对图像分类任务的影响不大,为什么要做上采样呢?上采样可以让包含高级抽象特征低分辨率图片在保留高级抽象特征的同时变为高分辨率,然后再与左边低级表层特征高分辨率图片进行concatenate操作)
(4)最后再经过两次卷积操作,生成特征图,再用两个卷积核大小为1*1的卷积做分类得到最后的两张heatmap,例如第一张表示第一类的得分,第二张表示第二类的得分heatmap,然后作为softmax函数的输入,算出概率比较大的softmax,然后再进行loss,反向传播计算。

Unet模型的代码实现(基于keras):

def get_unet():
    inputs = Input((img_rows, img_cols, 1))
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    # pool1 = Dropout(0.25)(pool1)
    # pool1 = BatchNormalization()(pool1)

    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    # pool2 = Dropout(0.5)(pool2)
    # pool2 = BatchNormalization()(pool2)

    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    # pool3 = Dropout(0.5)(pool3)
    # pool3 = BatchNormalization()(pool3)

    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)
    # pool4 = Dropout(0.5)(pool4)
    # pool4 = BatchNormalization()(pool4)

    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)

    up6 = concatenate([Conv2DTranspose(256, (2, 2), strides=(
        2, 2), padding='same')(conv5), conv4], axis=3)
    # up6 = Dropout(0.5)(up6)
    # up6 = BatchNormalization()(up6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)

    up7 = concatenate([Conv2DTranspose(128, (2, 2), strides=(
        2, 2), padding='same')(conv6), conv3], axis=3)
    # up7 = Dropout(0.5)(up7)
    # up7 = BatchNormalization()(up7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)

    up8 = concatenate([Conv2DTranspose(64, (2, 2), strides=(
        2, 2), padding='same')(conv7), conv2], axis=3)
    # up8 = Dropout(0.5)(up8)
    # up8 = BatchNormalization()(up8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)

    up9 = concatenate([Conv2DTranspose(32, (2, 2), strides=(
        2, 2), padding='same')(conv8), conv1], axis=3)
    # up9 = Dropout(0.5)(up9)
    # up9 = BatchNormalization()(up9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)

    # conv9 = Dropout(0.5)(conv9)

    conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)

    model = Model(inputs=[inputs], outputs=[conv10])

    model.compile(optimizer=Adam(lr=1e-5),
                  loss=dice_coef_loss, metrics=[dice_coef])

    return model
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/124855.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • webpack基础打包命令_逆向webpack打包后的js

    webpack基础打包命令_逆向webpack打包后的js没有配置文件的打包如果我们没有使用配置文件webpack.config.js,那么我们就需要通过命令来打包案例我们首先创建一个webpackTest文件夹,然后在文件夹中再创建2个子文件夹dis

    2022年7月29日
    7
  • WAR包补丁工具_修改war包配置文件

    WAR包补丁工具_修改war包配置文件简要:因目前处于运维历史悠久的WEB项目中,每次需求开发完成需要更打补丁文件,因此编写打补丁工具,以解决手动查找补丁文件的繁琐且重复操作。纯Java代码编写,使用Swing作为界面UI,原有代码只针对特殊使用场景,可以适当加以修改。适用:编译工具:EclipseLunaRelease(4.4.0)运行环境:JDK1.7代码:界面GUI部分:使用JSplitPane…

    2022年10月5日
    1
  • stun client java实现_stun 协议客户端实现

    stun client java实现_stun 协议客户端实现/**Spider–AnopensourceClanguagetoolkit.**Copyright(C)2011,Inc.**lidp**Thisprogramisfreesoftware,distributedunderthetermsof*theGNUGeneralPublicLicenseVersion2.Seethe…

    2022年7月16日
    18
  • 光功率 博科交换机_博科光纤交换机zone划分命令方法「建议收藏」

    光功率 博科交换机_博科光纤交换机zone划分命令方法「建议收藏」博科光纤交换机zone划分命令方法Brocade(博科)交换机为例,记录其划分命令和划分方法:连接交换机:可通过串口或网线从IE进入,默认IP  10.77.77.77,255.255.255.0创建ZONE有两种方式:一是通过交换机port号,二是通过主机和存储的WWN号 (单个硬盘没有WWN号,存储整体才有一个)命令:查看当前zone状况:zoneshow删除zone:zonedele…

    2022年5月22日
    40
  • 老鹰主机怎么样?多年的用户来说下

    老鹰主机怎么样?多年的用户来说下说到老鹰主机 我想我绝对很有发言权 因为老刘说主机这个网站就是老鹰主机搭建的 一直十分的稳定 而且国内访问速度很快 说实话之前一直非常的担心国内访问速度会很慢 但是一直以来都给我特别的惊喜和放心 下面我们一起来说说老鹰主机怎么样 1 价格便宜我自己网站用的是年付 44 刀的套餐 一个月下来平均也是就 2 刀多 提供 30 天的退款保障 这个价格在所有的国外知名的主机商里面也算是很便宜的了 2 功能强大

    2025年7月6日
    2
  • python df.iloc_python中loc

    python df.iloc_python中locstackoverflow原文:pandasilocvsixvslocexplanation;howaretheydifferent?在pandas0.20.0及以上版本,ix已经被loc和iloc取代了,因此不讨论它。前提,简单介绍一下它俩:–loc利用index的名称,来获取想要的行(或列)。–iloc利用index的具体位置(所以它只能是整数型参数),…

    2022年10月9日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号