加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱故事小小网_铜陵站长网 (http://www.0562zz.com/)- 视频终端、云渲染、应用安全、数据安全、安全管理!
当前位置: 首页 > 大数据 > 正文

如何将一个算法模型转换成端智能模型?

发布时间:2022-07-30 12:39:01 所属栏目:大数据 来源:互联网
导读:在开始端智能技术工程实践的介绍前,有一个无法绕过的问题:端上的计算能力到底如何?虽然我们对神经网络运算加速有所耳闻,也知道不同的移动设备有着不同的加速方案,但没有一个定量的分析很难让我们有一个清晰客观的认识。于是,我针对机器学习的 Hellowor
  在开始端智能技术工程实践的介绍前,有一个无法绕过的问题:端上的计算能力到底如何?虽然我们对神经网络运算加速有所耳闻,也知道不同的移动设备有着不同的加速方案,但没有一个定量的分析很难让我们有一个清晰客观的认识。于是,我针对机器学习的 Helloword 项目 Mnist 手写数字识别,做了一个小实验,分别在我的 MacBook Pro 和 iPhone 手机上运行了同样的算法模型,把两侧的训练样本、模型结构、模型参数、训练参数等对齐,最终得出图 1 的结果:面对 60000 个训练样本 10 个 Epoch 在 i7 CPU 的 2015 款 15 寸 MacBook Pro 上需要 128 秒,而在我的 iPhone 13 Pro Max 上只需要 86 秒,这足以证明端上计算能力能够满足我们使用模型进行预测乃至训练模型的计算能力要求。
 
 
  但是,在性能一般的手机终端上,还需要测量算力要求,并针对框架和平台优化算法模型来保证用户体验。这里的算法模型优化由两部分构成,一部分源于算法模型本身的压缩、剪枝、量化、知识蒸馏等,另一部分源于框架自带的工具或 JAX、TVM 第三方工具把算法模型针对性转换成不同平台上优化的模型。第一部分可以从机器学习相关著作里学习,下面着重介绍第二部分,围绕 TensorFlow 机器学习框架提供的工具,以及 iOS 机器学习技术,分别介绍端智能的技术工程基础。
 
  评估和准备算法模型
  在开始评估和准备算法模型之前,先介绍一下前文中 iPhone 13 Pro Max 的处理器。这块儿 A15 处理器采用台积电 5nm 工艺,共集成了 150 亿个晶体管,NPU 性能达到 15.8TOPS。TOPS(Tera Operations Per Second),1TOPS 代表处理器每秒钟可进行一万亿次操作。相对硬件的算力,算法模型的复杂度相对的用算力要求 FLOPs (floating point operations)来评估,指浮点运算计算量, 可以用来衡量算法模型的复杂度。从图 2 中可以得知,算法模型的参数、模型大小、FLOPs 都是用来评估算法模型的指标。由于这几个指标几乎呈现参数规模越大模型越大且算力要求越高的规律,因此,在进行算法模型评估的时候,借助图 1 中 模型参数规模 Total params: 585958 就可以大概评估出模型的算力要求。但是,也必须注意 AlexNet 和 ResNet152 这种参数少却模型大、FLOPs 更高的情况,这主要是由于网络结构、优化器不同等因素造成的。
 
  图片
 
  图 2 常见的算法模型复杂度对比
 
  当然,如果要较为精确的评估来识别模型参数少却对算力要求高的情况,图 1 中的算力要求仅就模型拥有 58 万参数进行估算是不够的,可以用 TensorFlow 的 API 计算出该模型需要的算力为 2.8 MFLOPs 。
 
  复制
  # TensorFlow 推荐计算方法
  from tensorflow.python.framework.convert_to_constants import  convert_variables_to_constants_v2_as_graph
 
  def get_flops(model):
      concrete = tf.function(lambda inputs: model(inputs))
      concrete_func = concrete.get_concrete_function(
          [tf.TensorSpec([1, *inputs.shape[1:]]) for inputs in model.inputs])
      frozen_func, graph_def = convert_variables_to_constants_v2_as_graph(concrete_func)
      with tf.Graph().as_default() as graph:
          tf.graph_util.import_graph_def(graph_def, name='')
          run_meta = tf.compat.v1.RunMetadata()
          opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()
          flops = tf.compat.v1.profiler.profile(graph=graph, run_meta=run_meta, cmd="op", options=opts)
          return flops.total_float_ops
      
  print("The FLOPs is:{}".format(get_flops(model)) ,flush=True )
 
  当然,如果使用 Pytorch 算法框架,则需要对应的工具来帮助我们评估算力要求。
 
  复制
  # 推荐开源工具 pytorch-OpCounter
  from thop import profile
  input = torch.randn(1, 1, 28, 28)
  macs, params = profile(model, inputs=(input, ))
  print('Total macc:{}, Total params: {}'.format(macs, params))
  #输出:Total macc:2307720.0, Total params: 431080.0
  1.
  2.
  3.
  4.
  5.
  6.
  再回到硬件的算力,苹果的 A15 处理器仅 NPU 就具备 15.8 TOPS 的算力,而高通骁龙 855 处理器 CPU+GPU+DSP 叠加的 AI 算力仅有 7 TOPS,可见,要想算法模型可以流畅的在移动端运行,还需要对算法模型进行一些处理,让算法模型可以适配 Android 或 iOS 的硬件加速能力。
 
  转换算法模型到移动端有很多种方法,大体上可以分为框架提供的转换功能和第三方转换工具两种。框架提供的转换功能优点是比较简单,可以直接通过 API 将模型进行转换,缺点是 Runtime 需要依赖于框架提供,而这些 Runtime 之间往往是不兼容的。第三方转换工具相对麻烦一点,为了能够转换不同的工具对模型输入有特殊的要求,输出方面也会有一定的限制,我们先看一下框架提供的转换功能。
 
  全面的介绍所有框架的转换方法超出了本文的范围,我仅以 TensorFlow 提供的转换功能为例,介绍通常情况下转换模型的方法,这些方法在不同框架下大同小异,只需要查找文档中相似功能的 API 即可。
 
  在 TensorFlow 中对模型进行转换主要分两种情况,一种是在调试、训练模型的过程中进行转换,另一种是在框架保存模型后进行转换。这两种情况的区别在于,在调试、训练模型过程中转换更简单和直观,有算子的兼容性等问题可以随时调整,保存后的模型文件转换则不能随时调整模型定义和算子等,但是,保存后的模型文件转换更容易做好工程链路,因为文件作为输入可以把模型训练和模型转换解耦开。我的建议是在端智能项目初期先用框架能力在调试、模型训练过程中转换,然后部署到移动设备上进行测试。
 
  复制
  import tensorflow as tf
 
  # Create a model using high-level tf.keras.* APIs
  model = tf.keras.models.Sequential([
      tf.keras.layers.Dense(units=1, input_shape=[1]),
      tf.keras.layers.Dense(units=16, activation='relu'),
      tf.keras.layers.Dense(units=1)
  ])
  model.compile(optimizer='sgd', loss='mean_squared_error') # compile the model
  model.fit(x=[-1, 0, 1], y=[-3, -1, 1], epochs=5) # train the model
  # (to generate a SavedModel) tf.saved_model.save(model, "saved_model_keras_dir")
 
  # Convert the model.
  converter = tf.lite.TFLiteConverter.from_keras_model(model)
  tflite_model = converter.convert()
 
  # Save the model.
  with open('model.tflite', 'wb') as f:
    f.write(tflite_model)
 
  通过上面的代码,借助 tf.keras 的 API 定义了一个简单的模型,再借助 tf.lite.TFLiteConverter 将 Keras 模型转换成 TFLite 模型,最终保存成 .tflite 后缀的模型文件,我们的模型准备工作就初步完成了。
 
  如果要把算法模型文件转换成 TFLite 用 TensorFlow 提供的命令行工具即可。
 
  复制
  # 转换 SaveModel 文件
  python -m tflite_convert
    --saved_model_dir=/tmp/mobilenet_saved_model
    --output_file=/tmp/mobilenet.tflite
  # 转换 H5 格式模型文件
  python -m tflite_convert
    --keras_model_file=/tmp/mobilenet_keras_model.h5
    --output_file=/tmp/mobilenet.tflite
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  第一个参数是原模型文件的输入路径,第二个参数是转换后 TFLite 模型的输出路径。
 
  由于 TensorFlow 框架在转换过程中做了一定的优化,因此,模型的 TOPs 也从 2.8 MFLOPs 降低到 1.8 MFLOPs。这里对 TFLite 模型算力评估使用了开源工具 tflite_flops ,按照下面的示例安装和使用即可。
 
  复制
  # 安装
  pip3 install git+https://github.com/lisosia/tflite-flops
  # 使用
  python -m tflite_flops model.tflite
  # 结果
  OP_NAME            | M FLOPS
  ------------------------------
  CONV_2D            | 0.4
  MAX_POOL_2D        | <IGNORED>
  CONV_2D            | 1.2
  MAX_POOL_2D        | <IGNORED>
  RESHAPE            | <IGNORED>
  FULLY_CONNECTED    | <IGNORED>
  FULLY_CONNECTED    | <IGNORED>
  SOFTMAX            | <IGNORED>
  ------------------------------
  Total: 1.6 M FLOPS
 
  本质上端智能用到的模型是从台式机、服务器上训练的模型转换过来的,这种转换在不同的移动端和边缘设备上是不同的,这就造成了转换的复杂性。
 
  ONNX 作为开放神经网络交换标准,对不同框架和不同的移动端、边缘设备 Runtime 进行了标准化,从而降低了模型在不同框架和不同 Runtime 之间转换的成本,现在主流的框架和设备都支持 ONNX。

(编辑:我爱故事小小网_铜陵站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读