Unet 细胞分割

pytorch训练网络需要注意的细节(以及模板)

笔记:https://www.zybuluo.com/CQUyh/note/2234948
标签(空格分隔): Pytorch
以细胞分割图为例(Unet和Convnext)

1.model的搭建

这个不多说,是独立的模块,只需要注意输出输出是什么,输入通道和输出通道;一个小技巧,使用monai的框架,十分方便,但是注意load_weights时读取方式。

2.整个代码架构

model、dataset作为存放模型的文件,其中每一个epcoh(训练和测试)单独写在utils,这是工具文件夹。而整体的代码写在跟目录的train.py

image_1fuj0q8jag5se801lhs1iv4bn7m.png-27.2kB

train.py:

①路径以及文件读取

②transform和dataset、dataloader

③定义模型,损失函数,优化器

④定义for训练,epcoh的for循环,最大层

main函数里面设置参数

image_1fvff083q1pfv1usf1dp6ms91va09.png-109.4kB
image_1fuj11ad511721ta51b521f8msnh1g.png-100.5kB

3.dataset(自定义)细节

①Transform

数据归一化一定要有(常用的参数),不然模型不收敛,对于简单的unet,收敛很慢很慢,对于复杂的,都不会变化。有没有决定你的模型好坏。(神经网络不收敛的原因:https://blog.csdn.net/weixin_39586997/article/details/118699735)

②一般步骤

ToTensor和Normlization:只有训练图片需要ToTensor(作用进行归一化,全部变到0-1),标签不需要进行任何transform,to_tensor都不需要可能(分情况,看像素值和one-hot)。标签具体需不需要其实看你标签本来的像素,像细胞图,像素点为0和255,需要进行norm到0和1,这样才是标准的,只是说我们默认标签值为0,1,2,3,4。

③PIL读取图像

因为torchvision支持PIL,经过ToTensor后得到[1,512,512],这里不需要扩充维度,因为dataloader会根据batchsize在读取时生成为[n,c,d,w,(h)]

③自定义dataset

这里使用PIL读取,因为transform支持PIL读取,它读取出来是一个类,然后是(3,256,256),CV读取是矩阵(256,256,3),需要转置一下,并且注意这里不需要返回加上n,因为dataloader读取的时候会根据batchsize来设置n的大小。

④常用函数

torch.Tensor是转化为float32,不要用torch.tensor; torch.transpose(data,dim1,dim2),根据维度来转置 ; torch.unsqueeze(data,dim=0)扩展一个维度。实现[d,w]->[1,d,w]

image_1fuj1i5qki2ss1a232117o1t6t1t.png-111.4kB

4.one-hot编码

①什么时候需要计算one-hot

首先是损失函数,之前总结过,哪些损失需要标签是one-hot,不需要one-hot,这个自己判断。然后就算计算dice是否需要one-hot(多分类一般都需要,保证pred和label一致channel)

②如何实现one-hot(亲测有效,多分类、二分类都可以,测试:one-hot ->argmax来imshow一下)

③细节:在one-hot那里对数据有要求,首先面前这个函数是正确的,以及用的v6的loss和dice计算不管几分类都是使用的通用模型。One-hot对细胞图,要求像素值小于分类数值,因此标准化为0,1;对于3d的数据,本来就是0,1,2,3,4,你还去ToTensor的话,就变成0.00XX,而one-hot那里要求数据转为long(),格式,会导致数据直接变为0,像素点全为0的后果。

image_1fuj1vf4l1hvd2co1pig7rh19va2a.png-25.5kB

5.Dice计算方法

非常牛逼的计算方法,是几分类,就返回[背景,前景1,前景2,、、、]需要注意的是,里面选择sigmoid还是softmax,这个根据标签来选择,是否把背景看做一类,这个之前也总结过的。我习惯用softmax。

image_1fuj228tts748hn1n5ggrm1guo34.png-134.3kB

6.推理

只提醒一个细节,推理的数据集必须跟训练时经过一样的norm,因为要符合一样的数据分布,不然没效果,推理出来跟个屎一样。

### UNet 网络中的膨胀卷积技术实现 在细胞分割任务中,UNet 架构通过引入膨胀卷积(Dilated Convolution),能够在不增加参数量的情况下扩大感受野,从而更好地捕捉上下文信息。这有助于提高模型对于不同尺度目标的检测能力。 #### 膨胀卷积的作用 传统卷积操作会随着层数加深逐渐缩小特征图尺寸,而膨胀卷积则允许保持相同大小的同时扩展感知区域。具体来说,在编码器部分可以采用常规卷积;而在解码阶段,则利用带有扩张率的卷积核进行处理[^1]。 #### 实现方式 为了在UNet框架内应用膨胀卷积,可以在原有的基础上调整某些层的设计: - **设置不同的dilation rate**:当构建网络时指定`Conv2D`函数里的`dilation_rate`参数值大于1即可启用此特性; - **控制层次结构**:通常建议在网络较深的位置加入这些特殊单元,因为此时输入已经过多次下采样具备足够的抽象度。 以下是Python代码片段展示如何修改Keras/TensorFlow版本下的UNet以支持膨胀卷积: ```python from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, concatenate import tensorflow as tf def build_unet_with_dilated_conv(input_size=(256, 256, 1)): inputs = Input(input_size) # 编码器路径 (Contracting path) conv1 = Conv2D(64, 3, activation='relu', padding='same')(inputs) pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) conv2 = Conv2D(128, 3, activation='relu', padding='same')(pool1) pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) # 中间瓶颈层使用膨胀卷积 dilated_conv = Conv2D(256, 3, dilation_rate=2, activation='relu', padding='same')(pool2) # 解码器路径 (Expansive path),这里也可以考虑继续使用膨胀卷积 up7 = UpSampling2D(size=(2, 2))(dilated_conv) merge7 = concatenate([conv2,up7], axis=-1) conv7 = Conv2D(128, 3, activation='relu', padding='same')(merge7) up8 = UpSampling2D(size=(2, 2))(conv7) merge8 = concatenate([conv1,up8], axis=-1) conv8 = Conv2D(64, 3, activation='relu', padding='same')(merge8) output_layer = Conv2D(1, 1, activation='sigmoid')(conv8) model = tf.keras.Model(inputs=[inputs], outputs=[output_layer]) return model ``` 该示例展示了怎样创建一个简单的具有膨胀卷积特性的UNet变体。注意实际应用场景可能还需要进一步优化超参配置以及探索更多组合策略来达到最佳效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值