Python 如何在tensorflow中解析张量而不给出_类型?

Python 如何在tensorflow中解析张量而不给出_类型?,python,tensorflow,serialization,Python,Tensorflow,Serialization,解析序列化张量时,tf.io.parse\u张量具有所需的kwarg“out\u类型”。然而,tf似乎确实需要知道序列化张量的类型,因为当一个人给出错误的类型时,它会设法打印出好的类型 没有这个参数我怎么能解析呢 MWE: tf.io.parse_tensor(tf.io.serialize_tensor(tf.constant([1])),tf.int32) 解析张量(tf.io.serialize张量(tf.constant([1])) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在

解析序列化张量时,
tf.io.parse\u张量
具有所需的kwarg“out\u类型”。然而,tf似乎确实需要知道序列化张量的类型,因为当一个人给出错误的类型时,它会设法打印出好的类型

没有这个参数我怎么能解析呢

MWE:

tf.io.parse_tensor(tf.io.serialize_tensor(tf.constant([1])),tf.int32)
解析张量(tf.io.serialize张量(tf.constant([1]))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:parse_tensor()缺少1个必需的位置参数:“out_type”
解析张量(tf.io.serialize张量(tf.constant([1])),tf.float32)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/Users/clementwart/.pyenv/versions/keras_fsl/lib/python3.6/site packages/tensorflow/python/ops/gen_parsing_ops.py”,第2160行,在parse_tensor中
_操作。从“不正常”状态(e,名称)提升
文件“/Users/clementwart/.pyenv/versions/keras_fsl/lib/python3.6/site packages/tensorflow/python/framework/ops.py”,第6653行,处于“从非正常状态提升”
六、将_从(核心状态)提升到_异常(例如代码、消息),无
文件“”,第3行,从
tensorflow.python.framework.errors\u impl.InvalidArgumentError:解析的张量(int32)和数据类型(float)之间的类型不匹配[Op:ParseTensor]
编辑:

我想出了一种“黑客”解决方案,可以读取不同类型的张量,将它们转换为给定的类型,并使用
@tf.function
(有趣的是,没有
@tf.function
,它就无法工作)。其思想是读取
TensorProto
消息的第二个字节,该字节应指示数据类型,然后制作
tf.switch\u case
以从一系列可能的源数据类型转换。以下是它的工作原理:

将tensorflow导入为tf
#可以使用的不同数据类型集
整数类型=冻结集({tf.bool,tf.uint8,tf.uint16,tf.uint32,tf.uint64,
tf.int8、tf.int16、tf.int32、tf.int64})
FLOAT_DTYPES=frozenset({tf.float16,tf.bfloat16,tf.float32,tf.float64})
复杂类型=冻结集({tf.complex64,tf.complex128})
实型=整数型|浮点型
数字类型=真实类型|复杂类型
@功能
def parse_tensor_cast(tensor_proto,out_dtype,可能的_dtypes=REAL_dtypes):
#备枝
分支={}
dtype_idx=[0]*128
对于i,枚举中的数据类型(可能的类型):
dtype_idx[dtype.as_datatype_enum]=i
分支[i]=lambda:tf.dtypes.cast(
tf.io.parse_tensor(tensor_proto,dtype),out_dtype)
dtype_idx=tf.constant(dtype_idx,tf.int32)
#提取数据类型字节(解决方案的“黑客”部分)
dtype_code=tf.strings.substr(张量_proto,1,1)
dtype_num=tf.io.decode_raw(dtype_代码,tf.uint8)[0]
dtype\u num\u idx=dtype\u idx[tf.dtypes.cast(dtype\u num,tf.int32)]
#开关操作
返回tf.switch\u case(dtype\u num\u idx,分支)
#试验
序列化的_张量=[
tf.io.serialize_张量(tf.constant([1,2,3],tf.int32)),
tf.io.serialize_张量(tf.constant([1,2,3],tf.float64))
]
对于序列化_张量中的t:
打印(解析张量转换(t,tf.float32))
# [1 2 3]
# [1 2 3]

不幸的是,你不能跳过这个论点。如果只有急切模式,则不需要该模式,但如果您希望“图形化”此操作(例如在
@tf.function
中),则需要在实际解析发生之前提前知道数据类型

如果您只对“渴望”模式感兴趣,那么解决此问题并不困难:

将numpy导入为np
导入tensorflow作为tf
输入张量=tf.常数([1,2,3],tf.int32)
#一个标量tf.string张量,包含序列化的输入_张量
serialized_tensor=tf.io.serialized_tensor(输入_tensor)
#从序列化的\u tensor内容创建TensorProto
tensor_proto=tf.core.framework.tensor_pb2.TensorProto()
tensor_proto.ParseFromString(序列化的_tensor.numpy())
#在这一点上,这相当于tf.make_tensor_proto
tf.make_tensor_proto(输入_tensor)
#从tensor_proto读回数据
tensor_parsed=tf.io.parse_tensor(序列化的_tensor.numpy(),
tf.dtypes.as\u dtype(张量\u原型dtype))
断言相等(输入张量,解析张量)
#您也可以直接从提取的消息创建张量
numpy_parsed=tf.make_ndarray(张量原)
np.testing.assert_array_equal(input_tensor.numpy(),numpy_解析)

非常好的答案,谢谢。我刚刚编辑了这个片段,希望能澄清一下bit@ClementWalter我为使用
@tf.function
的问题添加了一种“技巧”解决方案。老实说,我认为开发人员可以以更好的方式向库中添加类似的便利函数。。。