Javascript是我的“母语”,用它来学习人工智能,记得更牢靠。
学习人工智能门槛高不高?我入门花了2个月时间,学习了python、微积分,才大概弄懂了深度学习的基本原理,确实让人头大,不过现在回过头想想,其实基本原理是没这么难的。
1. 基本原理
这个小节不需要什么基础,各位工程师应该都可以看得懂。
经过我的消化之后,表达出来的人工智能的流程就是:有一些数据,假设这些数据遵循某种规律,但是这个规律里的具体参数是未知的,让电脑多次猜测这些参数的值,并从中找到误差最小的那组参数,就可以对新的数据进行预测。
比如有一组身高x、年龄y的数据:
arr = [
{x: 10, y: 131},
{x: 11, y: 135},
{x: 12, y: 139},
{x: 13, y: 145},
]
年龄越大,身高越高呗,所以假设身高和年龄遵循的规律是:
y = kx + b
k和b是多少,电脑是个学渣,看了公式和数据一脸懵逼,那就瞎猜一下吧。
k = 10
b = 15
则
10*10 + 15 = 115
10*11 + 15 = 125
10*12 + 15 = 135
10*13 + 15 = 145
看这个瞎猜和实际的值差别是多少,我们中学学过一个评估的方式,叫做方差,这里用类似的方式来评估loss:
let yArr = [131, 135, 139, 145]
let zArr = [115, 125, 135, 145]
let loss = 0
yArr.forEach((y, index) => {
let z = zArr[index]
loss += Math.pow(z - y, 2) // (z - y)²
})
loss = loss / data.length
// loss = 93
loss评估出来是93,是大了还是小了,电脑学渣也不太清楚,所以电脑需要进行更多的猜测,从所有猜测中取loss最小时的k和b,当成最终值。
用代码完整得实现就是:
model = {
xArr: [10, 11, 12, 13],
yArr: [131, 135, 139, 145],
k: 10, // 参数1
b: 15, // 参数2
// 损失函数:评估误差用的
getLoss (k, b) {
let zArr = this.xArr.map(x => this.getY(x, k, b))
let loss = 0
this.yArr.forEach((y, index) => {
let z = zArr[index]
loss += Math.pow(y - z, 2) // (y - z)²
})
loss = loss / this.yArr.length
return loss
},
// 规律的公式
getY(x, k, b) {
return k * x + b
},
// 训练:让电脑瞎猜,实际开发中不是像以下代码这样猜的,但是虽然手段不同,原理却是一样的
learn () {
// 让k和b分别取1到100
let kArr = Array.from(Array(100), (v,i) => i + 1)
let bArr = Array.from(Array(100), (v,i) => i + 1)
let lossArr = []
kArr.forEach(k => {
bArr.forEach(b => {
lossArr.push({
loss: this.getLoss(k, b), // 通通计算一遍,算出loss
k: k,
b: b
})
})
})
let result = {loss: Infinity}
lossArr.forEach(d => {
if (d.loss < result.loss) {
result = d // 找出最小的loss
}
})
console.log(result.loss)
this.k = result.k
this.b = result.b
}
}
model.learn()
console.log(model.k, model.b)
console.log(model.yArr)
console.log(model.xArr.map(x => model.getY(x, model.k, model.b)))
最后,求得
k = 5
b = 80
yArr = [131, 135, 139, 145]
zArr = [130, 135, 140, 145]
来试试预测个14岁的身高
y = kx + b
y = 5 * 14 + 80
y = 150
150cm很合理,这就是人工智能,带着从这里学到的知识,去开发人脸识别吧,呵呵🤪
都看到这里了,给个赞好不好???
2. 优化猜测算法
这个小节,需要提前了解导数、偏导数、向量的乘积等数学知识
在上一节中,我们暴力强猜,把k和b在1~100里挨个猜了一遍,但是有可能最优解不在1~100中,所以我们来优化一下猜测的算法。
首先,重温一下公式:
\(y = kx + b\)
\( L = \sum_{i=1}^N (y_{i} - z_{i})^2 \)
\( y_{i} \)是实际的值,\( z_{i} \)是电脑猜测的值,N是yArr的长度,这里loss我们不用代码表示了,改用数学公式表达,L = loss,看不懂的同学先去学习一下再回来重新看。
看清问题的本质,才能更好地优化算法,需要了解k、b、L之间的关系,我们把k和b和L的值绘制成图:
可以从图中看到,L是一个面,我们要求这个面的最低点,假如这时候放个玻璃珠在面上,那么这个玻璃珠回朝着最低点滚动,利用这个现象的原理优化算法,就可以让电脑在最短时间内找到L的最小值了。
玻璃珠自动向最低点运动的算法叫:梯度下降法,在L这个面上的某一点,求k、b的偏导数,这个偏导数的乘积就能算出梯度下降的方向,推导流程如下。
\( \frac{\mathrm{d} L}{\mathrm{d} k} = \frac{\mathrm{d} L}{\mathrm{d} z} \frac{\mathrm{d} z}{\mathrm{d} k} \)
先求 \( \frac{\mathrm{d} L}{\mathrm{d} z} \)
\( L = \sum_{i=1}^N (y_{i} - z_{i})^2 \)
\( \frac{\mathrm{d} L}{\mathrm{d} z} = \sum_{i=1}^N (2y_{i} - 2z_{i}) \)
\( \frac{\mathrm{d} L}{\mathrm{d} z} = \sum_{i=1}^N (2y_{i} - 2kx_{i} - 2b) \)
再求 \( \frac{\mathrm{d} z}{\mathrm{d} k} \)
\( z_{i} = kx_{i} + b \)
\( \frac{\mathrm{d} z}{\mathrm{d} k} = x_{i} \)
未完待续,点个收藏日后再来看吧
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。