Python机器学习笔记1

摘要:本系列学习笔记将会详细记录 《Python Machine Learning Second Edition》学习过程。

神经网络概述

参考章节: Chapter 2: Artificial neurons – a brief glimpse into the early history of machine learning (P18

这里我们通俗的解释一下神经网络过程的直观原理:

目标:实际上神经网络的目标很简单,我们给定一组训练样本,每个训练样本有若干的特征,然后每个样本有实际的分类类别。我们的目标找出一个方程式,通过输入每个样本的特征值,最后得到分类结果和实际分类结果一致。

有点像解方程组,但是样本数量巨大,也就是多元方程组,很难求出解析解。

这里通过另外一种途径来实现,首先初始化一个方程,在没有样本的情况下,我们就认为这个方程是最后的目标,实际上如果没有样本,也就是没有任何信息的情况下,任意的方程都可以被认为是目标函数。

然后依次出入样本来检验我们的初始化函数,如果样本碰巧符合,那就继续下一个样本,如果样本结果不符合,我们就需要修正我们当前的目标函数,怎么修正,这个实际上是不确定的,这里给出一种方案,通过学习速率控制修正的尺度,修正的目标是让当前样本的结果符合实际,但是不能过激。

我们可以看出,这种方法可行的两个条件:

  1. 样本集合可以近似线性分类的,否则我们会发现需要不停的来回调整权值
  2. 学习速率尽可能小,否则同样会出现来回摇摆的情况。

神经网络感知机学习实现

Implementing a perceptron learning algorithm

算法实现

首先我们需要理解,算法实现中的约定,我们将下划线(_)附加到属性,这些属性不是在对象初始化时创建的,而是通过调用对象的其他方法创建的,例如 self.w_

其次算法中语法的参考:

• NumPy: https://sebastianraschka.com/pdf/books/dlb/appendix_f_numpy-intro.pdf

• Pandas: https://pandas.pydata.org/pandas-docs/stable/10min.html

• Matplotlib: http://matplotlib.org/users/beginner.html

理解算法,我们先从其使用方法开始:

1
2
3
4
5
6
7
df = pd.read_csv('https://archive.ics.uci.edu/ml/' 'machine-learning-databases/iris/iris.data', header=None)
ppn = Perceptron(eta=0.1, n_iter=10)
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)
# extract sepal length and petal length
X = df.iloc[0:100, [0, 2]].values
ppn.fit(X, y)

这里主要有两个步骤:

  1. 初始化:ppn = Perceptron(eta=0.1, n_iter=10)
  2. 调用 fit 方法:ppn.fit(X, y)

输入的数据

首先我们看一下输入的数据:

X:这是一个二维数组,其中使用了两个 feature,参考书第9页,也就是这里矩阵下标所表示的范围。一共有100个样本,也就是矩阵上标的范围, 矩阵可以表示为:

y:是一个一维数组,表示样本的实际分类。

初始权值

算法的开始是初始化一组数据

1
2
3
rgen = np.random.RandomState(self.random_state)
self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
self.errors_ = []

这里 numpy.random.RandomState 是一个伪随机生成器,用于生成符合各种分布的随机数。通过这个生成器,我们初始化了 self.w_ 权值数组。

Via the fit method, we initialize the weights in self.w to a vector » m+1 , where m stands for the number of dimensions (features) in the dataset, where we add 1 for the first element in this vector that represents the bias unit. Remember that the first element in this vector, `self.w[0]`, represents the so-called bias unit that we discussed earlier.

rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) 生成正态分布的随机数,loc 表示是分布的中心位置,scale 标准方差,用于描述分布的集中程度。最后一个参数表示输出的形态:X.shape[1] 是2, 这里生成了3个数,其中下标为0的数是 bias unit

什么是 bias unit

参考原书的第 19 页,这里详细介绍了 bias unit的概念。书中描述的解释十分简单,一开始定义了预测的阈值,通过 阈值来进行分类,为了简单起见,在原来的决定方程中加入一项 $w_0x_0$,然后最后将阈值调整为 0,方便比较。其中加入的这一项就是偏置单元。在实现的时候,我们初始化 $w_0$ 的时候,多初始化了一个值,这个值就是这里的偏置单元

bias unit

根据这篇文章 神经网络中的偏置项b到底是什么? 我们知道这样做的还有另外一个原因就是,这个配置项也可以根据样本进行更新,从而在不同维度上更新。

浅谈神经网络中的bias

使用样本修正权值

有了初始化的权值,下面就需要根据训练数据集来修正权值。

1
2
3
4
5
6
7
8
9
for _ in range(self.n_iter):
errors = 0
for xi, target in zip(X, y):
update = self.eta * (target - self.predict(xi))
self.w_[1:] += update * xi
self.w_[0] += update
errors += int(update != 0.0)
self.errors_.append(errors)
return self

这段代码是算法的核心,对应的理论基础就是第21页的感知学习规则(perceptron learning rule)。感知学习规则的原理非常简单,只需要遵循两个规则:

  1. 初始化权值为 0 或者是一个很小的随机值
  2. 然后根据训练的样本 $x^{(i)}$,和代价函数,计算预测的分类,然后根据实际的分类和学习速率更新权值

通过第二个规则和大量的样本不断的迭代,从而获取到一组权值可以很好的对已知的样本进行正确的分类。

perceptron learning rule

代码中为了保证所有 feature 的权值同时更新,首先定义了一个 updateupdate = self.eta * (target - self.predict(xi)),然后根据这个 update 来更新所有的权值 w_[]self.w_[1:] 表示是一个数组。也就是每个 feature 的权值都要使用 update 乘以 feature 值。然后还要更新 bias unit。最后的 errors 为了统计每次迭代后预测值是否错误的结果,比如我们迭代10后,这个数组为 [1, 3, 3, 2, 1, 0, 0, 0, 0, 0],表明从第6次迭代就没有错误了,实际上当没有错误的时候,权值也就不会再更新了。

综合上面的分析,我们可以发现感知学习规则是非常简单的,其实现代码也很短,核心代码不超过30行。

数据处理 Pandas

下面我们根据这个具体的算法实现,再详细介绍一下,在实现算法是所涉及到的数据处理的技术,为以后学习奠定一定的基础。

从 CSV 中读取数据:

df = pd.read_csv('https://archive.ics.uci.edu/ml/' 'machine-learning-databases/iris/iris.data', header=None)

数据选择

enter image description here

1
2
df = pd.read_csv('https://archive.ics.uci.edu/ml/' 'machine-learning-databases/iris/iris.data', header=None)
X = df.iloc[0:100, [0, 2]].values

X 从读取的数据集中截取需要的数据,0-100 行,0和2列。这样得到的 X 是一个2x100 的矩阵。