【问题标题】:How to correctly encode labels with tensorflow's one-hot encoding?如何使用 tensorflow 的 one-hot 编码正确编码标签?
【发布时间】:2018-05-09 13:22:04
【问题描述】:

我一直在尝试使用 python 3.6 学习 Tensorflow,并决定使用来自埃塞克斯大学人脸数据库 (http://cswww.essex.ac.uk/mv/allfaces/index.html) 的数据构建一个人脸识别程序。到目前为止,我一直在关注 Tensorflow 的 MNIST 专家指南,但是当我开始测试时,每个 epoch 的准确度都是 0,所以我知道出了点问题。我对如何处理标签感到最不安,所以我认为这就是问题所在。

数据集中的标签可以是数字 ID,例如 987323,也可以是某人的名字,例如“fordj”。我处理这个问题的想法是创建一个“预编码”encode_labels 函数,它为测试和训练集中的每个唯一标签提供自己唯一的整数值。我检查以确保测试和训练集中的每个唯一标签都具有相同的唯一值。它还返回一个字典,以便我可以轻松地从编码版本映射回原始标签。如果我执行此步骤并在检索标签时传递标签(即“fordj”),我会收到一条错误消息

UnimplementedError(参见上面的回溯):不支持将字符串转换为 int32 [[节点:Cast = CastDstT=DT_INT32, SrcT=DT_STRING, _device="/job:localhost/replica:0/task:0/device:CPU:0"]]]

我对此的解释是,由于许多标签是人名,因此 tensorflow 无法将“fordj”之类的标签转换为 tf.int32。获取标签和路径的代码在这里:

def get_paths_and_labels(path):
    """ image_paths  :  list of relative image paths
        labels       :  mix of alphanumeric characters """
    image_paths = [path + image for image in os.listdir(path)]
    labels = [i.split(".")[-3] for i in image_paths]
    labels = [i.split("/")[-1] for i in labels]
    return image_paths, labels

def encode_labels(train_labels, test_labels):
    """ Assigns a numeric value to each label since some are subject's names """
    found_labels = []
    index = 0
    mapping = {}
    for i in train_labels:
        if i in found_labels:
            continue
        mapping[i] = index
        index += 1
        found_labels.append(i)
    return [mapping[i] for i in train_labels], [mapping[i] for i in test_labels], mapping

这是我分配训练和测试标签的方式。然后我想使用 tensorflow 的 one-hot 编码器为我再次编码。

def main():
    # Grabs the labels and each image's relative path 
    train_image_paths, train_labels = get_paths_and_labels(TRAIN_PATH)
    # Smallish dataset so I can read it all into memory
    train_images = [cv2.imread(image) for image in train_image_paths]

    test_image_paths, test_labels = get_paths_and_labels(TEST_PATH)
    test_images = [cv2.imread(image) for image in test_image_paths]

    num_classes = len(set(train_labels))

    # Placeholders
    x = tf.placeholder(tf.float32, shape=[None, IMAGE_SIZE[0] * IMAGE_SIZE[1]])
    y_ = tf.placeholder(tf.float32, shape=[None, num_classes])
    x_image = tf.reshape(x, [-1, IMAGE_SIZE[0], IMAGE_SIZE[1], 1])

    # One-hot labels
    train_labels, test_labels, mapping = encode_labels(train_labels, test_labels)

    train_labels = tf.one_hot(indices=tf.cast(train_labels, tf.int32), depth=num_classes)
    test_labels = tf.one_hot(indices=tf.cast(test_labels, tf.int32), depth=num_classes)

我确定我做错了什么。我知道 sklearn 有一个 LabelEncoder,虽然我还没有尝试过。感谢您对此的任何建议,感谢所有帮助!

【问题讨论】:

  • 我会尝试打印训练和测试标签,以确保您不会每次都输入 0 的标签,因为那将是一个不同的问题。

标签: python-3.x machine-learning tensorflow


【解决方案1】:

我的解释是,由于许多标签是人名,因此 tensorflow 无法将“fordj”之类的标签转换为 tf.int32。

你是对的。 TensorFlow 无法做到这一点。相反,您可以创建一个从名称到唯一(和渐进式)ID 的映射函数。一旦你这样做了,你就可以用它的 one-hot 表示正确地对每个数字 ID 进行一次编码。 您已经有了数字 ID 和字符串标签之间的关系,因此您可以执行以下操作:

train_labels, test_labels, mapping = encode_labels(train_labels, test_labels)
numeric_train_ids = [labels[idx] for idx in train_labels]
numeric_test_ids = [labels[idx] for idx in test_labels]     

one_hot_train_labels = tf.one_hot(indices=numeric_train_ids, depth=num_classes)
one_hot_test_labels = tf.one_hot(indices=numeric_test_ids, depth=num_classes)

【讨论】:

    猜你喜欢
    • 2021-08-05
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 2020-11-04
    • 2021-12-13
    • 1970-01-01
    • 2017-05-14
    • 2020-10-08
    相关资源
    最近更新 更多