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

参考资料

<PYTHON_MACHINE_LEARNING> chapter2
Training Ma
chine Learning Algorithms for Classifcation

引言

在上一节,我们学习了梯度下降算法,现在我们来了解一下梯度下降算法的一个类型——随机梯度下降,每一次更新只考虑一个样本的数据误差,所以速度很快,能进行在线的参数更新... ...

原理

基本原理与批量梯度下降算法相同,不同的是更新权值的方法
这是上一章节的权值更新方法


在随机梯度下降中,我们一次考虑一个样本的误差,再逐个加和,一旦到达最小,就可以停下来,所以可以大大加快模拟的速度,同时每一次迭代开始的时候,我们都打乱一遍训练集,为了减小样本之间造成的参数更新抵消问题

Python实现

我们在上一节AdalineGD类的基础上稍加改动就得到了AdalineSGD
主要的改动有:

  • 增加了一个洗牌(shuffle)方法,用于在每一次迭代开始的时候打乱训练集
  • 增加了一个权值更新(._update_weights)方法, 用于更新每一个样本的误差

ok
上代码吧, 有什么问题都在注释里说明了

__author__ = 'Administrator'
#! /usr/bin/python <br> # -*- coding:utf8 -*-
import numpy as np
from numpy.random import seed
class AdalineSGD(object):
    """
    ADAlineSGD 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(时间起点).
    shuffle: bool (default :True) 洗牌
    每次训练开始的时候将训练集重新打乱
    如果为真,阻止循环
    用随机数来 打乱数据集 并且初始化权值
    """

    def __init__(self, eta=0.01, n_iter=10,shuffle = True,
                 random_state = None):
        self.eta = eta
        self.n_iter = n_iter
        self.w_initialiezed = False
        self.shuffle = shuffle
        if random_state:
            seed(random_state)

    def _shuffle(self, X, y):
        """shuffle training data"""
        r = np.random.permutation(len(y))
        #random.permutation(array/number)
        #接受array的时候返回的是 array 的打乱的排列 ,
        # 接受 数字的时候 返回一个 range(number) 的打乱的排列
        # 所谓‘排列’可以理解成一个有数组序号组成的数组
        #X[r] 就是 X 按照 r 的排列重排的数组(只重排第一个索引(重排行)),
        # 同时 X[r] 返回一个copy 的对象
        #X 本身并没有改变
        #random.shuffle(array)不返回对象,重排array,改变array本身
        return X[r], y[r]

    def _initialize_weights(self, m):
        """Initialize weights to zeros"""
        self.w_ = np.zeros(1+m)
        #初始化之后把属性 w_initialiezd 设为 True
        self.w_initialiezed = True

    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._initialize_weights(X.shape[1])
        #将 权值属性self.w_初始化 (100,1)的0数组
        #X.shape = (100,2)
        self.cost_ =[]
        #self.cost_损失函数 cost_function
        for i in range(self.n_iter):
            #开始默认 shuffle为真
            if self.shuffle:
                X, y = self._shuffle(X,y)
            cost = []
            for xi,target in zip(X,y):
                cost.append(self._update_weights(xi,target))
            avg_cost = sum(cost)/len(y)
            #avg_cost = np.array(cost).mean()
            #也可用这种方法求平均数
            self.cost_.append(avg_cost)
        return self

    def partial_fit(self, X, y):
        """Fit training data  without reinitializing the weights"""
        if not self.w_initialiezed:
            self._initialize_weights(X.shape[1])
        if y.ravel().shape[0] > 1:
            for xi, target in zip(X, y):
                self._update_weights(xi,target)
        else:
            self._update_weights(X, y)
        return self




    def _update_weights(self, xi, target):
        """Apply Adaline learning rule to update the weights"""
        output = self.net_input(xi)
        error = (target - output)
        #每次error都是一个float
        #xi对应一个样本 (2,1)
        #wi 的 update = eta* xi[i]*error
        self.w_[1:] += self.eta * xi.dot(error)
        self.w_[0] += self.eta * error
        cost = 0.5 * error ** 2
        return cost

    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 的数据集来验证一下

__author__ = 'Administrator'
#!/usr/bin/python <br> # -*- coding: utf8 -*-
from GDR import AdalineSGD
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
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 = AdalineSGD(n_iter=15, eta=0.01,random_state=1)
ada.fit(X_std, y)

plot_decision_regions(X_std, y, classifier=ada)
plt.title('Adaline - Stochastic Gradient Descent')
plt.xlabel('sepal length [standardized]')
plt.ylabel('petal length [standardized]')
plt.legend(loc='upper left')
plt.savefig('Adaline- Stochastic Gradient Descent.png')
plt.show()
plt.plot(range(1,len(ada.cost_)+1), ada.cost_, marker='o')
plt.xlabel('Epoches')
plt.ylabel('Average Cost')
plt.savefig('Average Cost - Epoches.png')
plt.show()

比较一下达到最优的速率
SGD



BGD



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

推荐阅读更多精彩内容