0.写在前边
这算得上是真正意义上接触的第一个深度学习项目了。果真在既没有经验,又没有实力的情况下,项目被搞得一团糟。实践出真知,赶紧总结吸取教训!!!
1.项目流程
1.1数据流
(1)超参传递
1)通过.py传递
eg: params.py中存储超参[OPTIMIZER = ‘Adam’]的值;则在新的.py文件中导入[import params],便可通过 params.OPTIMIZER获得超参的值;
2)通过sys传递外部参数
(2)数据读取过程
1)获取图像名称列表:glob;
2)生成batches索引列表;
3)生成(图像,标签)batch:i加载数据;ii数据预处理[数据增广、归一化、标签转换等];
实用代码
数据增广
from albumentations import (
PadIfNeeded,
HorizontalFlip, #
VerticalFlip, #
CenterCrop,
Crop,
Compose, #
Transpose, #
RandomRotate90, #
ElasticTransform,
GridDistortion,
OpticalDistortion,
RandomSizedCrop,
OneOf,
CLAHE,
RandomContrast,
RandomGamma,
RandomBrightness
)
def image_augmentation(currImg, labelMask):
aug = Compose([VerticalFlip(p=0.5),
RandomRotate90(p=0.5),HorizontalFlip(p=0.5),Transpose(p=0.5)])
augmented = aug(image=currImg, mask=labelMask)
imageMedium = augmented['image']
labelMedium = augmented['mask']
return imageMedium,labelMedium
RGB图像归一化:从[0-255]到[0-1]
from keras.applications import imagenet_utils
imgBatch = imagenet_utils.preprocess_input(imgBatch)
imgBatch = imgBatch / 255.0
1.2模型&代码
(通用定义)
from keras.layers import Input
# 定义模型所需要的 [输入的张量(占位?),张量的形状]
input_tensor = Input(shape=(imgSz[0],imgSz[1],self.params.NUM_CHANNELS))
input_shape = (imgSz[0],imgSz[1],self.params.NUM_CHANNELS)
# 模型逐层定义
# backbone
# 自定义
# model = Model(input, x)
# 损失函数
# 优化算法
# 编译
# return model
#
后处理
语义分割
pred = np.argmax(pred, axis=2).astype('uint8')
高度预测
pred = convert_labels(pred, self.params, toLasStandard=True)
最后
pred = pred[:,:,0]
tifffile.imsave(os.path.join(self.params.OUTPUT_DIR, outName), pred, compress=6)
训练&推理
推理阶段:模型不需要损失函数和优化算法;
对数据的预处理和后处理是基本相同的;
2.模型&代码(基模差定义)
2.0 模型基础
特征交互的方式:
(1)级联:通道数变为原来的两倍
(2)级联再卷积:卷积的目的是降低通道数与原来保持一致
(3)加:逐元素相加 ----线性和、加权和
(4)乘:逐元素相乘
金字塔的表现方式:
(1)图像金字塔:图像resize到不同尺寸,基于不同尺寸的图像做预测;
(2)特征金字塔:图像–特征(不同尺寸的特征),基于不同尺寸的特征做预测;
(3)FPN:金字塔特征+顶层特征与低层特征融合;
resnet的特点: 包含残差块,即上一块的输出与下一层的输出融合
2.1 UNet
encoder-decoder结构
四个卷积块 & 四个上采样块 + skip connection
2.2 FPN
特征金字塔 预测
2.3 LinkNet
四个卷积块 & 四个上采样块 + skip connection
编码时resnet作为backbone
2.4 PSPNet
金字塔池化模块:不同尺度的池化得到不同尺度的特征,再上采样到原来的大小,进行级联;
3.小细节
- 命名: 项目、文件夹、文件、类、函数、方法、变量等,任何需要命名的东西,做到简洁、见名知意;
- 版本控制: 不同版本间的名称做到有序有意;
– 版本控制的方法:外隔离、内隔离;(源码多是外隔离[.py],师兄多是内隔离[class]) - 功能封装: (1)程序模块化:相似的功能模块集成(函数、类、包);(2)使用高级模块化的语句:即用尽可能少的、高效的代码完成需要的功能;