我可以对 sklearn 进行对数回归吗?

Posted

技术标签:

【中文标题】我可以对 sklearn 进行对数回归吗?【英文标题】:Can I make a logarithmic regression on sklearn? 【发布时间】:2018-03-05 00:59:17 【问题描述】:

我不知道“对数回归”是否是正确的术语,我需要在我的数据上拟合一条曲线,就像一条多项式曲线,但最终会变平。

这是一张图片,蓝色曲线是我所拥有的(二阶多项式回归),洋红色曲线是我所需要的。

我搜索了很多,但找不到,只有线性回归,多项式回归,但在 sklearn 上没有对数回归。我需要绘制曲线,然后使用该回归进行预测。

编辑

这是我发布的绘图图像的数据:

x,y
670,75
707,46
565,47
342,77
433,73
472,46
569,52
611,60
616,63
493,67
572,11
745,12
483,75
637,75
218,251
444,72
305,75
746,64
444,98
342,117
272,85
128,275
500,75
654,65
241,150
217,150
426,131
155,153
841,66
737,70
722,70
754,60
664,60
688,60
796,55
799,62
229,150
232,95
116,480
340,49
501,65

【问题讨论】:

你能发布一些示例数据(或生成示例数据的代码)吗?您能否对基础数据进行转换,然后拟合您的模型? 那里,我添加了数据 【参考方案1】:

如果我理解正确,您希望使用 y = a * exp(-b * (x - c)) + d 之类的函数来拟合数据。

我不确定 sklearn 是否可以做到。但是你可以使用 scipy.optimize.curve_fit() 来用你定义的任何函数来拟合你的数据。(scipy):

对于您的情况,我对您的数据进行了实验,结果如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

my_data = np.genfromtxt('yourdata.csv', delimiter=',')
my_data = my_data[my_data[:,0].argsort()]
xdata = my_data[:,0].transpose()
ydata = my_data[:,1].transpose()

# define a function for fitting
def func(x, a, b, c, d):
    return a * np.exp(-b * (x - c)) + d

init_vals = [50, 0, 90, 63]
# fit your data and getting fit parameters
popt, pcov = curve_fit(func, xdata, ydata, p0=init_vals, bounds=([0, 0, 90, 0], [1000, 0.1, 200, 200]))
# predict new data based on your fit
y_pred = func(200, *popt)
print(y_pred)

plt.plot(xdata, ydata, 'bo', label='data')
plt.plot(xdata, func(xdata, *popt), '-', label='fit')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

我发现b 的初始值对于拟合至关重要。我估计了一个小范围,然后拟合数据。

如果您对xy之间的关系没有先验知识,可以使用sklearn提供的回归方法,如线性回归、核岭回归(KRR)、最近邻回归、高斯过程回归等. 拟合非线性数据。 Find the documentation here

【讨论】:

是的,我想就是这样,谢谢,我会试试的。顺便一提;有没有一种 scipy 方法可以给它数据并让它决定使用什么模型?自动制作线性、多项式、对数等,检查什么是最好的并应用该模型?还是我必须手动完成?? @AlvaroHernandorena 我认为没有一种方法可以自动完成。但是你可以自己写一个脚本,定义几个函数,然后按照我回答的代码。 tnx 为你的答案,我最终这样做了,curve_fit 与自定义 func,起初它没有工作它只是一直说它找不到参数,直到我开始玩有界限,过了一会儿我明白当x = 0时'a + d'是y,'b'也很重要,所以我使用数据中的关系设置界限(我发现x和y的最大值和最小值在数据上并使用它; a = 3*maxX, b = 10*maxX , c = minY *3 ) 现在工作正常。再次感谢您! 有没有像对数变换之类的东西,比如多项式特征? ***.com/questions/54949969/… 这可以通过绘制y_pred 的x 值来改进,这些x 值恰好存在于xdata 中。例如1000 个预测数据点:x_pred = np.linspace(min(xdata), max(xdata), num=1000); y_pred = func(x_pred, *popt); plt.plot(x_pred, y_pred, '-', label='fit')【参考方案2】:

您正在查看exponentially distributed 数据。

您可以通过对数转换 y 变量,然后使用线性回归。这是因为 y 的较大值比较小的值更容易被压缩。

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import expon

x = np.linspace(1, 10, 10)
y = np.array([30, 20, 12, 8, 7, 4, 3, 2, 2, 1])
y_fit = expon.pdf(x, scale=2)*100

fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x, y)
ax.plot(x, y_fit)
ax.set_ylabel('y (blue)')
ax.grid(True)

ax2 = ax.twinx()
ax2.scatter(x, np.log(y), color='red')
ax2.set_ylabel('log(y) (red)')

plt.show()

【讨论】:

好的,所以不需要sklearn?但是我该如何基于此进行预测呢? 您仍然可以使用 scikit-learn LinearRegression 进行回归。或者您可以查看statsmodels 库。假设您要进行预测 yhat = alpha+beta*x0。您必须将 yhat 转换回您的空间,即 np.exp(yhat) 我刚刚找到了这个great explanation。 好的,我想我明白了。获取我的数据并通过应用 log 函数使其成为线性,然后对转换后的数据进行线性回归,预测,最后应用 exp 函数转换预测值。是这样吗?? 没错。您还应该绘制对数转换的数据,以查看拟合是否真正是线性的。您可能仍需要使用 poly fit,但拟合效果会比使用原始数据好得多。【参考方案3】:

要使用 sklearn,您可以先将您的案例 y = Aexp(-BX) 改造成 ln(Y) = ln(A) - BX,然后使用 LinearRegressor 来训练和拟合您的数据。

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

### Read Data
df = pd.read_csv('data.csv')

### Prepare X, Y & ln(Y)
X = df.sort_values(by=['x']).loc[:, 'x':'x']
Y = df.sort_values(by=['x']).loc[:, 'y':'y']
ln_Y = np.log(Y)

### Use the relation ln(Y) = ln(A) - BX to fit X to ln(Y)
from sklearn.linear_model import LinearRegression
exp_reg = LinearRegression()
exp_reg.fit(X, ln_Y)
#### You can introduce weights as well to apply more bias to the smaller X values, 
#### I am transforming X arbitrarily to apply higher arbitrary weights to smaller X values
exp_reg_weighted = LinearRegression()
exp_reg_weighted.fit(X, ln_Y, sample_weight=np.array(1/((X - 100).values**2)).reshape(-1))

### Get predicted values of Y
Y_pred = np.exp(exp_reg.predict(X))
Y_pred_weighted = np.exp(exp_reg_weighted.predict(X))

### Plot
plt.scatter(X, Y)
plt.plot(X, Y_pred, label='Default')
plt.plot(X, Y_pred_weighted, label='Weighted')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()

plt.show()

【讨论】:

对我来说,我改变了这一行,它工作正常:exp_reg_weighted.fit(X, ln_Y, sample_weight=np.array(1/((X - 100)**2)).reshape(-1))

以上是关于我可以对 sklearn 进行对数回归吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在sklearn中获得逻辑回归模型的对数似然?

这是多类回归的一个很好的对数损失吗?

如何使用 sklearn 训练算法对数据点进行加权

对目标变量进行对数转换后如何解释线性回归的结果?

获取 sklearn 逻辑回归的边际效应

使用 sklearn 在 python 中执行逻辑回归分析