我创建了一个模型来识别植物病害。我预计能识别 10 种疾病。在 jupyter 笔记本中,它运行良好,但由于 GPU 限制而速度很慢。然后我决定在 google colab 中运行该模型,但它没有运行。它停留在第一个纪元。
我用来构建模型的代码如下
BATCH_SIZE = 64
IMAGE_SIZE = 256
CHANNELS=3
EPOCHS=10
dataset = tf.keras.preprocessing.image_dataset_from_directory(
"/content/drive/MyDrive/google-colab-files/PlantVillage",
seed=123,
shuffle=True,
image_size=(IMAGE_SIZE,IMAGE_SIZE),
batch_size=BATCH_SIZE
)
def get_dataset_partisions_tf(ds,trains_split=0.8,val_split=0.1,test_split=0.1,shuffle=True,shuffle_size=10000):
ds_size = len(ds)
if shuffle:
ds = ds.shuffle(shuffle_size,seed=12)
train_size = int(trains_split * ds_size)
val_size = int(val_split * ds_size)
train_ds = ds.take(train_size)
val_ds = ds.skip(train_size).take(val_size)
test_ds = ds.skip(train_size).skip(val_size)
return train_ds,val_ds,test_ds
train_ds,val_ds,test_ds = get_dataset_partisions_tf(dataset)
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size = tf.data.AUTOTUNE)
val_ds = val_ds.cache().shuffle(1000).prefetch(buffer_size = tf.data.AUTOTUNE)
test_ds = test_ds.cache().shuffle(1000).prefetch(buffer_size = tf.data.AUTOTUNE)
resize_and_rescales = Sequential([
layers.experimental.preprocessing.Resizing(IMAGE_SIZE,IMAGE_SIZE),
layers.experimental.preprocessing.Rescaling(1.0/255)
])
data_agmetation = Sequential([
layers.experimental.preprocessing.RandomFlip('horizontal_and_vertical'),
layers.experimental.preprocessing.RandomRotation(0.2),
])
input_shape = (BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,CHANNELS)
n_classes = 10
model = Sequential([
resize_and_rescales,
data_agmetation,
layers.Conv2D(32,(3,3), activation='relu',input_shape = input_shape),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64,kernel_size = (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64,kernel_size = (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64,(3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64,(3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64,(3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Flatten(),
layers.Dense(64,activation='relu'),
layers.Dense(n_classes, activation='softmax'),
])
model.build(input_shape = input_shape)
model.summary()
模型摘要截图为:
model.compile(
optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['accuracy']
)
当我使用以下代码来训练数据时:
model.fit(
train_ds,
epochs=EPOCHS,
batch_size=BATCH_SIZE,
verbose=2,
validation_data=val_ds
)
它一直停留在第一个纪元
检查 TensorFlow 是否正在使用 GPU。您可以尝试减小批量大小。
我的假设是,这是因为你的 verbose,你应该将 verbose 设置为 1 以查看你所在纪元的步骤。
一种简单的方法是将数据加载到 Colab 空间中,而不是从驱动器访问它们。您可以压缩该文件夹,复制到本地空间(在 colab 中),解压缩并将您的路径指向该本地空间。第一个 epoch 仍然可能需要更长的时间,但是,后面的 epoch 的运行时间将不断改进。
我在根据Chollet 书第 8.3 节训练 CNN 时遇到了同样的问题,使用带有免费 T4 GPU 的 Google Colab 并将数据存储在 Google Drive 上。
我的解决方案是不使用
image_dataset_from_directory
。
使用
image_dataset_from_directory
,第一个 epoch 需要 5 到 10 分钟 来执行,而接下来的 epoch 则以几十秒(10-20 秒)的顺序执行。
通过使用 load_img
和
img_to_array
从 Google Drive 手动加载数据集,需要1 分钟 首先将数据集加载到 numpy 数组中,然后所有纪元(包括第一个纪元)在几十秒内执行完毕。 . 所以就我而言,手动操作显然是有利的。 这是代码:
import os
import numpy as np
input_dir = "drive/MyDrive/Colab Notebooks/dogs-vs-cats-small"
def get_images(images_dir):
images = []
for fn in os.listdir(images_dir):
img = keras.utils.load_img(
f"{images_dir}/{fn}",
target_size=(180,180),
interpolation='bilinear')
img = keras.utils.img_to_array(img)
images.append(img)
return np.array(images)
def get_dataset(dataset_dir):
data_dogs = get_images(f"{dataset_dir}/dogs")
data_cats = get_images(f"{dataset_dir}/cats")
return (
np.concatenate((data_dogs, data_cats)),
np.concatenate((np.zeros(len(data_dogs)), np.ones(len(data_cats))))
)
train_data, train_targets = get_dataset(f"{input_dir}/train/")
print(f"Loaded train dataset: {train_data.shape}, {train_targets.shape}")
validation_data, validation_targets = get_dataset(f"{input_dir}/validation/")
print(f"Loaded validation dataset: {validation_data.shape}, {validation_targets.shape}")
test_data, test_targets = get_dataset(f"{input_dir}/test/")
print(f"Loaded test dataset: {test_data.shape}, {test_targets.shape}")