Как организовать коэффициенты 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)