使用我自己的 Keras 插件的 TripletSemiHardLoss 图像

Using my own Images for TripletSemiHardLoss from Keras addons

我的图片文件夹设置为一个主文件夹,有 130 个独立的文件夹,每个文件夹都有自己的图片 folder_with_130_folders-
folder1_class1-
img_in_class1_folder.jpg
img_in_class1_folder.jpg
...
folder130_class130-
img_in_class130_folder.jpg
img_in_class130_folder.jpg


train_dataset =  prod_images.flow_from_directory(directory, target_size=(225, 225), class_mode='categorical', subset='training', save_format='jpg')
validation_set =  prod_images.flow_from_directory(directory, target_size=(225, 225), class_mode='categorical', subset='validation', save_format='jpg')

(x_train, y_train), (x_test, y_test) = train_dataset.next(), validation_set.next()

model = models.Sequential()
model.add(layers.Conv2D(filters=128, kernel_size=2, padding='same', activation='relu', input_shape=(225, 225, 3)))
model.add(layers.MaxPooling2D(pool_size=2))
model.add(layers.Dropout(0.3))
model.add(layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu'))
model.add(layers.MaxPooling2D(pool_size=2))
model.add(layers.Dropout(0.3))
model.add(layers.Conv2D(filters=32, kernel_size=2, padding='same', activation='relu'))
model.add(layers.MaxPooling2D(pool_size=2))
model.add(layers.Dropout(0.3))
model.add(layers.Conv2D(filters=16, kernel_size=2, padding='same', activation='relu'))
model.add(layers.MaxPooling2D(pool_size=2))
model.add(layers.Dropout(0.3))
model.add(layers.Flatten())
model.add(layers.Dense(256, activation=None)) # No activation on final dense layer
model.add(layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))) # L2 normalize embeddings

model.summary()

model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate=0.001), loss=tfa.losses.TripletSemiHardLoss())

model_fit = model.fit(train_dataset, steps_per_epoch=4, epochs=20, verbose=1, validation_data = validation_set)```

docs 中关于 tfa.losses.TripletSemiHardLoss 所述:

We expect labels y_true to be provided as 1-D integer Tensor with shape [batch_size] of multi-class integer labels. And embeddings y_pred must be 2-D float Tensor of l2 normalized embedding vectors

因此,您应该使用稀疏整数标签 (sparse_categorical) 而不是单热编码标签(分类)。这是一个工作示例:

import tensorflow as tf
import tensorflow_addons as tfa
import pathlib

dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)

batch_size = 32

train_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  label_mode='int', # sparse categorical
  subset="training",
  seed=123,
  image_size=(225, 225),
  batch_size=batch_size)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=128, kernel_size=2, padding='same', activation='relu', input_shape=(225, 225, 3)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=2, padding='same', activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Conv2D(filters=16, kernel_size=2, padding='same', activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(256, activation=None)) # No activation on final dense layer
model.add(tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=-1))) # L2 normalize embeddings

model.summary()

model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate=0.001), loss=tfa.losses.TripletSemiHardLoss())

model_fit = model.fit(train_ds, epochs=5, verbose=1)

在您的情况下,您必须将参数 class_mode 设置为 sparse:

flow_from_directory(directory, target_size=(225, 225), class_mode='sparse', subset='training', save_format='jpg')