有约束条件的加权最小二乘的实现

@[TOC] 有约束条件的加权最小二乘的实现

加权最小二乘原理

详细见网址:加权最小二乘法

Python实现

import numpy as np
import pandas as pd
from scipy.optimize import minimize


class Constrained_regression:
    def __init__(self, weight = None, intercept = True):
        """
        默认选择最小二乘
        """
        self.weight = weight
        self.intercept = intercept
    
    
    def weight_error(self, B, X_train, y_train):
        # 加权最小二乘的损失函数
        # 也是目标函数
        # B表示beta,为待优化参数

        data1 = np.dot(X_train, B)
        data2 = y_train - data1
        
        if self.weight is None: # 此时为普通最小二乘
            self.weight = np.identity(self.sample_num)
            
        weight_1 = np.linalg.pinv(self.weight)
        temp3 = data2.transpose()
        error1 = np.dot(temp3, weight_1)
        error = np.dot(error1, data2)
        return error
    
    
    def cons(self):
        # 创建约束条件
        if self.intercept == True:
            cons = ({'type': 'eq', 'fun': lambda x: np.sum(x[:-1])- 1})
        else:
            cons = ({'type': 'eq', 'fun': lambda x: np.sum(x)- 1})
            
        bnds = []
        for i in range(self.feature_num):
            bnds.append((0, 1))
            
        if self.intercept == True:
            bnds.append((None, None))   
        bnds = tuple(bnds)
        
        return cons, bnds
    
    
    def fit(self, X, y):
        # 模型训练
        X_train = X
        y_train = y
        sample_num = X_train.shape[0]
        feature_num = X_train.shape[1]
        self.feature_num = feature_num
        self.sample_num = sample_num
        
        # 创造截距项
        if self.intercept == True:
            X_train['inter'] = 1
            
        B_ini = list(np.zeros(feature_num) + 1/feature_num)
        B_ini.append(0.5)
        fun = lambda x: self.weight_error(B=x, X_train=X_train, y_train=y_train)
        cons, bnds = self.cons()
        res = minimize(fun, B_ini, method='SLSQP', constraints=cons, tol=1e-5, bounds = bnds)
        return res.x


if __name__ == "__main__":
    
    data = pd.read_csv('YFDdata.csv')
    X_train = data[['bond', 'Conbond', 'Credebt']]
    y_train = data['YFD']
    model = Constrained_regression()
    conf = model.fit(X_train, y_train)

第一次写CSDN,比较简单,下次会修正

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
首先,我们需要加载所需的包和数据集。这里我们使用`mtcars`数据集作为例子。 ```r library(lsei) library(tidyverse) data(mtcars) ``` 接下来,我们定义一个函数来执行约束最小二乘回归。该函数的输入包括矩阵`X`和向量`y`,以及约束条件`A`和`b`。函数将返回一个向量,其中包含回归系数。 ```r constrained_least_squares <- function(X, y, A, b) { n <- ncol(X) m <- nrow(A) # 构建增广矩阵 X_augmented <- cbind(X, A) y_augmented <- c(y, b) # 构建目标函数和约束条件 f <- c(rep(0, n), rep(1, m)) G <- rbind(X_augmented, diag(m)) h <- c(y, rep(0, m)) # 调用lsei函数求解 solution <- lsei(f, G, h) # 返回回归系数 solution$X[1:n] } ``` 现在,我们可以使用上述函数来执行多模型融合。假设我们有两个模型,一个基于`hp`和`wt`两个变量,另一个基于`disp`和`cyl`两个变量。我们将使用约束条件来确保两个模型的系数之和为1。 ```r # 定义模型1 X1 <- mtcars %>% select(hp, wt) y <- mtcars$mpg coef1 <- constrained_least_squares(X1, y, matrix(c(1, 1), nrow = 1), 1) # 定义模型2 X2 <- mtcars %>% select(disp, cyl) coef2 <- constrained_least_squares(X2, y, matrix(c(1, 1), nrow = 1), 1) # 计算加权平均系数 lambda <- 0.5 # 权重参数 coef_avg <- lambda * coef1 + (1 - lambda) * coef2 ``` 现在,`coef_avg`向量包含两个模型的加权平均系数。我们可以使用该向量来预测新数据点的响应变量。 ```r # 定义新数据点 new_data <- data.frame(hp = 200, wt = 3.5, disp = 300, cyl = 8) # 计算预测值 pred <- as.numeric(t(coef_avg) %*% t(as.matrix(new_data))) pred ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值