Могу ли я сделать логарифмическую регрессию на sklearn?

Я не знаю, подходит ли термин «логарифмическая регрессия», мне нужно подогнать кривую к моим данным, как полиномиальную кривую, но сглаживаясь на конце.

Вот изображение, синяя кривая - это то, что у меня есть (полиномиальная регрессия 2-го порядка), а пурпурная кривая - это то, что мне нужно.

введите описание изображения здесь

Я много искал и не могу найти этого, только линейную регрессию, полиномиальную регрессию, но не логарифмическую регрессию на 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

person Alvaro Hernandorena    schedule 23.09.2017    source источник
comment
Можете ли вы опубликовать образцы данных (или код для создания примеров данных)? Сможете ли вы преобразовать базовые данные, а затем подогнать их под свою модель?   -  person Greg Reda    schedule 23.09.2017
comment
Там я добавил данные   -  person Alvaro Hernandorena    schedule 23.09.2017


Ответы (3)


Если я правильно понимаю, вы хотите уместить данные с помощью функции типа 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 имеет решающее значение для подгонки. Я оценил небольшой диапазон для этого, а затем сопоставил данные.

Если у вас нет априорных знаний о взаимосвязи между x и y, вы можете использовать методы регрессии, предоставляемые sklearn, такие как линейная регрессия, регрессия гребня ядра (KRR), регрессия ближайших соседей, регрессия гауссовского процесса и т. Д., Чтобы соответствовать нелинейным данным. Здесь можно найти документацию

person Jack Chi    schedule 23.09.2017
comment
Да, думаю, все, спасибо, попробую. Кстати; есть ли scipy метод, чтобы предоставить ему данные и решить, какую модель использовать? Автоматически делать линейные, полиномиальные, логарифмические и т. Д., Проверять, что лучше, и применять эту модель? Или надо вручную делать ?? - person Alvaro Hernandorena; 23.09.2017
comment
@AlvaroHernandorena Я не думаю, что есть способ сделать это автоматически. Но вы можете написать сценарий самостоятельно, определив несколько функций, а затем следуя кодам в моих ответах. - person Jack Chi; 24.09.2017
comment
tnx для вашего ответа, я закончил тем, что сделал это, curve_fit с пользовательской функцией, сначала он не работал, он просто говорит, что не может найти параметры, пока я не начал играть с границами, и через некоторое время Я понял, что 'a + d' - это y, когда x = 0, и 'b' также важен, поэтому я установил границы, используя отношения из данных (я нашел максимальные и минимальные значения x и y в данных и использую их; a = 3 * maxX, b = 10 * maxX, c = minY * 3) и теперь работает отлично. еще раз спасибо! - person Alvaro Hernandorena; 24.09.2017
comment
Есть ли что-то вроде логарифмического преобразования, например, полиномиальных функций? stackoverflow.com/questions/54949969/ - person taga; 04.03.2019
comment
Это можно улучшить, построив y_pred для значений 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') - person ijoseph; 27.09.2020

Вы просматриваете данные экспоненциально распределенные.

Вы можете преобразовать свою 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()

введите описание изображения здесь

person binjip    schedule 23.09.2017
comment
ок, значит, склеарн не нужен? но как мне сделать прогноз на основе этого? - person Alvaro Hernandorena; 23.09.2017
comment
Вы все еще можете использовать scikit-learn LinearRegression для регрессии. Или вы можете воспользоваться библиотекой statsmodels. Допустим, вы хотите сделать прогноз yhat = alpha + beta * x0. Вам придется преобразовать его обратно в свое пространство, т.е. np.exp(yhat) - person binjip; 23.09.2017
comment
Я только что нашел этот отличное объяснение. - person binjip; 23.09.2017
comment
Хорошо, думаю, я понимаю. Возьмите мои данные и сделайте их линейными, применив функцию журнала, затем сделайте линейную регрессию на этих преобразованных данных, спрогнозируйте и, наконец, преобразуйте предсказанное значение, применив функцию exp. Это правильно?? - person Alvaro Hernandorena; 23.09.2017
comment
Это правильно. Вы также должны нанести на график данные, преобразованные в журнал, чтобы увидеть, действительно ли соответствие является линейным. Возможно, вам все равно понадобится использовать полигональную подгонку, но она будет намного лучше, чем с исходными данными. - person binjip; 24.09.2017

Чтобы использовать sklearn, вы можете сначала переделать свой case 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()

введите описание изображения здесь

person chaooder    schedule 14.07.2019
comment
У меня меняю эту строчку, все работало нормально: exp_reg_weighted.fit(X, ln_Y, sample_weight=np.array(1/((X - 100)**2)).reshape(-1)) - person Redhwan; 15.09.2020