Skip to content

Commit 2808d1f

Browse files
classifier
1 parent c0042d0 commit 2808d1f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1231
-132
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# APLRClassifier
2+
3+
## class aplr.APLRClassifier(m:int=9000, v:float=0.1, random_state:int=0, n_jobs:int=0, validation_ratio:float=0.2, bins:int=300, verbosity:int=0, max_interaction_level:int=1, max_interactions:int=100000, min_observations_in_split:int=20, ineligible_boosting_steps_added:int=10, max_eligible_terms:int=5)
4+
5+
### Constructor parameters
6+
7+
#### m (default = 9000)
8+
The maximum number of boosting steps. If validation error does not flatten out at the end of the ***m***th boosting step, then try increasing it (or alternatively increase the learning rate).
9+
10+
#### v (default = 0.1)
11+
The learning rate. Must be greater than zero and not more than one. The higher the faster the algorithm learns and the lower ***m*** is required. However, empirical evidence suggests that ***v <= 0.1*** gives better results. If the algorithm learns too fast (requires few boosting steps to converge) then try lowering the learning rate. Computational costs can be reduced by increasing the learning rate while simultaneously decreasing ***m***, potentially at the expense of predictiveness.
12+
13+
#### random_state (default = 0)
14+
Used to randomly split training observations into training and validation if ***validation_set_indexes*** is not specified when fitting.
15+
16+
#### n_jobs (default = 0)
17+
Multi-threading parameter. If ***0*** then uses all available cores for multi-threading. Any other positive integer specifies the number of cores to use (***1*** means single-threading).
18+
19+
#### validation_ratio (default = 0.2)
20+
The ratio of training observations to use for validation instead of training. The number of boosting steps is automatically tuned to minimize validation error.
21+
22+
#### bins (default = 300)
23+
Specifies the maximum number of bins to discretize the data into when searching for the best split. The default value works well according to empirical results. This hyperparameter is intended for reducing computational costs. Must be greater than 1.
24+
25+
#### verbosity (default = 0)
26+
***0*** does not print progress reports during fitting. ***1*** prints a summary after running the ***fit*** method. ***2*** prints a summary after each boosting step.
27+
28+
#### max_interaction_level (default = 1)
29+
Specifies the maximum allowed depth of interaction terms. ***0*** means that interactions are not allowed. This hyperparameter should be tuned.
30+
31+
#### max_interactions (default = 100000)
32+
The maximum number of interactions allowed. A lower value may be used to reduce computational time.
33+
34+
#### min_observations_in_split (default = 20)
35+
The minimum effective number of observations that a term in the model must rely on. This hyperparameter should be tuned. Larger values are more appropriate for larger datasets. Larger values result in more robust models (lower variance), potentially at the expense of increased bias.
36+
37+
#### ineligible_boosting_steps_added (default = 10)
38+
Controls how many boosting steps a term that becomes ineligible has to remain ineligible. The default value works well according to empirical results. This hyperparameter is intended for reducing computational costs.
39+
40+
#### max_eligible_terms (default = 5)
41+
Limits 1) the number of terms already in the model that can be considered as interaction partners in a boosting step and 2) how many terms remain eligible in the next boosting step. The default value works well according to empirical results. This hyperparameter is intended for reducing computational costs.
42+
43+
44+
## Method: fit(X:npt.ArrayLike, y:List[str], sample_weight:npt.ArrayLike = np.empty(0), X_names:List[str]=[], validation_set_indexes:List[int]=[], prioritized_predictors_indexes:List[int]=[], monotonic_constraints:List[int]=[], interaction_constraints:List[int]=[])
45+
46+
***This method fits the model to data.***
47+
48+
### Parameters
49+
50+
#### X
51+
A numpy matrix with predictor values.
52+
53+
#### y
54+
A numpy vector with response values.
55+
56+
#### sample_weight
57+
An optional numpy vector with sample weights. If not specified then the observations are weighted equally.
58+
59+
#### X_names
60+
An optional list of strings containing names for each predictor in ***X***. Naming predictors may increase model readability because model terms get names based on ***X_names***.
61+
62+
#### validation_set_indexes
63+
An optional list of integers specifying the indexes of observations to be used for validation instead of training. If this is specified then ***validation_ratio*** is not used. Specifying ***validation_set_indexes*** may be useful for example when modelling time series data (you can place more recent observations in the validation set).
64+
65+
#### prioritized_predictors_indexes
66+
An optional list of integers specifying the indexes of predictors (columns) in ***X*** that should be prioritized. Terms of the prioritized predictors will enter the model as long as they reduce the training error and do not contain too few effective observations. They will also be updated more often.
67+
68+
#### monotonic_constraints
69+
An optional list of integers specifying monotonic constraints on model terms. For example, if there are three predictors in ***X***, then monotonic_constraints = [1,0,-1] means that 1) the first predictor in ***X*** cannot be used in interaction terms as a secondary effect and all terms using the first predictor in ***X*** as a main effect must have positive regression coefficients, 2) there are no monotonic constraints on terms using the second predictor in ***X***, and 3) the third predictor in ***X*** cannot be used in interaction terms as a secondary effect and all terms using the third predictor in ***X*** as a main effect must have negative regression coefficients.
70+
71+
#### interaction_constraints
72+
An optional list of integers specifying interaction constraints on model terms. For example, if there are three predictors in ***X***, then interaction_constraints = [1,0,2] means that 1) the first predictor in ***X*** cannot be used in interaction terms as a secondary effect, 2) there are no interaction constraints on terms using the second predictor in ***X***, and 3) the third predictor in ***X*** cannot be used in any interaction terms.
73+
74+
75+
## Method: predict_class_probabilities(X:npt.ArrayLike, cap_predictions_to_minmax_in_training:bool=False)
76+
77+
***Returns a numpy matrix containing predictions of the data in X. Requires that the model has been fitted with the fit method.***
78+
79+
### Parameters
80+
81+
#### X
82+
A numpy matrix with predictor values.
83+
84+
#### cap_predictions_to_minmax_in_training
85+
If ***True*** then for each underlying logit model the predictions are capped so that they are not less than the minimum and not greater than the maximum prediction or response in the training dataset.
86+
87+
88+
## Method: predict(X:npt.ArrayLike, cap_predictions_to_minmax_in_training:bool=False)
89+
90+
***Returns a list of strings containing predictions of the data in X. An observation is classified to the category with the highest predicted class probability. Requires that the model has been fitted with the fit method.***
91+
92+
### Parameters
93+
Parameters are the same as in ***predict_class_probabilities()***.
94+
95+
96+
## Method: calculate_local_feature_importance(X:npt.ArrayLike)
97+
98+
***Returns a numpy matrix containing local feature importance for new data by each predictor in X.***
99+
100+
### Parameters
101+
102+
#### X
103+
A numpy matrix with predictor values.
104+
105+
106+
## Method: get_categories()
107+
108+
***Returns a list containing the names of each category.***
109+
110+
111+
## Method: get_logit_model(category:str)
112+
113+
***Returns the logit model (of type APLRRegressor) that predicts whether an observation belongs to class ***category*** or not. The logit model can be used for example to inspect which terms are in the model.***
114+
115+
### Parameters
116+
117+
#### category
118+
A string specifying the label of the category.
119+
120+
121+
## Method: get_validation_indexes()
122+
123+
***Returns a list of integers containing the indexes of the training data observations used for validation and not training.***
124+
125+
126+
## Method: get_validation_error_steps()
127+
128+
***Returns a numpy vector containing the validation error by boosting step (average of log loss for each underlying logit model). Use this to determine if the maximum number of boosting steps (m) or learning rate (v) should be changed.***
129+
130+
131+
## Method: get_validation_error()
132+
133+
***Returns the validation error measured by the average of log loss for each underlying logit model.***
134+
135+
136+
## Method: get_feature_importance()
137+
138+
***Returns a numpy vector containing the feature importance of each predictor, estimated on the validation set as an average of feature importances for the underlying logit models.***

API_REFERENCE.md renamed to API_REFERENCE_FOR_REGRESSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ The index of the term selected. So ***0*** is the first term, ***1*** is the sec
186186
***Returns a numpy vector containing the regression coefficients of the intercept term by boosting step.***
187187

188188

189-
## Method: get_m()
189+
## Method: get_optimal_m()
190190

191191
***Returns the number of boosting steps in the model (the value that minimized validation error).***
192192

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Automatic Piecewise Linear Regression.
33

44
# About
5-
Build predictive and interpretable parametric machine learning models in Python based on the Automatic Piecewise Linear Regression (APLR) methodology developed by Mathias von Ottenbreit. APLR is often able to compete with Random Forest on predictiveness, but unlike Random Forest and other tree-based methods APLR is interpretable. See the ***documentation*** folder for more information.
5+
Build predictive and interpretable parametric regression or classification machine learning models in Python based on the Automatic Piecewise Linear Regression (APLR) methodology developed by Mathias von Ottenbreit. APLR is often able to compete with Random Forest on predictiveness, but unlike Random Forest and other tree-based methods APLR is interpretable. See the ***documentation*** folder for more information.
66

77
# How to install
88
***pip install aplr***
@@ -17,4 +17,4 @@ Please see the two example Python scripts in the ***examples*** folder. They cov
1717
Please consider sponsoring Ottenbreit Data Science by clicking on the Sponsor button. Sufficient funding will enable maintenance of APLR and further development.
1818

1919
# API reference
20-
Please see ***API_REFERENCE.md***
20+
Please see ***API_REFERENCE_FOR_REGRESSION.md*** and ***API_REFERENCE_FOR_CLASSIFICATION.md***.

aplr/aplr.py

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ def get_intercept(self)->float:
9090
def get_intercept_steps(self)->npt.ArrayLike:
9191
return self.APLRRegressor.get_intercept_steps()
9292

93-
def get_m(self)->int:
94-
return self.APLRRegressor.get_m()
93+
def get_optimal_m(self)->int:
94+
return self.APLRRegressor.get_optimal_m()
9595

9696
def get_validation_tuning_metric(self)->str:
9797
return self.APLRRegressor.get_validation_tuning_metric()
@@ -122,6 +122,96 @@ def get_params(self, deep=True):
122122
"quantile":self.quantile
123123
}
124124

125+
#For sklearn
126+
def set_params(self, **parameters):
127+
for parameter, value in parameters.items():
128+
setattr(self, parameter, value)
129+
self.__set_params_cpp()
130+
return self
131+
132+
133+
class APLRClassifier():
134+
def __init__(self, m:int=9000, v:float=0.1, random_state:int=0, n_jobs:int=0, validation_ratio:float=0.2, bins:int=300, verbosity:int=0, max_interaction_level:int=1, max_interactions:int=100000, min_observations_in_split:int=20, ineligible_boosting_steps_added:int=10, max_eligible_terms:int=5):
135+
self.m=m
136+
self.v=v
137+
self.random_state=random_state
138+
self.n_jobs=n_jobs
139+
self.validation_ratio=validation_ratio
140+
self.bins=bins
141+
self.verbosity=verbosity
142+
self.max_interaction_level=max_interaction_level
143+
self.max_interactions=max_interactions
144+
self.min_observations_in_split=min_observations_in_split
145+
self.ineligible_boosting_steps_added=ineligible_boosting_steps_added
146+
self.max_eligible_terms=max_eligible_terms
147+
148+
#Creating aplr_cpp and setting parameters
149+
self.APLRClassifier=aplr_cpp.APLRClassifier()
150+
self.__set_params_cpp()
151+
152+
#Sets parameters for aplr_cpp.APLRClassifier cpp object
153+
def __set_params_cpp(self):
154+
self.APLRClassifier.m=self.m
155+
self.APLRClassifier.v=self.v
156+
self.APLRClassifier.random_state=self.random_state
157+
self.APLRClassifier.n_jobs=self.n_jobs
158+
self.APLRClassifier.validation_ratio=self.validation_ratio
159+
self.APLRClassifier.bins=self.bins
160+
self.APLRClassifier.verbosity=self.verbosity
161+
self.APLRClassifier.max_interaction_level=self.max_interaction_level
162+
self.APLRClassifier.max_interactions=self.max_interactions
163+
self.APLRClassifier.min_observations_in_split=self.min_observations_in_split
164+
self.APLRClassifier.ineligible_boosting_steps_added=self.ineligible_boosting_steps_added
165+
self.APLRClassifier.max_eligible_terms=self.max_eligible_terms
166+
167+
def fit(self, X:npt.ArrayLike, y:List[str], sample_weight:npt.ArrayLike = np.empty(0), X_names:List[str]=[], validation_set_indexes:List[int]=[], prioritized_predictors_indexes:List[int]=[], monotonic_constraints:List[int]=[], interaction_constraints:List[int]=[]):
168+
self.__set_params_cpp()
169+
self.APLRClassifier.fit(X,y,sample_weight,X_names,validation_set_indexes,prioritized_predictors_indexes,monotonic_constraints,interaction_constraints)
170+
171+
def predict_class_probabilities(self, X:npt.ArrayLike, cap_predictions_to_minmax_in_training:bool=False)->npt.ArrayLike:
172+
return self.APLRClassifier.predict_class_probabilities(X, cap_predictions_to_minmax_in_training)
173+
174+
def predict(self, X:npt.ArrayLike, cap_predictions_to_minmax_in_training:bool=False)->List[str]:
175+
return self.APLRClassifier.predict(X, cap_predictions_to_minmax_in_training)
176+
177+
def calculate_local_feature_importance(self,X:npt.ArrayLike)->npt.ArrayLike:
178+
return self.APLRClassifier.calculate_local_feature_importance(X)
179+
180+
def get_categories(self)->List[str]:
181+
return self.APLRClassifier.get_categories()
182+
183+
def get_logit_model(self,category:str)->APLRRegressor:
184+
return self.APLRClassifier.get_logit_model(category)
185+
186+
def get_validation_indexes(self)->List[int]:
187+
return self.APLRClassifier.get_validation_indexes()
188+
189+
def get_validation_error_steps(self)->npt.ArrayLike:
190+
return self.APLRClassifier.get_validation_error_steps()
191+
192+
def get_validation_error(self)->float:
193+
return self.APLRClassifier.get_validation_error()
194+
195+
def get_feature_importance(self)->npt.ArrayLike:
196+
return self.APLRClassifier.get_feature_importance()
197+
198+
#For sklearn
199+
def get_params(self, deep=True):
200+
return {
201+
"m": self.m,
202+
"v": self.v,
203+
"random_state":self.random_state,
204+
"n_jobs":self.n_jobs,
205+
"validation_ratio":self.validation_ratio,
206+
"bins":self.bins,
207+
"verbosity":self.verbosity,
208+
"max_interaction_level":self.max_interaction_level,
209+
"max_interactions":self.max_interactions,
210+
"min_observations_in_split":self.min_observations_in_split,
211+
"ineligible_boosting_steps_added":self.ineligible_boosting_steps_added,
212+
"max_eligible_terms":self.max_eligible_terms,
213+
}
214+
125215
#For sklearn
126216
def set_params(self, **parameters):
127217
for parameter, value in parameters.items():

0 commit comments

Comments
 (0)