前两篇的连载会以机器学习理论为主,之后的文档就基本是纯实际应用了,不会有太多理论内容了:[ Darknet 训练目标检测模型 ]、[ RT-Thread 连接 ROS 小车控制 ]。
首先,简单介绍一下上面提到的各个话题的范围 (Domain),人工智能 (Artifitial Intelligence) 是最大的话题,如果用一张图来说明的话:
监督学习 (Supervised Learning): 这应当是应用最多的领域了,例如人脸识别,我提前先给你大量的图片,然后告诉你当中哪些包含了人脸,哪些不包含,你从我给的照片中总结出人脸的特征,这就是训练过程。最后我再提供一些从来没有见过的图片,如果算法训练得好的话,就能很好的区分一张图片中是否包含人脸。所以监督学习最大的特点就是有训练集,告诉模型什么是对的,什么是错的。
非监督学习 (Unsupervised Learning): 例如网上购物的推荐系统,模型会对我的浏览记录进行分类,然后自动向我推荐相关的商品。非监督学习最大的特点就是没有一个标准答案,比如水杯既可以分类为日用品,也可以分类为礼品,都没有问题。
强化学习 (Reinforcement Learnong): 强化学习应当是机器学习当中最吸引人的一个部分了,例如 Gym 上就有很多训练电脑自己玩游戏最后拿高分的例子。强化学习主要就是通过试错 (Action),找到能让自己收益最大的方法,这也是为什么很多都例子都是电脑玩游戏。
回归 (Regression): 例如经典的房价预测,这类问题得到的结果是连续的,例如房价是会连续变化的,有无限多种可能,不像手写体识别那样只有 0-9 这 10 种类别。
人工神经网络 (Artifitial Neural Network):这是个比较通用的方法,可以应用在各个领域做数据拟合,但是像图像和语音也有各自更适合的算法。
卷积神经网络 (Convolutional Neural Network):主要应用在图像领域,后面也会详细介绍。
循环神经网络 (Recurrent Neural Network):比较适用于像声音这样的序列输入,因此在语言识别领域应用比较多。
最后总结一下,这篇文档介绍的是人工智能下面发展比较快的机器学习分支,然后解决的是机器学习监督学习下面的分类问题,用的是神经网络里的卷积神经网络 (CNN) 方法。
1 神经网络相关理论
这一部分主要介绍神经网络的整个运行流程,怎么准备训练集,什么是训练,为什么要训练,怎么进行训练,以及训练之后得到了什么。
1.1.1 回归模型
比如下面图上这些散点,希望能找到一条直线进行拟合,线性回归拟合的模型就是:
不过上面的公式通常使用另外一种表示方法,最终的预测值也就是 y 通常用 hθ (hypothesis) 表示,而它的下标 θ 代表不同训练参数也就是 k, b。这样模型就成了:
顺便一提,θ 需要一个转置 θT,是因为我们通常都习惯使用列向量。上面这个公式和 y=kx+b 其实是一样的,只是换了一种表示方法而已,不过这种表示方法就更加通用,而且也更加简洁优美了:
为了让上面的模型能够很好的拟合这些散点,我们的目标就是改变模型参数 θ0 和 θ1,也就是这条直线的斜率和截距,让它能很好的反应散点的趋势,下面的动画就很直观的反应了训练过程。
可以看到,一开始是一条几乎水平的直线,但是慢慢地它的斜率和截距就移动到一个比较好的位置,那么问题来了,我们要怎么评价这条直线当前的位置满不满足我们的需求呢?
函数右边之所以除以了2是为了求倒数的时候更加方便,因为如果右边的公式求导,上面的平方就会得到一个2,刚好和分母里的2抵消了。
1.1.3 模型训练
那么什么是"下坡"的方向呢?其实就是导数的方向,从上面的动画也可以看出来,黑点一直是沿着切线方向逐渐走到最低点的,如果我们对损失函数求导,也就是对 J(θ) 求导:
我们现在知道 θ 应该往哪个方向走了,那每一次应该走多远呢?就像上面的动画那样,黑点就算知道了运动方向,每一次运动多少也是需要确定的。这个每次运动的多少称之为学习速率 α (learning rate),这样我们就知道参数每次应该向哪个方向运动多少了:
这种训练方法就是很有名的 梯度下降法(Gradient Descent),当然现在也有很多改进的训练方法例如 Adam,其实原理都差不多,这里就不做过多的介绍了。
1.1.4 总结
机器学习的流程总结出来就是,我们先要设计一个模型,然后定义一个评价指标称之为损失函数,这样我们就知道怎么去判断模型的好坏,接下来就是用一种训练方法,让模型参数能朝着能让损失函数减少的方向运动,当损失函数几乎不再减少的时候,我们就可以认为训练结束了。最终训练得到的就是模型的参数,使用训练好的模型我们就可以对其他的数据进行预测了。
那么,明明有一步到位的理论解,我们为什么还需要一步一步的训练呢?因为上面的公式里有矩阵的逆运算,当矩阵规模比较小时,对矩阵求逆运算量并不大,但是一旦矩阵的规模提升上去,用现有的计算能力求逆是几乎不可能了,所以这个时候就需要用梯度下降这样的训练方法一步一步的逼近最优解。
我们回到手写体识别的例子,上面介绍的线性回归最后得到的是一个连续的数值,但是手写体识别最后的目标是得到一个离散的数值,也就是 0-9,那么这要怎么做到呢?
这个就是上一部分的模型,其实很简单,只需要在最后的结果再加一个 sigmoid 函数,把最终得到的结果限制在 0-1 就可以了。
如果把它应用到线性回归的模型,我们就得到了一个非线性回归模型,也就是 Logistic Regression:
1.3 人工神经网络 (ANN)
其实上面的模型可以看做是只有一层的神经网络,我们输入 x 经过一次计算就得到输出 hθ 了:
如果我们不那么快得到计算结果,而是在中间再插入一层呢?就得到了有一层隐藏层的神经网络了。
上面这张图里,我们用 a 代表 激活函数 (activation function) 的输出,激活函数也就是上一部分提到的 sigmoid 函数,为了将输出限制在 0-1,如果不这么做,很有可能经过几层神经网络的计算,输出值就爆炸到一个很大很大的数了。当然除了 sigmoid 函数外,激活函数还有很多,例如下一部分在卷积神经网络里非常常用的 Relu。
于是,我们可以总结一下上面的神经网络结构:
● 隐藏层:a(2)=g(θ(1)a(1))
如果我们设置最后的输出层节点是 10 个,那就刚好可以用来表示 0-9 这 10 个数字了。
如果我们再深入一点 Go Deeper (论文里作者提到,他做深度学习的灵感其实源自于盗梦空间)
这样我们就得到一个深度神经网络了:
如果你想知道,具体应当选多少层隐藏层,每个隐藏层应该选几个节点,这就跟你从哪里来,要到哪里去一样,是神经网络的终极问题了