-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathREDSVM.py
More file actions
232 lines (191 loc) · 6.95 KB
/
REDSVM.py
File metadata and controls
232 lines (191 loc) · 6.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
"""Reduction from ordinal regression to binary SVM (REDSVM)."""
from numbers import Integral, Real
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin, _fit_context
from sklearn.utils._param_validation import Interval, StrOptions
from sklearn.utils.multiclass import unique_labels
from sklearn.utils.validation import check_array, check_is_fitted, check_X_y
from orca_python.classifiers.libsvmRank.python import svm
class REDSVM(BaseEstimator, ClassifierMixin):
"""Reduction from ordinal regression to binary SVM classifiers.
The configuration used is the identity coding matrix, the absolute cost matrix and
the standard binary soft-margin SVM. This class uses libsvm-rank-2.81
implementation: (http://www.work.caltech.edu/~htlin/program/libsvm/)
Parameters
----------
C : float, default=1
Set the parameter C.
kernel : str, default="rbf"
Set type of kernel function.
- linear: u'*v
- polynomial: (gamma*u'*v + coef0)^degree
- rbf: exp(-gamma*|u-v|^2)
- sigmoid: tanh(gamma*u'*v + coef0)
- stump: -|u-v|_1 + coef0
- perceptron: -|u-v|_2 + coef0
- laplacian: exp(-gamma*|u-v|_1)
- exponential: exp(-gamma*|u-v|_2)
- precomputed: kernel values in training_instance_matrix
degree : int, default=3
Set degree in kernel function.
gamma : {'scale', 'auto'} or float, default=1.0
Kernel coefficient determining the influence of individual training samples:
- 'scale': 1 / (n_features * X.var())
- 'auto': 1 / n_features
- float: Must be non-negative.
coef0 : float, default=0
Set coef0 in kernel function.
shrinking : bool, default=True
Set whether to use the shrinking heuristics.
tol : float, default=0.001
Set tolerance of termination criterion.
cache_size : int, default=100
Set cache memory size in MB.
Attributes
----------
classes_ : ndarray of shape (n_classes,)
Array that contains all different class labels found in the original dataset.
model_ : object
Fitted estimator.
References
----------
.. [1] H.-T. Lin and L. Li, "Reduction from cost-sensitive ordinal ranking to
weighted binary classification", Neural Computation, vol. 24, no. 5, pp.
1329-1367, 2012, http://10.1162/NECO_a_00265
.. [2] P.A. Gutiérrez, M. Pérez-Ortiz, J. Sánchez-Monedero, F. Fernández-Navarro
and C. Hervás-Martínez, "Ordinal regression methods: survey and
experimental study", IEEE Transactions on Knowledge and Data Engineering,
Vol. 28. Issue 1, 2016,
https://doi.org/10.1109/TKDE.2015.2457911
"""
_parameter_constraints: dict = {
"C": [Interval(Real, 0.0, None, closed="neither")],
"kernel": [
StrOptions(
{
"linear",
"poly",
"rbf",
"sigmoid",
"stump",
"perceptron",
"laplacian",
"exponential",
"precomputed",
}
)
],
"degree": [Interval(Integral, 0, None, closed="left")],
"gamma": [
StrOptions({"scale", "auto"}),
Interval(Real, 0.0, None, closed="neither"),
],
"coef0": [Interval(Real, None, None, closed="neither")],
"shrinking": ["boolean"],
"tol": [Interval(Real, 0.0, None, closed="neither")],
"cache_size": [Interval(Real, 0.0, None, closed="neither")],
}
def __init__(
self,
C=1,
kernel="rbf",
degree=3,
gamma="auto",
coef0=0,
shrinking=True,
tol=0.001,
cache_size=100,
):
self.C = C
self.kernel = kernel
self.degree = degree
self.gamma = gamma
self.coef0 = coef0
self.shrinking = shrinking
self.tol = tol
self.cache_size = cache_size
@_fit_context(prefer_skip_nested_validation=True)
def fit(self, X, y):
"""Fit the model with the training data.
Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features)
Training patterns array, where n_samples is the number of samples and
n_features is the number of features.
y : array-like of shape (n_samples,)
Target vector relative to X.
Returns
-------
self : object
Fitted estimator.
Raises
------
ValueError
If parameters are invalid or data has wrong format.
"""
# Additional strict validation for boolean parameters
if not isinstance(self.shrinking, bool):
raise ValueError(
f"The 'shrinking' parameter must be of type bool. "
f"Got {type(self.shrinking).__name__} instead."
)
# Check that X and y have correct shape
X, y = check_X_y(X, y)
# Store the classes seen during fit
self.classes_ = unique_labels(y)
# Set default gamma value if not specified
gamma_value = self.gamma
if self.gamma == "auto":
gamma_value = 1.0 / X.shape[1]
elif self.gamma == "scale":
gamma_value = 1.0 / (X.shape[1] * X.var())
# Map kernel type
kernel_type_mapping = {
"linear": 0,
"poly": 1,
"rbf": 2,
"sigmoid": 3,
"stump": 4,
"perceptron": 5,
"laplacian": 6,
"exponential": 7,
"precomputed": 8,
}
kernel_type = kernel_type_mapping[self.kernel]
# Fit the model
options = "-s 5 -t {} -d {} -g {} -r {} -c {} -m {} -e {} -h {} -q".format(
str(kernel_type),
str(self.degree),
str(gamma_value),
str(self.coef0),
str(self.C),
str(self.cache_size),
str(self.tol),
str(1 if self.shrinking else 0),
)
self.model_ = svm.fit(y.tolist(), X.tolist(), options)
return self
def predict(self, X):
"""Perform classification on samples in X.
Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features)
Test patterns array, where n_samples is the number of samples and
n_features is the number of features.
Returns
-------
y_pred : array, shape (n_samples,)
Class labels for samples in X.
Raises
------
NotFittedError
If the model is not fitted yet.
ValueError
If input is invalid.
"""
# Check is fit had been called
check_is_fitted(self, ["model_"])
# Input validation
X = check_array(X)
y_pred = np.array(svm.predict(X.tolist(), self.model_))
return y_pred