zoukankan      html  css  js  c++  java
  • 感知机回归

    概述

    感知机分类一文中提到了感知机模型在分类问题上的应用,如果,我们需要将其使用于回归问题呢,应该怎样处理呢?

    其实只要修改算法的最后一步,
    sign(x)={+1,x01,x<0(1.1) sign(x)=left{egin{matrix}+1 &, xgeq 0\ -1 &, x< 0end{matrix} ight. ag{1.1}
    函数即可。经过sign函数的处理,只可能是两个值,要么1,要么-1,。如果将最后的sign函数改成该函数:
    f(x)=x(1.2) f(x)=x ag{1.2}
    那么,最后的输出值就是一个实数而不是1或-1中的一个值了,这样就达到了回归的目的。


    损失函数

    在实际问题中,损失函数是根据不同的问题进行设计的,因此,单单改变了激活函数还不够,还需要改变损失函数,通常情况下,回归问题使用的损失函数为:
    e=12(yy^)2(2.1) e=frac{1}{2}(y-hat{y})^2 ag{2.1}
    在公式(2.1)中,y y表示训练样本里面的标记,也就是实际值;y^ hat{y}表示模型计算的出来的预测值。e e叫做单个样本的误差。至于为什么前面要乘1/2 1/2,是为了后面计算方便。

    根据公式(2.1),在n n个样本的数据集中,可以将总误差E E记为:
    E=12i=1n(y(i)y^(i))2(2.2) egin{aligned}E&=frac{1}{2}sum_{i=1}^{n}(y^{(i)}-hat{y}^{(i)})^2end{aligned} ag{2.2}
    在公式(2.2)中,y(i) y^{(i)}表示第i i个样本的真实值,y^(i) hat{y}^{(i)}表示第i i个样本的预测值。且
    y^(i)=h(x(i))=wTx(i)(2.3) egin{aligned}hat{y}^{(i)}&=h(mathrm{x}^{(i)})\&=mathrm{w}^Tmathrm{x^{(i)}}end{aligned} ag{2.3}
    我们的目的,是训练模型:求取到合适的w mathrm{w},使(2.2)取得最小值。


    求参数的方法

    3.1 极大似然估计

    该方法之前有提到过,大致思路为让损失函数对参数求导并令其为0,求出参数的值。具体的可以参考线性回归模型 ,但该方法仅适用于激活函数为f(x)=x f(x)=x的情况。

    3.2 梯度下降算法

    该方法是计算机通过强大的计算能力,一步步把极值点“试”出来,大致过程如下:
    在这里插入图片描述
    还记的感知机学习的步骤吗?主要是解决两个问题:

    1. 往哪走?
    2. 走多远?

    首先随机选择一个点x x,在之后的过程中每次修改该点,经过数次迭代之后最终到达函数的最小值点。根据梯度的性质:梯度的反方向是函数值下降最快的方向,每次沿着梯度相反的方向修改x x的值,最后是有可能走到极小值附近的。该公式可以表示为:
    xnew=xoldηf(x)(3.1) mathrm{x}_{new}=mathrm{x}_{old}-eta abla{f(x)} ag{3.1}
    将其应用于我们的目标函数的权值中时,则有
    wnew=woldηE(w)(3.2) egin{aligned}mathrm{w}_{new}=&mathrm{w}_{old}-eta abla{E(mathrm{w})}\ ag{3.2}end{aligned}
    E(w) abla{E(mathrm{w})}则有:
    E(w)=wE(w)=w12i=1n(y(i)y^(i))2=12wi=1n(y(i)22y^(i)y(i)+y^(i)2)=12wi=1n(2y^(i)y(i)+y^(i)2)=12i=1n[2y(i)y^(i)w+y^(i)2w]=12i=1n[2y(i)wTx(i)w+2y^(i)wTx(i)w]=12i=1n[2y(i)x(i)+2y^(i)x(i)]=i=1n(y(i)y^(i))x(3.3) egin{aligned} abla{E(mathrm{w})}&=frac{partial}{partialmathrm{w}}E(mathrm{w})\&=frac{partial}{partialmathrm{w}}frac{1}{2}sum_{i=1}^{n}(y^{(i)}-hat{y}^{(i)})^2\&=frac{1}{2}frac{partial}{partialmathrm{w}}sum_{i=1}^{n}(y^{(i)2}-2hat{y}^{(i)}y^{(i)}+hat{y}^{(i)2})\&=frac{1}{2}frac{partial}{partialmathrm{w}}sum_{i=1}^{n}(-2hat{y}^{(i)}y^{(i)}+hat{y}^{(i)2})\&=frac{1}{2}sum_{i=1}^{n}[-2y^{(i)}frac{partial hat{y}^{(i)}}{partialmathrm{w}}+frac{partial hat{y}^{(i)2}}{partial mathrm{w}}]\&=frac{1}{2}sum_{i=1}^{n}[-2y^{(i)}frac{partial mathrm{w}^Tmathrm{x^{(i)}}}{partialmathrm{w}}+2hat{y}^{(i)}frac{partial mathrm{w}^Tmathrm{x^{(i)}}}{partial mathrm{w}}]\&=frac{1}{2}sum_{i=1}^{n}[-2y^{(i)}mathrm{x^{(i)}}+2hat{y}^{(i)}mathrm{x^{(i)}}]\&=-sum_{i=1}^{n}(y^{(i)}-hat{y}^{(i)})mathrm{x} ag{3.3}end{aligned}
    所以,梯度更新公式为:
    wnew=wold+ηi=1n(y(i)y^(i))x(i)(3.4) mathrm{w}_{new}=mathrm{w}_{old}+etasum_{i=1}^{n}(y^{(i)}-hat{y}^{(i)})mathrm{x}^{(i)} ag{3.4}
    若有M+1个特征,(常数项也包括在内),则w,x mathrm{w},mathrm{x}是M+1维列向量,所以(3.4)可以写成
    [w0w1w2...wm]new=[w0w1w2...wm]old+ηi=1n(y(i)y^(i))[1x1(i)x2(i)...xm(i)] egin{bmatrix}w_0 \w_1 \w_2 \... \w_m \end{bmatrix}_{new}=egin{bmatrix}w_0 \w_1 \w_2 \... \w_m \end{bmatrix}_{old}+etasum_{i=1}^{n}(y^{(i)}-hat{y}^{(i)})egin{bmatrix}1 \x_1^{(i)} \x_2^{(i)} \... \x_m^{(i)} \end{bmatrix}

    与分类器的比较

    算法 分类 回归
    模型 sign(x)={+1,x01,x<0 sign(x)=left{egin{matrix}+1 &, xgeq 0\ -1 &, x< 0end{matrix} ight. f(x)=x f(x)=x
    训练规则 ww+η(yy^)x mathrm{w}getsmathrm{w}+eta(y-hat{y})mathrm{x} ww+η(yy^)x mathrm{w}getsmathrm{w}+eta(y-hat{y})mathrm{x}

    5.代码实现

    代码在这里, 翻我牌子

    制作数据

    import numpy as np
    

    from sklearn.model_selection import train_test_split

    def load_data(n):
    X = np.arange(0, 10, 0.1)
    y = X + (np.random.rand(len(X)) - 0.5) * n
    X_train, X_test, y_train, y_test = train_test_split(X, y)
    return X_train, X_test, y_train, y_test

    def show_data():
    import matplotlib.pyplot as plt
    print(X.shape)
    plt.scatter(X, y)
    plt.plot(X, X)
    plt.show()

    主代码

    '''
    用感知机实现回归算法
    '''
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    sns.set()
    

    class ProceptronRegression():
    def init(self, max_itr=100, lr_rate=0.01, eps=0.1):
    self.max_itr = max_itr
    self.lr_rate = lr_rate
    self.eps = eps

    def SquareLoss(self, y, y_pred):
        return np.sum((y - y_pred)**2) / len(y)**2
    
    def fit(self, X, y):
        w = np.random.rand(2) # b, a, 构造y = a*x + b
    
        for itr in range(self.max_itr):
            # print(len(X)**2)
            temp = 0
            for d in range(len(X)):
    
                x_ = np.array([1, X[d]])
                y_ = y[d]
                temp += (y_ - np.dot(w, x_)) * x_
    
            # print(temp)
            w += self.lr_rate * temp
            # print(w)
            self.w = w
            y_pred = self.predict(X)
            if self.SquareLoss(y, y_pred) < self.eps:
                print("iterations:", itr+1)
                break
    
        print("Train Finished !")
        return
    
    
    
    def predict(self, X):
        return  np.dot(X, self.w[1]) + self.w[0]
    
    def score(self, X, y):
        y_pred = self.predict(X)
        return self.SquareLoss(y, y_pred)
    

    if name == "main":
    from Data.make_regression import load_data
    X_train, X_test, y_train, y_test = load_data(4) # 参数为离散程度
    rgs = ProceptronRegression(max_itr=100, lr_rate=1e-4, eps=0.01)
    rgs.fit(X_train, y_train)
    print("training loss: ", rgs.score(X_test, y_test))

    y_pred = rgs.predict(X_test)
    print("predict: ", y_pred)
    
    plt.scatter(X_train, y_train, label="train")
    xx = np.arange(X_train.min(), X_train.max(), 0.01)
    plt.plot(xx, rgs.w[1]*xx + rgs.w[0], 'r')
    plt.scatter(X_test, y_pred, label='predict')
    plt.legend()
    plt.show()
    
                                    </div>
    
  • 相关阅读:
    Windows Server 2012 R2的安装(GUI桌面版本)
    CentOS安装-(CentOS7)最小化安装
    【转】Makefile步步为营
    【转载】人工智能必备数学知识
    【萌新向】cartographer_ros最新安装指南 2019-12
    Ubuntu 16.04 允许进行vnc远程控制【转】
    UVW平台运动控制算法以及matlab仿真
    Java语言基础13—IO
    Java数组元素去重(不使用集合)
    java基础12—集合类
  • 原文地址:https://www.cnblogs.com/hichens/p/12340797.html
Copyright © 2011-2022 走看看