语义图像分割 NN (DeepLabV3+) 的内存过多问题
Posted
技术标签:
【中文标题】语义图像分割 NN (DeepLabV3+) 的内存过多问题【英文标题】:Too Much Memory Issue with Semantic Image Segmentation NN (DeepLabV3+) 【发布时间】:2019-07-15 06:40:05 【问题描述】:我首先解释我的任务:我有近 3000 张来自两条不同绳索的图像。它们包含绳索 1、绳索 2 和背景。我的标签/蒙版是图像,例如像素值 0 代表背景,1 代表第一根绳索,2 代表第二根绳索。您可以在下面的图片 1 和 2 中看到输入图片和基本事实/标签。请注意,我的基本事实/标签只有 3 个值:0、1 和 2。 我的输入图片是灰色的,但对于 DeepLab,我将其转换为 RGB 图片,因为 DeepLab 是在 RGB 图片上进行训练的。但是我转换后的图片仍然没有颜色。
这个任务的想法是神经网络应该从绳索中学习结构,因此即使有绳结它也可以正确地标记绳索。因此颜色信息并不重要,因为我的绳子有不同的颜色,所以很容易使用 KMeans 来创建 ground truth/labels。
对于这个任务,我在 Keras 中选择了一个名为 DeepLab V3+ 的语义分割网络,并以 TensorFlow 作为后端。我想用我的近 3000 张图像训练 NN。所有图像的大小都在 100MB 以下,它们是 300x200 像素。 也许 DeepLab 不是我任务的最佳选择,因为我的图片不包含颜色信息,而且我的图片尺寸非常小(300x200),但到目前为止我还没有为我的任务找到更好的语义分割 NN。
从 Keras 网站我知道如何使用 flow_from_directory 加载数据以及如何使用 fit_generator 方法。我不知道我的代码是否逻辑正确...
以下是链接:
https://keras.io/preprocessing/image/
https://keras.io/models/model/
https://github.com/bonlime/keras-deeplab-v3-plus
我的第一个问题是:
在我的实现中,我的显卡几乎使用了所有内存 (11GB)。我不知道为什么。有没有可能,DeepLab 的权重有那么大?我的 Batchsize 默认为 32,我所有的近 300 张图像都在 100MB 以下。我已经使用了 config.gpu_options.allow_growth = True 代码,请参阅下面的代码。
一般问题:
有人知道我的任务有一个好的语义分割神经网络吗?我不需要接受彩色图像训练的 NN。但我也不需要 NN,它是用二进制地面实况图片训练的...... 我用 DeepLab 测试了我的原始彩色图像(图 3),但我得到的结果标签并不好......
到目前为止,这是我的代码:
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "3"
import numpy as np
from model import Deeplabv3
import tensorflow as tf
import time
import tensorboard
import keras
from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import TensorBoard
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config)
from keras import backend as K
K.set_session(session)
NAME = "DeepLab-".format(int(time.time()))
deeplab_model = Deeplabv3(input_shape=(300,200,3), classes=3)
tensorboard = TensorBoard(log_dir="logpath/".format(NAME))
deeplab_model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=['accuracy'])
# we create two instances with the same arguments
data_gen_args = dict(featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=90,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
# Provide the same seed and keyword arguments to the fit and flow methods
seed = 1
#image_datagen.fit(images, augment=True, seed=seed)
#mask_datagen.fit(masks, augment=True, seed=seed)
image_generator = image_datagen.flow_from_directory(
'/path/Input/',
target_size=(300,200),
class_mode=None,
seed=seed)
mask_generator = mask_datagen.flow_from_directory(
'/path/Label/',
target_size=(300,200),
class_mode=None,
seed=seed)
# combine generators into one which yields image and masks
train_generator = zip(image_generator, mask_generator)
print("compiled")
#deeplab_model.fit(X, y, batch_size=32, epochs=10, validation_split=0.3, callbacks=[tensorboard])
deeplab_model.fit_generator(train_generator, steps_per_epoch= np.uint32(2935 / 32), epochs=10, callbacks=[tensorboard])
print("finish fit")
deeplab_model.save_weights('deeplab_1.h5')
deeplab_model.save('deeplab-1')
session.close()
这是我测试 DeepLab 的代码(来自 Github):
from matplotlib import pyplot as plt
import cv2 # used for resize. if you dont have it, use anything else
import numpy as np
from model import Deeplabv3
import tensorflow as tf
from PIL import Image, ImageEnhance
deeplab_model = Deeplabv3(input_shape=(512,512,3), classes=3)
#deeplab_model = Deeplabv3()
img = Image.open("Path/Input/0/0001.png")
imResize = img.resize((512,512), Image.ANTIALIAS)
imResize = np.array(imResize)
img2 = cv2.cvtColor(imResize, cv2.COLOR_GRAY2RGB)
w, h, _ = img2.shape
ratio = 512. / np.max([w,h])
resized = cv2.resize(img2,(int(ratio*h),int(ratio*w)))
resized = resized / 127.5 - 1.
pad_x = int(512 - resized.shape[0])
resized2 = np.pad(resized,((0,pad_x),(0,0),(0,0)),mode='constant')
res = deeplab_model.predict(np.expand_dims(resized2,0))
labels = np.argmax(res.squeeze(),-1)
plt.imshow(labels[:-pad_x])
plt.show()
【问题讨论】:
“不重要,0 必须是背景或 1 必须是背景......” 好吧,对于 你 这个可能并不重要。对于NN来说,当然是!请记住:归根结底,NN 只是一个在内部进行一些简单数学运算的数学函数。考虑两张几乎相同的图像,其中一张标注为 0,另一张标注为 1。您如何期望相同的数学函数对相同的输入产生不同的值? @sebrockm 是的,你是对的。我想也许你可以对 NN 说,这并不重要,所以用数学术语来说,你可以排列数字,重要的是面积,但我将再次使用 KMeans,并将背景标记为 0 等。我可以,因为在我的原始图像中,背景是绿色的,一根绳子是红色的,另一根是蓝色的……所以我将编辑我的问题…… 【参考方案1】:第一个问题:DeepLabV3+ 是一个非常大的模型(我假设您正在使用 Xception 主干?!),对于 32 的 bachsize 和 200x300 像素来说,需要 11 GB 的 GPU 容量是完全正常的 :)(训练 DeeplabV3+,我使用 5 个 500x500 像素的批大小需要大约 11 GB)。请注意您问题的第二句话:所需的 GPU 资源受许多因素(模型、优化器、批量大小、图像裁剪、预处理等)的影响,但数据集集的实际大小不应影响它。因此,您的数据集是 300MB 还是 300GB 都没有关系。
一般问题:您使用的是小型数据集。选择 DeeplabV3+ 和 Xception 可能不太合适,因为模型可能太大。这可能会导致过度拟合。如果您还没有获得令人满意的结果,您可以尝试使用较小的网络。如果你想坚持使用 DeepLab 框架,你可以将主干从 Xception 网络切换到 MobileNetV2(在官方 tensorflow 版本中它已经实现)。或者,您可以尝试使用独立网络,例如带有 FCN 头的 Inception 网络...
在每种情况下,都必须使用经过良好训练的特征表示的预训练编码器。如果您没有找到基于灰度输入图像的所需模型的良好初始化,只需使用在 RGB 图像上预训练的模型并使用灰度数据集扩展预训练(基本上您可以将任何大型 rgb 数据集转换为灰度)并在使用数据之前微调灰度输入的权重。
我希望这会有所帮助!干杯,弗兰克
【讨论】:
谢谢!好的,我只是想知道那个大小......我将我的 bachsize 减少到 16,现在内存分配不再是 11GB。我已经将 DeepLab V3+ 与 MobileNetV2 一起使用,但我的结果并不令人满意......有时我的准确率超过 80%,但是当我使用文档中的预测函数时,我只得到一个带有零的图像......我的任务是使用迁移学习,因为我的数据集很小,我的任务基本上是语义分割。现在我使用带有 RGB 输入的 DeepLab。我只是将我的灰度图像转换为 RGB ......这也可以吗? 灰度转RGB是什么意思?我假设您只是想以 RGB 表示形式保存灰度图像-> 将每个像素的值 x_gray 保存在 (x_gray ,x_gray ,x_gray ) 中。如果是这种情况,您的方法很好。但是您仍然可以通过添加一个额外的步骤来改进您的结果:在 RGB 表示的灰度图像上训练 RGB 预训练编码器:(x_gray, x_gray, x_gray)。为此,只需将数千张图像从一个很棒的 RGB 数据集转换为灰度并利用它们的标签。 好吧,如果您不想更改 NN 架构,只需将 RGB 图像转换为 RGB 表示中的灰度。因此,在额外的预训练和使用数据集进行训练期间,您仍然为网络图像提供 3 个通道 如果你想改变架构,你实际上只需要改变网络的第一层,所有后续层都应该没问题。更大的问题可能是更改输入管道(裁剪、扩充等)。因此,如果您不熟悉它,只需保留“3 通道”架构即可。 :) 不用担心 ;)。我从来没有使用过keras。我一直使用 tensorflow :D【参考方案2】:IBM 的大型模型支持 (LMS) 库支持对大型深度神经网络进行训练,这些网络通常会在训练时耗尽 GPU 内存。 LMS 通过在不需要时将张量临时交换到主机内存来管理这种 GPU 内存的超额订阅。
描述 - https://developer.ibm.com/components/ibm-power/articles/deeplabv3-image-segmentation-with-pytorch-lms/
Pytorch - https://github.com/IBM/pytorch-large-model-support
TensorFlow - https://github.com/IBM/tensorflow-large-model-support
【讨论】:
以上是关于语义图像分割 NN (DeepLabV3+) 的内存过多问题的主要内容,如果未能解决你的问题,请参考以下文章
自动驾驶感知算法实战4——语义分割网络详解(DeepLabV3FCNUNet等)