Как организовать коэффициенты PolynomialFeatures в лексикографическом порядке, чтобы они совпадали с многовариантным полиномом?

У меня был набор параметров, которые я вручную (я хочу сделать это вручную) подгонял к псевдообратному с использованием PolynomialFeatures:

poly_feat = PolynomialFeatures(degree=Degree_mdl)
Kern_train = poly_feat.fit_transform(X_train)
c_pinv = np.dot(np.linalg.pinv( Kern_train ),Y_train)

затем у меня был многомерный многочлен, который я упростил с помощью sympy с помощью класса poly и coeffs() функция. Тем не менее, функция coeffs говорит, что возвращает ненулевые коэффициенты в лексном порядке. Таким образом, я просто хотел узнать, как я могу получить порядок PolynomialFeatures, чтобы соответствовать вышеуказанному, чтобы я мог сравнивать коэффициенты по терминам, если мне нужно.

Кто-нибудь знает, как сопоставить порядок двух, чтобы такое сравнение было возможно?


Я знаю, что означает лексикографический порядок, глядя на документацию по mathematica, которая, на мой взгляд, имеет для меня интуитивный смысл (в основном лексикографический порядок определяется степенью монома, поэтому xy x^2 и y^2 имеют одинаковый порядок и "больше" "чем любой степени один термин, как х или у). Тем не менее, я думаю, что детали сводятся к тому, чтобы выяснить, как симпози против PolynomialFeatures упорядочить вещи. Sympy говорит, что заказывает лексикографически, но когда я проверяю свои полиномы, кажется, что он не подчиняется порядку, который я ожидал (в то время как PolyFeatures подчиняется некоторому порядку, но затем ломается умирает каким-то неизвестным для меня образом, когда у него несколько членов одного порядка, например х ^ 2у, ху ^2, у ^2). Так вот что получилось, когда я осмотрел симпы:

(Pdb) s_expr
Poly(-4.92243832500572e-13*x1**3 - 3.86418002630562e-13*x1**2*x2 - 284.848327636719*x1**2 - 1.97301728991142e-13*x1*x2**2 - 11.1939144134521*x1*x2 + 66.1333587984857*x1 - 1.35329085177577e-13*x2**3 - 108.171173095703*x2**2 + 28.227414137076*x2 - 11.0110442095318, x1, x2, domain='RR')
(Pdb) s_expr.coeffs()
[-4.92243832500572e-13, -3.86418002630562e-13, -284.848327636719, -1.97301728991142e-13, -11.1939144134521, 66.1333587984857, -1.35329085177577e-13, -108.171173095703, 28.2274141370760, -11.0110442095318]
(Pdb) s_expr.coeffs()[::-1]
[-11.0110442095318, 28.2274141370760, -108.171173095703, -1.35329085177577e-13, 66.1333587984857, -11.1939144134521, -1.97301728991142e-13, -284.848327636719, -3.86418002630562e-13, -4.92243832500572e-13]

и вот что вышло, когда я проверил PolynomailFeatures:

>>> xx
array([[2, 3]])
>>> poly_feat.fit_transform(xx)
array([[  1.,   2.,   3.,   4.,   6.,   9.,   8.,  12.,  18.,  27.]])
# maps to the following ordering:
## [1,x1,x2,x1^2,x1x2,x2^2,x1^3,x1^2x2,x1x2^2,x2^3]

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

Я взглянул на их исходный код, но не смог полностью переварить его, чтобы понять, что происходит (особенно на стороне симпати). Любая помощь приветствуется!

Я работал только с примерами с входными измерениями степени 3 и 2, но было бы хорошо, чтобы он работал для произвольных входных данных и степени.


Раздел щедрости: создание 3 измерения с работой 3 степени (и, надеюсь, выше)

Я пытался сопоставить коэффициенты для измерения 3 и степени 3, но по некоторым причинам они не совпадают. Кажется, что PolyFeatures не использует ни grevlex,grlex если у кого-то есть идеи, как это сделать, я бы с удовольствием это услышал. Я сделал коэффициенты полинома совпадают, что значение должно быть для этого монома, если входы где [x3,x2,x1] = [5,3,2] так, например, коэффициент для x3**2 имеет коэффициент 25 или если x2*x3**2 имеет коэффициент 75, Таким образом, я получаю вывод:

    x_poly_feat_list =  [1, 2, 3, 5, 4, 6, 10, 9, 15, 25, 8, 12, 20, 18, 30, 50, 27, 45, 75, 125]
    poly =  Poly(125*x3**3 + 75*x3**2*x2 + 50*x3**2*x1 + 25*x3**2 + 45*x3*x2**2 + 30*x3*x2*x1 + 15*x3*x2 + 20*x3*x1**2 + 10*x3*x1 + 5*x3 + 27*x2**3 + 18*x2**2*x1 + 9*x2**2 + 12*x2*x1**2 + 6*x2*x1 + 3*x2 + 8*x1**3 + 4*x1**2 + 2*x1 + 1, x3, x2, x1, domain='ZZ')
    c_grevlex =  [1, 2, 3, 5, 4, 6, 10, 9, 15, 25, 8, 12, 20, 18, 30, 50, 27, 45, 75, 125]
    c_grlex =  [1, 2, 3, 5, 4, 6, 9, 10, 15, 25, 8, 12, 18, 27, 20, 30, 45, 50, 75, 125]
    len(c_grlex) 20
    len(c_grevlex) 20
    len(x_poly_feat_list) 20
    all_match_grlex =  False
    all_match_grevlex =  False

что означает, что это не соответствует.

полный код:

from sklearn.preprocessing import PolynomialFeatures
import numpy as np
from sympy import *

# nb monomials (n+d,d), d=degree, n=# of inputs

def check(n,d,user_array=None):
    if user_array is None:
        x = np.arange(2,2+n).reshape(1,n) # e.g. array([[2, 3]])
    else:
        x = user_array.reshape(1,n)
    #x = np.arange(2,2+n).reshape(1,n) # e.g. array([[2, 3]])
    print('x = ', x)
    ##
    poly_feat = PolynomialFeatures(d)
    x_poly_feat = poly_feat.fit_transform(x)
    ##
    x_poly_feat_list = [ int(i) for i in x_poly_feat[0]]
    #print('x_poly_feat = ', x_poly_feat)
    #print('x_poly_feat = ', list(x_poly_feat[0]))
    print('x_poly_feat_list = ', x_poly_feat_list)
    return x_poly_feat_list

def check_sympy_degree():
    x3,x2,x1 = symbols('x3 x2 x1')
    poly = Poly( 125*x3**3 + 75*x2*x3**2 + 45*x2**2*x3 + 27*x2**3 + 50*x1*x3**2 + 30*x1*x2*x3 + 18*x1*x2**2 + 20*x1**2*x3 + 12*x1**2*x2
        + 8*x1**3 + 25*x3**2 + 15*x2*x3 + 9*x2**2 + 10*x1*x3 + 6*x1*x2 + 4*x1**2 + 2*x1 + 3*x2 + 5*x3 + 1,(x3,x2,x1) )
    c_grevlex = poly.coeffs(order='grevlex')
    c_grlex = poly.coeffs(order='grlex')
    print('poly = ',poly)
    print('c_grevlex = ', c_grevlex[::-1])
    print('c_grlex = ', c_grlex[::-1])
    return c_grlex, c_grevlex


if __name__ == '__main__':
    #check(n=2,d=3)
    ##
    x_poly_feat_list = check(n=3,d=3,user_array=np.array([2,3,5]))
    ##
    c_grlex, c_grevlex = check_sympy_degree()
    print('len(c_grlex)',len(c_grlex))
    print('len(c_grevlex)',len(c_grevlex))
    print('len(x_poly_feat_list)',len(x_poly_feat_list))
    all_match_grlex = all( c_grlex[i] == x_poly_feat_list for i in range(len(x_poly_feat_list)) )
    all_match_grevlex = all( c_grevlex[i] == x_poly_feat_list for i in range(len(x_poly_feat_list)) )
    print('all_match_grlex = ',all_match_grlex)
    print('all_match_grevlex = ',all_match_grevlex)

2 ответа

Итак, порядок многочленов PolynomialFeatures выглядит следующим образом:

1 + 2*x1 + 3*x2 + 4*x1**2 + 5*x1*x2 + 6*x2**2 + 7*x1**3 + 8*x1**2*x2 + 9*x1*x2**2 + 10*x2**3

и мы хотим, чтобы SymPy возвращал коэффициенты в указанном порядке: 1..10.

Первое, что нужно понять, это то, что это не лексикографический порядок, а градуированный (возможно, обратный?) Лексикографический порядок (см. Мономический порядок в Википедии). А именно, мономы сначала разделяются (то есть сортируются) по их общей степени, а затем в каждой группе применяется лексикографический порядок.

Метод SymPy coeffs поддерживает заказы 'lex' (лексикографический, по умолчанию), 'grlex' (градуированный лексикографический) и grevlex (обратный градуированный лексикографический). Однако для получения желаемого результата необходимо внести две корректировки:

  • при построении многочлена, объявите порядок переменных как (x2, x1) используя второй аргумент конструктора Poly.
  • перевернуть список коэффициентов из coeffs,

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

Пример:

q = Poly(1 + 2*x1 + 3*x2 + 4*x1**2 + 5*x1*x2 + 6*x2**2 + 7*x1**3 + 8*x1**2*x2 + 9*x1*x2**2 + 10*x2**3, (x2, x1))
c = q.coeffs(order='grevlex')[::-1]
print(c)

Это печатает [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Важно: grlex и grevlex совпадают для 1 и 2 переменных. Поскольку ваш пример состоит из 2 переменных, я не знаю, является ли 'grevlex' или 'grlex' в целом правильным; Я использовал 'grevlex' на догадку, но вы должны проверить это с полиномом от более чем 2 переменных.

Похоже, правильный ответ grevlex в соответствии с кодом, который я произвел. Надеюсь, что это помогает людям.

Код:

from sklearn.preprocessing import PolynomialFeatures
import numpy as np
from sympy import *

import pdb

# nb monomials (n+d,d), d=degree, n=# of inputs

def check(n,d,user_array=None):
    if user_array is None:
        x = np.arange(2,2+n).reshape(1,n) # e.g. array([[2, 3]])
    else:
        x = user_array.reshape(1,n)
    #x = np.arange(2,2+n).reshape(1,n) # e.g. array([[2, 3]])
    print('x = ', x)
    ##
    poly_feat = PolynomialFeatures(d)
    x_poly_feat = poly_feat.fit_transform(x)
    ##
    x_poly_feat_list = [ int(i) for i in x_poly_feat[0]]
    #print('x_poly_feat = ', x_poly_feat)
    #print('x_poly_feat = ', list(x_poly_feat[0]))
    print('x_poly_feat_list = ', x_poly_feat_list)
    return x_poly_feat_list

def check_sympy_degree():
    x3,x2,x1 = symbols('x3 x2 x1')
    poly = Poly( 125*x3**3 + 75*x2*x3**2 + 45*x2**2*x3 + 27*x2**3 + 50*x1*x3**2 + 30*x1*x2*x3 + 18*x1*x2**2 + 20*x1**2*x3 + 12*x1**2*x2
        + 8*x1**3 + 25*x3**2 + 15*x2*x3 + 9*x2**2 + 10*x1*x3 + 6*x1*x2 + 4*x1**2 + 2*x1 + 3*x2 + 5*x3 + 1,(x3,x2,x1) )
    c_grevlex = poly.coeffs(order='grevlex')[::-1]
    c_grlex = poly.coeffs(order='grlex')[::-1]
    print('poly = ',poly)
    return c_grevlex, c_grlex


if __name__ == '__main__':
    #check(n=2,d=3)
    ##
    x_poly_feat_list = check(n=3,d=3,user_array=np.array([2,3,5]))
    ##
    c_grevlex, c_grlex = check_sympy_degree()
    #c_grevlex = len(c_grevlex)*[-1]

    print('c_grevlex = ', c_grevlex)
    print('c_grlex = ', c_grlex)

    print('len(c_grevlex)',len(c_grevlex))
    print('len(c_grlex)',len(c_grlex))
    print('len(x_poly_feat_list)',len(x_poly_feat_list))

    match_grevlex_list = [ c_grevlex[i] == x_poly_feat_list[i] for i in range(len(x_poly_feat_list)) ]
    match_grlex_list = [ c_grlex[i] == x_poly_feat_list[i] for i in range(len(x_poly_feat_list)) ]

    all_match_grevlex = all( match_grevlex_list )
    all_match_grlex = all( match_grlex_list )

    print('match_grevlex_list = ',match_grevlex_list)
    print('match_grlex_list =',match_grlex_list)

    print('all_match_grevlex = ',all_match_grevlex)
    print('all_match_grlex = ',all_match_grlex)
Другие вопросы по тегам