以测量平差的角度看待机器学习中的回归问题

对于回归问题,最小二乘可以说是黄金油。首先说正规方程,笔者本科学的是测绘,测绘的核心是确定点在空间坐标系中的位置,对于外业测量的数据难免会存在误差,如何消除粗差,获得最优值,笔者经历了《测量平差》这门课程。而机器学习的正规方程可以对应测量平差的法方程。
如 y=a*x+b 问题,按照平差知识,观测值+观测值改正数=近似值+近似值改正数,即 这里写图片描述
测量平差的核心就是:min[PVV],即改正数的加权平方和最小。
故可以将一元线性回归写成如下误差方程:
这里写图片描述
法方程为:
这里写图片描述
正规方程的优点是无需迭代、但是当你的数据量很大的时候,程序就会很吃力。所以我们要采取它的替代品—梯度下降
梯度下降的原理很简单,这里写图片描述

这里写图片描述

编程的时候,对于matlab 或者python一定要利用其向量化优势,这样可以避免循环。
对于逻辑回归的假设:
这里写图片描述
对于非线性肯定首先要线性化,然后迭代需要初值。笔者程序以LR为类,当然逻辑回归不等于回归,一个损失函数是平方,一个是对数,而且逻辑回归属于分类。
对于欠拟合和过拟合问题:
对于欠拟合:
1、 增加特征数目
2、 使用复杂模型
对于过拟合
1、 增加训练集
2、 正则化
3、 降维
笔者下面代码是LR回归的正则化,仔细看的话,将其写成法方程形式,无非就是给法方程系数主对角线增加了一个系数,相当于岭回归,加上惩罚函数。
LR代码:

import numpy as  np
import matplotlib.pyplot as plt
def sigmiod(x):
    return 1/(1+np.exp(-x))
def gradient_decreasing(traindata,trainlabel):
    # traindata 第一列数据为1
    m,n=traindata.shape
    alpha=0.01
    thelta=np.ones((n,1))
    num=200
    for i in range(num):
        thelta1=thelta
        h=sigmiod(traindata*thelta)
        error=h-trainlabel
        thelta=thelta-alpha*traindata.T*error*(1/len(traindata))
    return thelta
   #计算训练集分类误差
def error_train(thelta):
#    traindata=np.matrix(traindata)
    h=sigmiod(traindata*thelta)
    label=np.ones((traindata.shape[0],1))
    count=0
    for i in range(traindata.shape[0]):
        if h[i,0]>=0.5:
            label[i,0]=1
        else:
            label[i,0]=0
        if label[i,0]!=trainlabel[i,0]:
            count+=1
    print("error_rate:%g"%(count/traindata.shape[0]))
 #预测测试集
def test_data(testdata,thelta):
    testdata=np.matrix(testdata)
    h=sigmiod(testdata*thelta)
    label=np.zeros((len(testdata),1))
    for i in range(len(h)):
        if h[i,0]>=0.5:
            label[i,0]= 1
        else:
            label[i,0] =0
    return label
''' 当特征数目为2时,可以画图'''
def plotdecision_boundary(thelta):
    x1,y1,x2,y2=[],[],[],[]
    for i in range(len(traindata)):
        if trainlabel[i]==1:
            x1.append(traindata[i,1])
            y1.append(traindata[i,2])
        else:
            x2.append(traindata[i,1])
            y2.append(traindata[i,2])
    x=np.arange(-3,3,0.01)
    y=(-thelta[0,0]-thelta[1,0]*x)/thelta[2,0]
    fig=plt.figure()
    ax=fig.add_subplot(1,1,1)   
    ax.plot(x1,y1,'r+',label="label=1")
    ax.plot(x2,y2,'g+',label="label=0")
    plt.legend(loc='best')
    ax.plot(x,y,'r-')
if __name__=='__main__':
    traindata=[]
    trainlabel=[]
    with open(r'C:\Users\Y\Desktop\python 3程序\traindata.csv','r') as file:
        for line in file.readlines():
            feature =line.strip().split(',')
            traindata.append([1.0]+feature[0:-1])#数据第一列为1,连接列表
            trainlabel.append([feature[-1]])#最后一列,标签值
    traindata=np.matrix(traindata,np.float)
    trainlabel=np.matrix(trainlabel,np.float)
    thelta=gradient_decreasing(traindata,trainlabel)
    error_train(thelta)
    plotdecision_boundary(thelta)
    label=test_data([[1,0.45,8.23],[1,0.3,100]],thelta)

正则化代码:

```
# -*- coding: utf-8 -*-
import numpy as  np
import matplotlib.pyplot as plt
def sigmiod(x):
    return 1/(1+np.exp(-x))
def gradient_decreasing_Regu(traindata,trainlabel):
    m,n=traindata.shape
    alpha=0.01
    thelta=np.matrix(np.ones((n,1)))
    iter_numer=200
    lampda=10#正则化参数,lampda,过大的话造成除了thelta0,其它都为0,欠拟合,一条直线
    loss=[]
    for i in range(iter_numer):
        h=sigmiod(traindata*thelta)
        error=h-trainlabel

        #正则化时候i,thelta 0 和其它值变化如下两行代码,区别之处
        thelta[0,0]=thelta[0,0]-alpha*traindata[:,0].T*error*(1/m)
        thelta[1:,0]=thelta[1:,0]*(1-alpha*lampda/m)-alpha*traindata[:,1:].T*error*(1/m)
        loss.append((np.sum(np.array(error)*np.array(error)[0]))/(2*len(traindata)))
    return thelta,loss
def plotdecision_boundary(thelta):
    x1,y1,x2,y2=[],[],[],[]
    for i in range(len(traindata)):
        if trainlabel[i]==1:
            x1.append(traindata[i,1])
            y1.append(traindata[i,2])
        else:
            x2.append(traindata[i,1])
            y2.append(traindata[i,2])
    x=np.arange(-3,3,0.01)
    y=(-thelta[0,0]-thelta[1,0]*x)/thelta[2,0]
    fig=plt.figure()
    ax=fig.add_subplot(1,1,1)   
    ax.plot(x1,y1,'r+',label="label=1")
    ax.plot(x2,y2,'g+',label="label=0")
    plt.legend(loc='best')
    ax.plot(x,y,'r-')
    plt.title("LR正则化",fontproperties='FangSong',fontsize=14)
    plt.text(x[-1],y[-1],"y=%s*x+%s"%(-thelta[1,0]/thelta[2,0],-thelta[0,0]/thelta[2,0]),fontproperties='FangSong',fontsize=14)
if __name__=='__main__':
    traindata=[]
    trainlabel=[]
    with open(r'C:\Users\Y\Desktop\python 3程序\traindata.csv','r') as file:
        for line in file.readlines():
            feature =line.strip().split(',')
            traindata.append([1.0]+feature[0:-1])
            trainlabel.append([feature[-1]])
    traindata=np.matrix(traindata,np.float)
    trainlabel=np.matrix(trainlabel,np.float)
    thelta,loss=gradient_decreasing_Regu(traindata,trainlabel)
    plotdecision_boundary(thelta)
    x1=np.arange(1,201)
    fig=plt.figure()
    ax=fig.add_subplot(111)
    ax.plot(x1,loss,'r-')
    plt.xlabel("N-parameters updata")
    plt.ylabel("loss")

迭代次数与代价函数的关系图
这里写图片描述,
这里写图片描述
当正则化系数很大的时候,它就会近似一条直线,lampda=1000时候如下图:
这里写图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值