我想拟合曲线在我的数据点上使用具有单个预测变量的线性回归。
然而,成本函数不是均匀的,而是在每一边都有不同的权重,即:
在哪里:
是否有任何众所周知的方法可以找到任意一条线价值
我特别想知道我应该如何找到这条线那完全是下分吗?(IE)
我想拟合曲线在我的数据点上使用具有单个预测变量的线性回归。
然而,成本函数不是均匀的,而是在每一边都有不同的权重,即:
在哪里:
是否有任何众所周知的方法可以找到任意一条线价值
我特别想知道我应该如何找到这条线那完全是下分吗?(IE)
正如Mark L. Stone 评论的那样,您更普遍的问题确实被称为预期回归。可以在Waltrup 等人中找到一个很好的概述。(2015 年)。我们需要映射您的权重和总和为的期望值; 一点代数表明你需要- 预期。
再次根据 Mark 的评论, R的expectreg
软件包将为您提供合适的服务(如果您愿意,甚至包括惩罚)。这是一些具有相关性的随机数据,期望回归适合:
代码:
n_points <- 25
set.seed(1)
xx <- rnorm(n_points)
yy <- xx+rnorm(n_points)
dataset <- data.frame(x=xx,y=yy)
x_predict <- range(xx)
alpha <- c(0.1,1,10)
expectiles <- 1/(1+alpha)
library(expectreg)
opar <- par(mai=c(.8,.8,.1,.1))
plot(dataset,las=1,pch=19)
for ( ii in seq_along(alpha) ) {
model <- expectreg.ls(y~x,dataset,lambda=0,expectiles=expectiles[ii])
lines(x_predict,predict(model,newdata=data.frame(x=x_predict))$fitted,col=ii,lwd=2)
}
legend("bottomright",lwd=2,col=seq_along(alpha),legend=paste("alpha =",alpha))
par(opar)
现在,对于您更具体的问题,即找到一条通过所有点且平方误差之和最小的线。有多种方法可以解决这个问题:
在期望回归的设置中,您可以简单地使用-expectile(这只是极限,)。只需expectiles=0
在上面的调用中使用参数,就expectreg.ls()
可以得到你的线路。对称地,会在你的观点之上expectiles=1
给你一条线(以及大量的警告,这对我来说看起来并不严重)。
或者,以最小的成本在所有点下方(或上方)找到一条线是一个简单的二次规划练习。您的目标函数是您想要最小化的残差平方和。你的限制是对所有人,而这些显然是线性的。您可以将其输入到您选择的二次规划求解器中。
最后,一种几何方法是计算点云的凸包。完全位于点云下方的线由云下方该船体的有限多个部分之一确定。因此,您可以简单地查看每个这样的段,将其扩展到两个方向的线,并计算残差平方和 - 最后使用具有最小此类和的线。同样,同样可以在点云上方找到最小平方残差线。
这是使用 Python scipy.optimize.differential_evolution 遗传算法模块的示例代码,它实现了一个“砖墙”,如果遗传算法找到的参数产生的任何预测值高于或低于每个代码开关的任何数据点的预测值,则会产生非常大的错误. 当我在代码中翻转“上/下”开关时,它在我的测试中起作用。
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import warnings
from scipy.optimize import differential_evolution
xData = np.array([5.0, 6.1, 7.2, 8.3, 9.4])
yData = np.array([ 10.0, 18.4, 20.8, 23.2, 35.0])
def func(data, a, b):
return a * data + b
# function for genetic algorithm to minimize (sum of squared error)
# this contains the "brick wall" switch for upper/lower
def sumOfSquaredError(parameterTuple):
warnings.filterwarnings("ignore") # do not print warnings by genetic algorithm
val = func(xData, *parameterTuple)
for i in range(len(val)):
if val[i] < yData[i]: # ****** upper/lower switch ******
val[i] = 1.0E10
return np.sum((yData - val) ** 2.0)
def generate_Initial_Parameters():
# min and max used for bounds
maxX = max(xData)
minX = min(xData)
maxY = max(yData)
minY = min(yData)
parameterBounds = []
maxSlope = (maxY - minY) / (maxX / minX)
parameterBounds.append([-maxSlope, maxSlope]) # parameter bounds for a
parameterBounds.append([-maxY, maxY]) # parameter bounds for b
# "seed" the numpy random number generator for repeatable results
result = differential_evolution(sumOfSquaredError, parameterBounds, seed=3)
return result.x
# generate initial parameter values
geneticParameters = generate_Initial_Parameters()
# create values for display of fitted peak function
a, b = geneticParameters
y_fit = func(xData, a, b)
plt.plot(xData, yData, 'D') # plot the raw data
plt.plot(xData, y_fit) # plot the equation using the fitted parameters
plt.show()
print('parameters:', geneticParameters)