专栏名称: 量子位
վ'ᴗ' ի 追踪AI行业和技术动态,这里更快一步!关注我们,回复“今天”,更多大新闻等你来发现
目录
相关文章推荐
51好读  ›  专栏  ›  量子位

码农の带娃绝技:TensorFlow+传感器,200美元自制猜拳手套

量子位  · 公众号  · AI  · 2017-10-16 13:23

正文

王小新 编译自 Google Cloud Blog
量子位 出品 | 公众号 QbitAI

你们程序员啊,连带娃都这么技术流……

今年夏天,谷歌云负责维护开发者关系的Kaz Sato带着他的儿子,用一些传感器和一个简单的机器学习线性模型,开发了一个“猜拳机器”,能检测石头剪刀布的手势。

最近他还还根据这个过程写了一份教程,详细介绍了怎样构建这个机器,以及怎样用机器学习算法解决日常问题。

量子位搬运编译整理如下,适合有一定编程基础的同学,需要大约200美元的硬件设备。

我们先来看一下这个机器:


上面视频中,我们搭建的系统正在通过手套上的传感器,借助一个用Tensorflow编写的简单机器学习算法来检测我儿子的手势,然后选择相应的选项:石头、剪刀、布。

项目源代码在此:
https://github.com/kazunori279/ml-misc/tree/master/glove-sensor

具体是怎样实现的呢?接下来我会一步一步地讲。

第1步:
制作手套传感器

我们使用littleBits来构建硬件系统。这套设备对儿童很友好,包含各种各样的组件,如LED灯、电机、开关、传感器和控制器等,这些组件可以靠磁性链接,无需焊接。在这个实验中,我们使用了三个 弯曲传感器 ,将它们附在塑料手套上。

littleBits弯曲传感器

当你戴着手套、弯曲手指时,传感器会输出一个从0V到5V变化的电压信号。为传感器输出加一个指示器,比如LED光柱,就能实时看到每个传感器受到的压力。


弯曲传感器输出0V-5V信号

第2步:
安装Arduino和伺服模块

要读取弯曲传感器的输出信号并控制机器的转动幅度,我们使用了Arduino模块和伺服模块。Arduino模块内部有一个微控制器芯片,且具有多个输入和输出端口。你可以在笔记本电脑上用Processing语言(和C语言比较像)编写一个程序并编译,然后通过USB线传输到该模块中。

littleBits Arduino模块

伺服模块

我儿子在画转盘指示图

现在,用于构建猜拳机的所有硬件已经准确齐全,接下来,就该写代码了。

猜拳机硬件部分

第3步:
写程序从弯曲传感器读取数据

在配置好硬件后,我们开始在Arduino模块上编写代码,实现从弯曲传感器读取数据的功能。在Arduino的IDE中,设定为每隔0.1秒读取传感器数据,然后将其记录在串行控制台上,代码如下。

在Arduino IDE中编写程序

运行这段代码时,你会在控制台上看到这样的数字:


其中,每行的三个数字表示弯曲传感器输出的三个数据。Arduino模块将输入信号电压(0V - 5V)转换成从0到1023变化的数字。

上图是“石头”手势的数据,所有传感器都是弯曲的。如果换成“布”的收拾,所有传感器都不弯曲,则上图的数据都会趋近于0。

第4步:
使用Cloud Datalab可视化数据

该如何确定这三个数字的组合是代表着“石头”、“布”还是“剪刀”?

最简单的方法是编写能判断阈值和条件的IF语句。比如:

  • 当三个输出数值都低于100时,则输出“布”;

  • 当三个输出数值都高于400时,则输出“石头”;

  • 若不满足以上两个条件,则输出“剪刀”。

这个程序可能满足当前任务的要求,但是很不灵活也不稳定。

如果我儿子要求我在手套上添加更多传感器,来捕获10个不同手势,那该怎么办?或者,如何向紧身衣添加多个传感器,来识别不同身体姿势?显然,上述程序无法处理这么复杂的任务。

当然,主要是因为我比较懒,想编写出更强大和更灵活的代码,能在不改变基本设计的前提下,灵活处理善变的甲方(我儿子)可能提出的各种请求。

为了找到更好的数据处理方法,我对手套传感器数据做了一些快速的分析。我使用的工具是Cloud Datalab,这是一个很受欢迎的Jupyter Notebook版本,并已集成到Google Cloud平台,可提供基于云数据分析的一站式服务。你可以在Web UI中编写Python代码,使用如NumPy、Scikit-learning和TensorFlow等函数库,并将其与Google Cloud服务(如BigQuery、Cloud Dataflow和Cloud ML Engine)相结合。

根据不同手势,我把手套传感器数据分开保存成三个CSV文件,每个文件包含800行数据。你可以在Cloud Datalab上编写Python代码,将它们读取并转换为NumPy数组,示例代码如下:

使用Cloud Datalab读取CSV文件转为NumPy数组

完整代码:https://github.com/kazunori279/ml-misc/blob/master/glove-sensor/Rock-paper-scissors.ipynb

你也可以使用Matplotlib库来可视化NumPy数组。下面代码画出了一个3D图,其中每个轴对应着一个不同传感器。

用3D图绘制传感器数据,已缩放原始多维数据

通过观察上面的3D图,你可以更清楚地看到数据的空间分布。

第5步:
创建一个线性模型

接下来,我们要将这些原始传感器数据划分到三种不同手势类别中。这里会用到线性代数,你们在高中或者大学应该都学过了。

线性代数是一种可以将某个空间映射到另一空间的数学方法。例如,下面公式表示了一种从某个一维空间到另一个一维空间的线性映射。

一元公式

其中,x和y分别为两个一维空间中的变量,w为权重,b为偏差。利用这个公式,可以将一维空间“纽约市出租车的行驶距离”映射到另一个一维空间“出租车费用”,其中把2.5美元(每英里费用)作为权重,把3.3美元(初始费用)设置为偏差。

“行驶距离”和“出租车费用”的映射函数

从图中看出,权重和偏差(也叫参数)分别定义该直线的斜率和初始位置。你可以通过调整这些参数,来创建从一个一维空间到另一个一维空间的任何线性映射。

线性代数的优点在于,在从任意m维空间到任意n维空间进行线性映射时,可使用相同公式。例如,在将三维空间(x1,x2,x3)中的某个点映射到另一个三维空间(y1,y2,y3)中,均可使用以下公式。

三维空间之间的映射函数

数学家认为上面公式写得太冗长了,所以设计了一种更容易的表示方法:矩阵乘法。

三维映射关系也可以这么表示:

或者,更简单写成:

其中,x和y为3维列向量,W为3×3的权重矩阵,b是3维偏置列向量。是的,它与一维空间的映射函数完全一样。而且,该公式可应用于m维空间和n维空间之间的任何线性映射,这就是所谓的“线性模型”。

那么,线性模型在本项目能起到什么作用呢?我们可以利用它,将“手套传感器数据”的3维空间转换为“石头剪刀布”的3维空间,如下所示:

3维空间的动态转换

在完成手套传感器数据与“石头剪刀布”3维空间的配对后,很容易写出用于分类的IF语句,如下:







请到「今天看啥」查看全文