Многомерная полиномиальная регрессия второго порядка Python

Я имею дело с проблемами многомерной регрессии. Мой набор данных выглядит примерно так: X = (nsample, nx) и Y = (nsample, ny). nx и ny могут различаться в зависимости от разных наборов данных для разных случаев, поэтому они должны быть общими в коде.

Я хотел бы определить коэффициенты для многомерной полиномиальной регрессии, минимизирующие среднеквадратичную ошибку. Я решил разделить проблему на ny разных регрессий, поэтому для каждой из них мой набор данных равен X = (nsample, nx) и Y = (nsample, 1). Итак, для каждой зависимой переменной (Uj) полином второго порядка имеет следующий вид:

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

Я закодировал функцию в python как:

def func(x,nx,pars0,pars1,pars2):
  y = pars0 #pars0 = bias
  for i in range(nx):
    y = y + pars1[i]*x[i] #pars1 linear coeff (beta_i in the equation)
    for j in range(nx):
        if (j < i ):
            continue
        y = y + pars2[i,j]*x[i]*x[j] 
        #diag pars2 =  coeff of x^2 (beta_ii in the equation)
        #upper triangle pars2 = coeff of x_i*x_k (beta_ik in the equation)
  return y

и среднеквадратическая ошибка как:

def resid(nsample,nx,pars0,pars1,pars2,x,y):
  res=0.0
  for i in range(nsample):
    y_pred = func(nx,pars0,pars1,pars2,x[i])
    res=res+((y_pred - y[i]) ** 2)
  res=res/nsample
  res=res**0.5
  return res

Для определения коэффициентов я думал использовать scipy.optmize.minimize, но это не работает example_1 example_2 . Любые идеи или советы? Должен ли я использовать sklearn?

-> РЕДАКТИРОВАТЬ: Данные теста игрушек nx = 3, ny = 1

0.20    -0.02   0.20    1.0229781
0.20    -0.02   0.40    1.0218807
0.20    -0.02   0.60    1.0220439
0.20    -0.02   0.80    1.0227083
0.20    -0.02   1.00    1.0237960
0.20    -0.02   1.20    1.0255770
0.20    -0.02   1.40    1.0284888
0.20    -0.06   0.20    1.0123552
0.24    -0.02   1.40    1.0295350
0.24    -0.06   0.20    1.0125935
0.24    -0.06   0.40    1.0195798
0.24    -0.06   0.60    1.0124632
0.24    -0.06   0.80    1.0131748
0.24    -0.06   1.00    1.0141751
0.24    -0.06   1.20    1.0153533
0.24    -0.06   1.40    1.0170036
0.24    -0.10   0.20    1.0026915
0.24    -0.10   0.40    1.0058125
0.24    -0.10   0.60    1.0055921
0.24    -0.10   0.80    1.0057868
0.24    -0.10   1.00    1.0014004
0.24    -0.10   1.20    1.0026257
0.24    -0.10   1.40    1.0024578
0.30    -0.18   0.60    0.9748765
0.30    -0.18   0.80    0.9753220
0.30    -0.18   1.00    0.9740970
0.30    -0.18   1.20    0.9727272
0.30    -0.18   1.40    0.9732258
0.30    -0.20   0.20    0.9722360
0.30    -0.20   0.40    0.9687567
0.30    -0.20   0.60    0.9676569
0.30    -0.20   0.80    0.9672319
0.30    -0.20   1.00    0.9682354
0.30    -0.20   1.20    0.9674461
0.30    -0.20   1.40    0.9673747
0.36    -0.02   0.20    1.0272033
0.36    -0.02   0.40    1.0265790
0.36    -0.02   0.60    1.0271688
0.36    -0.02   0.80    1.0277286
0.36    -0.02   1.00    1.0285388
0.36    -0.02   1.20    1.0295619
0.36    -0.02   1.40    1.0310734
0.36    -0.06   0.20    1.0159603
0.36    -0.06   0.40    1.0159753
0.36    -0.06   0.60    1.0161890
0.36    -0.06   0.80    1.0153346
0.36    -0.06   1.00    1.0159790
0.36    -0.06   1.20    1.0167520
0.36    -0.06   1.40    1.0176916
0.36    -0.10   0.20    1.0048287
0.36    -0.10   0.40    1.0034699
0.36    -0.10   0.60    1.0032798
0.36    -0.10   0.80    1.0037224
0.36    -0.10   1.00    1.0059301
0.36    -0.10   1.20    1.0047114
0.36    -0.10   1.40    1.0041287
0.36    -0.14   0.20    0.9926268
0.40    -0.08   0.80    1.0089013
0.40    -0.08   1.20    1.0096265
0.40    -0.08   1.40    1.0103305
0.40    -0.10   0.20    1.0045464
0.40    -0.10   0.40    1.0041031
0.40    -0.10   0.60    1.0035650
0.40    -0.10   0.80    1.0034553
0.40    -0.10   1.00    1.0034699
0.40    -0.10   1.20    1.0030276
0.40    -0.10   1.40    1.0035284
0.40    -0.10   1.60    1.0042166
0.40    -0.14   0.20    0.9924336
0.40    -0.14   0.40    0.9914971
0.40    -0.14   0.60    0.9910082
0.40    -0.14   0.80    0.9903772
0.40    -0.14   1.00    0.9900816

person Drugo    schedule 12.04.2021    source источник
comment
Не могли бы вы поделиться тестовыми данными?   -  person Willem Hendriks    schedule 12.04.2021
comment
Я отредактировал вопрос, добавив несколько игрушечных тестовых данных, которые я использую для тестирования своего кода.   -  person Drugo    schedule 13.04.2021
comment
Каковы ожидаемые значения pars'? Это переменные, которые нужно оптимизировать правильно?   -  person Warlax56    schedule 13.04.2021
comment
Кроме того, я сгенерировал некоторые значения для значений pars, но когда я запускаю результат через resid, он терпит неудачу в y_pred = func(nx,pars0,pars1,pars2,x[i]), предположительно потому, что nx в resid передается x в func   -  person Warlax56    schedule 13.04.2021


Ответы (4)


Минимизация ошибок — огромная и сложная проблема. Таким образом, многие очень умные люди придумали много крутых решений. Вот некоторые из них:

(из всех я думаю, что байесовская оптимизация с помощью sklearn может быть хорошим выбором для вашего варианта использования, хотя я никогда не использовал его)

(также удалите последние s в URL-адресе изображения, чтобы увидеть полный размер)

Случайные подходы:

  • генетические алгоритмы: форматирует вашу проблему, как хромосомы в геноме, и выводит оптимальное решение (мой личный фаворит)

ga процесс

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

Имитация отжига

  • случайный поиск: лучше, чем кажется. случайным образом проверяет истинность входных переменных.

Изображение случайного поиска

  • Поиск по сетке: прост в реализации, но часто менее эффективен, чем методы, использующие настоящую случайность (повторное исследование). вдоль определенной оси интереса. Эта стратегия часто тратит вычислительные ресурсы впустую)

Изображение для поиска в сетке

Многие из них возникают при оптимизации гиперпараметров для моделей машинного обучения.

Более предписывающие подходы:

  • Градиентный спуск: использует градиент, вычисленный в дифференцируемой функции, для перехода к локальным минимумам.

Градиентный спуск

Байсовская оптимизация

  • scipy.optimize.minimize: я знаю вы уже используете это, но есть 15 различных алгоритмов, которые можно использовать, изменив флаг method.

Руб

в то время как минимизация ошибок концептуально проста, на практике сложные топологии ошибок в многомерных пространствах могут быть очень трудными для эффективного прохождения. Он соответствует локальным и глобальным экстремумам, проблеме исследования/использования и нашему математическому пониманию. что такое вычислительная сложность. Часто хорошее уменьшение ошибок достигается за счет сочетания глубокого понимания проблемы и экспериментов с несколькими алгоритмами и гиперпараметрами. В ML это часто называется настройкой гиперпараметров и, если хотите, является своего рода шагом по уменьшению мета-ошибок.

Да, есть загвоздка

примечание: не стесняйтесь рекомендовать другие методы оптимизации, я добавлю их в список.

person Warlax56    schedule 12.04.2021
comment
Я бы добавил градиентный спуск (и даже поставил его на первое место в списке). Хороший список кстати! - person Joseph Budin; 12.04.2021

У меня есть пример с использованием имитации отжига, как указано в хорошем списке в этой теме.

Во-первых, мне нужно загрузить данные и определить целевую функцию. Я сохранил ваши данные в data.csv и загрузил с помощью

import pandas as pd
data = pd.read_csv("../data.csv", sep="   ", header=None, engine='python')

И получите свои значения с помощью

X = data[ [0,1,2] ].values
Y = data[ 3 ].values

Я определяю вашу полифункцию с помощью

from itertools import combinations

def poly_function(X, beta):
    X_dimension = X.shape[1]

    i,j = zip( *list(combinations( range(X_dimension), 2)) )
    X_cross = X[:,i] * X[:,j] 
    X_expanded = np.concatenate([X,X**2,X_cross] , axis=1)
    
    assert X_expanded.shape[1] == beta.shape[0], "Expect beta to be of size {}".format(X_expanded.shape[1])
    
    return np.matmul(X_expanded, beta)

Для имитации отжига нам просто нужна объективная

def obj(beta,X=X,Y=Y):
    
    Y_hat = poly_function(X, beta)
    
    BOOSTER = 10**5
    
    return BOOSTER * np.mean( (Y-Y_hat)**2 )**.5

и некоторые предложения

def small_delta(beta):
    new_beta = beta.copy()
    
    random_index = np.random.randint(0,new_beta.shape[0])
    
    new_beta[ random_index ] += (np.random.random() - .5) * .01
 
    return new_beta

def large_delta(beta):
    new_beta = beta.copy()
    
    random_index = np.random.randint(0,new_beta.shape[0])
    
    new_beta[ random_index ] += np.random.random() - .5 
 
    return new_beta

И рандомный старт

def random_beta():
    return np.random.random(size=9)

И СА с

import frigidum


local_opt = frigidum.sa(random_start=random_beta, 
                        neighbours=[small_delta, large_delta], 
                        objective_function=obj, 
                        T_start=10**2, 
                        T_stop=10**-12, 
                        repeats=10**3, 
                        copy_state=frigidum.annealing.copy)

RMSE, который я нашел с вашими данными, был около 0.026254 с бета-версией.

array([ 7.73168440e+00,  2.93929578e+00,  4.10133180e-02, -1.37266444e+01,
       -3.43978686e+00, -1.12816177e-02, -1.00262307e+01, -3.12327590e-02,
        9.07369588e-02])

где вам нужно знать, что он построен как (X1,X2,X3,X1**2, X2**2, X3**2, X1*X2,X1*X3,X2*X3)


Более длительный запуск с большим количеством повторов может привести к ошибке 0.026150 с бета-версией.

array([ 7.89212770e+00,  3.24138652e+00,  1.24436937e-02, -1.41549553e+01,
       -3.31912739e+00, -5.54411310e-03, -1.08317125e+01,  2.09684769e-02,
        6.84396750e-02])
person Willem Hendriks    schedule 14.04.2021

Вы можете попробовать statsmodelslibrary в сочетании с объяснением по этой ссылке, чтобы соответствовать полиномиальным моделям. https://ostwalprasad.github.io/machine-learning/Polynomial-Regression-using-statsmodel.html

person jhmt    schedule 28.04.2021

После некоторых проб и ошибок я, наконец, нашел решение. Задачу можно рассматривать как линейную с использованием замены переменных. Я использовал scikit- научиться строить модель. После некоторых тестов на реальных случаях это работает очень хорошо

person Drugo    schedule 06.05.2021