菜鸟笔记Python3——机器学习(一) :梯度下降模型

参考资料

<PYTHON_MACHINE_LEARNING> chapter2
Training Machine Learning Algorithms for Classifcation

引言:

在学习过基本的单层感知机模型之后,我们现在来学习了解另一种单层神经网络模型:
ADAptive LInear NEuron (Adaline) 自适应线性神经单元 这种 Adaline 的特别之处在于 它引入了损失函数 cost function
Adaline 与 Perceptron 的根本区别在于它们对权值更新方法的不同
***the weights are updated based on a linear activation function rather than a unit step function ***
Perceptron (感知机):


Adaline (自适应线性) J是损失函数

展开形式如下

......

算法原理

1:算法流程

自适应线性单元 Adaline



感知机 Perceptron


Adaline 比 perceptron 多了一个量化器,用于将激励函数输出的结果进行二分,来判断样本的类别

2: 损失函数

损失函数是用来衡量模拟结果与实际结果差异的一个函数
我们的思路是,选择一个方法使得损失函数趋向最小值,那么这也就说明了我们的模型对实际符合的越好,根据这一个原理去更新权值
思路图:

在 Adaline 中,我们选择 SSE 平方差函数作为损失函数

由于 Adaline 采用的线性激励函数 (本次练习采用的是恒同映射) 是一个可微的函数(differentiable), 所以我们可以定义 J 的梯度(偏分)


把这个式子用矩阵表达一下~


再根据这个梯度更新权值


分类根据每一次迭代使用的训练集范围不同,梯度下降算法可以分成三种: 批量梯度下降(BGD),随机梯度下降(SGD),小批量梯度下降(MBGD)

  • 批量梯度下降(BGD):损失函数由全部训练集的数据误差构成,当数据量很大的时候,速度会非常慢
  • 随机梯度下降(SGD): 每一次更新只考虑一个样本的数据误差,所以速度很快,能进行在线的参数更新
  • 小批量梯度下降(MBGD): 每次跟新只考虑小批量的样本数据误差, 是前两种策略的折中方案

Python 实现(BGD)

有了第一节的基础,这个实现起来就比较容易了,我们新建一个Adaline类,这个类与Perceptron 类的区别在于更新权值的方法不同,一样,需要注释的地方都在代码里面了,直接看代码

__author__ = 'Administrator'
#! /usr/bin/python <br> # -*- coding:utf8 -*-
import numpy as np
class AdalineGD(object):
    """
    ADAlineGD 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_ : list
    Number of misclassifications in every epoch(时间起点).
    """

    def __init__(self, eta=0.01, n_iter=10):
        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] X的形式是列表的列表
    Training vectors, where n_samples is the number of samples
    and n_features is the number of features.
    y : array-like, shape = [n_samples]
    Target values.
    Returns
    -------
    self : object
'''
        self.w_ = np.zeros(1 + X.shape[1])
        #X.shape = (100,2),zeros 生成的是列向量
        #self.w_ 是一个(3,1)的矩阵
        # print('X.shape[1]=',X.shape[1])
        self.cost_ =[]
        #self.cost_损失函数 cost_function
        # zeros()创建了一个 长度为 1+X.shape[1] = 1+n_features 的 0数组
        # self.w_ 权向量
        self.errors_ = []
        for i in range(self.n_iter):
            output = self.net_input(X)
            '''
            if i==1:
                print(output)
                print(y)
            '''
            # y(100,1) output(100,1),errors(100,1)
            errors = (y - output)

            self.w_[1:] += self.eta * X.T.dot(errors)
            #   X先取转置(2,100),再矩阵乘法乘以 errors(100,1) X.T.dot(errors) (2,1)
            self.w_[0] += self.eta * errors.sum()
            cost = (errors**2).sum()/2
            self.cost_.append(cost)
        # print(self.w_.shape)
        # print(self.w_)
        # print(X.shape)
        return self

    def net_input(self, X):
        """Calculate net input"""
        #np.dot(A,B)表示矩阵乘法 ,X(100,2) self.w_[1:](2,1)
        #注意 这里每一组 向量x = [x1,x2] 不是 [x1,,,,,,x100]!!!
        #所以得到的 net_input 是(100,1)的矩阵 表示100个样本的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.net_input(X) >= 0.0, 1, -1)




然后还是用鸢尾花Iris的数据集来测试一下

from GD import AdalineGD
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from PDC import plot_decision_regions
filename = 'Iris.csv'
df = pd.read_csv(filename,header=None)
y = df.iloc[0:100, 4].values # .values将dataframe中的值存进一个list中
y = np.where(y=='Iris-setosa',-1,1) #如果是 Iris-setosa y=-1否则就是1 (二元分类)
X = df.iloc[0:100,[0,2]].values

fig, ax = plt.subplots(nrows=1, ncols=2,figsize=(10, 6))
adal = AdalineGD(n_iter=10,eta=0.01).fit(X,y)

ax[0].plot(range(1,len(adal.cost_)+1),
           np.log10(adal.cost_),marker='o')
ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('log(Sum-squared-error)')
ax[0].set_title('Adaline - Learing rate 0.01')
ada2 = AdalineGD(n_iter=10,eta=0.0001).fit(X,y)
ax[1].plot(range(1,len(ada2.cost_)+1),
           np.log10(ada2.cost_),marker='o')
ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('log(Sum-squared-error)')
ax[1].set_title('Adaline - Learing rate 0.0001')
plt.savefig('Compare effect.png')
plt.show()

结果如图

我们可以发现当学习速率过快时,有可能会让误差发散
这是因为
这个时候的学习速率(dw)已经超过了 |Wmin-Winitial|



但是,学习速率过小又会导致收敛速率过慢,于是我们要引入归一化/标准化处理,让各个数据的维度处在一个级别

归一化/标准化处理

常用的归一化处理方法是

减去平均值再除以标准差

#接上面的代码
X_std = np.copy(X)
X_std[:,0] = (X[:,0]-X[:,0].mean())/ X[:,0].std() #.std() 标准差
X_std[:,1] = (X[:,1]-X[:,1].mean())/ X[:,1].std() #.std() 标准差

ada = AdalineGD(n_iter=15, eta=0.01)
ada.fit(X_std,y)
print(ada.predict(X_std))
plot_decision_regions(X_std, y, classifier=ada)
plt.title('Adaline- Dradient Descent')
plt.xlabel('sepal length [standardized]')
plt.ylabel('petal length [standardized]')
plt.legend(loc='upper left')
plt.savefig('Adaline- Dradient Descent.png')
plt.show()
plt.plot(range(1,len(ada.cost_)+1), ada.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Sum-squared-error')
plt.savefig('Sum-squared-error.png')
plt.show()

看一下结果


刚刚对学习速率是 0.01 发散的,现在收敛了


学习的成果 ~ ~ ~~~
我们像第一节一样换一下训练集然后测试一下

Adaline- Dradient Descent.png

OK!

PS : 有一个问题没有想通,对于激励信号是阶跃函数,我们定义了 W0 应该是阈值,这个阈值应该是固定,但是很显然在模型中我们依然把它当作了未知数,对于激励信号是线性函数的,阈值的作用,,,,,暂时我还没有想明白

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容