Tensorflow model.fit()不适用于字符串作为标签

时间:2019-05-03 13:30:05

标签: python tensorflow keras

请参见以下代码示例:

import tensorflow as tf
import numpy as np

images = np.random.rand(5, 108, 56, 3)
y_pred = np.random.rand(5, 4)
y_true = np.array(['aa', 'bb', 'cc', 'dd', 'ee'])

dataset = tf.data.Dataset.from_tensor_slices((images, y_true))
dataset = dataset.batch(5)
dataset = dataset.repeat()

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(16, [3,3], activation='relu'),
    tf.keras.layers.GlobalAveragePooling2D(),
    tf.keras.layers.Dense(4)
])

def triplet_loss(y_true, y_pred):
    all_diffs = tf.expand_dims(y_pred, axis=1) - tf.expand_dims(y_pred, axis=0)
    distances = tf.sqrt(tf.reduce_sum(tf.square(all_diffs), axis=-1) + 1e-12)

    furthest_positive = tf.reduce_max(distances, axis=1)

    closest_negative = tf.map_fn(lambda x: tf.reduce_min(x),
                             distances)

    diff = furthest_positive - closest_negative
    diff = tf.nn.softplus(diff)

    return diff

optimizer = tf.optimizers.Adam(learning_rate=0.001)

model.compile(loss=triplet_loss,
          optimizer=optimizer)

model.fit(dataset, steps_per_epoch=5, epochs=10, verbose=1)

此处y_true包含可以比较的字符串(假设一些度量学习实验)。网络为每个输入输出一个特征向量。具有相同标签的输入在特征空间中应该相似。

但是此代码给出错误:

  

tensorflow.python.framework.errors_impl.UnimplementedError:强制转换   不支持浮点字符串[Op:Cast]名称:Cast /

似乎无法将字符串作为标签处理,并试图将它们转换为某个位置的浮点数。

但是当我使用gradientTape而不是model.fit时就没有问题

for images, labels in dataset:
    with tf.GradientTape() as tape:
        y_pred = model(images, training=True)
        loss_value = triplet_loss(labels, y_pred)

        grads = tape.gradient(loss_value, model.trainable_variables)
        optimizer.apply_gradients(zip(grads, model.trainable_variables))
        print('iteration done')

这很好。这是model.fit()中的错误吗?是否有一些解决方法仍然可以使用model.fit()?

1 个答案:

答案 0 :(得分:0)

转换所需的小代码(建议@danzfang)

import numpy as np

raw_y_true = ['a', 'b', 'c', 'd', 'b', 'c']
mapping_to_numbers = {}
y_true = np.zeros((len(raw_y_true)))
for i, raw_label in enumerate(raw_y_true):
    if raw_label not in mapping_to_numbers:
        mapping_to_numbers[raw_label] = len(mapping_to_numbers)
    y_true[i] = mapping_to_numbers[raw_label]
print(y_true)
# [0. 1. 2. 3. 1. 2.]
print(mapping_to_numbers)
# {'d': 3, 'a': 0, 'c': 2, 'b': 1}

如您所见,您不需要知道标签的数量。