Unet学习笔记

最近在看Unet,记录一下。

论文地址

https://arxiv.org/pdf/1505.04597.pdf

网络结构


图上画的还是很清晰的,但是对于不了解Unet结构的人来说,可能还是有一些不清楚的地方。我这里结合我看的时候的疑问,来讲一下Unet的结构的一些问题。

  1. 可以看到,输入是572x572的,但是输出变成了388x388,这说明经过网络以后,输出的结果和原图不是完全对应的,这在计算loss和输出结果都可以得到体现。
  2. 蓝色箭头代表3x3的卷积操作,并且stride是1,padding策略是vaild,因此,每个该操作以后,featuremap的大小会减2。
  3. 红色箭头代表2x2的maxpooling操作,需要注意的是,此时的padding策略也是vaild(same 策略会在边缘填充0,保证featuremap的每个值都会被取到,vaild会忽略掉不能进行下去的pooling操作,而不是进行填充),这就会导致如果pooling之前featuremap的大小是奇数,那么就会损失一些信息 。
  4. 绿色箭头代表2x2的反卷积操作,这个只要理解了反卷积操作,就没什么问题,操作会将featuremap的大小乘2。
  5. 灰色箭头表示复制和剪切操作,可以发现,在同一层左边的最后一层要比右边的第一层要大一些,这就导致了,想要利用浅层的feature,就要进行一些剪切,也导致了最终的输出是输入的中心某个区域。
  6. 输出的最后一层,使用了1x1的卷积层做了分类。

网络结构代码

纸上得来终觉浅,还是要写个代码,才能了解细节部分。

下面这个代码,我参考了
https://github.com/jakeret/tf_unet

主要把每一层拆开了一步一步写了下来,虽然写的很啰嗦,但是看起来比较容易理解。另外,我忽略了一些对featuremap大小没有影响的操作,比如relu,bn,dropout等。

# conding:utf-8
from __future__ import print_function
import tensorflow as tf
import numpy as np

def weight_variable(shape, stddev=0.1, name="weight"):
    initial = tf.truncated_normal(shape, stddev=stddev)
    return tf.Variable(initial, name=name)

def bias_variable(shape, name="bias"):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial, name=name)

def get_w_and_b(kernel_size, input_feature_size, output_feature_size, name):
    w = weight_variable([kernel_size, kernel_size, input_feature_size, output_feature_size], name=name + '_w')
    b = bias_variable([output_feature_size], name=name + '_b')
    return w, b

def get_deconv_w_and_b(kernel_size, input_feature_size, output_feature_size, name):
    w = weight_variable([kernel_size, kernel_size, input_feature_size, output_feature_size], name=name + '_w')
    b = bias_variable([input_feature_size], name=name + '_b')
    return w, b

def conv2d(x, W, b):
    with tf.name_scope("conv2d"):
        conv_2d = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='VALID')
        conv_2d_b = tf.nn.bias_add(conv_2d, b)
        return conv_2d_b

def max_pool(x, n):
    return tf.nn.max_pool(x, ksize=[1, n, n, 1], strides=[1, n, n, 1], padding='VALID')

def deconv2d(x, W, stride):
    with tf.name_scope("deconv2d"):
        x_shape = tf.shape(x)
        output_shape = tf.stack([x_shape[0], x_shape[1]*2, x_shape[2]*2, x_shape[3]//2])
        return tf.nn.co
  • 31
    点赞
  • 164
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值