11
头图

Javascript是我的“母语”,用它来学习人工智能,记得更牢靠。

学习人工智能门槛高不高?我入门花了2个月时间,学习了python、微积分,才大概弄懂了深度学习的基本原理,确实让人头大,不过现在回过头想想,其实基本原理是没这么难的。

image.png

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的值绘制成图:
image.png

可以从图中看到,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} \)

未完待续,点个收藏日后再来看吧


6666
2.7k 声望247 粉丝