Подгонка точек к обведенной линии - PullRequest
0 голосов
/ 14 мая 2018

У меня есть набор точек, который находится между -360 и 360 градусов. В настоящее время я пытаюсь провести линию через них, не разворачивая набор данных. Есть ли способ изменить модель LinearRegression от Scikit? В противном случае, каков наилучший способ написания алгоритма подгонки линий, который бы учитывал перенос в модели данных?

enter image description here

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

При интересных уровнях шума, возможно, нельзя избежать грубой силы.

Вот квадратные ошибки (с использованием расстояния обтекания) как функция наклона (лучший перехват выбран в каждой точке) для трех моделейс уровнями шума 90, 180, 180 и 64, 96, 128 точек данных (см. скрипт ниже).

enter image description here

Я не уверен, что тамэто умный способ надежного поиска глобальных минимумов из них.

OTOH, грубая сила работает достаточно хорошо, даже в случаях, которые выглядят довольно сложно, как нижний.Пунктирная линия - истинная модель без шума, точки - фактические данные, полученные путем добавления шума к истинной модели, сплошная линия - реконструкция.

enter image description here

Код:

import numpy as np
import scipy.optimize as so
from operator import attrgetter
from matplotlib import pylab

def setup(interc, slope, sigma, N):
    x = np.random.uniform(0.1, 2.0, (N,)).cumsum()
    y = (interc + x*slope + np.random.normal(0, sigma, (N,)) + 360) % 720 - 360
    return x, y

def err_model_full(params, x, y):
    interc, slope = params
    err = (interc + x*slope - y + 360) % 720 - 360
    return np.dot(err, err)

def err_model(interc, slope, x, y):
    err = (interc + x*slope - y + 360) % 720 - 360
    return np.dot(err, err)

for i, (interc, slope, sigma, N) in enumerate([(100, -12, 90, 64),
                                               (-30, 20, 180, 96),
                                               (66, -49, 180, 128)]):

    # create problem
    x, y = setup(interc, slope, sigma, N)

    # brute force through slopes
    slps = np.linspace(-128, 128, 257)
    ics, err = zip(*map(attrgetter('x', 'fun'), (so.minimize(err_model, (0,), args = (sl, x, y)) for sl in slps)))
    best = np.argmin(err)
    # polish
    res = so.minimize(err_model_full, (ics[best], slps[best]), args = (x, y))

    # plot

    pylab.figure(1)
    pylab.subplot(3, 1, i+1)
    pylab.plot(slps, err)
    pylab.figure(2)
    pylab.subplot(3, 1, i+1)
    pylab.plot(x, y, 'o')
    ic_rec, sl_rec = res.x
    pylab.plot(x, (ic_rec + x*sl_rec + 360) % 720 - 360)
    pylab.plot(x, (interc + x*slope + 360) % 720 - 360, '--')

    print('true (intercept, slope)', (interc, slope), 'reconstructed',
          tuple(res.x))
    print('noise level', sigma)
    print('squared error for true params', err_model_full((interc, slope), x, y))
    print('squared error for reconstructed params', err_model_full(res.x, x, y))
pylab.figure(1)
pylab.savefig('bf.png')
pylab.figure(2)
pylab.savefig('recon.png')
0 голосов
/ 15 мая 2018

Это довольно интересная проблема, потому что у вас есть только одна функция в качестве входных данных, которая не содержит информации об упаковке.Самый простой способ, который приходит на ум, - это просто использовать метод ближайших соседей

from sklearn.neighbors import KNeighborsRegressor
import numpy as np

####################
# Create some data
n_points = 100
X = np.linspace(0, 1, n_points) - 0.3
y = (X*720*2 % 720) - 360
y = y + np.random.normal(0, 15, n_points)
X = X.reshape(-1, 1)
#######################

knn = KNeighborsRegressor()
knn.fit(X, y)

lspace = np.linspace(0, 1, 1000) - 0.3
lspace = lspace.reshape(-1, 1)
plt.scatter(X, y)
plt.plot(lspace, svr.predict(lspace), color='C1')

KNN example

Однако если вам нужно, чтобы он был кусочно-линейным, то яПредлагаю вам посмотреть это сообщение в блоге

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...