**欢迎大家前往[腾讯云+社区](https://cloud.tencent.com/developer/?fromSource=waitui),获取更多腾讯海量技术实践干货哦~**
> 本文由[未来守护者](https://cloud.tencent.com/developer/user/1637280)发表于[云+社区专栏](https://cloud.tencent.com/developer/column/2417?fromSource=waitui)
本项目探讨如何将机器学习(Machine learning)应用到物联网(IoT,Internet of Things)中。我们将使用 **Android Things** 作为我们的物联网平台,并且采用 **Google TensorFlow** 作为我们的机器学习引擎。如今,机器学习与物联网都是技术话题中的大热门。下面是[维基百科上对机器学习的一个简单定义](https://en.wikipedia.org/wiki/Machine_learning):
机器学习是计算机科学中的一个领域,它使计算机系统能够利用数据进行 “学习”(即逐步提高特定任务的性能),而不需要进行显式编程(Explicitly programmed)。
换句话说,在进行训练步骤以后,系统就可以预测结果(即使这不是专门为这些结果进行编程的)。另一方面,我们都了解物联网以及连接设备的概念。最有前途的话题之一便是如何将机器学习应用于物联网之中,以构建能够 “学习” 的专家系统。此外,该系统会运用这些知识来控制和管理实物。
下面列举一些应用到机器学习,以及物联网能产生重要价值的领域:
- 预测维护(Predictive maintenance)中的工业物联网(IIoT,Industrial IoT)。
- 在消费者物联网(Consumer IoT)中,机器学习可以使设备变得更加智能化,从而适应我们的习惯。
在本教程中,我们将探索如何使用 Android Things 和 TensorFlow 将机器学习应用到物联网中。这一 Android Things 物联网项目背后的基本思想就是,探索如何构建一个能够识别一些基本形状(比如箭头)并被控制的机器人小车(Robot car)。我们已经介绍过[如何使用 Android Things 构建机器人小车](https://www.survivingwithandroid.com/2017/12/building-a-remote-controlled-car-using-android-things-gpio.html),我建议您在开始此项目之前先阅读那篇教程。
本次机器学习和物联网项目主要涵盖以下主题:
- 如何使用 Docker 配置 TensorFlow 环境
- 如何训练 TensorFlow 系统
- 如何集成 TensorFlow 与 Android Things
- 如何使用 TensorFlow 输出结果来控制机器人小车
本项目衍生自 [Android Things TensorFlow 图像分类器](https://github.com/androidthings/sample-tensorflow-imageclassifier)。
我们开始吧!
## 如何在 Tensorflow 中创建一个图像分类器
在开始之前,我们有必要先安装并配置好 TensorFlow 环境。我并非机器学习专家,所以我需要找一些速成的东西并准备好使用,以便我们可以构建 TensorFlow 图像分类器。因此,我们可以使用 Docker 来运行一个搭载了 TensorFlow 的映像。照着以下步骤进行:
\1. 克隆 TensorFlow 仓库:
```makefile
git clone https://github.com/tensorflow/tensorflow.git
cd /tensorflow
git checkout v1.5.0
```
\2. 创建一个目录(/tf-data),该目录将保存我们在项目中需要用到的所有文件。
\3. 运行 Docker:
```makefile
docker run -it \
--volume /tf-data:/tf-data \
--volume /tensorflow:/tensorflow \
--workdir /tensorflow tensorflow/tensorflow:1.5.0 bash
```
使用这些命令,我们就可以运行一个交互式 TensorFlow 环境并增加(Mount)一些我们将在项目中使用到的目录。
### 如何训练 TensorFlow
在 Android Things 系统能够识别图像之前,我们有必要先训练 TensorFlow 引擎,以构建其模型。以此为由,收集一些图片是有必要的。如前所述,我们希望使用箭头来控制 Android Things 机器人小车 —— 所以我们必须收集至少四种类型的箭头:
- 向上箭头
- 向下箭头
- 左箭头
- 右箭头
为训练该系统,我们有必要对这四种不同的图像类别创建一个“知识库”。在 /tf-data 中一个名为 images 的目录下创建四个目录,命名如下:
- up-arrow
- down-arrow
- left-arrow
- right-arrow
现在是时候去搜集图像资源了。我使用的是 Google 图片搜索,您也可以使用其他方法进行搜集。为了简化图片下载过程,您应该安装 Chrome 插件,它能够一键下载所有图片。可别忘了,您下载的图像越多,其训练过程(Training process)越好(即使创建模型的时间可能会有所增加)。
打开浏览器,开始查找以下四类图像:
![img](https://ask.qcloudimg.com/http-save/1206219/gh5a6f2ml9.png?imageView2/2/w/1620)
每个类别我分别下载了 80 张图。我并不关心图片的扩展。
一旦所有类别都有其图像,请按照以下步骤操作(在 Docker 界面中):
```makefile
python /tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=tf_files/bottlenecks \
--how_many_training_steps=4000 \
--output_graph=/tf-data/retrained_graph.pb \
--output_labels=/tf-data/retrained_labels.txt \
--image_dir=/tf-data/images
```
这操作可能需要花费一些时间,所以要耐心等待。最后,在你的文件夹 /tf-data 中应有两个文件:
1. retrained_graph.pb
2. retrained_labels.txt
第一个文件包含我们的模型,这是 TensorFlow 训练过程的结果。而第二个文件则包含了与我们的四个图像类别相关的标签。
### 如何测试 Tensorflow 模型
如果你想测试模型,以检查一切是否正常,你可以使用以下命令:
```makefile
python scripts.label_image \
--graph=/tf-data/retrained-graph.pb \
--image=/tf-data/images/[category]/[image_name.jpg]
```
### 优化模型
在能够使用这个 TensorFlow 模型到 Android Things 项目中之前,我们有必要优化它:
```js
python /tensorflow/python/tools/optimize_for_inference.py \
--input=/tf-data/retrained_graph.pb \
--output=/tf-data/opt_graph.pb \
--input_names="Mul" \
--output_names="final_result"
```
这就是我们的模型。我们将使用此模型将机器学习应用于物联网(即集成 Android Things 与 TensorFlow)。其目标是为 Android Things 应用提供智能识别箭头图像,并作出相应反应,从而控制机器人小车的方向。
如果您想了解更多关于 TensorFlow 的细节,以及如何生成模型,请查看官方文档和[这个教程](https://codelabs.developers.google.com/codelabs/tensorflow-for-poets/#0)。
## 如何使用 Android Things 和 TensorFlow 将机器学习应用到物联网中
一旦 TensorFlow 数据模型准备就绪,我们就可以进入下一步:如何集成 Android Things 与 TensorFlow。为达成这一目的,我们可以将此任务分为两步:
1. 硬件部分,我们将电机和其他外围设备(Peripheral)连接到 Android Things 板上
2. 实现应用程序
### Android Things 原理图
在深入探讨如何连接外围设备之前,我们先看看下面这个 Android Things 项目中使用的组件列表:
1. Android Things 板(树莓派 3,Raspberry Pi 3)
2. 树莓派相机
3. 一个 LED 灯
4. LN298N 双H桥(用以控制电机)
5. 带两个轮子的机器人小车底盘
我不在此介绍[如何使用 Android Things 控制电机,](https://www.survivingwithandroid.com/2017/12/building-a-remote-controlled-car-using-android-things-gpio.html)因为我们已经在之前的文章中介绍过这一点。
以下是原理图:
![img](https://ask.qcloudimg.com/http-save/1206219/yzl88a3ezn.png?imageView2/2/w/1620)
上图中,相机组件并未表现出来。其最终的结果如下:
![img](https://ask.qcloudimg.com/http-save/1206219/hfsycfxf3i.jpeg?imageView2/2/w/1620)
### 基于 TensorFlow 实现 Android Things App
最后一步便是实现 Android Things 应用程序。为此,我们可以重用 GitHub 上名为[ TensorFlow 图像分类器示例](https://github.com/androidthings/sample-tensorflow-imageclassifier)的示例项目。在开始之前,先克隆 GitHub 仓库,以便您可以修改源代码。
该 Android Things 应用与原来的应用有所不同,在于:
1. 它不使用按钮来启动相机捕捉图像
2. 它使用不同的模型
3. 它使用一个闪烁的 LED 进行通知,摄像机在 LED 停止闪烁后拍摄照片
4. 它在 TensorFlow 检测到图像(箭头)时控制电机。此外,在从步骤 3 开始循环之前,先打开电机 5 秒
要处理闪烁的 LED,请使用以下代码:
```js
private Handler blinkingHandler = new Handler();
private Runnable blinkingLED = new Runnable() {
@Override
public void run() {
try {
// If the motor is running the app does not start the cam
if (mc.getStatus())
return ;
Log.d(TAG, "Blinking..");
mReadyLED.setValue(!mReadyLED.getValue());
if (currentValue <= NUM_OF_TIMES) {
currentValue++;
blinkingHandler.postDelayed(blinkingLED,
BLINKING_INTERVAL_MS);
}
else {
mReadyLED.setValue(false);
currentValue = 0;
mBackgroundHandler.post(mBackgroundClickHandler);
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
```
当 LED 停止闪烁时,应用程序将捕获图像。
现在有必要关注如何根据检测到的图像来控制电机。修改方法如下:
```js
@Override
public void onImageAvailable(ImageReader reader) {
final Bitmap bitmap;
try (Image image = reader.acquireNextImage()) {
bitmap = mImagePreprocessor.preprocessImage(image);
}
final List<Classifier.Recognition> results =
mTensorFlowClassifier.doRecognize(bitmap);
Log.d(TAG,
"Got the following results from Tensorflow: " + results);
// Check the result
if (results == null || results.size() == 0) {
Log.d(TAG, "No command..");
blinkingHandler.post(blinkingLED);
return ;
}
Classifier.Recognition rec = results.get(0);
Float confidence = rec.getConfidence();
Log.d(TAG, "Confidence " + confidence.floatValue());
if (confidence.floatValue() < 0.55) {
Log.d(TAG, "Confidence too low..");
blinkingHandler.post(blinkingLED);
return ;
}
String command = rec.getTitle();
Log.d(TAG, "Command: " + rec.getTitle());
if (command.indexOf("down") != -1)
mc.backward();
else if (command.indexOf("up") != -1)
mc.forward();
else if (command.indexOf("left") != -1)
mc.turnLeft();
else if (command.indexOf("right") != -1)
mc.turnRight();
}
```
在这种方法中,当 TensorFlow 返回匹配捕获图像的可能标签后,应用程序会将结果与可能的方向进行比较,从而控制电机。
最后,是时候使用在刚开始时创建的模型了。拷贝 assets 文件夹下的 opt_graph.pb 与 reatrained_labels.txt 文件,并替换现有文件。
打开 Helper.java 并修改以下几行:
```js
public static final int IMAGE_SIZE = 299;
private static final int IMAGE_MEAN = 128;
private static final float IMAGE_STD = 128;
private static final String LABELS_FILE = "retrained_labels.txt";
public static final String MODEL_FILE = "file:///android_asset/opt_graph.pb";
public static final String INPUT_NAME = "Mul";
public static final String OUTPUT_OPERATION = "output";
public static final String OUTPUT_NAME = "final_result";
```
运行应用程序,试试向相机展示箭头,并检查结果。机器人小车必须按照所示的箭头进行移动。
## 小结
在本教程的最后,我们介绍了如何运用 Android Things 与 TensorFlow 将机器学习应用到物联网中。我们可以使用图像控制机器人小车,并根据显示的图像移动机器人小车。
>**相关阅读**
>[【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识](https://cloud.tencent.com/developer/edu/course-1128?fromSource=waitui)
**此文已由作者授权腾讯云+社区发布,更多原文请[点击](https://cloud.tencent.com/developer/article/1115668?fromSource=waitui )**
**搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!**
海量技术实践经验,尽在[云加社区](https://cloud.tencent.com/developer?fromSource=waitui)!
有疑问加站长微信联系(非本文作者)