Python实现自适应线性神经元

既然感知机和Adaline的学习规则非常相似,所以在实现Adaline的时候我们不需要完全重写,而是在感知机代码基础上进行修改得到Adaline,具体地,我们需要修改fit方法,实现梯度下降算法:

class AdalineGD(object):
    """ADAptive LInear NEuron classifier.

    Parameters
    ----------------
    eta: float
        Learning rate (between 0.0 and 1.0)
    n_iter: int
        Passes over the training dataset.

    Attributes:
    ------------------
    w_: 1d-array
        Weights after fitting.
    errors_: int
        Number of misclassification in every epoch.

    """

    def __init__(self, eta=0.01, n_iter=50):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        """Fit training data.

        Parameters
        ---------------
        X: {array-like}, shape=[n_samples, n_features]
            Training vectors,
        y: array-like, shape=[n_samples]
            Target values.

        Returns
        -----------
        self: object 
        """
        self.w_ = np.zeros(1 + X.shape[1])
        self.cost_ = []

        for i in range(self.n_iter):
            output = self.net_input(X)
            errors = (y - output)
            self.w_[1:] += self.eta * X.T.dot(errors)
            self.w_[0] += self.eta * errors.sum()
            cost = (errors ** 2).sum() / 2.0 
            self.cost_.append(cost)
        return self

    def net_input(self, X):
        """ Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """ Compute linear activation"""
        return self.net_input(X)

    def predict(self, X):
        """ Return class label after unit step"""
        return np.where(self.activation(X) >= 0.0, 1, -1)

不像感知机那样每次用一个训练样本来更新权重参数,Adaline基于整个训练集的梯度来更新权重。

注意,X.T.dot(errors)是一个矩阵和向量的乘法,可见numpy做矩阵计算的方便性。

在将Adaline应用到实际问题中时,通常需要先确定一个好的学习率这样才能保证算法真正收敛。我们来做一个试验,设置两个不同的值:。然后将每一轮的损失函数值画出来,窥探Adaline是如何学习的.

(学习率,迭代轮数n_iter也被称为超参数(hyperparameters),超参数对于模型至关重要,在第四章我们将学习一些技巧,能够自动找到能使模型达到最好效果的超参数。)

分析上面两幅图各自的问题,左图根本不是在最小化损失函数,反而在每一轮迭代过程中,损失函数值不断在增大!这说明取值过大的学习率不但对算法毫无益处反而危害大大滴。右图虽然能够在每一轮迭代过程中一直在减小损失函数的值,但是减小的幅度太小了,估计至少上百轮迭代才能收敛,而这个时间我们是耗不起的,所以学习率值过小就会导致算法收敛的时间巨长,使得算法根本不能应用于实际问题。

下面左图展示了权重再更新过程中如何得到损失函数最小值的。右图展示了学习率过大时权重更新,每次都跳过了最小损失函数对应的权重值。

许多机器学习算法都要求先对特征进行某种缩放操作,比如标准化(standardization)和归一化(normalization)。而缩放后的特征通常更有助于算法收敛,实际上,对特征缩放后在运用梯度下降算法往往会有更好的学习效果。

特征标准化的计算很简单,比如要对第j维度特征进行标准化,只需要计算所有训练集样本中第j维度的平均值和标准差即可,然后套公式:

标准化后的特征 均值为0,标准差为1.

在Numpy中,调用mean和std方法很容易对特征进行标准化:

标准化后,我们用Adaline算法来训练模型,看看如何收敛的(学习率为0.01):

我们将决策界和算法学习情况可视化出来:

Wow 标准化后的数据再使用梯度下降Adaline算法竟然收敛了! 注意看Sum-squared-error(即,)最后并没有等于0,即使所有样本都正确分类。

results matching ""

    No results matching ""