ValueError: None поддерживается только в первом измерении. Тензор «flatbuffer_data» имеет недопустимую форму «[None, None, 1, 512]» - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь преобразовать мою модель тензорного потока (2.0) в облегченный формат тензорного потока. Моя модель имеет два входных слоя следующим образом:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import load_model
from tensorflow.keras.layers import Lambda, Input, add, Dot, multiply, dot 
from tensorflow.keras.backend import dot, transpose, expand_dims
from tensorflow.keras.models import Model

r1 = Input(shape=[None, 1, 512], name='flatbuffer_data') # I want to take a variable amount of 
# 512 float embeddings from my flatbuffer, if the flatbuffer has 4, embeddings then it would
# be inferred as shape=[4, 1, 512], if it has a 100 embeddings, then it is [100, 1, 512].
r2 = Input(shape=[1, 512], name='query_embedding')

#Example code

minus_r1 = Lambda(lambda x: -x, name='invert_value')(r1)
subtracted = add([r2, minus_r1], name='embeddings_diff')

out1 = tf.argsort(subtracted)
out2 = tf.sort(subtracted)

model = Model([r1, r2], [out1, out2])

Затем я делаю некоторые тензорные операции над слоями и сохраняю модели следующим образом (нет обучения и, следовательно, нет обучаемых параметров, только некоторые операции линейной алгебры который я хочу перенести на android)

model.save('combined_model.h5')

Я получаю свою модель tenorflow .h5, но затем, когда я пытаюсь преобразовать ее в тензор потока lite, я получаю следующую ошибку:

import tensorflow as tf
model = tf.keras.models.load_model('combined_model.h5')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

#Error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/aspiring1/.virtualenvs/faiss/lib/python3.6/site-packages/tensorflow_core/lite/python/lite.py", line 446, in convert
    "invalid shape '{1}'.".format(_get_tensor_name(tensor), shape_list))
ValueError: None is only supported in the 1st dimension. Tensor 'flatbuffer_data' has invalid shape '[None, None, 1, 512]'.

Я знаю, что мы имели динамический c и stati c вывод формы в тензорном потоке 1.x с использованием заполнителей тензорного потока. Есть ли здесь аналог в tenorflow 2.x. Кроме того, я был бы признателен за решение в tenorflow 1.x.

Некоторые ответы и блоги, которые я прочитал, могут помочь: Tensorflow: как сохранить / восстановить модель?

Понимание динамических c и stati c форм в тензорном потоке

Понимание тензорных форм

Использование первой ссылки выше Я также попытался создать график tenorflow 1.x и попытался сохранить его в формате saved model, но я не получил желаемых результатов.

Вы можете найти мой код для этого здесь: Тензор потока 1.x суть код

1 Ответ

3 голосов
/ 26 марта 2020

Полный код: https://drive.google.com/file/d/1MN4-FX_-hz3y-UAuf7OTj_XYuVTlsSTP/view?usp=sharing


Почему это не работает?

Я знаю, что у нас были Dynami c и stati c вывод формы в тензорном потоке 1.x с использованием заполнителей тензорного потока. Есть ли здесь аналог в tenorflow 2.x

, который все еще работает нормально. Я думаю, проблема в том, что tf.lite не обрабатывает динамические c фигуры. Я думаю, что он предварительно вычисляет все свои тензоры, один раз и повторно использует их (я могу ошибаться).

Итак, прежде всего это дополнительное измерение:

[None, None, 1, 512]

keras.Input всегда включает размер партии, который tf.lite может обрабатывать, будучи неизвестным (это ограничение кажется ослабленным в tf-nightly).

Но lite, похоже, предпочитает партию размерность 1. Если вы переключитесь на:

r1 = Input(shape=[4], batch_size=None, name='flatbuffer_data')
r2 = Input(shape=[4], batch_size=1, name='query_embedding')

Пропускает преобразование, но все равно не удается, когда вы пытаетесь выполнить модель tflite, потому что модель хочет, чтобы все неизвестные измерения были 1:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

i = tf.lite.Interpreter(model_content=tflite_model)
i.allocate_tensors()
i.get_input_details()

i.set_tensor(0, tf.constant([[0.,0,0,0],[1,1,1,1],[2,2,2,2]]))
i.set_tensor(1, tf.constant([[0.,0,0,0]]))
ValueError: Cannot set tensor: Dimension mismatch. Got 3 but expected 1 for dimension 0 of input 0.

С помощью tf-nightly вы можете преобразовать модель в том виде, в каком вы ее написали, но она также не запускается, поскольку неизвестное измерение считается равным 1:

r1 = Input(shape=[None, 4], name='flatbuffer_data') 
r2 = Input(shape=[1, 4], name='query_embedding')

...

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

i = tf.lite.Interpreter(model_content=tflite_model)
i.allocate_tensors()
print(i.get_input_details())

i.set_tensor(0, tf.constant([[[0.,0,0,0],[1,1,1,1],[2,2,2,2]]]))
i.set_tensor(1, tf.constant([[[0.,0,0,0]]]))
ValueError: Cannot set tensor: Dimension mismatch. Got 3 but expected 1 for dimension 1 of input 0.

Решение? Почти.

Я думаю, вам нужно придать этому массиву размер больше ожидаемого, и передать int, сообщающий вашей модели, сколько элементов нарезать:

n = Input(shape=(), dtype=tf.int32, name='num_inputs')
r1 = Input(shape=[1000, 4], name='flatbuffer_data')
r2 = Input(shape=[4], name='query_embedding')

#Example code
x = tf.reshape(r1, [1000,4])
x = tf.gather(x, tf.range(tf.squeeze(n)))
minus_r1 = Lambda(lambda x: -x, name='invert_value')(x)
subtracted = add([r2, minus_r1], name='embeddings_diff')

out1 = tf.argsort(subtracted, name='argsort')
out2 = tf.sort(subtracted, name="sorted")

model = Model([r1, r2, n], [out1, out2])

Тогда это работает:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

i = tf.lite.Interpreter(model_content=tflite_model)
i.allocate_tensors()

for d in i.get_input_details():
  print(d)

a = np.zeros([1000, 4], dtype=np.float32)
a[:3] = [
          [0.,0,0,0],
          [1,1,1,1],
          [2,2,2,2]]

i.set_tensor(0, tf.constant(a[np.newaxis,...], dtype=tf.float32))
i.set_tensor(1, tf.constant([[0.,0,0,0]]))
i.set_tensor(2, tf.constant([3], dtype=tf.int32))

i.invoke()

print()
for d in i.get_output_details():
  print(i.get_tensor(d['index']))
[[ 0.  0.  0.  0.]
 [-1. -1. -1. -1.]
 [-2. -2. -2. -2.]]
[[0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]]

ОП попробовал это в java интерпретаторе и получил:

java.lang.IllegalArgumentException: Internal error: Failed to apply delegate: Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors.

Так что мы еще не закончили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...