欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

局部加权线性回归Lowess

程序员文章站 2022-03-14 21:21:40
当要预测的样本序列不是明显的线性关系时,用线性回归会存在拟合不好的现象,即欠拟合。局部加权回归定义:以一个点 x为中心,向前后截取一段长度为frac的数据,对于该段数据用权值函数 w做一个加权的线性回归,记 ( x , y ^ )为该回归线的中心值,其中 y ^为x拟合后曲线对应值。对于所有的n个数据点则可以做出n条加权回归线,每条回归线的中心值y ^的连线则为这段数据的Lowess曲线(上述为单次回归,局部加权回归可多次迭代)。线性回归与局部加权回归的损失函数:可以发现:局部加权回归对局部特征能较...

当要预测的样本序列不是明显的线性关系时,用线性回归会存在拟合不好的现象,即欠拟合。

局部加权回归定义

以一个点 x为中心,向前后截取一段长度为frac的数据,对于该段数据用权值函数 w做一个加权的线性回归,记 ( x , y ^ )为该回归线的中心值,其中 y ^为x拟合后曲线对应值。对于所有的n个数据点则可以做出n条加权回归线,每条回归线的中心值y ^的连线则为这段数据的Lowess曲线(上述为单次回归,局部加权回归可多次迭代)。

线性回归与局部加权回归的损失函数

局部加权线性回归Lowess可以发现:局部加权回归对局部特征能较好拟合,但同时受噪声点影响。通过增大衰减因子τ,增加局部加权回归迭代次数可以减小其影响。

线性回归的Python代码实现:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

class linear_regress(object):
    def __init__(self):
        self.W = None
        self.b = None

    def loss(self, X, y):
        """求样本点X,y(此处是某一个样本点)的损失值,参数w,b的微分项"""
        num_feature = X.shape[1]
        num_train = X.shape[0]
        # h为样本预测值
        h = X.dot(self.W) + self.b
        loss = np.sum(np.square(h - y))
        # 参数的微分
        dW = X.T.dot((h - y)) / 0.5
        db = np.sum((h - y)) / 0.5

        return loss, dW, db

    def train(self, X, y, learn_rate=0.001, iters=10000):
        """训练参数w,b"""
        num_feature = X.shape[1]             # 输入矩阵特征数目,对于时序预测,X是一维
        num_train = X.shape[0]
        self.W = np.zeros((num_feature, 1))  # 初始化参数矩阵 W, 对于时序预测,是一维
        self.b = 0
        # 定义loss_list列表,保存每次迭代的loss值
        loss_list = []

        for i in range(iters):
            for j in range(num_train):
                random_index = np.random.randint(num_train)    # 随机选取一个点进行梯度下降
                loss, dW, db = self.loss(X[random_index:random_index+1], y[random_index:random_index+1])
                loss_list.append(loss)
                # 梯度下降法更新参数w,b
                self.W += -learn_rate * dW
                self.b += -learn_rate * db

            if i % 100 == 0:
                print('iters = %d,loss = %f' % (i, loss))
        return loss_list

    def predict(self, X_test):
        y_pred = X.dot(self.W) + self.b
        return y_pred


"""线性拟合回归训练"""
classify = linear_regress()
loss_list = classify.train(X_train, y_train)     # 损失量变化。输入X_train, y_train为矩阵形式,shape[0]为样本数量
print(classify.W, classify.b)                    # 返回模型训练参数值

局部加权回归的Python代码实现:

def lwlr(testPoint, xArr, yArr, tao=1.0):
    """
    :param xArr: 训练集x矩阵,对于时序拟合问题,xArr即有序自然数列
    :param yArr: 训练集输出y矩阵,对于时序拟合问题,yArr即时序数列
    :param tao: 衰减因子,取值越小,周围样本权重随着距离增大而减得越快,即易过拟合,一般取值0.001-1
    :return:返回模型权重矩阵w,和样本testPoint的输出testPoint * w
    没有用到frac参数,单词迭代(未根据局部加权回归误差,对样本权重进行更新,进行下一次迭代)
    """
    # 样本数量m
    m = np.shape(xArr)[0]
    # 初始化权重矩阵weights
    weights = np.mat(np.eye((m)))
	# 更新测试点testPoint 周围的样本权重矩阵weights
    for j in range(m):  
        diffMat = testPoint - xArr[j, :]  
        weights[j, j] = np.exp(diffMat*diffMat.T / (-2.0 * tao ** 2)) 
    xTx = xArr.T * (weights * xArr)
    if np.linalg.det(xTx) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    # 
    w = xTx.I * (xArr.T * (weights * yArr))  # normal equation
    return testPoint * w


def lwlrTest(testArr, xArr, yArr, tao=1.0):
    """
    :param testArr: 测试集矩阵
    :param xArr: 训练集矩阵
    :param yArr: 训练集输出
    :param tao: 衰减因子
    :return: 测试集矩阵testArr的对应输出
    """
    m = np.shape(testArr)[0]
    yHat = np.zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i], xArr, yArr, tao)
    return yHat

调用statsmodels模块实现局部加权回归:

"""
调用lowess函数实现局部加权回归
frac:应该截取多长的作为局部处理, frac为原数据量的比例;
w:使用什么样的权值函数w合适,权值函数不可调
it:迭代次数,一般2-3次(求权值函数w,计算局部回归y^,求回归误差e,修正权值函数w,整个过程算一次迭代)
delta回归间隔:是否真的每个点都需要算一次局部加权回归,能否间隔delta距离算一次,间隔点用插值替换
"""
import statsmodels.api as sm


lowess = sm.nonparametric.lowess
result = lowess(y, X, frac=0.3, it=3, delta=0.0)   # 输入的x,y是array数据形式;输出的result为mX2的两列数组

**

参考鲁棒局部加权回归文中的局部加权回归完整算法伪代码:

**
局部加权线性回归Lowess

本文地址:https://blog.csdn.net/weixin_37598719/article/details/110249148

相关标签: python