@@ -714,6 +714,11 @@ class plq_ElasticNet_Classifier(plqERM_ElasticNet, ClassifierMixin):
714714 - 0 < l1_ratio < 1 → combined L1 + L2 penalty
715715 Must be strictly less than 1.0 to avoid division by zero in rho/C_eff.
716716
717+ omega : array of shape (n_features, ), default=np.empty(shape=(0, 0))
718+ Non-negative weight coefficients for adaptive lasso. If not provided, all non-intercept coefficients
719+ receive the same L1 penalty controlled by ``l1_ratio``. The penalty for the intercept
720+ can be scaled via ``intercept_scaling``.
721+
717722 fit_intercept : bool, default=True
718723 Whether to fit an intercept term via an augmented constant feature column.
719724
@@ -754,6 +759,7 @@ def __init__(
754759 constraint = None ,
755760 C = 1.0 ,
756761 l1_ratio = 0.5 ,
762+ omega = None ,
757763 U = None ,
758764 V = None ,
759765 Tau = None ,
@@ -780,6 +786,7 @@ def __init__(
780786 )
781787
782788 constraint = [] if constraint is None else constraint
789+ omega = np .empty ((0 ,)) if omega is None else omega
783790 U = np .empty ((0 , 0 )) if U is None else U
784791 V = np .empty ((0 , 0 )) if V is None else V
785792 Tau = np .empty ((0 , 0 )) if Tau is None else Tau
@@ -794,6 +801,7 @@ def __init__(
794801 constraint = constraint ,
795802 C = C ,
796803 l1_ratio = l1_ratio ,
804+ omega = omega ,
797805 U = U ,
798806 V = V ,
799807 Tau = Tau ,
@@ -850,6 +858,7 @@ def _fit_subproblem(estimator, X_aug, y_pm, sample_weight, fit_intercept):
850858 constraint = estimator .constraint ,
851859 C = estimator .C ,
852860 l1_ratio = estimator .l1_ratio ,
861+ omega = estimator .omega ,
853862 max_iter = estimator .max_iter ,
854863 tol = estimator .tol ,
855864 shrink = estimator .shrink ,
@@ -908,17 +917,19 @@ def fit(self, X, y, sample_weight=None):
908917
909918 # Intercept augmentation
910919 X_aug = X
920+ omega_copy = self .omega .copy ()
911921 if self .fit_intercept :
912922 col = np .full ((X .shape [0 ], 1 ), self .intercept_scaling , dtype = X .dtype )
913923 X_aug = np .hstack ([X , col ])
924+ self .omega = np .append (self .omega , 1 ) if self .omega .size > 0 else self .omega
914925
915926 if self .classes_ .size == 2 :
916927 y01 = le .transform (y )
917928 y_pm = 2 * y01 - 1
918929
919930 # super() resolves to plqERM_ElasticNet.fit()
920931 super ().fit (X_aug , y_pm , sample_weight = sample_weight )
921-
932+ self . omega = omega_copy
922933 if self .fit_intercept :
923934 self .intercept_ = float (self .coef_ [- 1 ])
924935 self .coef_ = self .coef_ [:- 1 ].copy ()
@@ -931,6 +942,7 @@ def fit(self, X, y, sample_weight=None):
931942 f"multi_class must be 'ovr' or 'ovo' for multiclass problems, got '{ self .multi_class } '."
932943 )
933944 self ._fit_multiclass (X_aug , y , sample_weight )
945+ self .omega = omega_copy
934946
935947 return self
936948
@@ -1067,6 +1079,11 @@ class plq_ElasticNet_Regressor(plqERM_ElasticNet, RegressorMixin):
10671079 - l1_ratio = 0 → pure Ridge (equivalent to plq_Ridge_Regressor)
10681080 - 0 < l1_ratio < 1 → combined L1 + L2 penalty
10691081 Must be strictly less than 1.0 to avoid division by zero in rho/C_eff.
1082+
1083+ omega : array of shape (n_features, ), default=np.empty(shape=(0, 0))
1084+ Non-negative weight coefficients for adaptive lasso. If not provided, all non-intercept coefficients
1085+ receive the same L1 penalty controlled by ``l1_ratio``. The penalty for the intercept
1086+ can be scaled via ``intercept_scaling``.
10701087
10711088 fit_intercept : bool, default=True
10721089 If True, append a constant column (value = ``intercept_scaling``) to
@@ -1101,6 +1118,7 @@ def __init__(
11011118 constraint = None ,
11021119 C = 1.0 ,
11031120 l1_ratio = 0.5 ,
1121+ omega = None ,
11041122 U = None ,
11051123 V = None ,
11061124 Tau = None ,
@@ -1125,6 +1143,7 @@ def __init__(
11251143
11261144 loss = {"name" : "QR" , "qt" : 0.5 } if loss is None else loss
11271145 constraint = [] if constraint is None else constraint
1146+ omega = np .empty ((0 ,)) if omega is None else omega
11281147 U = np .empty ((0 , 0 )) if U is None else U
11291148 V = np .empty ((0 , 0 )) if V is None else V
11301149 Tau = np .empty ((0 , 0 )) if Tau is None else Tau
@@ -1138,6 +1157,7 @@ def __init__(
11381157 constraint = constraint ,
11391158 C = C ,
11401159 l1_ratio = l1_ratio ,
1160+ omega = omega ,
11411161 U = U ,
11421162 V = V ,
11431163 Tau = Tau ,
@@ -1183,12 +1203,15 @@ def fit(self, X, y, sample_weight=None):
11831203 self .n_features_in_ = X .shape [1 ]
11841204
11851205 X_aug = X
1206+ omega_copy = self .omega .copy ()
11861207 if self .fit_intercept :
11871208 col = np .full ((X .shape [0 ], 1 ), self .intercept_scaling , dtype = X .dtype )
11881209 X_aug = np .hstack ([X , col ])
1210+ self .omega = np .append (self .omega , 1 ) if self .omega .size > 0 else self .omega
11891211
11901212 # MRO resolves super() to plqERM_ElasticNet.fit()
11911213 super ().fit (X_aug , y , sample_weight = sample_weight )
1214+ self .omega = omega_copy
11921215
11931216 if self .fit_intercept :
11941217 self .intercept_ = float (self .coef_ [- 1 ])
0 commit comments