TensorFlow:一次预测多个类

时间:2018-09-06 12:46:50

标签: python tensorflow

我觉得这个答案一定已经被问过(并回答过)十几次了,但是我搜索失败了(也许是由于缺乏正确的术语),所以我在这里问。

(说实话,请澄清一些问题:这个问题是基于较晚的作业,但是我们被要求以某种方式获得结果,而不必以我选择的方式来完成。该课程着重于使用但是,TensorFlow实际上,我应该预测单词的几个(〜15个)特征,因此我想使用RNN,也许还有很多要解决的问题,但是现在,我决定创建一个玩具问题并仅使用“基本”网络。)

我有一些数据,对于每个样本,我应该预测两类标签。也就是说,我应该e。 G。例如,对于样品1,正确的A标签为A3,正确的B标签为B2,而对于样品2,正确的A标签为A2,正确的B标签为B7。这些类在某种程度上是相互依赖的,因此我认为单个网络比两个独立训练的网络要好。

但是,我真的不确定如何使TensorFlow进行两个(或通常多个)预测。 更确切地说,我设法做到了(至少在TensorBoard中进行检查时,似乎网络确实学会了预测这两种情况)对我来说似乎并不正确。 代码如下(我希望它包含所有相关部分,并且仅包含相关部分):

class Network:
    SIZE = 200

    def __init__(self, threads, seed=42):
        # Create an empty graph and a session
        graph = tf.Graph()
        graph.seed = seed
        self.session = tf.Session(graph = graph, config=tf.ConfigProto(inter_op_parallelism_threads=threads,
                                                                       intra_op_parallelism_threads=threads))

    def construct(self, args):
        with self.session.graph.as_default():
            # Inputs
            self.data = tf.placeholder(tf.float32, [None, self.SIZE], name='data')
            self.labels_one = tf.placeholder(tf.int64, [None], name='labels1')
            self.labels_two = tf.placeholder(tf.int64, [None], name='labels2')
            self.is_training = tf.placeholder(tf.bool, [], name='is_training')

            hidden = tf.layers.flatten(tf.layers.dense(self.data, 80, activation=tf.nn.relu))
            output_layer_one = tf.layers.dense(hidden, 2)
            output_layer_two = tf.layers.dense(hidden, 41)

            self.labels_predictions_one = tf.argmax(output_layer_one, axis=1)
            self.labels_predictions_two = tf.argmax(output_layer_two, axis=1)

            loss_one = tf.losses.sparse_softmax_cross_entropy(self.labels_one, output_layer_one, scope='loss')
            loss_two = tf.losses.sparse_softmax_cross_entropy(self.labels_two, output_layer_two, scope='loss')
            loss = loss_one + loss_two

            global_step = tf.train.create_global_step()
            self.training = tf.train.AdamOptimizer().minimize(loss, global_step=global_step, name='training')

            ### These two lines are reported in summaries but I ommit the rest of summary handling
            accuracy1 = tf.reduce_mean(tf.cast(tf.equal(self.labels_one, self.labels_predictions_one), tf.float32))
            accuracy2 = tf.reduce_mean(tf.cast(tf.equal(self.labels_two, self.labels_predictions_two), tf.float32))

            # Initialize variables
            self.session.run(tf.global_variables_initializer())

    def train(self, data, labels_one, labels_two):
        self.session.run([self.training, self.summaries['train']],
                         {self.data: data, self.labels_one: labels_one, self.labels_two: labels_two, self.is_training: True})

    def evaluate(self, dataset, data, labels_one, labels_two):
        self.session.run(self.summaries[dataset],
                         {self.data: data, self.labels_one: labels_one, self.labels_two: labels_two, self.is_training: False})

    def predict(self, data):
        return self.session.run([self.labels_predictions_one, self.labels_predictions_two],
                                {self.data: data, self.is_training: False})

数据作为数组数组提供,每个内部数组包含200个整数。提供的标签就像整数数组一样。 我觉得应该用数组替换所有具有近乎混乱的处理的labels_one和labels_two。也就是说,我很想得出这样的结论:

class Network:
    SIZE = 200
    LABELS = [2, 41]

    ...

    def construct(self, args):
        with self.session.graph.as_default():
            # Inputs
            self.data = tf.placeholder(tf.float32, [None, self.SIZE], name='data')
            self.labels = []
            for i in range(len(self.LABELS)):
                self.labels.append(tf.placeholder(tf.int64, [None], name='labels{}'.format(i)))
            self.is_training = tf.placeholder(tf.bool, [], name='is_training')

            hidden = tf.layers.flatten(tf.layers.dense(self.data, 80, activation=tf.nn.relu))

            self.output_layers = []
            self.labels_predictions = []
            self.losses = []
            loss = 0
            for i in range(len(self.LABELS)):
                self.output_layers.append(tf.layers.dense(hidden, self.LABELS[i]))
                self.labels_predictions.append(tf.argmax(self.output_layers[i], axis=1))
                self.losses.append(tf.losses.sparse_softmax_cross_entropy(self.labels[i], self.output_layers[i], scopre='loss'))
                loss += self.losses[i]

            global_step = tf.train.create_global_step()
            self.training = tf.train.AdamOptimizer().minimize(loss, global_step=global_step, name='training')

            ...
            accuracy[i] = tf.reduce_mean(tf.cast(tf.equal(self.labels[i], self.labels_predictions[i]), tf.float32))

            # Initialize variables
            self.session.run(tf.global_variables_initializer())

    def train(self, data, labels):
        self.session.run([self.training, self.summaries['train']],
                         {self.data: data, self.labels: labels,  self.is_training: True})

    ...

数据仍将以数组的形式提供,但标签也将以数组的形式提供,每个内部数组包含2个值。 但是,这种特定方法会导致错误:

Traceback (most recent call last):
  File "./so_multi.py", line 62, in <module>
    network.train(data, labels)
  File "./so_multi.py", line 50, in train
    {self.data: data, self.labels: labels, self.is_training: True})
TypeError: unhashable type: 'list'

为全面参考,这是带有微数据的可运行代码摘录:

#!/usr/bin/env python3
import numpy as np
import tensorflow as tf

class Network:
    SIZE = 10
    LABELS = [2, 41]

    def __init__(self, threads, seed=42):
        # Create an empty graph and a session
        graph = tf.Graph()
        graph.seed = seed
        self.session = tf.Session(graph = graph, config=tf.ConfigProto(inter_op_parallelism_threads=threads,
                                                                       intra_op_parallelism_threads=threads))

    def construct(self):
        with self.session.graph.as_default():
            # Inputs
            self.data = tf.placeholder(tf.float32, [None, self.SIZE], name='data')
            self.labels = []
            for i in range(len(self.LABELS)):
                self.labels.append(tf.placeholder(tf.int64, [None], name='labels{}'.format(i)))
            self.is_training = tf.placeholder(tf.bool, [], name='is_training')

            hidden = tf.layers.flatten(tf.layers.dense(self.data, 80, activation=tf.nn.relu))
            self.output_layers = []
            self.labels_predictions = []
            self.losses = []
            loss = 0
            for i in range(len(self.LABELS)):
                self.output_layers.append(tf.layers.dense(hidden, self.LABELS[i]))
                self.labels_predictions.append(tf.argmax(self.output_layers[i], axis=1))
                self.losses.append(tf.losses.sparse_softmax_cross_entropy(self.labels[i], self.output_layers[i], scope='loss'))
                loss += self.losses[i]

            global_step = tf.train.create_global_step()
            self.training = tf.train.AdamOptimizer().minimize(loss, global_step=global_step, name='training')

            # Initialize variables
            self.session.run(tf.global_variables_initializer())

    def train(self, data, labels):
        self.session.run([self.training],
                         {self.data: data, self.labels: labels, self.is_training: True})



if __name__ == '__main__':
    train_data = np.array([[25, 61, 23, 250, 149, 81, 21, 36, 213, 180], [48, 203, 118, 164, 131, 246, 2, 130, 187, 82]])
    train_labels = np.array([[1, 3], [0, 11]])

    # Construct the network
    network = Network(threads=1)
    network.construct()

    network.train(train_data, train_labels)

太好了。我在俯视什么吗?这是某个地方的愚蠢错误吗,总体来说是个不好的方法吗?

对于使用TensorFlow 1.5的解决方案,我将是最伟大的,但是我可以使用任何东西,我只是讨厌必须学习太多新知识的想法。

0 个答案:

没有答案