感知器规则与Adaline非常相似,我们将在前面实现的感知器代码的基础上修改fit方法,将其权重的更新改为通过梯度下降最小化代价函数来实现Adaline算法。
与感知器中针对每一个样本做一次权重更新不同,我们基于训练数据集通过self.eta*errors.sum来计算梯度的第0个位置的权重,通过self.eta*X.T.dot(errors)来计算1到m位置的权重,其中X.T.dot(errors)是特征矩阵与误差向量之间的乘积。与前面感知器的实现类似,我们设置一个列表self.cost_来存储代价函数的输出值以检查本轮训练后算法是否收敛。
矩阵与向量的乘法计算类似于将矩阵中的每一行单独作为一个行向量与原列向量的点积计算。这种向量化方法使得书写更加紧凑,同时借助于NumPy也使得计算更加高效。例如:
在实践中,为优化收敛效果,常常需要通过实验来找到合适的学习速率η。因此,我们分别使用η=0.1和η=0.0001两个学习速率来绘制迭代次数与代价函数的图像,以观察Adaline通过训练数据进行学习的效果。
这里的学习速率η和迭代次数n_iter都被称作感知器和Adaline算法的超参(hyperp-arameter)。在第4章,我们将学习自动调整超参值以得到分类性能最优模型的各种技术。
现在我们分别绘制在两个不同的学习速率下,代价函数与迭代次数的图像。
从下面代价函数输出结果的图像中可以看到,我们面临两种不同类型的问题。左边的图像显示了学习速率过大可能会出现的问题——并没有使代价函数的值尽可能的低,反而因为算法跳过了全局最优解,导致误差随着迭代次数增加而增大。
虽然在右边的图中代价函数逐渐减小,但是选择的学习速率η=0.0001的值太小,以致为了达到算法收敛的目标,需要更多的迭代次数。下图说明了我们如何通过更改特定的权重参数值来最小化代价函数J(左子图)。右子图则展示了,如果学习速率选择过大会发生什么情况:算法跳过全局最优解(全局最小值)。
本书涉及的许多机器学习算法要求对特征值范围进行特征缩放,以优化算法的性能,我们将在第3章中做更深入的介绍。梯度下降就是通过特征缩放而受益的众多算法之一。在此,采用一种称作标准化的特征缩放方法,此方法可以使数据具备标准正态分布的特性:各特征值的均值为0,标准差为1。例如,为了对第j个特征的值进行标准化处理,只需要将其值与所有样本的平均值μj相减,并除以其标准差σj。
这里的xj是包含训练样本n中第j个特征的所有值的向量。
标准化可以简单地通过NumPy的mean和std方法来完成:
在进行标准化操作后,我们以学习速率η=0.01再次对Adaline进行训练,看看它是否是收敛的:
执行上述代码,我们可以看到图中判定区域,以及代价函数逐步减小的趋势,如下图所示:
如上图所示,以η=0.01为学习速率,Adaline算法在经过标准化特征处理的数据上训练可以收敛。虽然所有样本都被正确分类,但是其误差平方和(SSE)的值仍旧不为零。