评分并提供意见反馈 :
华为采用机器翻译与人工审校相结合的方式将此文档翻译成不同语言,希望能帮助您更容易理解此文档的内容。 请注意:即使是最好的机器翻译,其准确度也不及专业翻译人员的水平。 华为对于翻译的准确性不承担任何责任,并建议您参考英文文档(已提供链接)。
样例参考
使用在线推理需要充分考虑到sess.run首次执行时需要对模型进行编译和优化,耗时会增多。在编写推理应用时,应尽量保证应用生命周期内不频繁初始化。本例中,我们使用将推理过程封装到Classifier类中,以便应用可以控制Classifier对象的生命周期。
样例代码sample_resnet50.py:
# 通过加载已经训练好的pb模型,执行推理 import numpy as np import time import tensorflow as tf from tensorflow.core.protobuf.rewriter_config_pb2 import RewriterConfig import cv2 from npu_bridge.estimator import npu_ops import glob # 用户自定义模型路径、输入、输出 image_path = '../data/image/*.jpg' model_path = '../model/resnet_v1_50.pb' input_tensor_name = 'input:0' output_tensor_name = 'resnet_v1_50/predictions/Softmax:0' input_shape = (224, 224, 3) # (height, width, channel) CHANNEL_MEANS = [123.68, 116.78, 103.94] # (R, G, B) class Classifier(object): # 定义模型的batch_size规格 batch_size = 4 def __init__(self): # 昇腾AI处理器模型编译和优化配置 # -------------------------------------------------------------------------------- config = tf.ConfigProto() custom_op = config.graph_options.rewrite_options.custom_optimizers.add() custom_op.name = "NpuOptimizer" # 配置1: 选择在昇腾AI处理器上执行推理 custom_op.parameter_map["use_off_line"].b = True # 配置2:在线推理场景下建议保持默认值force_fp16,使用float16精度推理,以获得较优的性能 custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("force_fp16") # 配置3:图执行模式,推理场景下请配置为0,训练场景下为默认1 custom_op.parameter_map["graph_run_mode"].i = 0 # 配置4:关闭remapping config.graph_options.rewrite_options.remapping = RewriterConfig.OFF # -------------------------------------------------------------------------------- # 加载模型,并指定该模型的输入和输出节点 self.graph = self.__load_model(model_path) self.input_tensor = self.graph.get_tensor_by_name(input_tensor_name) self.output_tensor = self.graph.get_tensor_by_name(output_tensor_name) # 由于首次执行session run会触发模型编译,耗时较长,可以将session的生命周期和实例绑定 self.sess = tf.Session(config=config, graph=self.graph) def __load_model(self, model_file): """ 加载用于推理fronzen graph模型 如果加载其他的类型的模型文件(saved model/check point),可按照对应类型的加载方法 :param model_file: :return: """ with tf.gfile.GFile(model_file, "rb") as gf: graph_def = tf.GraphDef() graph_def.ParseFromString(gf.read()) with tf.Graph().as_default() as graph: tf.import_graph_def(graph_def, name="") return graph def do_infer(self, batch_data): """ 执行推理, 推理输入的shape必须保持一致 :param image_data: :return: """ out_list = [] for data in batch_data: out = self.sess.run(self.output_tensor, feed_dict={self.input_tensor: data}) out_list.append(out) return out_list def batch_process(self, image_data): """ 图像预处理,加载数据集 :return: """ # 获取当前输入数据的batch信息,将数据自动调整到固定batch n_dim = image_data.shape[0] batch_size = self.batch_size # 如果尾部的数据不足整batch,则需要补齐数据 m = n_dim % batch_size if m < batch_size: # 不足部分按照N维度,补0 pad = np.zeros((batch_size - m, 224, 224, 3)).astype(np.float32) image_data = np.concatenate((image_data, pad), axis=0) # 定义本次数据可以分几个批次的mini_batch mini_batch = [] i = 0 while i < n_dim: # 将image_data切分为多个mini batch mini_batch.append(image_data[i: i + batch_size, :, :, :]) i += batch_size return mini_batch def image_preprocces(image_path): ''' 将jpeg图像,加工为可以进行推理的数据224*224*3。 处理步骤:1、图像解码、2、图像resize 3、图像crop(Central Crop) 3、图像归一化 4、image2tensor 说明:图像预处理采用opencv,本例不代表最优处理方式,请根据模型实际的数据预处理逻辑进行处理,样例仅供参考 :return: ''' fpath = glob.glob(image_path) images = [] for image_file in fpath: bgr_img = cv2.imread(image_file) if len(bgr_img.shape) != 3: continue # 默认为BGR,转换为RGB img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB) img = img.astype(np.float32) img = image_resize(img, 256) img = central_crop(img) img = mean_normalize(img) images.append(img) images_array = np.array(images) return images_array def image_resize(image, target_size): ''' 可以先采样到256 :param image: :param target_size: :return: ''' height, width, _ = np.shape(image) if target_size is None: target_size = 256 if height < width: size_ratio = target_size / height else: size_ratio = target_size / width resize_shape = (int(width * size_ratio), int(height * size_ratio)) return cv2.resize(image, resize_shape) def mean_normalize(image): ''' 对单张图片做减均值 :param image: :return: ''' return image - CHANNEL_MEANS def central_crop(image): ''' 从目标图像中心crop 224*224的图像 :param image: :return: ''' height, width, _ = np.shape(image) target_h, target_w, _ = input_shape amount_to_be_cropped_h = (height - target_h) amount_to_be_cropped_w = (width - target_w) crop_y = amount_to_be_cropped_h //2 crop_x = amount_to_be_cropped_w //2 return image[crop_y: crop_y + target_h, crop_x: crop_x + target_h, :] if __name__ == '__main__': images = image_preprocces(image_path) classifier = Classifier() batch_images = classifier.batch_process(images) start_time = time.time() labels_list = classifier.do_infer(batch_images) end_time = time.time() print("cost time:", end_time - start_time) # lables shape is [n, 1000] for labels in labels_list: # 取出每个图片对应的Label向量(1000,) for label in labels: # Do something whatever you want print(label)
用户可以通过创建run_model.sh,添加环境变量配置所示的环境变量来执行sample_resnet50.py。