奖励线性回归的负导数

数据挖掘 scikit-学习 线性回归
2021-09-19 08:56:32

我实际上是数据科学的新手,我正在尝试使用 Python 和所有数据在杂色数据集上仅使用一个特征 X(我在添加多项式特征之前添加了特征 log(X))进行简单的线性回归附带的科学堆栈(numpy、pandas、sci-kit learn,...)

在这里,您可以使用 scikitlearn 找到我的回归代码:

def add_log(x):
    return np.concatenate((x, np.log(x)), axis=1)

 # Fetch the training set
_X = np.array(X).reshape(-1, 1) # X = [1, 26, 45, ..., 100, ..., 8000 ]
_Y = np.array(Y).reshape(-1, 1) # Y = [1206.78, 412.4, 20.8, ..., 1.34, ..., 0.034]
Y_train = _Y
X_train = add_log(_X) if use_log else _X

# Create the pipeline
steps = [
    ('scalar', StandardScaler()),
    ('poly', PolynomialFeatures(6)),
    ('model', Lasso(alpha=alpha, fit_intercept=True))
]



pipeline = Pipeline(steps)
pipeline.fit(X_train, Y_train)

我的特征 X 可以在1~80 000之间,而 Y 可以在0~2M之间

关于我应该获得的曲线,我知道一件事是它应该总是减小,所以导数应该总是负的

我做了一个小模式来解释我的期望与我所拥有的: 因此,即使我的数据表明相反,在此处输入图像描述 我想奖励导数始终为负的预测。

有没有办法用 sci-kit learn 做到这一点?或者,也许我对我的问题提出了一个不好的解决方案,并且还有另一种方法可以获得我想要的东西?

谢谢

3个回答

这是一个经典的异常值。例如,您可以删除他或用新值替换他(通过插值)。您有很多方法可以解决此问题。

给你的链接:

https://towardsdatascience.com/ways-to-detect-and-remove-the-outliers-404d16608dba

使用一些代码: https ://towardsdatascience.com/5-ways-to-detect-outliers-that-every-data-scientist-should-know-python-code-70a54335a623

当你使用线性回归时,你总是需要定义一个你想要拟合的参数函数。因此,如果您知道您的拟合曲线/直线应该有一个负斜率,您可以简单地选择一个线性函数,例如:(y = b0 + b1*x + u没有多边形!)。从你的图来看,斜率(b1)应该是负数。结果将是您可能不会很适合,因为该功能不是很灵活。但是你会得到一个易于解释的结果。

在这种情况下,为了提高性能,您可以做的是处理您的功能。您可以将特征居中(除以平均值)或缩放它们(除以 1000 左右)。但是,由于这是一个线性变换,因此您不会从中获得太多收益。y另一种选择是进行对数转换(为和获取日志X)。这会给你一个解释,例如“如果 X 增加 1%,y 改变 b1% ”。优点是“大”值会变小,从而更好地拟合具有大(r)值的数据。由于您的数据似乎大多是积极的,这可能是一种选择。模型看起来像:log(y) = b0 + b1*log(x) + u

另一种方法是查看您的某些观察是否是“异常值”并导致您的估计函数“不稳定”。例如,您可以定义一个二次模型,例如:y = b0 + b1*x + b2*x^2 + u估计模型,并根据库克距离检测异常值。但是,这种方法似乎是任意的,因为您需要删除观察值,直到获得所需的斜率。在数据符合我们想要看到的情况之前选择数据并不是一个好主意。如果只有少数观察会引起麻烦,它可能只是一种选择(就像您的情节中的情况一样)。

另一种可能性是您“拆分”您的数据。在这里,我假设只有在某个范围内的观察会引起麻烦(在你看来是“低”x),而其余的观察(“高”x)遵循线性趋势左右。我最近遇到了完全相同的问题。我的 x 的最大部分有一个线性趋势,而只有少数观察具有高度非线性模式。我使用广义加法模型 (GAM) 检测到这一点。这是Python 实现的教程。

这是我的结果: 在此处输入图像描述

该图显示,大部分数据(此处低于 90%)存在大部分呈线性趋势。只有上层的 10% 造成了麻烦。所以我估计了一个线性模型,但添加了一个交互项到低为上 10% 数据的单独斜率。通过这样做,我得到了较低 90% 的斜率的合理线性估计,同时避免了“不稳定”的上 10% 数据的“有偏”估计。其工作原理如下:您生成一个等于I=1“摆动”数据的虚拟/指标变量,I=0否则。然后你估计一个线性模型,如:y = b0 + b1*X + b2*I + b3*I*X + u结果是,对于由 指示的数据的“摇摆不定”部分,您获得了额外的截距 ( b2) 和斜率 ( ) b3Ib0, b1)。

另一件事:你为什么使用套索?套索用于“缩小”特征/变量。您只有一个变量,因此无需缩小它。我会选择普通最小二乘法(OLS),所以是一个简单的线性回归。

这个问题似乎是相关的,我认为Adarsh 的回答可以帮助你。

Lasso 有一个参数 positive 可以设置为 True 并强制系数为正。此外,将正则化系数 alpha 设置为接近 0 会使 Lasso 模拟没有正则化的线性回归。

在您的情况下,您需要系数为负而不是正。如果您翻转目标值的符号,则这相当于强制使用正系数。我认为对您的代码进行以下修改会起作用:

def add_log(x):
    return np.concatenate((x, np.log(x)), axis=1)

# Fetch the training set
_X = np.array(X).reshape(-1, 1) # X = [1, 26, 45, ..., 100, ..., 8000 ]
_Y = np.array(Y).reshape(-1, 1) # Y = [1206.78, 412.4, 20.8, ..., 1.34, ..., 0.034]

# flip the sign of the targets
Y_train = -1 * _Y
X_train = add_log(_X) if use_log else _X

# Create the pipeline
steps = [
    ('scalar', StandardScaler()),
    ('poly', PolynomialFeatures(6)),
    ('model', Lasso(alpha=alpha, fit_intercept=True, positive=True))
]

pipeline = Pipeline(steps)
pipeline.fit(X_train, Y_train)

# Don't forget to flip the sign of your model output
```