Преобразование объекта генератора в список приводит к ошибке значения - PullRequest
0 голосов
/ 14 мая 2018

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

Я использую Python 2.7, Ubuntu 16.04 и Tensorflow 1.8.0

Вот код, который я изначально использовал для печати объекта генератора:

predict_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy[0]}, y=None, batch_size=1, num_epochs=None, shuffle=False)
prediction_results = classifier.predict(input_fn=predict_input_fn)
print (prediction_results)  

Это приводит к следующему выводу:
<generator object predict at 0x7f2fbdffd460>

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

predict_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy[0]}, y=None, batch_size=1, num_epochs=None, shuffle=False)
prediction_results = classifier.predict(input_fn=predict_input_fn)
print (list(prediction_results))  

Вот ошибка, которую он выдает:

Traceback (most recent call last):
  File "vqa_training.py", line 107, in <module>
    print (list(prediction_results))
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/estimator/estimator.py", line 496, in predict
    features, None, model_fn_lib.ModeKeys.PREDICT, self.config)
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/estimator/estimator.py", line 831, in _call_model_fn
    model_fn_results = self._model_fn(features=features, **kwargs)
  File "vqa_training.py", line 13, in cnn_model_fn
    input_layer = tf.reshape(features["images"], [-1, 200, 200, 3])
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_array_ops.py", line 6113, in reshape
    "Reshape", tensor=tensor, shape=shape, name=name)
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py", line 787, in _apply_op_helper
    op_def=op_def)
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 3392, in create_op
    op_def=op_def)
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1734, in __init__
    control_input_ops)
  File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1570, in _create_c_op
    raise ValueError(str(e))
ValueError: Dimension size must be evenly divisible by 120000 but is 600 for 'Reshape' (op: 'Reshape') with input shapes: [1,200,3], [4] and with input tensors computed as partial shapes: input[1] = [?,200,200,3].

Я полагаю, что число 120000 происходит из-за того, что каждый вход в train_data_numpy является массивом numpy, представляющим изображение с формой (200, 200, 3). 200 * 200 * 3 = 120000.

Почему происходит эта ошибка?

Дополнительная информация, если необходимо: вот полный скрипт Python, который я использую

import numpy as np
import tensorflow as tf
import os
import cv2
from pprint import pprint



# CNN function
def cnn_model_fn(features, labels, mode):

    # define the layers of the cnn
    input_layer = tf.reshape(features["images"], [-1, 200, 200, 3])
    conv_layer = tf.layers.conv2d(inputs=input_layer, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)
    pool_layer = tf.layers.max_pooling2d(inputs=conv_layer, pool_size=[2, 2], strides=2)
    conv_layer_two = tf.layers.conv2d(inputs=pool_layer, filters=64, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)
    pool_layer_two = tf.layers.max_pooling2d(inputs=conv_layer_two, pool_size=[2, 2], strides=2)
    flat_pool_two = tf.reshape(pool_layer_two, [-1, 50 * 50 * 64])
    dense_layer = tf.layers.dense(inputs=flat_pool_two, units=1024, activation=tf.nn.relu)
    logits = tf.layers.dense(inputs=dense_layer, units=2)

   # Generate predictions (for PREDICT and EVAL mode)
    predictions = {
        "classes": tf.argmax(input=logits, axis=1),
        "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
    }

    if mode == tf.estimator.ModeKeys.PREDICT:
        return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

    # Calculate Loss (for both TRAIN and EVAL modes)
    loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

    # Configure the Training Operation (for TRAIN mode)
    if mode == tf.estimator.ModeKeys.TRAIN:
        optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
        train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step())
        return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

    # Add evaluation metrics (for EVAL mode)
    eval_metric_ops = {"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}
    return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)




# Load and process dataset

filenames = []
images = []
unstable = []
labels = []

# load images from folders
for root, dirs, files in os.walk("images/cropped"):  
    for filename in files:
        filenames.append(filename)
for root, dirs, files in os.walk("images/unstable"):  
    for filename in files:
        unstable.append(filename)

# for each image in images, append the corresponding label to labels: 0 means unstable, 1 means stable
for filename in filenames:
    images.append(cv2.imread("images/cropped/"+filename))
    if filename in unstable:
        labels.append(0)
    else:
        labels.append(1)

# separate images and labels into train and test sets - 80% train, 20% evaluate
train_images = images[0:40]
train_labels = labels[0:40]
test_images = images[40:]
test_labels = labels[40:]

# convert dataset into numpy arrays
train_data_numpy = np.array(train_images, np.float32)
train_labels_numpy = np.array(train_labels, np.int32)
test_data_numpy = np.array(test_images, np.float32)
test_labels_numpy = np.array(test_labels, np.int32)



# Put images through CNN to get feature vector

# Create the Estimator
classifier = tf.estimator.Estimator(model_fn=cnn_model_fn, model_dir="temp/cnn")

# Set up logging for predictions
tensors_to_log = {"probabilities": "softmax_tensor"}
logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=1)

# Train the model
train_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy}, y=train_labels_numpy, batch_size=1, num_epochs=None, shuffle=True)
classifier.train(input_fn=train_input_fn, steps=200, hooks=[logging_hook])

# Evaluate the model and print results
eval_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":test_data_numpy}, y=test_labels_numpy, num_epochs=1, shuffle=False)
eval_results = classifier.evaluate(input_fn=eval_input_fn)
print (eval_results)



# Use the CNN model to get predictions
predict_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy[0]}, y=None, batch_size=1, num_epochs=None, shuffle=False)
prediction_results = classifier.predict(input_fn=predict_input_fn)
print (list(prediction_results))

1 Ответ

0 голосов
/ 15 мая 2018

Я нашел решение своей проблемы, хотя точно не знаю , почему это решает ошибку.

Когда я изменил первую строку с:
predict_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy[0]}, y=None, batch_size=1, num_epochs=None, shuffle=False)
чтобы:
predict_input_fn = tf.estimator.inputs.numpy_input_fn(x={"images":train_data_numpy[0:1]}, y=None, batch_size=1, num_epochs=None, shuffle=False)
затем print(list(prediction_results)) распечатал словарь.

Внесенное мной изменение использовало train_data_numpy[0:1] вместо train_data_numpy[0].

...