python-ldl 0.0.2__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. pyldl/algorithms/__init__.py +192 -20
  2. pyldl/algorithms/_algorithm_adaptation.py +41 -235
  3. pyldl/algorithms/_bp.py +12 -0
  4. pyldl/algorithms/_classifier.py +96 -98
  5. pyldl/algorithms/_cpnn.py +96 -0
  6. pyldl/algorithms/_delta_ldl.py +172 -0
  7. pyldl/algorithms/_duo_ldl.py +33 -0
  8. pyldl/algorithms/_ensemble.py +210 -64
  9. pyldl/algorithms/_incomplete.py +60 -38
  10. pyldl/algorithms/_label_enhancement.py +230 -214
  11. pyldl/algorithms/_ldl_da.py +176 -0
  12. pyldl/algorithms/_ldl_dpa.py +39 -0
  13. pyldl/algorithms/_ldl_dpm.py +201 -0
  14. pyldl/algorithms/_ldl_dvs.py +71 -0
  15. pyldl/algorithms/_ldl_hvlc.py +65 -0
  16. pyldl/algorithms/_ldl_lclr.py +167 -0
  17. pyldl/algorithms/_ldl_lrr.py +31 -40
  18. pyldl/algorithms/_ldl_scl.py +63 -48
  19. pyldl/algorithms/_ldlf.py +85 -60
  20. pyldl/algorithms/_ldllc.py +26 -0
  21. pyldl/algorithms/_ldlsf.py +101 -0
  22. pyldl/algorithms/_lrldl.py +105 -0
  23. pyldl/algorithms/_problem_transformation.py +84 -45
  24. pyldl/algorithms/_rbm.c +14902 -0
  25. pyldl/algorithms/_rknn_ldl.py +117 -0
  26. pyldl/algorithms/_s_ldl.py +220 -0
  27. pyldl/algorithms/_snefy_ldl.py +91 -0
  28. pyldl/algorithms/_specialized_algorithms.py +216 -60
  29. pyldl/algorithms/_ssg_ldl.py +22 -18
  30. pyldl/algorithms/_tree.c +33826 -0
  31. pyldl/algorithms/base/__init__.py +42 -0
  32. pyldl/algorithms/base/_lazy.py +19 -0
  33. pyldl/algorithms/base/deep.py +398 -0
  34. pyldl/algorithms/base/shallow.py +533 -0
  35. pyldl/algorithms/callbacks.py +71 -0
  36. pyldl/algorithms/loss_function_engineering.py +68 -0
  37. pyldl/algorithms/optimizers.py +81 -0
  38. pyldl/algorithms/utils.py +660 -0
  39. pyldl/applications/emphasis_selection.py +39 -32
  40. pyldl/applications/facial_emotion_recognition.py +186 -15
  41. pyldl/applications/lesion_counting.py +73 -62
  42. pyldl/experiment.py +170 -0
  43. pyldl/matlab_algorithms/__init__.py +12 -10
  44. pyldl/metrics.py +531 -54
  45. pyldl/utils.py +283 -74
  46. {python_ldl-0.0.2.dist-info → python_ldl-0.1.0.dist-info}/METADATA +103 -45
  47. python_ldl-0.1.0.dist-info/RECORD +66 -0
  48. {python_ldl-0.0.2.dist-info → python_ldl-0.1.0.dist-info}/WHEEL +1 -1
  49. {python_ldl-0.0.2.dist-info → python_ldl-0.1.0.dist-info/licenses}/LICENSE +1 -1
  50. {python_ldl-0.0.2.dist-info → python_ldl-0.1.0.dist-info}/top_level.txt +1 -0
  51. tests/__init__.py +0 -0
  52. tests/test.py +40 -0
  53. pyldl/algorithms/base.py +0 -226
  54. python_ldl-0.0.2.dist-info/RECORD +0 -38
@@ -1,26 +1,198 @@
1
- from ._problem_transformation import PT_Bayes, PT_SVM, LDSVR
2
- from ._algorithm_adaptation import AA_BP, AA_KNN, CAD, QFD2, CJS, CPNN, BCPNN, ACPNN
3
- from ._specialized_algorithms import SA_BFGS, SA_IIS
1
+ from typing import TYPE_CHECKING
4
2
 
5
- from ._incomplete import IncomLDL
6
- from ._classifier import LDL4C, LDL_HR, LDLM
7
- from ._ensemble import DF_LDL, AdaBoostLDL
3
+ if TYPE_CHECKING:
4
+ from ._problem_transformation import *
5
+ from ._algorithm_adaptation import *
6
+ from ._specialized_algorithms import *
8
7
 
9
- from ._ldlf import LDLF
10
- from ._ldl_scl import LDL_SCL
11
- from ._ldl_lrr import LDL_LRR
8
+ from ._incomplete import *
9
+ from ._classifier import *
10
+ from ._ensemble import *
12
11
 
13
- from ._ssg_ldl import SSG_LDL
12
+ from ._bp import *
13
+ from ._cpnn import *
14
+ from ._duo_ldl import *
15
+ from ._ldlf import *
16
+ from ._ldllc import *
17
+ from ._ldlsf import *
18
+ from ._ldl_lclr import *
19
+ from ._ldl_scl import *
20
+ from ._ldl_lrr import *
21
+ from ._ldl_dpa import *
22
+ from ._lrldl import *
23
+ from ._ldl_hvlc import *
24
+ from ._rknn_ldl import *
25
+ from ._s_ldl import *
26
+ from ._delta_ldl import *
27
+ from ._snefy_ldl import *
28
+ from ._ldl_dvs import *
29
+ from ._ldl_dpm import *
14
30
 
15
- from ._label_enhancement import FCM, KM, LP, ML, GLLE, LEVI, LIBLE
31
+ from ._ssg_ldl import *
16
32
 
33
+ from ._label_enhancement import *
17
34
 
18
- __all__ = ["SA_BFGS", "SA_IIS", "AA_KNN", "AA_BP", "PT_Bayes", "PT_SVM",
19
- "CPNN", "BCPNN", "ACPNN", "LDSVR",
20
- "LDLF", "LDL_SCL", "LDL_LRR", "CAD", "QFD2", "CJS",
21
- "DF_LDL", "AdaBoostLDL",
22
- "LDL4C", "LDL_HR", "LDLM",
23
- "IncomLDL",
24
- "SSG_LDL",
25
- "FCM", "KM", "LP", "ML", "GLLE",
26
- "LEVI", 'LIBLE']
35
+ from ._ldl_da import *
36
+
37
+
38
+ _LDL_MODULE_MAP = {
39
+ # -------------------- 2026 --------------------
40
+ "LDL_DVS": "._ldl_dvs",
41
+ "LDL_DPM": "._ldl_dpm",
42
+ # -------------------- 2025 --------------------
43
+ "RG4LDL": "._ensemble",
44
+ "RKNN_LDL": "._rknn_ldl",
45
+ "SNEFY_LDL": "._snefy_ldl",
46
+ **dict.fromkeys(
47
+ [
48
+ "_S_LDL",
49
+ "S_LRR",
50
+ "S_SCL",
51
+ "S_KLD",
52
+ "S_CJS",
53
+ "S_QFD2",
54
+ "Shallow_S_LDL",
55
+ ],
56
+ "._s_ldl"
57
+ ),
58
+ "Delta_LDL": "._delta_ldl",
59
+ # -------------------- 2024 --------------------
60
+ "LDL_HVLC": "._ldl_hvlc",
61
+ **dict.fromkeys(
62
+ [
63
+ "_LRLDL",
64
+ "TKLRLDL",
65
+ "TLRLDL",
66
+ ],
67
+ "._lrldl"
68
+ ),
69
+ "LDL_DPA": "._ldl_dpa",
70
+ # -------------------- 2023 --------------------
71
+ "LDL_LRR": "._ldl_lrr",
72
+ # -------------------- 2021 --------------------
73
+ "DF_LDL": "._ensemble",
74
+ "LDL_SCL": "._ldl_scl",
75
+ "Duo_LDL": "._duo_ldl",
76
+ "BD_LDL": "._algorithm_adaptation",
77
+ # -------------------- 2019 --------------------
78
+ "LDL_LCLR": "._ldl_lclr",
79
+ "LDLSF": "._ldlsf",
80
+ # -------------------- 2018 --------------------
81
+ "LDLLC": "._ldllc",
82
+ "LALOT": "._specialized_algorithms",
83
+ "StructRF": "._ensemble",
84
+ # -------------------- 2017 --------------------
85
+ "BCPNN": "._cpnn",
86
+ "ACPNN": "._cpnn",
87
+ "LDLF": "._ldlf",
88
+ # -------------------- 2016 --------------------
89
+ "LDLogitBoost": "._ensemble",
90
+ **dict.fromkeys(
91
+ [
92
+ "_SA",
93
+ "SA_BFGS",
94
+ "SA_IIS",
95
+ ],
96
+ "._specialized_algorithms"
97
+ ),
98
+ "AA_KNN": "._algorithm_adaptation",
99
+ "AA_BP": "._bp",
100
+ **dict.fromkeys(
101
+ [
102
+ "_PT",
103
+ "PT_Bayes",
104
+ "PT_SVM",
105
+ ],
106
+ "._problem_transformation"
107
+ ),
108
+ # -------------------- 2015 --------------------
109
+ "LDSVR": "._problem_transformation",
110
+ # -------------------- 2013 --------------------
111
+ "CPNN": "._cpnn",
112
+ }
113
+
114
+ _LE_MODULE_MAP = {
115
+ # -------------------- 2023 --------------------
116
+ **dict.fromkeys(
117
+ [
118
+ "LIBLE",
119
+ "ConLE",
120
+ ],
121
+ "._label_enhancement"
122
+ ),
123
+ # -------------------- 2020 --------------------
124
+ "LEVI": "._label_enhancement",
125
+ # -------------------- 2019 --------------------
126
+ **dict.fromkeys(
127
+ [
128
+ "GLLE",
129
+ "ML",
130
+ "LP",
131
+ "KM",
132
+ "FCM",
133
+ ],
134
+ "._label_enhancement"
135
+ ),
136
+ }
137
+
138
+ _INCOMLDL_MODULE_MAP = {
139
+ # -------------------- 2024 --------------------
140
+ "WInLDL": "._incomplete",
141
+ # -------------------- 2017 --------------------
142
+ "IncomLDL": "._incomplete",
143
+ }
144
+
145
+ _LDL4C_MODULE_MAP = {
146
+ # -------------------- 2021 --------------------
147
+ **dict.fromkeys(
148
+ [
149
+ "LDLM",
150
+ "LDL_HR",
151
+ "LDL4C",
152
+ ],
153
+ "._classifier"
154
+ ),
155
+ }
156
+
157
+ _SSG_LDL_MODULE_MAP = {
158
+ # -------------------- 2021 --------------------
159
+ "SSG_LDL": "._ssg_ldl"
160
+ }
161
+
162
+ _LDL_DA_MODULE_MAP = {
163
+ # -------------------- 2025 --------------------
164
+ "LDL_DA": "._ldl_da"
165
+ }
166
+
167
+ _GLD_MODULE_MAP = {
168
+ # -------------------- 2026 --------------------
169
+ "GLD_SVR": "._problem_transformation",
170
+ "GLD_KNN": "._algorithm_adaptation",
171
+ "GLD_BFGS": "._specialized_algorithms",
172
+ }
173
+
174
+ _MODULE_MAP = {
175
+ **_LDL_MODULE_MAP,
176
+ **_LE_MODULE_MAP,
177
+ **_INCOMLDL_MODULE_MAP,
178
+ **_LDL4C_MODULE_MAP,
179
+ **_SSG_LDL_MODULE_MAP,
180
+ **_LDL_DA_MODULE_MAP,
181
+ **_GLD_MODULE_MAP,
182
+ }
183
+
184
+
185
+ _ldl__ = list(_LDL_MODULE_MAP)
186
+ _le__ = list(_LE_MODULE_MAP)
187
+ _incomldl__ = list(_INCOMLDL_MODULE_MAP)
188
+ _ldl4c__ = list(_LDL4C_MODULE_MAP)
189
+ _ssg_ldl__ = list(_SSG_LDL_MODULE_MAP)
190
+ _ldl_da__ = list(_LDL_DA_MODULE_MAP)
191
+ _gld__ = list(_GLD_MODULE_MAP)
192
+
193
+
194
+ __all__ = _ldl__ + _le__ + _incomldl__ + _ldl4c__ + _ssg_ldl__ + _ldl_da__ + _gld__
195
+
196
+
197
+ from .base._lazy import lazy_module
198
+ __getattr__ = lazy_module(_MODULE_MAP, __name__)
@@ -1,257 +1,63 @@
1
1
  import numpy as np
2
- from sklearn.neighbors import NearestNeighbors
3
- from sklearn.preprocessing import OneHotEncoder
4
2
 
5
- import keras
6
- import tensorflow as tf
7
- from keras import backend as K
3
+ from pyldl.algorithms.base import Base, BaseLDL, BaseGLD
8
4
 
9
- from pyldl.algorithms.base import BaseLDL, BaseDeepLDL
10
5
 
6
+ EPS = np.finfo(np.float32).eps
11
7
 
12
- class AA_KNN(BaseLDL):
13
-
14
- def __init__(self,
15
- k=5,
16
- random_state=None):
17
-
18
- super().__init__(random_state)
19
8
 
9
+ class _AA_KNN(Base):
10
+ def __init__(self, *, k: int = 5, **kwargs):
11
+ super().__init__(**kwargs)
20
12
  self.k = k
21
- self._model = NearestNeighbors(n_neighbors=self.k)
22
13
 
23
- def fit(self, X, y):
24
- super().fit(X, y)
25
- self._model.fit(self._X)
14
+ def fit(self, X: np.ndarray, target: np.ndarray):
15
+ from sklearn.neighbors import NearestNeighbors
16
+ super().fit(X, target)
17
+ self._knn = NearestNeighbors(n_neighbors=self.k).fit(self._X)
18
+ return self
26
19
 
27
20
  def predict(self, X):
28
- _, inds = self._model.kneighbors(X)
29
- return np.average(self._y[inds], axis=1)
30
-
31
-
32
- class AA_BP(BaseDeepLDL):
33
-
34
- def __init__(self, n_hidden=None, n_latent=None, random_state=None):
35
- super().__init__(n_hidden, n_latent, random_state)
36
-
37
- @tf.function
38
- def _loss_function(self, y, y_pred):
39
- return tf.math.reduce_mean(keras.losses.mean_squared_error(y, y_pred))
40
-
41
- def fit(self, X, y, learning_rate=5e-3, epochs=3000, batch_size=32,
42
- model=None, activation='sigmoid', optimizer='SGD', X_test=None, y_test=None):
43
- super().fit(X, y)
44
-
45
- self._batch_size = batch_size
46
-
47
- if self._n_hidden is None:
48
- self._n_hidden = self._n_features * 3 // 2
49
-
50
- self._model = model
51
- if self._model is None:
52
- self._model = keras.Sequential([keras.layers.InputLayer(input_shape=(self._n_features,)),
53
- keras.layers.Dense(self._n_hidden, activation=activation),
54
- keras.layers.Dense(self._n_outputs, activation='softmax')])
55
- self._optimizer = eval(f'keras.optimizers.{optimizer}({learning_rate})')
56
- data = tf.data.Dataset.from_tensor_slices((self._X, self._y)).batch(self._batch_size)
57
-
58
- for _ in range(epochs):
59
- total_loss = 0.
60
- for batch in data:
61
- with tf.GradientTape() as tape:
62
- y_pred = self._model(batch[0])
63
- loss = self._loss_function(batch[1], y_pred)
64
- gradients = tape.gradient(loss, self.trainable_variables)
65
- self._optimizer.apply_gradients(zip(gradients, self.trainable_variables))
66
- total_loss += loss
67
-
68
- def predict(self, X):
69
- return self._model(X)
70
-
71
-
72
- class CAD(AA_BP):
73
-
74
- @tf.function
75
- def _loss_function(self, y, y_pred):
76
- def _CAD(y, y_pred):
77
- return tf.reduce_mean(tf.abs(
78
- tf.cumsum(y, axis=1) - tf.cumsum(y_pred, axis=1)
79
- ), axis=1)
80
- return tf.math.reduce_sum(
81
- tf.map_fn(lambda i: _CAD(y[:, :i], y_pred[:, :i]),
82
- tf.range(1, self._n_outputs + 1),
83
- fn_output_signature=tf.float32)
84
- )
85
-
86
- def fit(self, X, y, learning_rate=1e-4, epochs=500,
87
- activation='relu', optimizer='Adam'):
88
- return super().fit(X, y, learning_rate, epochs, activation, optimizer)
89
-
90
-
91
- class QFD2(AA_BP):
92
-
93
- @tf.function
94
- def _loss_function(self, y, y_pred):
95
- Q = y - y_pred
96
- j = tf.reshape(tf.range(self._n_outputs), [self._n_outputs, 1])
97
- k = tf.reshape(tf.range(self._n_outputs), [1, self._n_outputs])
98
- A = tf.cast(1 - tf.abs(j - k) / (self._n_outputs - 1), dtype=tf.float32)
99
- return tf.math.reduce_mean(
100
- tf.linalg.diag_part(tf.matmul(tf.matmul(Q, A), tf.transpose(Q)))
101
- )
102
-
103
- def fit(self, X, y, learning_rate=1e-4, epochs=500,
104
- activation='relu', optimizer='Adam'):
105
- return super().fit(X, y, learning_rate, epochs, activation, optimizer)
106
-
107
-
108
- class CJS(AA_BP):
21
+ _, inds = self._knn.kneighbors(X)
22
+ return np.average(self._target[inds], axis=1)
109
23
 
110
- @tf.function
111
- def _loss_function(self, y, y_pred):
112
- def _CJS(y, y_pred):
113
- m = 0.5 * (y + y_pred)
114
- js = 0.5 * (keras.losses.kl_divergence(y, m) + keras.losses.kl_divergence(y_pred, m))
115
- return tf.reduce_mean(js)
116
- return tf.math.reduce_sum(
117
- tf.map_fn(lambda i: _CJS(y[:, :i], y_pred[:, :i]),
118
- tf.range(1, self._n_outputs + 1),
119
- fn_output_signature=tf.float32)
120
- )
24
+ def __getstate__(self):
25
+ return self.__dict__.copy()
121
26
 
122
- def fit(self, X, y, learning_rate=1e-4, epochs=500,
123
- activation='relu', optimizer='Adam'):
124
- return super().fit(X, y, learning_rate, epochs, activation, optimizer)
27
+ def __setstate__(self, state):
28
+ self.__dict__.update(state)
125
29
 
126
30
 
127
- class RProp(keras.optimizers.Optimizer):
128
-
129
- def __init__(self, init_alpha=1e-3, scale_up=1.2, scale_down=0.5, min_alpha=1e-6, max_alpha=50., **kwargs):
130
- super(RProp, self).__init__(name='rprop', **kwargs)
131
- self.init_alpha = K.variable(init_alpha, name='init_alpha')
132
- self.scale_up = K.variable(scale_up, name='scale_up')
133
- self.scale_down = K.variable(scale_down, name='scale_down')
134
- self.min_alpha = K.variable(min_alpha, name='min_alpha')
135
- self.max_alpha = K.variable(max_alpha, name='max_alpha')
31
+ class AA_KNN(_AA_KNN, BaseLDL):
32
+ """:class:`AA-kNN <pyldl.algorithms.AA_KNN>` is proposed in paper :cite:`2016:geng`.
33
+ """
34
+ pass
136
35
 
137
- def get_updates(self, params, gradients):
138
- grads = gradients
139
- shapes = [K.int_shape(p) for p in params]
140
- alphas = [K.variable(np.ones(shape) * self.init_alpha) for shape in shapes]
141
- old_grads = [K.zeros(shape) for shape in shapes]
142
- prev_weight_deltas = [K.zeros(shape) for shape in shapes]
143
- self.updates = []
144
36
 
145
- for param, grad, old_grad, prev_weight_delta, alpha in zip(params, grads,
146
- old_grads, prev_weight_deltas,
147
- alphas):
37
+ class GLD_KNN(_AA_KNN, BaseGLD):
38
+ """:class:`GLD-kNN <pyldl.algorithms.GLD_KNN>` is proposed in paper :cite:`2026:wu`.
39
+ """
40
+ pass
148
41
 
149
- new_alpha = K.switch(
150
- K.greater(grad * old_grad, 0),
151
- K.minimum(alpha * self.scale_up, self.max_alpha),
152
- K.switch(K.less(grad * old_grad, 0), K.maximum(alpha * self.scale_down, self.min_alpha), alpha)
153
- )
154
42
 
155
- new_delta = K.switch(K.greater(grad, 0),
156
- -new_alpha,
157
- K.switch(K.less(grad, 0),
158
- new_alpha,
159
- K.zeros_like(new_alpha)))
43
+ class BD_LDL(BaseLDL):
44
+ """:class:`BD-LDL <pyldl.algorithms.BD_LDL>` is proposed in paper :cite:`2021:liu2`.
45
+ """
160
46
 
161
- weight_delta = K.switch(K.less(grad*old_grad, 0), -prev_weight_delta, new_delta)
47
+ def __init__(self, *, alpha: float = 1e-3, beta: float = 1e-2, **kwargs):
48
+ super().__init__(**kwargs)
49
+ self.alpha = alpha
50
+ self.beta = beta
162
51
 
163
- new_param = param + weight_delta
164
-
165
- grad = K.switch(K.less(grad*old_grad, 0), K.zeros_like(grad), grad)
166
-
167
- self.updates.append(K.update(param, new_param))
168
- self.updates.append(K.update(alpha, new_alpha))
169
- self.updates.append(K.update(old_grad, grad))
170
- self.updates.append(K.update(prev_weight_delta, weight_delta))
171
-
172
- return self.updates
173
-
174
- def get_config(self):
175
- config = {
176
- 'init_alpha': float(K.get_value(self.init_alpha)),
177
- 'scale_up': float(K.get_value(self.scale_up)),
178
- 'scale_down': float(K.get_value(self.scale_down)),
179
- 'min_alpha': float(K.get_value(self.min_alpha)),
180
- 'max_alpha': float(K.get_value(self.max_alpha)),
181
- }
182
- base_config = super(RProp, self).get_config()
183
- return dict(list(base_config.items()) + list(config.items()))
184
-
185
-
186
- class CPNN(BaseDeepLDL):
187
-
188
- def _not_proper_mode(self):
189
- raise ValueError("The argument 'mode' can only be 'none', 'binary' or 'augment'.")
190
-
191
- def __init__(self, mode='none', v=5, n_hidden=None, n_latent=None, random_state=None):
192
- super().__init__(n_hidden, n_latent, random_state)
193
- if mode == 'none' or mode == 'binary' or mode == 'augment':
194
- self._mode = mode
195
- else:
196
- self._not_proper_mode()
197
- self._v = v
198
-
199
- def fit(self, X, y, learning_rate=5e-3, epochs=3000):
200
- super().fit(X, y)
201
-
202
- self._optimizer = RProp(init_alpha=learning_rate)
203
-
204
- if self._n_hidden is None:
205
- self._n_hidden = self._n_features * 3 // 2
206
-
207
- if self._mode == 'augment':
208
- one_hot = tf.one_hot(tf.math.argmax(self._y, axis=1), self.n_outputs)
209
- self._X = tf.repeat(self._X, self._v, axis=0)
210
- self._y = tf.repeat(self._y, self._v, axis=0)
211
- one_hot = tf.repeat(one_hot, self._v, axis=0)
212
- v = tf.reshape(tf.tile([1 / (i + 1) for i in range(self._v)], [X.shape[0]]), (-1, 1))
213
- self._y += self._y * one_hot * v
214
-
215
- input_shape = (self._n_features + (1 if self._mode == 'none' else self._n_outputs),)
216
- self._model = keras.Sequential([keras.layers.InputLayer(input_shape=input_shape),
217
- keras.layers.Dense(self._n_hidden, activation='sigmoid'),
218
- keras.layers.Dense(1, activation=None)])
219
-
220
- for _ in range(epochs):
221
- with tf.GradientTape() as tape:
222
- loss = self._loss(self._X, self._y)
223
- gradients = tape.gradient(loss, self.trainable_variables)
224
- self._optimizer.get_updates(self.trainable_variables, gradients)
225
-
226
- def _make_inputs(self, X):
227
- temp = tf.reshape(tf.tile([i + 1 for i in range(self._n_outputs)], [X.shape[0]]), (-1, 1))
228
- if self._mode != 'none':
229
- temp = OneHotEncoder(sparse=False).fit_transform(temp)
230
- return tf.concat([tf.cast(tf.repeat(X, self._n_outputs, axis=0), dtype=tf.float32),
231
- tf.cast(temp, dtype=tf.float32)],
232
- axis=1)
233
-
234
- def _call(self, X):
235
- inputs = self._make_inputs(X)
236
- outputs = self._model(inputs)
237
- results = tf.reshape(outputs, (X.shape[0], self._n_outputs))
238
- b = tf.reshape(-tf.math.log(tf.math.reduce_sum(tf.math.exp(results), axis=1)), (-1, 1))
239
- return tf.math.exp(b + results)
240
-
241
- def _loss(self, X, y):
242
- return tf.math.reduce_mean(keras.losses.kl_divergence(y, self._call(X)))
52
+ def fit(self, X, D):
53
+ from scipy.linalg import solve_sylvester
54
+ super().fit(X, D)
55
+ A = self._X.T @ self._X + self.beta * np.eye(self._n_features)
56
+ B = self.alpha * self._D.T @ self._D
57
+ C = (1 + self.alpha) * self._X.T @ self._D
58
+ self._W = solve_sylvester(A, B, C)
59
+ return self
243
60
 
244
61
  def predict(self, X):
245
- return self._call(X)
246
-
247
-
248
- class BCPNN(CPNN):
249
-
250
- def __init__(self, **params):
251
- super().__init__(mode='binary', **params)
252
-
253
-
254
- class ACPNN(CPNN):
255
-
256
- def __init__(self, **params):
257
- super().__init__(mode='augment', **params)
62
+ from pyldl.algorithms.utils import proj
63
+ return proj(X @ self._W)
@@ -0,0 +1,12 @@
1
+ import keras
2
+
3
+ from pyldl.algorithms.base import BaseDeepLDL, BaseGD
4
+
5
+
6
+ @keras.saving.register_keras_serializable()
7
+ class AA_BP(BaseGD, BaseDeepLDL):
8
+ """:class:`AA-BP <pyldl.algorithms.AA_BP>` is proposed in paper :cite:`2016:geng`.
9
+ """
10
+
11
+ def __init__(self, **kwargs):
12
+ super().__init__(**kwargs)