如何使用tensorflow的单热编码正确编码标签?

时间:2017-11-25 23:59:49

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

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

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

  

UnimplementedError(参见上面的回溯):不支持将字符串转换为int32        [[Node: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,虽然我还没有尝试过。感谢您对此提出任何建议,感谢所有帮助!

1 个答案:

答案 0 :(得分:1)

  

我解释这一点的方式是,由于许多标签都是人的名字,因此张量流不能转换标签,例如" fordj"到了tf.int32。

你是对的。 Tensorflow无法做到这一点。相反,您可以创建从nome到唯一(和渐进)ID的映射功能。完成后,您可以使用其一个热表示正确地对每个数字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)