2017-05-25 3 views
0

Je modifie un CNN simple dans Tensorflow et lorsque j'indexe un tableau 4d, j'obtiens cette erreur. Mon exemple reproductible est:Tensorflow Erreur lors de l'indexation d'un tableau 4D: ValueError: Les formes doivent être de rang égal, mais sont 1 et 0

from __future__ import print_function 
import pdb 
import numpy as np 
import tensorflow as tf 
from tensorflow.examples.tutorials.mnist import input_data 

def weight_variable(shape): 
    initial = tf.truncated_normal(shape, stddev=0.1) 
    return tf.Variable(initial) 

def bias_variable(shape): 
    initial = tf.constant(0.1, shape=shape) 
    return tf.Variable(initial) 

def conv2d(x, W, stride=1): 
    return tf.nn.conv2d(x, W, strides=[1, stride, stride, 1], padding='SAME') 

def max_pool_2d(x, k=10): 
    return tf.nn.max_pool(x, ksize=[1, k, k, 1], 
               strides=[1, k, k, 1], padding='SAME') 


indices = np.array([[0, 1], [5, 2],[300, 400]]).astype(np.int32) 

input_updatable = weight_variable(shape=[1, 1200, 600, 100]) 

# Convolutional layer 1 
W_conv1 = weight_variable([5, 5, 100, 100]) 
b_conv1 = bias_variable([100]) 

h_conv1 = tf.nn.relu(conv2d(input_updatable, W_conv1) + b_conv1) 
h_pool1 = max_pool_2d(h_conv1) 

# Convolutional layer 2 
W_conv2 = weight_variable([5, 5, 100, 100]) 
b_conv2 = bias_variable([100]) 

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) 
h_pool2 = max_pool_2d(h_conv2) 

#extract vectoris based on input 
l1_vecs = input_updatable[0, indices[:, 0], indices[:, 1], :] 



# Training steps 
with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 

    max_steps = 1000 
    for step in range(max_steps): 
     l1 = sess.run(l1_vecs) 
     pdb.set_trace() 

Ce code génère l'erreur suivante:

l1_vecs = input_updatable[0, indices[:, 0], indices[:, 1], :] 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 722, in _SliceHelperVar 
    return _SliceHelper(var._AsTensor(), slice_spec, var) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 480, in _SliceHelper 
    stack(begin), stack(end), stack(strides)) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 824, in stack 
    return gen_array_ops._pack(values, axis=axis, name=name) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/ops/gen_array_ops.py", line 2041, in _pack 
    result = _op_def_lib.apply_op("Pack", values=values, axis=axis, name=name) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/op_def_library.py", line 763, in apply_op 
    op_def=op_def) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 2329, in create_op 
    set_shapes_for_outputs(ret) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1717, in set_shapes_for_outputs 
    shapes = shape_func(op) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1667, in call_with_requiring 
    return call_cpp_shape_fn(op, require_shape_fn=True) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/common_shapes.py", line 610, in call_cpp_shape_fn 
    debug_python_shape_fn, require_shape_fn) 
    File "/home/arahimi/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/common_shapes.py", line 676, in _call_cpp_shape_fn_impl 
    raise ValueError(err.message) 
ValueError: Shapes must be equal rank, but are 1 and 0 
     From merging shape 2 with other shapes. for 'strided_slice/stack_1' (op: 'Pack') with input shapes: [], [3], [3], []. 

Notez que lorsque j'extraire les valeurs de input_updatable avec:

ip = sess.run(input_updatable) 

alors je peux l'indexer utilisant:

l1_vecs = input_updatable[0, indices[:, 0], indices[:, 1], :] 

Je ne suis pas sûr de la raison.

+1

avez-vous essayé d'utiliser tf.gather_nd() ?? https://www.tensorflow.org/api_docs/python/tf/gather_nd – hars

+0

comme @hars mentionné tf.gather_nd() fonctionne. TF ne supporte pas l'indexation avancée de numpy, j'ai donc dû changer les index en une matrice 3D pour indexer input_updatable. – Ash

Répondre

0

Si vous avez une variable comme suit dans tensorflow:

input_updatable = weight_variable(shape=[1, 1200, 600, 100]) 

et vous avez des indices, un tableau 2D avec la taille Nx2 qui indexe input_updatable en sortie, un tableau NX100 à numpy, vous pouvez le faire par:

input_updatable[0, Indices[:, 0], Indices[:, 1], :] 

Je pense que vous pourriez aussi le faire dans Theano. Mais Tensorflow ne prend pas en charge l'indexation avancée, vous devrez donc utiliser tf.gather_nd().

Vous devez d'abord convertir les 2d indices en 3d en ajoutant un colonne à toutes les lignes par:

# create a zero column to index into the first dimension of input_updatable 
zz = np.zeros(shape=(Indices.shape[0], 1), dtype=np.int32) 
#then attach this vector to 2d matrix Indices (Nx2) to create a 3d (Nx3) matrix where the first column is zero. 
Indices = np.hstack((zz, Indices)) 
#then use gather_nd 
output = tf.gather_nd(input_updatable, Indices) 

où la production est une matrice NX100.

+1

Bon de savoir que cela a fonctionné. J'espère que vous avez vérifié les valeurs de la sortie. – hars

+0

Oui, vérifié, c'est correct. Merci @hars. – Ash