Как мы помещаем сигмовидную функцию в Python?

#python #python-3.x #numpy #scikit-learn #logistic-regression

#python #python-3.x #numpy #scikit-learn #логистическая регрессия

Вопрос:

По соображениям воспроизводимости я делюсь простым набором данных, над которым я работаю здесь.

Чтобы было понятно, что я делаю — из столбца 2 я считываю текущую строку и сравниваю ее со значением предыдущей строки. Если она больше, я продолжаю сравнивать. Если текущее значение меньше значения предыдущей строки, я хочу разделить текущее значение (меньшее) на предыдущее значение (большее). Соответственно, ниже приведен мой исходный код.

 import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import beta

protocols = {}

types = {"data_v": "data_v.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }
    plt.figure(); plt.clf()
    plt.plot(quotient_times, quotient, ".", label=protname, color="blue")
    plt.ylim(0, 1.0001)
    plt.title(protname)
    plt.xlabel("quotient_times")
    plt.ylabel("quotient")
    plt.legend()
    plt.show()
    sns.distplot(quotient, hist=False, label=protname)
  

Это дает следующие графики.

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

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

Как мы можем видеть из графиков

  • Data-V имеет коэффициент 0,8, когда quotient_times меньше 3, и коэффициент остается 0,5, если quotient_times больше 3.

Я также встроил ее в бета-дистрибутив, используя следующий код

 xt = plt.xticks()[0]  
xmin, xmax = min(xt), max(xt)  
lnspc = np.linspace(xmin, xmax, len(quotient))

alpha,beta,loc,scale = stats.beta.fit(quotient)  
pdf_beta = stats.beta.pdf(lnspc, alpha, beta,loc, scale)  
plt.plot(lnspc, pdf_beta, label="Data-V", color="darkblue", alpha=0.9)
plt.xlabel('$quotient$')
#plt.ylabel(r'$p(x|alpha,beta)$')
plt.title('Beta Distribution')
plt.legend(loc="best", frameon=False)
  

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

Как мы можем вписать quotient (определенное выше) в сигмовидную функцию, чтобы получить график примерно следующего вида?

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

Комментарии:

1. Я рекомендую вам пакет lmfit. Здесь у вас есть простой способ реализовать ваши собственные подогнанные функции. (Надеюсь, я правильно понял вашу проблему)

2. lmfit для сигмовидной функции? Я раньше с этим не работал, но можешь попробовать с набором данных, которым я поделился, Ричард? Спасибо.

3. Разве подгонка набора данных в sigmoid не такая же, как использование классификатора sigmoid? Вам просто нужно извлечь параметры. В Scikit learn есть сигмовидный классификатор, который очень прост в использовании.

4. Я сделал что-то очень похожее в R, поможет ли это, если я поделюсь этим?

5. @MedImage, спасибо, но я хочу это на Python. Если бы вы могли поделиться своим ответом на Python с теми же данными, которыми поделился я, это было бы здорово, и я отмечу это как принятый ответ.

Ответ №1:

Вы хотите подогнать sigmoid или фактически логистическую функцию. Это можно изменять несколькими способами, такими как наклон, средняя точка, величина и смещение.

Вот код, который определяет эту sigmoid функцию и использует scipy.optimize.curve_fit функцию для минимизации ошибки путем настройки параметров.

 from scipy.optimize import curve_fit

def sigmoid (x, A, h, slope, C):
    return 1 / (1   np.exp ((x - h) / slope)) *  A   C

# Fits the function sigmoid with the x and y data
#   Note, we are using the cumulative sum of your beta distribution!
p, _ = curve_fit(sigmoid, lnspc, pdf_beta.cumsum())

# Plots the data
plt.plot(lnspc, pdf_beta.cumsum(), label='original')
plt.plot(lnspc, sigmoid(lnspc, *p), label='sigmoid fit')
plt.legend()

# Show parameters for the fit
print(p)
  

Это дает вам следующий график:

сравнение исходных данных и подгонки сигмоида

и следующее пространство параметров (для вышеупомянутой используемой функции):

 [-1.82910694e 01  4.88870236e-01  6.15103201e-03  1.82895890e 01]
  

Если вы хотите подогнать переменные quotient_time и quotient , вы просто меняете переменные.

 ...
p, _ = curve_fit(sigmoid, quotient_times, quotient)
...
  

и отобразить ее:

частное и сигмовидная подгонка

Комментарии:

1. Я все еще не уверен, действительно ли это то, чего вы «хотите» (с научной точки зрения), но это то, о чем вы просили 😉

2. Да, это именно то, о чем я спрашивал, но не могли бы вы попробовать это с набором данных, которым я поделился?

3. @Brown, это твой набор данных! Это совокупная сумма бета-дистрибутива.

4. Действительно? Тогда куда вы передаете бета-версию данных? Может быть, мне принести кофе:-D

5. @Brown, это pdf_beta.cumsum() команда, pdf_beta именно то, что вы указали в своем примере кода. Я дополнительно предоставил теперь подгонку quotient и quotient_times (в качестве вашего первого графика). Надеюсь, это поможет. И когда данные распределены настолько неоднородно, то подгонка, скорее всего, будет не слишком хорошей.