高级实训任务二U-Net图像分割实验报告

1.任务描述

● 将卷积神经网络(CNN)应用在图像分割任务上,我们需要对网络结构进行设计。
● 需要提交博客报告以及GitHub代码仓库。
● 可选的任务:图像实例分割、语义分割、医疗图像分割。
● 可选的网络结构:YOLO v3、Mask R-CNN、U-Net。
● 可选的数据集:参考下文:
● https://zhuanlan.zhihu.com/p/50925449
● 可选深度学习框架:Tensorflow、PyTorch、Keras。
● 提交结果:项目报告、答辩幻灯片、相关代码和测试用例。

2.任务开始准备

U-Net原理:

1.Unet 介绍

Unet 发表于 2015 年,属于 FCN 的一种变体。Unet 的初衷是为了解决生物医学图像方面的问题,由于效果确实很好后来也被广泛的应用在语义分割的各个方向,比如卫星图像分割,工业瑕疵检测等。Unet 跟 FCN 都是 Encoder-Decoder 结构,结构简单但很有效。Encoder 负责特征提取,你可以将自己熟悉的各种特征提取网络放在这个位置。由于在医学方面,样本收集较为困难,作者为了解决这个问题,应用了图像增强的方法,在数据集有限的情况下获得了不错的精度。

2.Unet 网络结构

  • Encoder

如上图,Unet 网络结构是对称的,形似英文字母 U 所以被称为 Unet。整张图都是由蓝/白色框与各种颜色的箭头组成,其中,蓝/白色框表示 feature map;蓝色箭头表示 3x3 卷积,用于特征提取;灰色箭头表示 skip-connection,用于特征融合;红色箭头表示池化 pooling,用于降低维度;绿色箭头表示上采样 upsample,用于恢复维度;青色箭头表示 1x1 卷积,用于输出结果。其中灰色箭头copy and crop中的copy就是concatenate而crop是为了让两者的长宽一致。Encoder 由卷积操作和下采样操作组成,文中所用的卷积结构统一为 3x3 的卷积核,padding 为 0 ,striding 为 1。没有 padding 所以每次卷积之后 feature map 的 H 和 W 变小了,在 skip-connection 时要注意 feature map 的维度(其实也可以将 padding 设置为 1 避免维度不对应问题)。
更多可以参考:Unet详解

常见的图像分割损失函数有交叉熵,dice系数,FocalLoss等。今天我将分享图像分割FocalLoss损失函数及Tensorflow版本的复现。

3.图像分割unet_Tensorflow入门

FocalLoss介绍

FocalLoss思想出自何凯明大神的论文《Focal Loss for Dense Object Detection》,主要是为了解决one-stage目标检测中正负样本比例严重失衡的问题。

FocalLoss是在交叉熵函数的基础上进行的改进,改进的地方主要在两个地方

(1)、改进第一点如下公式所示。

首先在原有交叉熵函数基础上加了一个权重因子,其中gamma>0,使得更关注于困难的、错分的样本。比如:若 gamma = 2,对于正类样本来说,如果预测结果为0.97,那么肯定是易分类的样本,权重值为0.0009,损失函数值就会很小了;对于正类样本来说,如果预测结果为0.3,那么肯定是难分类的样本,权重值为0.49,其损失函数值相对就会很大;对于负类样本来说,如果预测结果为0.8,那么肯定是难分类的样本,权重值为0.64,其损失函数值相对就会很大;对于负类样本来说,如果预测结果为0.1,那么肯定是易分类的样本,权重值为0.01,其损失函数值就会很小。而对于预测概率为0.5时,损失函数值只减少了0.25倍,所以FocalLoss减少了简单样本的影响从而更加关注于难以区分的样本。

(2)、改进第二点如下公式所示。

FocalLoss还引入了平衡因子alpha,用来平衡正负样本本身的比例不均匀。alpha取值范围0~1,当alpha>0.5时,可以相对增加y=1所占的比例,保证正负样本的平衡。

2、FocalLoss公式推导

在github上已经可以找到很多FocalLoss的实现,如下二分类的FocalLoss实现。实现其实不是很难,但是在实际训练时会出现NAN的现象。

3、FocalLoss代码实现

按照上面导出的表达式FocalLoss的伪代码可以表示为:

从这里可以看到1-y_pred项可能为0或1,这会导致log函数值出现NAN现象,所以好需要对y_pred项进行固定范围值的截断操作。最后在TensorFlow1.8下实现了该函数。

import tensorflow as tfdef focal_loss(y_true, y_pred, alpha=0.25, gamma=2):    epsilon = 1e-5    y_pred =
tf.clip_by_value(y_pred, epsilon, 1 - epsilon)    logits = tf.log(y_pred / (1 - y_pred))    weight_a = alpha * tf.pow((1
- y_pred), gamma) * y_true    weight_b = (1 - alpha) * tf.pow(y_pred, gamma) * (1 - y_true)    loss = tf.log1p(tf.exp(-
- logits)) * (weight_a + weight_b) + logits * weight_b    return tf.reduce_mean(loss)

3.任务实现方法

工具选择
语言:python
框架选择:tensorflow,keras

此外还用了absl库函数。用absl库定义可重复的代码段,定义训练的各个参数(比如学习率,周期数,每个周期的训练轮数等)。

  • tensorflow定义
'''
参数设定:eopch=4,step=100,batch_size=2,learning_rate=0.0002
'''
inputs = tf.keras.layers.Input((512, 512, 1))# Contracting partconv1 = tf.keras.layers.Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(inputs)conv1 = tf.keras.layers.Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv1)assert conv1.shape[1:] == (512, 512, 64)pool1 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv1)assert pool1.shape[1:] == (256, 256, 64)conv2 = tf.keras.layers.Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool1)conv2 = tf.keras.layers.Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv2)assert conv2.shape[1:] == (256, 256, 128)pool2 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv2)assert pool2.shape[1:] == (128, 128, 128)ng='same', kernel_initializer='he_normal')(tf.keras.layers.UpSampling2D(size=(2, 2))(drop5))assert up6.shape[1:] == (64, 64, 512)merge6 = tf.keras.layers.concatenate([drop4, up6], axis=3)assert merge6.shape[1:] == (64, 64, 1024)conv6 = tf.keras.layers.Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge6)conv6 = tf.keras.layers.Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv6)assert conv6.shape[1:] == (64, 64, 512)up7 = tf.keras.layers.Conv2D(256, 2, activation='relu', padding='same', kernel_initializer='he_normal')(tf.keras.layers.UpSampling2D(size=(2, 2))(conv6))assert up7.shape[1:] == (128, 128, 256)merge7 = tf.keras.layers.concatenate([conv3, up7], axis=3)assert merge7.shape[1:] == (128, 128, 512)conv7 = tf.keras.layers.Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge7)conv7 = tf.keras.layers.Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv7)assert conv7.shape[1:] == (128, 128, 256)up8 = tf.keras.layers.Conv2D(128, 2, activation='relu', padding='same', kernel_initializer='he_normal')(tf.keras.layers.UpSampling2D(size=(2, 2))(conv7))assert up8.shape[1:] == (256, 256, 128)merge8 = tf.keras.layers.concatenate([conv2, up8], axis=3)assert merge8.shape[1:] == (256, 256, 256)conv8 = tf.keras.layers.Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge8)conv8 = tf.keras.layers.Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv8)assert conv8.shape[1:] == (256, 256, 128)up9 = tf.keras.layers.Conv2D(64, 2, activation='relu', padding='same', kernel_initializer='he_normal')(tf.keras.layers.UpSampling2D(size=(2, 2))(conv8))assert up9.shape[1:] == (512, 512, 64)merge9 = tf.keras.layers.concatenate([conv1, up9], axis=3)assert merge9.shape[1:] == (512, 512, 128)conv9 = tf.keras.layers.Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge9)conv9 = tf.keras.layers.Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9)assert conv9.shape[1:] == (512, 512, 64)conv9 = tf.keras.layers.Conv2D(2, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9)assert conv9.shape[1:] == (512, 512, 2)conv10 = tf.keras.layers.Conv2D(num_classes, 1, activation='sigmoid')(conv9)assert conv10.shape[1:] == (512, 512, num_classes)model = tf.keras.Model(inputs=inputs, outputs=conv10)
  • data
import os
import tensorflow as tf
import numpy as np
import scipy.miscclass Read_TFRecords(object):def __init__(self, filename, batch_size=64,image_h=256, image_w=256, image_c=1, num_threads=8, capacity_factor=3, min_after_dequeue=1000):self.filename = filenameself.batch_size = batch_sizeself.image_h = image_hself.image_w = image_wself.image_c = image_cself.num_threads = num_threadsself.capacity_factor = capacity_factorself.min_after_dequeue = min_after_dequeuedef read(self):reader = tf.TFRecordReader()filename_queue = tf.train.string_input_producer([self.filename])key, serialized_example = reader.read(filename_queue)features = tf.parse_single_example(serialized_example,features={"image_raw": tf.FixedLenFeature([], tf.string),"image_label": tf.FixedLenFeature([], tf.string),})image_raw = tf.image.decode_jpeg(features["image_raw"], channels=self.image_c, name="decode_image")image_label = tf.image.decode_jpeg(features["image_label"], channels=self.image_c, name="decode_image")if self.image_h is not None and self.image_w is not None:image_raw = tf.image.resize_images(image_raw, [self.image_h, self.image_w], method=tf.image.ResizeMethod.BICUBIC)image_label = tf.image.resize_images(image_label, [324, 324], method=tf.image.ResizeMethod.BICUBIC)image_raw = tf.cast(image_raw, tf.float32) / 255.0 # convert to float32image_label = tf.cast(image_label, tf.float32) / 255.0 # convert to float32input_data, input_masks = tf.train.shuffle_batch([image_raw, image_label],batch_size=self.batch_size,capacity=self.min_after_dequeue + self.capacity_factor * self.batch_size,min_after_dequeue=self.min_after_dequeue,num_threads=self.num_threads,name='images')return input_data, input_masks
  • train
  # trainif self.is_training:self.training_set = tf_flags.training_setself.sample_dir = "train_results"# makedir aux dirself._make_aux_dirs()# compute and define lossself._build_training()# logging, only use in traininglog_file = self.output_dir + "/Unet.log"logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s',filename=log_file,level=logging.DEBUG,filemode='w')logging.getLogger().addHandler(logging.StreamHandler())else:# testself.testing_set = tf_flags.testing_set# build modelself.output = self._build_test()

运行结果:

由运行结果可以看出来周期数的推进,训练准确度不断提高。但是由于没有服务器,只能进行4轮的训练,但是也能看出随着周期数增加,准确率不断提升的。

4.个人总结

通过本次实验,我也进一步了解了用Tensorflow定义神经网络的相关操作,以及通过论文的阅读,资料的查阅,以及开源代码的学习,能够学习到Unet 网络在图像处理,图像分割上的基本应用。不仅个人编程技能上取得进步,同时也增强了资料查询,论文阅读能力,学会自己动手学习新的知识,克服畏难心理。

高级实训任务二U-Net图像分割实验报告相关推荐

  1. 计算机实训机器人实验原理是什么,实验报告机器人控制技术基础实验报告.doc...

    实验报告机器人控制技术基础实验报告 华北电力大学 实 验 报 告 | | 实验名称: 机器人控制技术基础 课程名称: 机器人控制技术基础 | | 实 验 人: 成 绩: 18.00秒 指导教师: 实验 ...

  2. 会计计算机实训结果及分析,会计学实验报告的结果与分析怎么写?

    都说谈恋爱影响学习我看失恋才影响学习 优质答主 04-04 TA获得超过5708个赞 大学生的会计电算化实验报告: 实习是每一个学生必须拥有的一段经历,它使我们在实践中了解社会,让我们学到了很多在课堂 ...

  3. c语言程序设计实训目的,c语言程序设计实验报告(三)

    C程序设计实验报告 实验项目: 4.3.1.if语句的应用 4.3.2.switch--case语句的应用 4.3.3.switch--case语句嵌套if语句的应用 4.3.4.switch--ca ...

  4. 交换机vlan配置实训心得_计算机网络实践实验报告基本交换机使用及VLAN配置

    计算机网络实践实验报告基本交换机使用及VLAN配置 计算机网络技术实践 实验报告 实验名称:基本交换机使用及VLAN配置 姓名: 实验日期:2014年5月4日 学号: 实验报告日期: 2014年5月4 ...

  5. 流体力学实验室设备实训设备自循环水击实验装置

    ZN-LT603型 流体力学实验室设备实训设备自循环水击实验装置 一.实验目的: 1.适合于工程流体力学(水力学)教学实验. 2.演示水击扬水机.水击波传播(水击能的利用)的工作原理. 3.演示调压筒 ...

  6. 电大计算机实训任务结果文档及报告汇总,国家开放大学《计算机基础应用》第二次考核任务-实训任务报告.docx...

    计算机基础应用实训I任务报告 实验室名称:公共机房 实验实训日期:10月10日 实验实训题目:计算机基本操作 实验实训目的: 1.认识计算机硬件. 2.认识键盘. 3.掌握Windows启动与退出. ...

  7. 计算机实训室管理工作计划,实验实训中心2016年工作计划

    实验实训中心2016年工作计划 (2015年12月8日) 2016年,实验实训中心全体教职工将在学校党委.行政的领导下,围绕学校升本目标,开拓创新.努力工作.结合部门职能,制定具体工作计划如下: 一. ...

  8. Java暑期实训任务二——单词检测程序

    实训内容:模仿"百词斩"手机App,设计并用Java语言实现一个"百词斩"图形界面程序(根据自己的能力,可以适当地增加或删除部分功能). 最低要求: (1)事先 ...

  9. 计算机组成实验箱控制信号测,计算机组成原理实验报告-杨睿.doc

    计算机组成原理实验报告-杨睿,计算机组成原理实验,计算机组成原理实验箱,计算机组成原理实验十,计算机组成原理实验1,计算机组成原理实验13,计算机组成原理实验仪,前妻竹玉儿杨睿番外,杨睿南京,计算机组 ...

最新文章

  1. Debian上网的问题小结
  2. java 捕获数据包,缓存从pcap捕获的数据包
  3. 安装和配置以下合同 14.1管理
  4. android ble 助手源码_[源码和文档分享]基于Android的生活助手APP的设计与实现
  5. solr服务器的查询过程
  6. 第四范式陈雨强获评首届世界人工智能大会云帆奖 | 2020WAIC
  7. 给所有想从事软件研发的年轻工程师的忠告与建议
  8. 实战课堂:一则CPU 100%的故障分析处理知识和警示
  9. 中兴通讯推出全球首款Wi-Fi 7标准5G CPE
  10. AS 3.0 socket 通信,比较基础比较全【转载】
  11. 22.Linux/Unix 系统编程手册(上) -- 信号:高级特性
  12. 在Vue项目中引入echarts图表的方法(引入cdn)
  13. 动环监控整体方案,动环监控系统施工方案
  14. 电路布线问题(迷宫问题)
  15. DDoS原理、分类与防御
  16. 学java要学哪些_想学好Java要学哪些东西
  17. eclipse豆沙绿设置(一些其他的编辑器也变成豆沙绿)
  18. lvm硬盘扩容了,或者使用fdisk格式化大于2T硬盘后,如何通过pvresize扩容
  19. 互联网中常见的实名认证方式有哪几种?
  20. python避障小车_MicroPython实战:DIY一台会思考的避障车

热门文章

  1. MT6572/MT6570芯片资料介绍,MT6572+MT6570处理器
  2. Photoshop 可选颜色原理
  3. c++用宏定义和函数来求圆的面积,半径可为表达式
  4. 【LeetCode】594. 最长和谐子序列(js 实现)
  5. 如何将Excel数据快速生成炫酷仪表盘
  6. 毕业设计《软件工程》教学网站的设计与实现ASP+SQL Sever2000
  7. 软工大作业·倾物语(二)
  8. php神策数据统计,神策数据上报操作(示例代码)
  9. python中错误TypeError: __init__() got an unexpected keyword argument 'shape'
  10. 【智能制造】「人.机.料.法.环」最全面解析