@@ -570,6 +570,8 @@ class NARX(MultiOutputMixin, RegressorMixin, BaseEstimator):
570
570
The id numbers indicate which output the polynomial term belongs to.
571
571
It is useful in multi-output case.
572
572
573
+ fit_intercept : bool, default=True
574
+ Whether to fit the intercept. If set to False, intercept will be zeros.
573
575
574
576
Attributes
575
577
----------
@@ -641,6 +643,7 @@ class NARX(MultiOutputMixin, RegressorMixin, BaseEstimator):
641
643
"feat_ids" : [None , "array-like" ],
642
644
"delay_ids" : [None , "array-like" ],
643
645
"output_ids" : [None , "array-like" ],
646
+ "fit_intercept" : ["boolean" ],
644
647
}
645
648
646
649
def __init__ (
@@ -649,10 +652,12 @@ def __init__(
649
652
feat_ids = None ,
650
653
delay_ids = None ,
651
654
output_ids = None ,
655
+ fit_intercept = True ,
652
656
):
653
657
self .feat_ids = feat_ids
654
658
self .delay_ids = delay_ids
655
659
self .output_ids = output_ids
660
+ self .fit_intercept = fit_intercept
656
661
657
662
@validate_params (
658
663
{
@@ -769,13 +774,12 @@ def fit(self, X, y, sample_weight=None, coef_init=None, **params):
769
774
)
770
775
771
776
self .max_delay_ = self .delay_ids_ .max ()
772
- n_coef_intercept = n_terms + self .n_outputs_
773
777
774
778
if isinstance (coef_init , (type (None ), str )):
775
779
# fit a one-step-ahead NARX model
776
780
time_shift_ids , poly_ids = fd2tp (self .feat_ids_ , self .delay_ids_ )
777
781
xy_hstack = np .c_ [X , y ]
778
- osa_narx = LinearRegression ()
782
+ osa_narx = LinearRegression (fit_intercept = self . fit_intercept )
779
783
time_shift_vars = make_time_shift_features (xy_hstack , time_shift_ids )
780
784
poly_terms = make_poly_features (time_shift_vars , poly_ids )
781
785
# Remove missing values
@@ -787,7 +791,10 @@ def fit(self, X, y, sample_weight=None, coef_init=None, **params):
787
791
for i in range (self .n_outputs_ ):
788
792
output_i_mask = self .output_ids_ == i
789
793
if np .sum (output_i_mask ) == 0 :
790
- intercept [i ] = np .mean (y_masked [:, i ])
794
+ if self .fit_intercept :
795
+ intercept [i ] = np .mean (y_masked [:, i ])
796
+ else :
797
+ intercept [i ] = 0.0
791
798
continue
792
799
osa_narx .fit (
793
800
poly_terms_masked [:, output_i_mask ],
@@ -801,13 +808,20 @@ def fit(self, X, y, sample_weight=None, coef_init=None, **params):
801
808
self .intercept_ = intercept
802
809
return self
803
810
804
- coef_init = np .r_ [coef , intercept ]
811
+ if self .fit_intercept :
812
+ coef_init = np .r_ [coef , intercept ]
813
+ else :
814
+ coef_init = coef
805
815
else :
806
816
coef_init = check_array (
807
817
coef_init ,
808
818
ensure_2d = False ,
809
819
dtype = float ,
810
820
)
821
+ if self .fit_intercept :
822
+ n_coef_intercept = n_terms + self .n_outputs_
823
+ else :
824
+ n_coef_intercept = n_terms
811
825
if coef_init .shape [0 ] != n_coef_intercept :
812
826
raise ValueError (
813
827
"`coef_init` should have the shape of "
@@ -829,6 +843,7 @@ def fit(self, X, y, sample_weight=None, coef_init=None, **params):
829
843
self .feat_ids_ ,
830
844
self .delay_ids_ ,
831
845
self .output_ids_ ,
846
+ self .fit_intercept ,
832
847
sample_weight_sqrt ,
833
848
grad_yyd_ids ,
834
849
grad_coef_ids ,
@@ -837,8 +852,12 @@ def fit(self, X, y, sample_weight=None, coef_init=None, **params):
837
852
),
838
853
** params ,
839
854
)
840
- self .coef_ = res .x [: - self .n_outputs_ ]
841
- self .intercept_ = res .x [- self .n_outputs_ :]
855
+ if self .fit_intercept :
856
+ self .coef_ = res .x [: - self .n_outputs_ ]
857
+ self .intercept_ = res .x [- self .n_outputs_ :]
858
+ else :
859
+ self .coef_ = res .x
860
+ self .intercept_ = np .zeros (self .n_outputs_ , dtype = float )
842
861
return self
843
862
844
863
@staticmethod
@@ -931,6 +950,7 @@ def _update_dydx(
931
950
feat_ids ,
932
951
delay_ids ,
933
952
output_ids ,
953
+ fit_intercept ,
934
954
grad_yyd_ids ,
935
955
grad_coef_ids ,
936
956
grad_feat_ids ,
@@ -947,8 +967,13 @@ def _update_dydx(
947
967
n_samples , n_y = y_hat .shape
948
968
max_delay = np .max (delay_ids )
949
969
n_coefs = feat_ids .shape [0 ]
950
- n_x = n_coefs + n_y # Total number of coefficients and intercepts
951
- y_ids = np .r_ [output_ids , np .arange (n_y )]
970
+ if fit_intercept :
971
+ n_x = n_coefs + n_y # Total number of coefficients and intercepts
972
+ y_ids = np .r_ [output_ids , np .arange (n_y )]
973
+ else :
974
+ n_x = n_coefs
975
+ y_ids = output_ids
976
+
952
977
x_ids = np .arange (n_x )
953
978
954
979
dydx = np .zeros ((n_samples , n_y , n_x ), dtype = float )
@@ -1011,13 +1036,18 @@ def _loss(
1011
1036
feat_ids ,
1012
1037
delay_ids ,
1013
1038
output_ids ,
1039
+ fit_intercept ,
1014
1040
sample_weight_sqrt ,
1015
1041
* args ,
1016
1042
):
1017
1043
# Sum of squared errors
1018
1044
n_outputs = y .shape [1 ]
1019
- coef = coef_intercept [:- n_outputs ]
1020
- intercept = coef_intercept [- n_outputs :]
1045
+ if fit_intercept :
1046
+ coef = coef_intercept [:- n_outputs ]
1047
+ intercept = coef_intercept [- n_outputs :]
1048
+ else :
1049
+ coef = coef_intercept
1050
+ intercept = np .zeros (n_outputs , dtype = float )
1021
1051
1022
1052
y_hat = NARX ._predict (
1023
1053
expression ,
@@ -1045,6 +1075,7 @@ def _grad(
1045
1075
feat_ids ,
1046
1076
delay_ids ,
1047
1077
output_ids ,
1078
+ fit_intercept ,
1048
1079
sample_weight_sqrt ,
1049
1080
grad_yyd_ids ,
1050
1081
grad_coef_ids ,
@@ -1053,8 +1084,12 @@ def _grad(
1053
1084
):
1054
1085
# Sum of squared errors
1055
1086
n_outputs = y .shape [1 ]
1056
- coef = coef_intercept [:- n_outputs ]
1057
- intercept = coef_intercept [- n_outputs :]
1087
+ if fit_intercept :
1088
+ coef = coef_intercept [:- n_outputs ]
1089
+ intercept = coef_intercept [- n_outputs :]
1090
+ else :
1091
+ coef = coef_intercept
1092
+ intercept = np .zeros (n_outputs , dtype = float )
1058
1093
1059
1094
y_hat = NARX ._predict (
1060
1095
expression ,
@@ -1073,6 +1108,7 @@ def _grad(
1073
1108
feat_ids ,
1074
1109
delay_ids ,
1075
1110
output_ids ,
1111
+ fit_intercept ,
1076
1112
grad_yyd_ids ,
1077
1113
grad_coef_ids ,
1078
1114
grad_feat_ids ,
@@ -1266,6 +1302,7 @@ def _get_term_str(term_feat_ids, term_delay_ids):
1266
1302
"poly_degree" : [
1267
1303
Interval (Integral , 1 , None , closed = "left" ),
1268
1304
],
1305
+ "fit_intercept" : ["boolean" ],
1269
1306
"include_zero_delay" : [None , "array-like" ],
1270
1307
"static_indices" : [None , "array-like" ],
1271
1308
"refine_verbose" : ["verbose" ],
@@ -1288,6 +1325,7 @@ def make_narx(
1288
1325
max_delay = 1 ,
1289
1326
poly_degree = 1 ,
1290
1327
* ,
1328
+ fit_intercept = True ,
1291
1329
include_zero_delay = None ,
1292
1330
static_indices = None ,
1293
1331
refine_verbose = 1 ,
@@ -1316,6 +1354,9 @@ def make_narx(
1316
1354
poly_degree : int, default=1
1317
1355
The maximum degree of polynomial features.
1318
1356
1357
+ fit_intercept : bool, default=True
1358
+ Whether to fit the intercept. If set to False, intercept will be zeros.
1359
+
1319
1360
include_zero_delay : {None, array-like} of shape (n_features,) default=None
1320
1361
Whether to include the original (zero-delay) features.
1321
1362
@@ -1469,4 +1510,5 @@ def make_narx(
1469
1510
feat_ids = feat_ids ,
1470
1511
delay_ids = delay_ids ,
1471
1512
output_ids = output_ids ,
1513
+ fit_intercept = fit_intercept ,
1472
1514
)
0 commit comments