创建一个基于tensorflow:latest-gpu-py3-jupyter的Dockerfile更好还是重构load



我正在Jupyter笔记本电脑环境中开发图像分类模型。在让我的模型与CPU一起工作后,我尝试使用Jupyter&GPU(tensorflow/tensorflow:latest-GPU-py3-jupyter(,所以我可以利用我的GPU进行训练。GPU配置不是问题(nvidia-smi命令显示GPU可用(,但我现在纠结于如何设置图像数据管道。

我有包含以下结构的图像的文件夹:

my_folder
│
└───Training
│   │
│   └───Class_A
│   │       01234.jpg
│   │       56789.jpg
│   │       ...
│   │        
│   └───Class_B
│   │       01234.jpg
│   │       56789.jpg
│   │       ...
│   
└───Validation
│   │
│   └───Class_A
│   │       01234.jpg
│   │       56789.jpg
│   │       ...
│   │        
│   └───Class_B
│   │       01234.jpg
│   │       56789.jpg
│   │       ...
path_training = 'my_folder/Training/'
path_validation = 'my_folder/Validation/'
image_size = (90, 90)

使用tensorflow==2.6.2,我可以使用以下代码轻松地加载我的训练/验证图像数据集:

train_ds = tf.keras.preprocessing.image_dataset_from_directory(path_training,
seed=1993, 
image_size = image_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(path_validation,
seed=1993,
image_size = image_size)

然而,很明显,当使用Docker镜像时,这个命令不起作用:

---->3 train_ds=tf.keras.preprocessing.image_dataset_from_directory(path_training,4种子=1993,5 image_size=image_size(

AttributeError:模块"tensorflow_core.keras.preprocessing"没有属性'image_dataset_from_directory'

所以我发现Docker镜像的tensorflow版本是2.1.0,并且该属性没有在API中列出,这给我留下了这个选项:

# Read in all image files and split into training/validation sets (tensorflow-gpu 2.1.0)
train_ds = tf.keras.preprocessing.image.load_img(path_training, target_size = image_size)
val_ds = tf.keras.preprocessing.image.load_img(path_validation, target_size = image_size)

正如预期的那样,TensorFlow 2.1.0中的load_img((命令不会像image_dataset_from_directory((那样在目录中读取。

IsADirectoryError:[Erno 21]是一个目录:'my_folder/Training/'

我不确定最好或最简单的前进道路是什么,因为我不太熟悉构建Docker映像。构建一个基于TensorFlow最新官方TensorFlow GPU&Jupyter Docker镜像,这样我就可以使用tf.keras.preprocessing.image_dataset_from_directory()了,还是我应该将就着使用这个预构建的Docker镜像并通过循环目录路径中的文件并以这种方式创建训练/验证镜像数据集来用tf.keras.preprocessing.image.load_img()加载我的镜像数据?对于后一种方法,我搜索并找到了一些类似的示例,特别是这个示例代码:

def get_data(dir):
X_train, Y_train = [], []
X_test, Y_test = [], []
subfolders = sorted([file.path for file in os.scandir(dir) if file.is_dir()])
for idx, folder in enumerate(subfolders):
for file in sorted(os.listdir(folder)):
img = load_img(folder+"/"+file, color_mode='grayscale')
img = img_to_array(img).astype('float32')/255
img = img.reshape(img.shape[0], img.shape[1],1)
if idx < 35:
X_train.append(img)
Y_train.append(idx)
else:
X_test.append(img)
Y_test.append(idx-35)
X_train = np.array(X_train)
X_test = np.array(X_test)
Y_train = np.array(Y_train)
Y_test = np.array(Y_test)
return (X_train, Y_train), (X_test, Y_test) 

我尝试重构TF 2.1.0:中的load_img((函数

def get_data(dir, set_option):
if set_option == 'train':
train_ds = []
subfolders = sorted([file.path for file in os.scandir(dir) if file.is_dir()])
for folder in subfolders:
for file in sorted(os.listdir(folder)):
img = tf.keras.preprocessing.image.load_img(folder+"/"+file, color_mode='grayscale')
train_ds.append(img)
return train_ds
elif set_option == 'test':  
test_ds = []
subfolders = sorted([file.path for file in os.scandir(dir) if file.is_dir()])
for folder in subfolders:
for file in sorted(os.listdir(folder)):
img = tf.keras.preprocessing.image.load_img(folder+"/"+file, color_mode='grayscale')
test_ds.append(img)
return test_ds

train_ds = get_data(path_training, 'train')
test_ds = get_data(path_validation, 'test')

它以列表的形式返回图像数据集,格式如下:

[<PIL.Image.Image image mode=L size=92x114 at 0x7FE6D11B67B8>,
<PIL.Image.Image image mode=L size=88x110 at 0x7FE6D11B6898>]

然而,使用更简单的TF 2.6.2tf.keras.preprocessing.image_dataset_from_directory()函数返回以下格式的图像数据集:

<BatchDataset element_spec=(TensorSpec(shape=(None, 90, 90, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None,), dtype=tf.int32, name=None))>

我已经意识到,我将图像附加到列表中的方法(基本上是我尝试的image_dataset_from_directory(会导致训练和验证数据集的一个热编码问题,因为它会引发以下AttributeError:

one_hot_encoded_train_ds = train_ds.map(lambda x, y: (x, tf.one_hot(y, depth=3)))
one_hot_encoded_val_ds = test_ds.map(lambda x, y: (x, tf.one_hot(y, depth=3)))
属性错误:"list"对象没有属性"map"

我不确定我是否试图错误地创建图像数据集对象。无论如何,考虑到我迄今为止在尝试不使用image_dataset_from_directory()函数时遇到的困难,我认为从长远来看,使用TensorFlow的更新图像可能会更容易。

好吧,所以我放弃了重构方法,但我学会了如何构建Docker映像!这比我预想的要容易得多。现在我可以使用tf.keras.preprocessing.image_dataset_from_directory()和我的GPU进行深度学习了。

这基本上就是我构建的Dockerfile:

FROM tensorflow/tensorflow:latest-gpu-jupyter
ENV python_version 3.8
# Install desired Python version (the current TF image is based on Ubuntu at the moment)
RUN apt install -y python${python_version}
# Set default version for root user 
RUN update-alternatives --install /usr/local/bin/python python /usr/bin/python${python_version} 1
# Update pip: https://packaging.python.org/tutorials/installing-packages/#ensure-pip-setuptools-and-wheel-are-up-to-date
RUN python -m pip install --upgrade pip setuptools wheel
COPY requirements.txt requirements.txt
RUN python -m pip install -r requirements.txt
EXPOSE 8888

以下是我使用的基本requirements.txt文件的内容:

numpy
matplotlib
pandas
scikit-learn
tensorflow-gpu==2.10.0

导入tensorflow后,以下是TensorFlow版本的打印结果以及可用的设备:

print(tf. __version__)
print(tf.config.get_visible_devices())

2.10.0[PhysicalDevice(name='/physical_device:CPU:0',device_type='CPU'(,PhysicalDevice(name='/physical _device:GPU:0',device_type='GPU'(]

然后我可以轻松加载图像数据集!

以下是一些有用的链接:

使用GPU加速快速设置TensorFlow

安装TensorFlow和Jupyter,GPU支持

对于任何看到这篇文章的人,我希望你能发现我的思考过程很有用。干杯

最新更新