Подтвердить что ты не робот

Вывод TensorFlow

Я долго копался в этом. Я нашел тонну статей; но ни один из них не показывает просто вывод о тензорном потоке как простой вывод. Его всегда "использовать обслуживающий двигатель" или использовать график, который предварительно закодирован/определен.

Вот проблема: у меня есть устройство, которое периодически проверяет наличие обновленных моделей. Затем необходимо загрузить эту модель и выполнить входные прогнозы через модель.

В Керасе это было просто: построить модель; обучаем модель и вызываем model.predict(). В скикит-учи то же самое.

Я могу взять новую модель и загрузить ее; Я могу распечатать все веса; но как в мире я делаю вывод против этого?

Код для загрузки модели и печати весов:

    with tf.Session() as sess:
        new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta', clear_devices=True)
        new_saver.restore(sess, MODEL_PATH)
        for var in tf.trainable_variables():
            print(sess.run(var))

Я распечатал все свои коллекции, и у меня есть: ['queue_runners', 'variable', 'loss', 'summary', 'train_op', 'cond_context', 'trainable_variables']

Я пытался использовать sess.run(train_op); однако это только начало поднимать полную тренировку; это не то, что я хочу сделать. Я просто хочу провести вывод относительно другого набора входных данных, которые я предоставляю, которые не являются записями TF.

Еще немного подробнее:

Устройство может использовать C++ или Python; до тех пор, пока я могу произвести .exe. Я могу настроить подачу, если я хочу кормить систему. Я тренировался с TFRecords; но в производстве я не собираюсь использовать TFRecords; это система реального/почти реального времени.

Спасибо за любой вклад. Я отправляю пример кода в этот репозиторий: https://github.com/drcrook1/CIFAR10/TensorFlow, который выполняет весь процесс обучения и выборки.

Любые советы приветствуются!

------------ РЕДАКТИРОВАТЬ ----------------- Я перестроил модель так, как показано ниже:

def inference(images):
    '''
    Portion of the compute graph that takes an input and converts it into a Y output
    '''
    with tf.variable_scope('Conv1') as scope:
        C_1_1 = ld.cnn_layer(images, (5, 5, 3, 32), (1, 1, 1, 1), scope, name_postfix='1')
        C_1_2 = ld.cnn_layer(C_1_1, (5, 5, 32, 32), (1, 1, 1, 1), scope, name_postfix='2')
        P_1 = ld.pool_layer(C_1_2, (1, 2, 2, 1), (1, 2, 2, 1), scope)
    with tf.variable_scope('Dense1') as scope:
        P_1 = tf.reshape(C_1_2, (CONSTANTS.BATCH_SIZE, -1))
        dim = P_1.get_shape()[1].value
        D_1 = ld.mlp_layer(P_1, dim, NUM_DENSE_NEURONS, scope, act_func=tf.nn.relu)
    with tf.variable_scope('Dense2') as scope:
        D_2 = ld.mlp_layer(D_1, NUM_DENSE_NEURONS, CONSTANTS.NUM_CLASSES, scope)
    H = tf.nn.softmax(D_2, name='prediction')
    return H

обратите внимание, что я добавляю имя 'prediction' к операции TF, чтобы я мог получить его позже.

При обучении я использовал конвейер ввода для tfrecords и очередей ввода.

GRAPH = tf.Graph()
with GRAPH.as_default():
    examples, labels = Inputs.read_inputs(CONSTANTS.RecordPaths,
                                          batch_size=CONSTANTS.BATCH_SIZE,
                                          img_shape=CONSTANTS.IMAGE_SHAPE,
                                          num_threads=CONSTANTS.INPUT_PIPELINE_THREADS)
    examples = tf.reshape(examples, [CONSTANTS.BATCH_SIZE, CONSTANTS.IMAGE_SHAPE[0],
                                     CONSTANTS.IMAGE_SHAPE[1], CONSTANTS.IMAGE_SHAPE[2]])
    logits = Vgg3CIFAR10.inference(examples)
    loss = Vgg3CIFAR10.loss(logits, labels)
    OPTIMIZER = tf.train.AdamOptimizer(CONSTANTS.LEARNING_RATE)

Я feed_dict использовать feed_dict для загруженной операции в графе; однако сейчас это просто висит....

MODEL_PATH = 'models/' + CONSTANTS.MODEL_NAME + '.model'

images = tf.placeholder(tf.float32, shape=(1, 32, 32, 3))

def run_inference():
    '''Runs inference against a loaded model'''
    with tf.Session() as sess:
        #sess.run(tf.global_variables_initializer())
        new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta', clear_devices=True)
        new_saver.restore(sess, MODEL_PATH)
        pred = tf.get_default_graph().get_operation_by_name('prediction')
        rand = np.random.rand(1, 32, 32, 3)
        print(rand)
        print(pred)
        print(sess.run(pred, feed_dict={images: rand}))
        print('done')

run_inference()

Я считаю, что это не работает, потому что исходная сеть была обучена с использованием TFRecords. В примере набора данных CIFAR данные невелики; наш реальный набор данных огромен, и, насколько я понимаю, TFRecords является лучшей практикой по умолчанию для обучения сети. feed_dict имеет большой смысл с точки зрения производства; мы можем раскрутить несколько потоков и заполнить эту вещь из наших систем ввода.

Итак, я думаю, у меня есть обученная сеть, я могу получить прогнозируемую операцию; но как мне сказать ему прекратить использовать входные очереди и начать использовать feed_dict? Помните, что с точки зрения производства у меня нет доступа к тому, что ученые сделали для этого. Они делают свое дело; и мы внедряем его в производство, используя любой согласованный стандарт.

-------INPUT OPS--------

tf.Operation 'input/input_producer/Const' type = Const, tf.Operation 'input/input_producer/Size' type = Const, tf.Operation 'input/input_producer/Greater/y' type = Const, tf.Operation 'input/input_producer/Greater 'type = Greater, tf.Operation' input/input_producer/Assert/Const 'type = Const, tf.Operation' input/input_producer/Assert/Assert/data_0 'type = Const, tf.Operation' input/input_producer/Assert/Assert 'type = Assert, tf.Operation' input/input_producer/Identity 'type = Identity, tf.Operation' input/input_producer/RandomShuffle 'type = RandomShuffle, tf.Operation' input/input_producer 'type = FIFOQueueV2, tf. Операция 'input/input_producer/input_producer_EnqueueMany' type = QueueEnqueueManyV2, tf.Operation 'input/input_producer/input_producer_Close' type = QueueCloseV2, tf.Operation 'input/input_producer/input_producer_ input/input_rodu_ input_rodu_ входной_свойства_точка_в_доставке_входной_входной/вводной/вводной_произведения_входной/вводной/вводной_перечисленной типовой операции type = QueueSizeV2, tf.Operation 'input/input_producer/Cast' type = Cast, tf.Operation 'input/input_produc er/mul/y 'type = Const, tf.Operation' input/input_producer/mul 'type = Mul, tf.Operation' input/input_producer/фракция_of_32_full/tags 'type = Const, tf.Operation' input/input_producer/fra_of_32_full ' type = ScalarSummary, tf.Operation 'input/TFRecordReaderV2' type = TFRecordReaderV2, tf.Operation 'input/ReaderReadV2' type = ReaderReadV2,

------END ВХОД OPS-----

----UPDATE 3----

Я считаю, что мне нужно сделать, чтобы убить секцию ввода графика, обученного с помощью TF Records, и перевести ввод с первого слоя на новый ввод. Это похоже на проведение операции; но это единственный способ сделать вывод, если я тренировался с использованием TFRecords настолько безумно, как это звучит...

Полный график:

enter image description here

Раздел, чтобы убить:

enter image description here

Поэтому я думаю, что возникает вопрос: как убить входной раздел графа и заменить его на feed_dict?

Последующие меры могут быть следующими: действительно ли это правильный путь? Это кажется помешанным.

----END ОБНОВЛЕНИЕ 3----

---link до контрольной точки files---

https://drcdata.blob.core.windows.net/checkpoints/CIFAR_10_VGG3_50neuron_1pool_1e-3lr_adam.model.zip?st=2017-05-01T21%3A56%3A00Z&se=2020-05-02T21%3A56%3A00Z&sp=rl&sv=2015- 12-11 & SR = B & сиг = oBCGxlOusB4NOEKnSnD% 2FTlRYa5NKNIwAX1IyuZXAr9o% 3D

--end ссылка на контрольно-пропускной пункт files---

- ----UPDATE 4 -----

Я сдался и просто попробовал "нормальный" способ выполнения логического вывода, предполагая, что я мог бы заставить ученых просто мариновать их модели, и мы могли бы захватить макет модели; распакуйте его и запустите на нем логический вывод. Поэтому, чтобы проверить, я попробовал нормальный способ, предполагая, что мы уже распаковали его... Это также не работает стоит бобов...

import tensorflow as tf
import CONSTANTS
import Vgg3CIFAR10
import numpy as np
from scipy import misc
import time

MODEL_PATH = 'models/' + CONSTANTS.MODEL_NAME + '.model'
imgs_bsdir = 'C:/data/cifar_10/train/'

images = tf.placeholder(tf.float32, shape=(1, 32, 32, 3))

logits = Vgg3CIFAR10.inference(images)

def run_inference():
'''Runs inference against a loaded model'''
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta')#, import_scope='1', input_map={'input:0': images})
        new_saver.restore(sess, MODEL_PATH)
        pred = tf.get_default_graph().get_operation_by_name('prediction')
        enq = sess.graph.get_operation_by_name(enqueue_op)
        #tf.train.start_queue_runners(sess)
        print(rand)
        print(pred)
        print(enq)
        for i in range(1, 25):
            img = misc.imread(imgs_bsdir + str(i) + '.png').astype(np.float32) / 255.0
            img = img.reshape(1, 32, 32, 3)
            print(sess.run(logits, feed_dict={images : img}))
            time.sleep(3)
        print('done')

run_inference()

Tensorflow завершает построение нового графа с функцией вывода из загруженной модели; затем он добавляет все остальные вещи из другого графа в конец. Итак, когда я заполняю feed_dict ожидая получить выводы обратно; Я просто получаю кучу случайного мусора, как если бы это был первый проход по сети...

Снова; это кажется сумасшедшим; мне действительно нужно написать собственную структуру для сериализации и десериализации случайных сетей? Это должно было быть сделано раньше...

- ----UPDATE 4 -----

Снова; Спасибо!

4b9b3361

Ответ 1

Хорошо, это заняло слишком много времени, чтобы понять; так вот ответ для остального мира.

Быстрое напоминание: мне нужно было сохранить модель, которую можно динамически загружать и выводить, не зная о подкреплениях или внутренностях того, как она работает.

Шаг 1. Создайте модель как класс и в идеале используйте определение интерфейса

class Vgg3Model:

    NUM_DENSE_NEURONS = 50
    DENSE_RESHAPE = 32 * (CONSTANTS.IMAGE_SHAPE[0] // 2) * (CONSTANTS.IMAGE_SHAPE[1] // 2)

    def inference(self, images):
        '''
        Portion of the compute graph that takes an input and converts it into a Y output
        '''
        with tf.variable_scope('Conv1') as scope:
            C_1_1 = ld.cnn_layer(images, (5, 5, 3, 32), (1, 1, 1, 1), scope, name_postfix='1')
            C_1_2 = ld.cnn_layer(C_1_1, (5, 5, 32, 32), (1, 1, 1, 1), scope, name_postfix='2')
            P_1 = ld.pool_layer(C_1_2, (1, 2, 2, 1), (1, 2, 2, 1), scope)
        with tf.variable_scope('Dense1') as scope:
            P_1 = tf.reshape(P_1, (-1, self.DENSE_RESHAPE))
            dim = P_1.get_shape()[1].value
            D_1 = ld.mlp_layer(P_1, dim, self.NUM_DENSE_NEURONS, scope, act_func=tf.nn.relu)
        with tf.variable_scope('Dense2') as scope:
            D_2 = ld.mlp_layer(D_1, self.NUM_DENSE_NEURONS, CONSTANTS.NUM_CLASSES, scope)
        H = tf.nn.softmax(D_2, name='prediction')
        return H

    def loss(self, logits, labels):
        '''
        Adds Loss to all variables
        '''
        cross_entr = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels)
        cross_entr = tf.reduce_mean(cross_entr)
        tf.summary.scalar('cost', cross_entr)
        tf.add_to_collection('losses', cross_entr)
        return tf.add_n(tf.get_collection('losses'), name='total_loss')

Шаг 2: Тренируйте свою сеть с любыми входами, которые вы хотите; в моем случае я использовал Queue Runners и TF Records. Обратите внимание, что этот шаг выполняется другой командой, которая выполняет итерации, создает, проектирует и оптимизирует модели. Это также может измениться со временем. Вывод, который они производят, должен извлекаться из удаленного местоположения, чтобы мы могли динамически загружать обновленные модели на устройства (перепрошивка оборудования является проблемой, особенно если она географически распределена). В этом случае; команда удаляет 3 файла, связанных с графической заставкой; но также рассол модели, используемой для этой тренировки

model = vgg3.Vgg3Model()

def create_sess_ops():
    '''
    Creates and returns operations needed for running
    a tensorflow training session
    '''
    GRAPH = tf.Graph()
    with GRAPH.as_default():
        examples, labels = Inputs.read_inputs(CONSTANTS.RecordPaths,
                                          batch_size=CONSTANTS.BATCH_SIZE,
                                          img_shape=CONSTANTS.IMAGE_SHAPE,
                                          num_threads=CONSTANTS.INPUT_PIPELINE_THREADS)
        examples = tf.reshape(examples, [-1, CONSTANTS.IMAGE_SHAPE[0],
                                     CONSTANTS.IMAGE_SHAPE[1], CONSTANTS.IMAGE_SHAPE[2]], name='infer/input')
        logits = model.inference(examples)
        loss = model.loss(logits, labels)
        OPTIMIZER = tf.train.AdamOptimizer(CONSTANTS.LEARNING_RATE)
        gradients = OPTIMIZER.compute_gradients(loss)
        apply_gradient_op = OPTIMIZER.apply_gradients(gradients)
        gradients_summary(gradients)
        summaries_op = tf.summary.merge_all()
        return [apply_gradient_op, summaries_op, loss, logits], GRAPH

def main():
    '''
    Run and Train CIFAR 10
    '''
    print('starting...')
    ops, GRAPH = create_sess_ops()
    total_duration = 0.0
    with tf.Session(graph=GRAPH) as SESSION:
        COORDINATOR = tf.train.Coordinator()
        THREADS = tf.train.start_queue_runners(SESSION, COORDINATOR)
        SESSION.run(tf.global_variables_initializer())
        SUMMARY_WRITER = tf.summary.FileWriter('Tensorboard/' + CONSTANTS.MODEL_NAME, graph=GRAPH)
        GRAPH_SAVER = tf.train.Saver()

        for EPOCH in range(CONSTANTS.EPOCHS):
            duration = 0
            error = 0.0
            start_time = time.time()
            for batch in range(CONSTANTS.MINI_BATCHES):
                _, summaries, cost_val, prediction = SESSION.run(ops)
                error += cost_val
            duration += time.time() - start_time
            total_duration += duration
            SUMMARY_WRITER.add_summary(summaries, EPOCH)
            print('Epoch %d: loss = %.2f (%.3f sec)' % (EPOCH, error, duration))
            if EPOCH == CONSTANTS.EPOCHS - 1 or error < 0.005:
                print(
                'Done training for %d epochs. (%.3f sec)' % (EPOCH, total_duration)
            )
                break
        GRAPH_SAVER.save(SESSION, 'models/' + CONSTANTS.MODEL_NAME + '.model')
        with open('models/' + CONSTANTS.MODEL_NAME + '.pkl', 'wb') as output:
            pickle.dump(model, output)
        COORDINATOR.request_stop()
        COORDINATOR.join(THREADS)

Шаг 3: Выполнить некоторый вывод. Загрузите свою маринованную модель; создать новый граф, добавив в него новый заполнитель для логитов; а затем вызвать восстановление сеанса. НЕ ВОССТАНАВЛИВАЙТЕ ВЕСЬ ГРАФ; ПРОСТО ПЕРЕМЕННЫЕ.

MODEL_PATH = 'models/' + CONSTANTS.MODEL_NAME + '.model'
imgs_bsdir = 'C:/data/cifar_10/train/'

images = tf.placeholder(tf.float32, shape=(1, 32, 32, 3))
with open('models/vgg3.pkl', 'rb') as model_in:
model = pickle.load(model_in)
logits = model.inference(images)

def run_inference():
    '''Runs inference against a loaded model'''
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        new_saver = tf.train.Saver()
        new_saver.restore(sess, MODEL_PATH)
        print("Starting...")
        for i in range(20, 30):
            print(str(i) + '.png')
            img = misc.imread(imgs_bsdir + str(i) + '.png').astype(np.float32) / 255.0
            img = img.reshape(1, 32, 32, 3)
            pred = sess.run(logits, feed_dict={images : img})
            max_node = np.argmax(pred)
            print('predicted label: ' + str(max_node))
        print('done')

run_inference()

Определенно, есть способы улучшить это, используя интерфейсы и, возможно, упаковать все лучше; но это работает и создает основу для того, как мы будем двигаться вперед.

ЗАКЛЮЧИТЕЛЬНОЕ ЗАМЕЧАНИЕ Когда мы наконец отправили это в производство, нам пришлось отправить глупый файл mymodel_model.py вместе со всем, чтобы построить график. Таким образом, теперь мы применяем соглашение об именах для всех моделей, а также существует стандарт кодирования для рабочих моделей, поэтому мы можем сделать это правильно.

Удачи!

Ответ 2

Хотя это не так, как вырезано и сухое, как model.predict(), оно по-прежнему действительно тривиально.

В вашей модели у вас должен быть тензор, который вычисляет конечный результат, который вас интересует, пусть назовите этот тензор output. В настоящее время у вас есть функция потерь. Если это так, создайте еще один тензор (переменный в модели), который фактически вычисляет желаемый результат.

Например, если ваша функция потерь:

tf.nn.sigmoid_cross_entropy_with_logits(last_layer_activation, labels)

И вы ожидаете, что ваши выходы будут в диапазоне [0,1] за класс, создайте другую переменную:

output = tf.sigmoid(last_layer_activation)

Теперь, когда вы вызываете sess.run(...), просто запросите тензор output. Не запрашивайте оптимизационный OP, который вы обычно тренируете. Когда вы запрашиваете эту переменную, тензорный поток выполнит минимальную работу, необходимую для получения значения (например, он не будет беспокоиться о backprop, потерях и все, потому что простой прохождение прямой передачи - это все, что необходимо для вычисления output.

Итак, если вы создаете сервис для возврата к выводам модели, вы захотите сохранить модель, загруженную в память /gpu, и повторите:

sess.run(output, feed_dict={X: input_data})

Вам не нужно будет подавать эти ярлыки, потому что tensorflow не потрудится вычислить операционные системы, которые не нужны для создания запрашиваемого вами результата. Вам не нужно менять свою модель или что-то еще.

Хотя этот подход может быть не столь очевидным, как model.predict(...), я бы сказал, что он намного более гибкий. Если вы начнете играть с более сложными моделями, вы, вероятно, научитесь любить этот подход. model.predict() похож на "мышление внутри коробки".