77from ..kernel .preprocessing import asinterval
88
99
10- class LIGAM (object ):
10+ class ISPAE (object ):
1111
12- def __init__ (self , alpha = 0 , beta = 1 ):
12+ def __init__ (self , alpha = 0 , beta = 1 , basis = 'monom' ):
1313 """
1414 Linear Interval Generalized Additive Model
1515 """
1616 self .alpha = alpha
1717 self .beta = beta
18+
19+ self .__bases = {
20+ 'monom' : np .polynomial .polynomial .Polynomial .basis ,
21+ 'chebyshev' : np .polynomial .chebyshev .Chebyshev .basis ,
22+ 'hermite' : np .polynomial .hermite .Hermite .basis ,
23+ 'laguerre' : np .polynomial .laguerre .Laguerre .basis ,
24+ 'legendre' : np .polynomial .legendre .Legendre .basis ,
25+ }
26+ self .basis = self .__bases [basis ]
1827
1928
2029 def _wrap_norm (self , residual , norm ):
@@ -30,26 +39,42 @@ def _wrap_norm(self, residual, norm):
3039 return obj , mcs
3140
3241
33- def value_of_one_col (self , beta , x ):
42+ def value_of_one_col (self , beta , x , deg = None ):
3443 """
44+ if basis is 'monom'
3545 y = beta[0]*x + ... + beta[N-1]*x**(N-2) + beta[N]*x**(N-1)
3646 """
37- def _value_of_one_element (inf , sup ):
38- roots = np .roots ( np .polyder (beta , m = 1 ) ) # roots of the first deriv
39- roots = roots [np .isreal (roots )].real # only real roots
40- roots = roots [(inf <= roots ) & (roots <= sup )] # only in interval (bounded)
41- roots = [inf , sup ] + list (roots )
42- vals = np .array ([np .polyval (beta , root ) for root in roots ])
43- return Interval (min (vals ), max (vals ), sortQ = False )
44-
45- infs , sups = inf (x ), sup (x )
46- # need reverse for np.polyder, np.polyval
47- # the fictitious zero coefficient is needed for the free term
48- beta = np .array ([0 ] + list (beta ))[::- 1 ]
49- if hasattr (x , '__iter__' ):
50- res = asinterval ([_value_of_one_element (inf , sup ) for inf , sup in zip (infs , sups )])
47+ #+-----+-----+-----+-----+-----+
48+ # initialization block
49+ infs , sups = np .array ([inf (x )]).flatten (), np .array ([sup (x )]).flatten ()
50+ beta = np .array ([beta ]).flatten ()
51+ if deg is None :
52+ basis = np .array ([self .basis (k ) for k in range (1 , len (beta )+ 1 )])
5153 else :
52- res = _value_of_one_element (infs , sups )
54+ deg = np .array ([deg ]).flatten ()
55+ text = 'The length of the array for the degree of the basis polynomial must match the length of the array of beta coefficients.'
56+ assert len (deg ) == len (beta ), text
57+ basis = np .array ([self .basis (d ) for d in deg ])
58+
59+ #+-----+-----+-----+-----+-----+
60+ poly = beta @ basis
61+ roots = poly .deriv (1 ).roots ().real
62+
63+ vals = np .zeros ( (len (infs ), 2 + len (roots )) , dtype = float )
64+ vals [:, 0 ] = poly (infs )
65+ vals [:, 1 ] = poly (sups )
66+ vals [:, 2 :] = poly (roots )
67+
68+ dots = np .zeros ( (len (infs ), 2 + len (roots )) , dtype = float )
69+ dots [:, 0 ] = infs
70+ dots [:, 1 ] = sups
71+ dots [:, 2 :] = roots
72+ masks = (infs [:, np .newaxis ] <= dots ) & (dots <= sups [:, np .newaxis ])
73+
74+ res = asinterval ([
75+ Interval (min (val [mask ]), max (val [mask ]), sortQ = False )
76+ for val , mask in zip (vals , masks )
77+ ])
5378 return res
5479
5580
@@ -105,8 +130,8 @@ def _expand_dataframe(self, dataframe):
105130 X_expand = pd .DataFrame ()
106131 nit = 0
107132 for k , col in enumerate (self .columns ):
108- for l in range (1 , self .order [k ]+ 1 ):
109- X_expand [nit ] = dataframe [col ]** l
133+ for deg in range (1 , self .order [k ]+ 1 ):
134+ X_expand [nit ] = self . value_of_one_col ( 1 , dataframe [col ], deg = deg ) # self.basis(d)(dataframe[col])
110135 nit = nit + 1
111136 return X_expand
112137
@@ -120,7 +145,7 @@ def fit(
120145 weight = None ,
121146 objective = 'Tol' ,
122147 norm = 'inf' ,
123- constraint = None ,
148+ constraint = None ,
124149 ** kwargs
125150 ):
126151 #+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
@@ -131,7 +156,7 @@ def fit(
131156 assert len (order )== m , 'Inconsistent order array sizes and the number of parameters.'
132157 else :
133158 order = np .full (m , order )
134- self .order = order
159+ self .order = np . array ( order )
135160
136161 X_expand = self ._expand_dataframe (X_train )
137162 infX , supX = inf (X_expand ), sup (X_expand )
@@ -162,7 +187,6 @@ def fit(
162187 #+-----+-----+-----+-----+-----+-----+
163188 if weight is None :
164189 weight = np .ones (n )
165- # äåëàåì ñãëàæèâàíèå
166190 weight [0 ] = self .beta * weight [0 ]* (1 - self .alpha )
167191 for k in range (1 , n ):
168192 weight [k ] = self .beta * (weight [k ]* (1 - self .alpha ) + self .alpha * weight [k - 1 ])
0 commit comments