Android 端智能技术案例—数字左右手识别 | 青训营笔记

1,674 阅读5分钟

这是我参与「第四届青训营 」笔记创作活动的的第11天

一、前言

今天学习到的是Android 客户端专场 学习资料二】第四届字节跳动青训营中的Android的第六节:端智能技术演进与实践,根据学习资料中的内容和本节课的学习,将本文提供的两个案例——手写数字识别和左右手识别进行案例分析,达到巩固本节课的学习,其理论知识的总结笔记可以参考Android 智能技术演进与实践 | 青训营笔记

本节课案例实现效果图: 手写数字识别: image.png

image.png

左右手识别:

image.png

二、本节课知识点大纲:

- 手写数字识别

实现思路

  • 分三个步骤

    • 首先,把问题描述和定义清楚,并调研出通过机器学习解决问题的方法。
    • 然后,设计和训练出机器学习模型,并针对端侧设备优化和转换模型。
    • 最后,把优化后模型部署和集成到端侧设备应用中,执行推理预测,并以进预测结果解决定义的问题。

方案

  • 方案:

    • 训练一个可以识别手写数字的机器学习模型。
    • 将此模型部署应用到App中,实现手写输入到识别的过程,并将识别结果供给用户选择输入。
  • 机器学习部分:

    • 输入:手写输入数字(图片)
    • 输出:其可能代表的数字数值,多种可能时给出各自置信度(0.0~1.0)。

训练AI模型

数据收集
  • 数据收集来源方式

    • 人工收集和标注的数据 (本次模型训练仅使用此种方式)

      • 设计和实际需求贴合的一个数据采集程序
      • 兼顾不同年龄段、性别、左手/右手等

TensorFlow模型设计与训练

模型设计和训练

  • 模型设计 环境核心:matplotlib numpy Pillow tensorflow torch torchvision

image.png

  • 模型训练

    • 模型Summary

    image.png

    • 模型训练

    • # 全连接网络
      def creat_nn(print_summary=False):
          model = Sequential()
          model.add(layers.Flatten(input_shape=(28, 28)))
          model.add(layers.Dense(128, activation='relu'))
          model.add(layers.Dropout(0.2))
          model.add(layers.Dense(10, activation='softmax'))
          model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
          if print_summary:
              model.summary()
          return model
        
      train_x = X
      # 将label转成向量,如 2 => [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
      train_y = tf.keras.utils.to_categorical(Y, num_classes=10)
      model.fit(train_x, train_y, batch_size=24, epochs=16, verbose=1)
      

      image.png

    • 验证模型准确度

    • y_pred = model.predict(valid_x)
      // 用y_pred预测值与真值对比,计算准确度
      
模型压缩和转换
  • 为什么要做模型转换?

    • 移动端使用的是被优化的推理引擎,可以在不同CPU和GPU架构下高效的执行模型推理计算。
  • 这里我们使用Tensorflow Lite作为移动端上推理引擎。

    • TensorFlow Lite 的设计旨在在各种设备上高效执行模型。这种高效部分源于在存储模型时,采用了一种特殊的格式。
    • TensorFlow模型在被TensorFlow Lite 使用前,必须转换成这种格式。
    • Tensorflow Lite 提供转换器 TFLite Convert
    • #save tflite model
      converter = tf.lite.TFLiteConverter.from_keras_model(model)
      tflite_model = converter.convert()
      open(tflite_name, "wb").write(tflite_mode
      
模型部署到移动端
  • 核心:让移动端可以加载到前面转化的模型

    • 简单做法:放在App包体内assets目录下

image.png

  • 加载模型

    • var model: ByteBuffer = load(mymodel.tflite)
      val interpreter = Interpreter(model, options)
      // 可通过 interpreter 查看输入和输出格式
      // inputShape:[1, 28, 28], outputShape:[1, 10]
      
      
  • 构造模型输入

    • 模型的输入28x28单通道灰度图,而用手写输入是数据是存在bitmap中
    • 需要将bitmap图片 resize 缩放到28x28像素,转灰度,再转成bytebuffer,这是 interpreter 接受的输入格式。
  • 执行推理预测

    • 构造输出buffer,调用run执行计算
    • val result = Array(1)  { FloatArray(10)  } // outputShape:[1, 10] 
      interpreter.run(inputByteBuffer,result)
      
      
  • 获取推理预测结果

    • result中的10个数值代表手写输入是 0~9 这10个数字置信度分值,对分值进行排序,把排序前三的数字作为预测输出,供用户选择。

小结

  • 一个端智能案例的落地套路流程

四、左右手智能识别和应用:

训练AI模型

数据收集
  • 数据格式:

    • X样本:[p0, p1, p2, p3, p4, … ] ,p=(x, y, w, h, density, dt)。
    • Y样本:left / right
  • 收集方式:(特殊客户端,内测用户收集)

    • 滑动轨迹:拦截Activity的dispatchTouchEvent

    • 事件,缓存手指滑动产生的MotionEvent序列。

    • 左右手标签:

      • 开启左手样本收集时,只用左手持机操作,只录制左手滑动数据。
      • 开启右手样本收集时,只用右手持机操作,只录制右手滑动数据。

模型设计

  • 二分类模型( Left or Right ),卷积神经网络。

# 卷积神经网络
def creat_cnn(input_shape=(9, 6), print_summary=False):
    model = Sequential()
    model.add(layers.Conv1D(6, kernel_size=3, input_shape=input_shape, padding='same', activation='relu'))
    model.add(layers.Conv1D(12, kernel_size=3, padding='same', activation='relu'))
    model.add(layers.Conv1D(24, kernel_size=3, strides=2, padding='same', activation='relu'))
    model.add(layers.Flatten())
    model.add(layers.Dense(128, activation='relu'))
    model.add(layers.Dense(64, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    if print_summary:
        model.summary()
    return model

模型训练和转换

  • 训练样本处理

    • 滑动轨迹X样本需要采样对齐成9个固定点输入方式
    • def getX(points):
          size = len(points)
          if size < 6 : # 过滤误触
              return None
          sample_count = 9
          tensor_size = 6
          step = size * 1.0 / sample_count
          x = []
          for i in range(sample_count):
              p = points[int(i*step)]
              if len(p) == 6:
                  x.append(p) # x, y, w, h, density, dtime
          return x
      
      
  • 模型训练

image.png

  • 验证模型准确度

image.png

端智能工程师进阶

入门

  • 达成:对端智能技术有一定认识,可以协作完成端智能技术的需求落地

    • 了解端智能技术是什么、可以做什么
    • 掌握移动端开发、Machine Learning 基础知识,了解业内端智能框架
    • 理解怎么做端智能,可以协作完成端智能技术解决实际业务问题的需求落地

进阶

  • 达成:对移动端技术、端智能技术和负责业务有更深入的理解,可以站在更全面的视野上设计端上智能解决方案,建设端上智能架构。

引用参考:

课外补充引用:

文章学习来源:

感谢以上作者的文章,今天的学习收获满满!!Thanks and HappyCoding!