Let’s play a game:

Input1 Input2 Input3 Output
0 0 1 0
1 1 1 1
1 0 1 1
0 1 1 0
1 0 0 ?

当人类看到这种游戏的时候应该怎么思考?肯定是找相关性,结果与每一个元素的相关性。怎么用数学语言度量这种相关性,自然想到加权求和。如何寻找适当的权重得到“正确的”(注:这里的引号意指没有绝对正确的答案,只要依照现有的数据集,给出的权重能够符合所有的例子,则我们可以说找到了一个封闭集能够完整解释;当引入新的数据集时,若权重或者说规律无法满足,则需重新训练或者说重新找规律)答案,需要不断的试错(也就是所谓的用数据集训练机器),根据输出调整权重。

到此,就可以给出机器学习的训练过程了:

  1. 从训练集样本读取输入,根据权重进行调整,代入方程计算神经元的输出。
  2. 计算误差,也就是神经元的实际输出和训练样本的期望输出之差。
  3. 根据误差(大小和方向)调整权重。
  4. 重复1、2、3迭代10000次,进而得到“正确的”权重。

训练过程中的方程如何确定,emmm,不得不用到一些数学公式,霍金说多一个数学公式就会减少一半的读者,我尽量只减少1/2^3的读者:)

加权求和

加权总和公式很容易给出:

\[\sum_{i=1}^n {weight_i · input_i} = weight_1 · input_1 + weight_2 · input_2 + weight_3 · input_3\]

正规化

目的是将输出限制在0和1之间,这里用一个叫做Sigmoid的函数,于是可以得到神经元的输出方程:

\[output = \frac{1}{ 1 + e^{ - \sum_{i=1}^n {weight_i · input_i} } }\]

调整权重方程

训练过程中如何调整权重是关键,选取调整方程亦如此。方程应满足如下性质:

  1. 调整量与误差量成正比。这样可以加速收敛。
  2. 如果输出为0,则权重就不会被调整。因为不管权重为多少,对于0来说都没有意义。便于理解此时可以将权重看成自变量,将输出看成权重系数。
  3. 如果输出的绝对值很大,则表示该神经元很“自信”,确认自己得到的答案是正确的,认为“模棱两可”的可能性很小。
  4. 接3:如果神经元确信当前的权重是近乎正确的,那就不需要太大的调整。

鉴于3和4,恰好,Sigmoid曲线在绝对值较大处的梯度 $SigmoidCurveGradient(output) = output · (1 - output)$ 较小(求导即可得到),综上,就得出了误差加权导数方程

\[adjustment = error · input · SigmoidCurveGradient(output)\]

至此,我们就构建出了一个简单的神经网络,也是一个机器学习的过程。

以下是该算法的简单实现:

from numpy import exp, array, random, dot

training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])
training_set_outputs = array([[0, 1, 1, 0]]).T

random.seed(1)
synaptic_weights = 2 * random.random((3, 1)) - 1

for iteration in range(10000):
    output = 1 / (1 + exp(-dot(training_set_inputs, synaptic_weights)))
    synaptic_weights += dot(training_set_inputs.T,
                            (training_set_outputs - output) * output * (1 - output))

print(1 / (1 + exp(-dot(array([1, 0, 1]), synaptic_weights))))

完整代码参见NeuralNetwork

Note: Funny of machine learning is more than this.