是否可不安装完整TensorFlow包使用make_tensor_proto方法?
轻量化实现
make_tensor_proto功能的可行方案 不需要安装1.3GB的完整TensorFlow包即可实现同等功能,以下两种方案都可以将依赖体积控制在100MB以内,满足Docker镜像轻量化要求:
方案1:使用精简版TensorFlow Proto依赖
开源社区已经剥离了完整TensorFlow中训练、算子执行、GPU驱动等冗余逻辑,单独打包了仅包含Proto定义和基础序列化工具的轻量包tensorflow-protobuf,安装包体积不到5MB,安装后可以和完整TensorFlow一样直接导入make_tensor_proto方法:
安装命令:pip install tensorflow-protobuf导入方式:
from tensorflow.python.framework.tensor_util import make_tensor_proto该方法的入参、返回值和完整TensorFlow中的实现完全一致,不需要修改原有业务代码。
方案2:自行实现等价转换逻辑,零TensorFlow依赖
make_tensor_proto的本质是将Python原生数值、numpy数组转换为符合TensorFlow接口规范的TensorProto序列化结构,逻辑完全透明,仅依赖numpy和protobuf两个基础包(两者合计体积不到50MB),可以直接用自定义实现替代官方方法,参考代码如下:import numpy as np # 若不想引入任何TF相关依赖,可直接通过protoc编译官方公开的tensor.proto文件得到TensorProto类,单文件无额外依赖 from tensorflow.core.framework.tensor_pb2 import TensorProto # numpy dtype 对应 TF DataType 枚举值映射 _TF_DTYPE_MAP = { np.float32: 1, np.float64: 2, np.int32: 3, np.uint8: 4, np.int16: 5, np.int8: 6, np.str_: 7, np.complex64: 8, np.int64: 9, np.bool_: 10, np.uint16: 17, np.complex128: 18, np.uint32: 22, np.uint64: 23, } def make_tensor_proto(values, dtype=None, shape=None): # 统一转换为numpy数组处理 if not isinstance(values, np.ndarray): values = np.asarray(values) if dtype is not None: values = values.astype(dtype) else: dtype = values.dtype # 处理shape参数 if shape is None: shape = values.shape else: values = values.reshape(shape) tensor_proto = TensorProto() tensor_proto.dtype = _TF_DTYPE_MAP[np.dtype(dtype).type] # 填充shape信息 for dim_size in shape: tensor_proto.tensor_shape.dim.add(size=dim_size) # 根据dtype填充对应的值字段 flatten_vals = values.flatten().tolist() if np.issubdtype(dtype, np.float32) or np.issubdtype(dtype, np.float16): tensor_proto.float_val.extend(flatten_vals) elif np.issubdtype(dtype, np.float64): tensor_proto.double_val.extend(flatten_vals) elif np.issubdtype(dtype, np.int32) or np.issubdtype(dtype, np.int8) or np.issubdtype(dtype, np.int16) or np.issubdtype(dtype, np.uint8) or np.issubdtype(dtype, np.uint16): tensor_proto.int_val.extend(flatten_vals) elif np.issubdtype(dtype, np.int64) or np.issubdtype(dtype, np.uint32) or np.issubdtype(dtype, np.uint64): tensor_proto.int64_val.extend(flatten_vals) elif np.issubdtype(dtype, np.bool_): tensor_proto.bool_val.extend(flatten_vals) elif np.issubdtype(dtype, np.str_) or np.issubdtype(dtype, np.bytes_): tensor_proto.string_val.extend([v.encode("utf-8") if isinstance(v, str) else v for v in flatten_vals]) return tensor_proto如果你使用TensorFlow Serving的REST接口而非gRPC接口,连
TensorProto的构造都可以省略,直接按照接口规范组装包含instances/inputs字段的JSON请求体即可,不需要任何序列化相关依赖。
注意:如果使用自定义实现,需要保证dtype映射和值填充逻辑和官方实现对齐,避免出现类型不匹配的请求错误。
内容的提问来源于stack exchange,提问作者cookiecutter
相关产品推荐
相关产品推荐

