python-ldl 0.0.2__tar.gz → 0.0.3__tar.gz
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.
- {python-ldl-0.0.2/python_ldl.egg-info → python_ldl-0.0.3}/PKG-INFO +7 -7
- {python-ldl-0.0.2 → python_ldl-0.0.3}/README.md +6 -5
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/__init__.py +6 -2
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_algorithm_adaptation.py +41 -100
- python_ldl-0.0.3/pyldl/algorithms/_classifier.py +105 -0
- python_ldl-0.0.3/pyldl/algorithms/_incomplete.py +58 -0
- python_ldl-0.0.3/pyldl/algorithms/_label_enhancement.py +285 -0
- python_ldl-0.0.3/pyldl/algorithms/_ldl_da.py +182 -0
- python_ldl-0.0.3/pyldl/algorithms/_ldl_dpa.py +40 -0
- python_ldl-0.0.3/pyldl/algorithms/_ldl_lrr.py +39 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_ldl_scl.py +19 -32
- python_ldl-0.0.3/pyldl/algorithms/_ldlf.py +84 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_problem_transformation.py +15 -23
- python_ldl-0.0.3/pyldl/algorithms/base.py +357 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/applications/emphasis_selection.py +26 -27
- python_ldl-0.0.3/pyldl/applications/facial_emotion_recognition.py +209 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/applications/lesion_counting.py +39 -46
- python_ldl-0.0.3/pyldl/metrics.py +144 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/utils.py +45 -1
- {python-ldl-0.0.2 → python_ldl-0.0.3/python_ldl.egg-info}/PKG-INFO +7 -7
- {python-ldl-0.0.2 → python_ldl-0.0.3}/python_ldl.egg-info/SOURCES.txt +2 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/python_ldl.egg-info/requires.txt +0 -1
- {python-ldl-0.0.2 → python_ldl-0.0.3}/setup.py +1 -2
- python-ldl-0.0.2/pyldl/algorithms/_classifier.py +0 -133
- python-ldl-0.0.2/pyldl/algorithms/_incomplete.py +0 -45
- python-ldl-0.0.2/pyldl/algorithms/_label_enhancement.py +0 -328
- python-ldl-0.0.2/pyldl/algorithms/_ldl_lrr.py +0 -49
- python-ldl-0.0.2/pyldl/algorithms/_ldlf.py +0 -89
- python-ldl-0.0.2/pyldl/algorithms/base.py +0 -226
- python-ldl-0.0.2/pyldl/applications/facial_emotion_recognition.py +0 -60
- python-ldl-0.0.2/pyldl/metrics.py +0 -99
- {python-ldl-0.0.2 → python_ldl-0.0.3}/LICENSE +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/__init__.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_ensemble.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_specialized_algorithms.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/algorithms/_ssg_ldl.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/applications/__init__.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/AA_BP_fit.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/AA_BP_predict.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/AA_KNN.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/BFGS_Process.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/PT_Bayes_fit.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/PT_Bayes_predict.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/PT_SVM_fit.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/PT_SVM_predict.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/SA_BFGS_fit.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/SA_BFGS_predict.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/SA_IIS_fit.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/SA_IIS_predict.m +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/pyldl/matlab_algorithms/__init__.py +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/python_ldl.egg-info/dependency_links.txt +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/python_ldl.egg-info/top_level.txt +0 -0
- {python-ldl-0.0.2 → python_ldl-0.0.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-ldl
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Label distribution learning (LDL) and label enhancement (LE) toolkit implemented in python.
|
|
5
5
|
Home-page: https://github.com/SpriteMisaka/PyLDL
|
|
6
6
|
Author: SpriteMisaka
|
|
@@ -19,7 +19,6 @@ Requires-Dist: scikit-fuzzy
|
|
|
19
19
|
Requires-Dist: scikit-learn
|
|
20
20
|
Requires-Dist: scipy
|
|
21
21
|
Requires-Dist: tensorflow
|
|
22
|
-
Requires-Dist: tensorflow-addons
|
|
23
22
|
Requires-Dist: tensorflow-probability
|
|
24
23
|
|
|
25
24
|
# PyLDL
|
|
@@ -35,12 +34,13 @@ Label distribution learning (LDL) and label enhancement (LE) toolkit implemented
|
|
|
35
34
|
+ ([Shen et al. 2017](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shen2017.pdf))[*NeurIPS*]: `LDLF`.
|
|
36
35
|
+ ([Wang and Geng 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2019.pdf))[*IJCAI*]: `LDL4C`$^3$.
|
|
37
36
|
+ ([Shen et al. 2020](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shen2020.pdf))[*南京理工大学学报* (Chinese)]: `AdaBoostLDL`.
|
|
38
|
-
+ ([González et al. 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021a.pdf))[*
|
|
39
|
-
+ ([González et al. 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021b.pdf))[*
|
|
37
|
+
+ ([González et al. 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021a.pdf))[*Inf. Sci.*]: `SSG_LDL`$^4$.
|
|
38
|
+
+ ([González et al. 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021b.pdf))[*Inf. Fusion*]: `DF_LDL`.
|
|
40
39
|
+ ([Wang and Geng 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2021a.pdf))[*IJCAI*]: `LDL_HR`$^3$.
|
|
41
40
|
+ ([Wang and Geng 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2021b.pdf))[*ICML*]: `LDLM`$^3$.
|
|
42
41
|
+ ([Jia et al. 2021](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2021.pdf))[*TKDE*]: `LDL_SCL`.
|
|
43
|
-
+ ([Jia et al.
|
|
42
|
+
+ ([Jia et al. 2023a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2023a.pdf))[*TKDE*]: `LDL_LRR`.
|
|
43
|
+
+ ([Jia et al. 2023b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2023b.pdf))[*TNNLS*]: `LDL_DPA`.
|
|
44
44
|
+ ([Wen et al. 2023](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wen2023.pdf))[*ICCV*]: `CAD`$^1$, `QFD2`$^1$, and `CJS`$^1$.
|
|
45
45
|
+ LE algorithms:
|
|
46
46
|
+ ([Xu, Liu, and Geng 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/xu2019.pdf))[*TKDE*]: `FCM`, `KM`, `LP`, `ML`, and `GLLE`.
|
|
@@ -49,9 +49,10 @@ Label distribution learning (LDL) and label enhancement (LE) toolkit implemented
|
|
|
49
49
|
+ LDL metrics: `chebyshev`, `clark`, `canberra`, `kl_divergence`, `cosine`, `intersection`, etc.
|
|
50
50
|
+ Structured LDL datasets: *Human_Gene*, *Movie*, *Natural_Scene*, *s-BU_3DFE*, *s-JAFFE*, *Yeast*, etc.
|
|
51
51
|
+ LDL applications:
|
|
52
|
-
+ Facial emotion recognition (supported datasets: [*JAFFE*](https://zenodo.org/records/3451524))
|
|
52
|
+
+ Facial emotion recognition (supported datasets: [*JAFFE*](https://zenodo.org/records/3451524))
|
|
53
53
|
+ ([Shirani et al. 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shirani2019.pdf))[*ACL*]: Emphasis selection (supported datasets: [*SemEval2020*](https://github.com/RiTUAL-UH/SemEval2020_Task10_Emphasis_Selection); pre-trained GloVe embeddings can be downloaded [here](https://nlp.stanford.edu/projects/glove/)).
|
|
54
54
|
+ ([Wu et al. 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wu2019.pdf))[*ICCV*]: Lesion counting (supported datasets: [*ACNE04*](https://drive.google.com/drive/folders/18yJcHXhzOv7H89t-Lda6phheAicLqMuZ)).
|
|
55
|
+
+ ([Chen et al. 2020](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/chen2020.pdf))[*CVPR*]: Facial emotion recognition with auxiliary label space graphs (supported datasets: [*CK+*](https://www.jeffcohn.net/Resources/); OpenFace can be downloaded [here](https://github.com/TadasBaltrusaitis/OpenFace/releases), and the required models can be downloaded [here](https://github.com/TadasBaltrusaitis/OpenFace/wiki/Model-download)).
|
|
55
56
|
|
|
56
57
|
> $^1$ Technically, these methods are only suitable for totally ordered labels.
|
|
57
58
|
>
|
|
@@ -181,7 +182,6 @@ scikit-fuzzy>=0.4.2
|
|
|
181
182
|
scikit-learn>=1.0.2
|
|
182
183
|
scipy>=1.8.0
|
|
183
184
|
tensorflow>=2.8.0
|
|
184
|
-
tensorflow-addons>=0.22.0
|
|
185
185
|
tensorflow-probability>=0.16.0
|
|
186
186
|
```
|
|
187
187
|
|
|
@@ -11,12 +11,13 @@ Label distribution learning (LDL) and label enhancement (LE) toolkit implemented
|
|
|
11
11
|
+ ([Shen et al. 2017](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shen2017.pdf))[*NeurIPS*]: `LDLF`.
|
|
12
12
|
+ ([Wang and Geng 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2019.pdf))[*IJCAI*]: `LDL4C`$^3$.
|
|
13
13
|
+ ([Shen et al. 2020](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shen2020.pdf))[*南京理工大学学报* (Chinese)]: `AdaBoostLDL`.
|
|
14
|
-
+ ([González et al. 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021a.pdf))[*
|
|
15
|
-
+ ([González et al. 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021b.pdf))[*
|
|
14
|
+
+ ([González et al. 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021a.pdf))[*Inf. Sci.*]: `SSG_LDL`$^4$.
|
|
15
|
+
+ ([González et al. 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/gonz%C3%A1lez2021b.pdf))[*Inf. Fusion*]: `DF_LDL`.
|
|
16
16
|
+ ([Wang and Geng 2021a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2021a.pdf))[*IJCAI*]: `LDL_HR`$^3$.
|
|
17
17
|
+ ([Wang and Geng 2021b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wang2021b.pdf))[*ICML*]: `LDLM`$^3$.
|
|
18
18
|
+ ([Jia et al. 2021](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2021.pdf))[*TKDE*]: `LDL_SCL`.
|
|
19
|
-
+ ([Jia et al.
|
|
19
|
+
+ ([Jia et al. 2023a](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2023a.pdf))[*TKDE*]: `LDL_LRR`.
|
|
20
|
+
+ ([Jia et al. 2023b](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/jia2023b.pdf))[*TNNLS*]: `LDL_DPA`.
|
|
20
21
|
+ ([Wen et al. 2023](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wen2023.pdf))[*ICCV*]: `CAD`$^1$, `QFD2`$^1$, and `CJS`$^1$.
|
|
21
22
|
+ LE algorithms:
|
|
22
23
|
+ ([Xu, Liu, and Geng 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/xu2019.pdf))[*TKDE*]: `FCM`, `KM`, `LP`, `ML`, and `GLLE`.
|
|
@@ -25,9 +26,10 @@ Label distribution learning (LDL) and label enhancement (LE) toolkit implemented
|
|
|
25
26
|
+ LDL metrics: `chebyshev`, `clark`, `canberra`, `kl_divergence`, `cosine`, `intersection`, etc.
|
|
26
27
|
+ Structured LDL datasets: *Human_Gene*, *Movie*, *Natural_Scene*, *s-BU_3DFE*, *s-JAFFE*, *Yeast*, etc.
|
|
27
28
|
+ LDL applications:
|
|
28
|
-
+ Facial emotion recognition (supported datasets: [*JAFFE*](https://zenodo.org/records/3451524))
|
|
29
|
+
+ Facial emotion recognition (supported datasets: [*JAFFE*](https://zenodo.org/records/3451524))
|
|
29
30
|
+ ([Shirani et al. 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/shirani2019.pdf))[*ACL*]: Emphasis selection (supported datasets: [*SemEval2020*](https://github.com/RiTUAL-UH/SemEval2020_Task10_Emphasis_Selection); pre-trained GloVe embeddings can be downloaded [here](https://nlp.stanford.edu/projects/glove/)).
|
|
30
31
|
+ ([Wu et al. 2019](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/wu2019.pdf))[*ICCV*]: Lesion counting (supported datasets: [*ACNE04*](https://drive.google.com/drive/folders/18yJcHXhzOv7H89t-Lda6phheAicLqMuZ)).
|
|
32
|
+
+ ([Chen et al. 2020](https://github.com/SpriteMisaka/PyLDL/blob/main/bibliography/chen2020.pdf))[*CVPR*]: Facial emotion recognition with auxiliary label space graphs (supported datasets: [*CK+*](https://www.jeffcohn.net/Resources/); OpenFace can be downloaded [here](https://github.com/TadasBaltrusaitis/OpenFace/releases), and the required models can be downloaded [here](https://github.com/TadasBaltrusaitis/OpenFace/wiki/Model-download)).
|
|
31
33
|
|
|
32
34
|
> $^1$ Technically, these methods are only suitable for totally ordered labels.
|
|
33
35
|
>
|
|
@@ -157,7 +159,6 @@ scikit-fuzzy>=0.4.2
|
|
|
157
159
|
scikit-learn>=1.0.2
|
|
158
160
|
scipy>=1.8.0
|
|
159
161
|
tensorflow>=2.8.0
|
|
160
|
-
tensorflow-addons>=0.22.0
|
|
161
162
|
tensorflow-probability>=0.16.0
|
|
162
163
|
```
|
|
163
164
|
|
|
@@ -9,18 +9,22 @@ from ._ensemble import DF_LDL, AdaBoostLDL
|
|
|
9
9
|
from ._ldlf import LDLF
|
|
10
10
|
from ._ldl_scl import LDL_SCL
|
|
11
11
|
from ._ldl_lrr import LDL_LRR
|
|
12
|
+
from ._ldl_dpa import LDL_DPA
|
|
12
13
|
|
|
13
14
|
from ._ssg_ldl import SSG_LDL
|
|
14
15
|
|
|
15
16
|
from ._label_enhancement import FCM, KM, LP, ML, GLLE, LEVI, LIBLE
|
|
16
17
|
|
|
18
|
+
from ._ldl_da import LDL_DA
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
__all__ = ["SA_BFGS", "SA_IIS", "AA_KNN", "AA_BP", "PT_Bayes", "PT_SVM",
|
|
19
22
|
"CPNN", "BCPNN", "ACPNN", "LDSVR",
|
|
20
|
-
"LDLF", "LDL_SCL", "LDL_LRR", "CAD", "QFD2", "CJS",
|
|
23
|
+
"LDLF", "LDL_SCL", "LDL_LRR", "LDL_DPA", "CAD", "QFD2", "CJS",
|
|
21
24
|
"DF_LDL", "AdaBoostLDL",
|
|
22
25
|
"LDL4C", "LDL_HR", "LDLM",
|
|
23
26
|
"IncomLDL",
|
|
24
27
|
"SSG_LDL",
|
|
25
28
|
"FCM", "KM", "LP", "ML", "GLLE",
|
|
26
|
-
"LEVI",
|
|
29
|
+
"LEVI", "LIBLE",
|
|
30
|
+
"LDL_DA"]
|
|
@@ -1,128 +1,74 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from sklearn.neighbors import NearestNeighbors
|
|
3
|
-
from sklearn.preprocessing import OneHotEncoder
|
|
4
3
|
|
|
5
4
|
import keras
|
|
6
5
|
import tensorflow as tf
|
|
7
6
|
from keras import backend as K
|
|
8
7
|
|
|
9
|
-
from pyldl.algorithms.base import BaseLDL, BaseDeepLDL
|
|
8
|
+
from pyldl.algorithms.base import BaseLDL, BaseDeepLDL, BaseGD, BaseAdam
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class AA_KNN(BaseLDL):
|
|
13
12
|
|
|
14
|
-
def
|
|
15
|
-
k=5,
|
|
16
|
-
random_state=None):
|
|
17
|
-
|
|
18
|
-
super().__init__(random_state)
|
|
19
|
-
|
|
20
|
-
self.k = k
|
|
21
|
-
self._model = NearestNeighbors(n_neighbors=self.k)
|
|
22
|
-
|
|
23
|
-
def fit(self, X, y):
|
|
13
|
+
def fit(self, X, y, k=5):
|
|
24
14
|
super().fit(X, y)
|
|
25
|
-
self._model.fit(self._X)
|
|
15
|
+
self._model = NearestNeighbors(n_neighbors=k).fit(self._X)
|
|
16
|
+
return self
|
|
26
17
|
|
|
27
18
|
def predict(self, X):
|
|
28
19
|
_, inds = self._model.kneighbors(X)
|
|
29
20
|
return np.average(self._y[inds], axis=1)
|
|
30
21
|
|
|
31
22
|
|
|
32
|
-
class AA_BP(BaseDeepLDL):
|
|
23
|
+
class AA_BP(BaseGD, BaseDeepLDL):
|
|
24
|
+
pass
|
|
33
25
|
|
|
34
|
-
def __init__(self, n_hidden=None, n_latent=None, random_state=None):
|
|
35
|
-
super().__init__(n_hidden, n_latent, random_state)
|
|
36
26
|
|
|
37
|
-
|
|
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):
|
|
27
|
+
class CAD(BaseAdam, BaseDeepLDL):
|
|
73
28
|
|
|
29
|
+
@staticmethod
|
|
74
30
|
@tf.function
|
|
75
|
-
def
|
|
31
|
+
def loss_function(y, y_pred):
|
|
76
32
|
def _CAD(y, y_pred):
|
|
77
33
|
return tf.reduce_mean(tf.abs(
|
|
78
34
|
tf.cumsum(y, axis=1) - tf.cumsum(y_pred, axis=1)
|
|
79
35
|
), axis=1)
|
|
80
36
|
return tf.math.reduce_sum(
|
|
81
37
|
tf.map_fn(lambda i: _CAD(y[:, :i], y_pred[:, :i]),
|
|
82
|
-
tf.range(1,
|
|
38
|
+
tf.range(1, y.shape[1] + 1),
|
|
83
39
|
fn_output_signature=tf.float32)
|
|
84
40
|
)
|
|
85
41
|
|
|
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
42
|
|
|
91
|
-
class QFD2(
|
|
43
|
+
class QFD2(BaseAdam, BaseDeepLDL):
|
|
92
44
|
|
|
45
|
+
@staticmethod
|
|
93
46
|
@tf.function
|
|
94
|
-
def _loss_function(
|
|
47
|
+
def _loss_function(y, y_pred):
|
|
95
48
|
Q = y - y_pred
|
|
96
|
-
j = tf.reshape(tf.range(
|
|
97
|
-
k = tf.reshape(tf.range(
|
|
98
|
-
A = tf.cast(1 - tf.abs(j - k) / (
|
|
49
|
+
j = tf.reshape(tf.range(y.shape[1]), [y.shape[1], 1])
|
|
50
|
+
k = tf.reshape(tf.range(y.shape[1]), [1, y.shape[1]])
|
|
51
|
+
A = tf.cast(1 - tf.abs(j - k) / (y.shape[1] - 1), dtype=tf.float32)
|
|
99
52
|
return tf.math.reduce_mean(
|
|
100
53
|
tf.linalg.diag_part(tf.matmul(tf.matmul(Q, A), tf.transpose(Q)))
|
|
101
54
|
)
|
|
102
55
|
|
|
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
56
|
|
|
57
|
+
class CJS(BaseAdam, BaseDeepLDL):
|
|
107
58
|
|
|
108
|
-
|
|
109
|
-
|
|
59
|
+
@staticmethod
|
|
110
60
|
@tf.function
|
|
111
|
-
def
|
|
61
|
+
def loss_function(y, y_pred):
|
|
112
62
|
def _CJS(y, y_pred):
|
|
113
63
|
m = 0.5 * (y + y_pred)
|
|
114
64
|
js = 0.5 * (keras.losses.kl_divergence(y, m) + keras.losses.kl_divergence(y_pred, m))
|
|
115
65
|
return tf.reduce_mean(js)
|
|
116
66
|
return tf.math.reduce_sum(
|
|
117
67
|
tf.map_fn(lambda i: _CJS(y[:, :i], y_pred[:, :i]),
|
|
118
|
-
tf.range(1,
|
|
68
|
+
tf.range(1, y.shape[1] + 1),
|
|
119
69
|
fn_output_signature=tf.float32)
|
|
120
70
|
)
|
|
121
71
|
|
|
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)
|
|
125
|
-
|
|
126
72
|
|
|
127
73
|
class RProp(keras.optimizers.Optimizer):
|
|
128
74
|
|
|
@@ -134,6 +80,10 @@ class RProp(keras.optimizers.Optimizer):
|
|
|
134
80
|
self.min_alpha = K.variable(min_alpha, name='min_alpha')
|
|
135
81
|
self.max_alpha = K.variable(max_alpha, name='max_alpha')
|
|
136
82
|
|
|
83
|
+
def apply_gradients(self, grads_and_vars):
|
|
84
|
+
grads, trainable_variables = zip(*grads_and_vars)
|
|
85
|
+
self.get_updates(trainable_variables, grads)
|
|
86
|
+
|
|
137
87
|
def get_updates(self, params, gradients):
|
|
138
88
|
grads = gradients
|
|
139
89
|
shapes = [K.int_shape(p) for p in params]
|
|
@@ -183,12 +133,12 @@ class RProp(keras.optimizers.Optimizer):
|
|
|
183
133
|
return dict(list(base_config.items()) + list(config.items()))
|
|
184
134
|
|
|
185
135
|
|
|
186
|
-
class CPNN(BaseDeepLDL):
|
|
136
|
+
class CPNN(BaseGD, BaseDeepLDL):
|
|
187
137
|
|
|
188
138
|
def _not_proper_mode(self):
|
|
189
139
|
raise ValueError("The argument 'mode' can only be 'none', 'binary' or 'augment'.")
|
|
190
140
|
|
|
191
|
-
def __init__(self, mode='none', v=5, n_hidden=
|
|
141
|
+
def __init__(self, mode='none', v=5, n_hidden=64, n_latent=None, random_state=None):
|
|
192
142
|
super().__init__(n_hidden, n_latent, random_state)
|
|
193
143
|
if mode == 'none' or mode == 'binary' or mode == 'augment':
|
|
194
144
|
self._mode = mode
|
|
@@ -196,37 +146,34 @@ class CPNN(BaseDeepLDL):
|
|
|
196
146
|
self._not_proper_mode()
|
|
197
147
|
self._v = v
|
|
198
148
|
|
|
199
|
-
|
|
200
|
-
|
|
149
|
+
@staticmethod
|
|
150
|
+
@tf.function
|
|
151
|
+
def loss_function(y, y_pred):
|
|
152
|
+
return tf.math.reduce_mean(keras.losses.kl_divergence(y, y_pred))
|
|
201
153
|
|
|
202
|
-
|
|
154
|
+
def _get_default_model(self):
|
|
155
|
+
input_shape = (self._n_features + (1 if self._mode == 'none' else self._n_outputs),)
|
|
156
|
+
return keras.Sequential([keras.layers.InputLayer(input_shape=input_shape),
|
|
157
|
+
keras.layers.Dense(self._n_hidden, activation='sigmoid'),
|
|
158
|
+
keras.layers.Dense(1, activation=None)])
|
|
203
159
|
|
|
204
|
-
|
|
205
|
-
|
|
160
|
+
def _get_default_optimizer(self):
|
|
161
|
+
return RProp()
|
|
206
162
|
|
|
163
|
+
def _before_train(self):
|
|
207
164
|
if self._mode == 'augment':
|
|
165
|
+
n = self._X.shape[0]
|
|
208
166
|
one_hot = tf.one_hot(tf.math.argmax(self._y, axis=1), self.n_outputs)
|
|
209
167
|
self._X = tf.repeat(self._X, self._v, axis=0)
|
|
210
168
|
self._y = tf.repeat(self._y, self._v, axis=0)
|
|
211
169
|
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)], [
|
|
170
|
+
v = tf.reshape(tf.tile([1 / (i + 1) for i in range(self._v)], [n]), (-1, 1))
|
|
213
171
|
self._y += self._y * one_hot * v
|
|
214
172
|
|
|
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
173
|
def _make_inputs(self, X):
|
|
227
174
|
temp = tf.reshape(tf.tile([i + 1 for i in range(self._n_outputs)], [X.shape[0]]), (-1, 1))
|
|
228
175
|
if self._mode != 'none':
|
|
229
|
-
temp =
|
|
176
|
+
temp = tf.one_hot(tf.reshape(temp, (-1, )) - 1, depth=self._n_outputs)
|
|
230
177
|
return tf.concat([tf.cast(tf.repeat(X, self._n_outputs, axis=0), dtype=tf.float32),
|
|
231
178
|
tf.cast(temp, dtype=tf.float32)],
|
|
232
179
|
axis=1)
|
|
@@ -238,12 +185,6 @@ class CPNN(BaseDeepLDL):
|
|
|
238
185
|
b = tf.reshape(-tf.math.log(tf.math.reduce_sum(tf.math.exp(results), axis=1)), (-1, 1))
|
|
239
186
|
return tf.math.exp(b + results)
|
|
240
187
|
|
|
241
|
-
def _loss(self, X, y):
|
|
242
|
-
return tf.math.reduce_mean(keras.losses.kl_divergence(y, self._call(X)))
|
|
243
|
-
|
|
244
|
-
def predict(self, X):
|
|
245
|
-
return self._call(X)
|
|
246
|
-
|
|
247
188
|
|
|
248
189
|
class BCPNN(CPNN):
|
|
249
190
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import keras
|
|
2
|
+
import tensorflow as tf
|
|
3
|
+
|
|
4
|
+
from pyldl.algorithms.base import BaseDeepLDLClassifier, BaseGD, BaseBFGS
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LDL4C(BaseBFGS, BaseDeepLDLClassifier):
|
|
8
|
+
"""LDL4C is proposed in paper Classification with Label Distribution Learning.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
@tf.function
|
|
12
|
+
def _loss(self, params_1d):
|
|
13
|
+
y_pred = keras.activations.softmax(self._X @ self._params2model(params_1d)[0])
|
|
14
|
+
top2 = tf.gather(y_pred, self._top2, axis=1, batch_dims=1)
|
|
15
|
+
margin = tf.reduce_sum(tf.maximum(0., 1. - (top2[:, 0] - top2[:, 1]) / self._rho))
|
|
16
|
+
mae = keras.losses.mean_absolute_error(self._y, y_pred)
|
|
17
|
+
return tf.reduce_sum(self._entropy * mae) + self._alpha * margin + self._beta * self._l2_reg(self._model)
|
|
18
|
+
|
|
19
|
+
def _before_train(self):
|
|
20
|
+
self._top2 = tf.math.top_k(self._y, k=2)[1]
|
|
21
|
+
self._entropy = tf.cast(-tf.reduce_sum(self._y * tf.math.log(self._y) + 1e-7, axis=1), dtype=tf.float32)
|
|
22
|
+
|
|
23
|
+
def fit(self, X, y, alpha=1e-2, beta=1e-6, rho=1e-2, **kwargs):
|
|
24
|
+
self._alpha = alpha
|
|
25
|
+
self._beta = beta
|
|
26
|
+
self._rho = rho
|
|
27
|
+
return super().fit(X, y, **kwargs)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LDL_HR(BaseBFGS, BaseDeepLDLClassifier):
|
|
31
|
+
"""LDL-HR is proposed in paper Learn the Highest Label and Rest Label Description Degrees.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
@tf.function
|
|
35
|
+
def _loss(self, params_1d):
|
|
36
|
+
y_pred = keras.activations.softmax(self._X @ self._params2model(params_1d)[0])
|
|
37
|
+
|
|
38
|
+
highest = tf.gather(y_pred, self._highest, axis=1, batch_dims=1)
|
|
39
|
+
rest = tf.gather(y_pred, self._rest, axis=1, batch_dims=1)
|
|
40
|
+
margin = tf.reduce_sum(tf.maximum(0., 1. - (highest - rest) / self._rho))
|
|
41
|
+
|
|
42
|
+
real_rest = tf.gather(self._y, self._rest, axis=1, batch_dims=1)
|
|
43
|
+
rest_mae = tf.reduce_sum(keras.losses.mean_absolute_error(real_rest, rest))
|
|
44
|
+
|
|
45
|
+
mae = tf.reduce_sum(keras.losses.mean_absolute_error(self._l, y_pred))
|
|
46
|
+
|
|
47
|
+
return mae + self._alpha * margin + self._beta * rest_mae + self._gamma * self._l2_reg(self._model)
|
|
48
|
+
|
|
49
|
+
def _before_train(self):
|
|
50
|
+
temp = tf.math.top_k(self._y, k=self._n_outputs)[1]
|
|
51
|
+
self._highest = temp[:, 0:1]
|
|
52
|
+
self._rest = temp[:, 1:]
|
|
53
|
+
self._l = tf.one_hot(tf.reshape(self._highest, -1), self._n_outputs)
|
|
54
|
+
|
|
55
|
+
def fit(self, X, y, alpha=1e-2, beta=1e-2, gamma=1e-6, rho=1e-2, **kwargs):
|
|
56
|
+
self._alpha = alpha
|
|
57
|
+
self._beta = beta
|
|
58
|
+
self._gamma = gamma
|
|
59
|
+
self._rho = rho
|
|
60
|
+
return super().fit(X, y, **kwargs)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class LDLM(BaseGD, BaseDeepLDLClassifier):
|
|
64
|
+
"""LDLM is proposed in paper Label Distribution Learning Machine.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
@tf.function
|
|
68
|
+
def _loss(self, X, y, start, end):
|
|
69
|
+
y_pred = self._model(X)
|
|
70
|
+
|
|
71
|
+
pred_margin = tf.reduce_sum(tf.clip_by_value(
|
|
72
|
+
tf.reduce_sum(tf.abs(self._l[start:end] - y_pred), axis=1) - self._rho,
|
|
73
|
+
0., float('inf')))
|
|
74
|
+
|
|
75
|
+
highest = tf.gather(y_pred, self._highest[start:end], axis=1, batch_dims=1)
|
|
76
|
+
rest = tf.gather(y_pred, self._rest[start:end], axis=1, batch_dims=1)
|
|
77
|
+
label_margin = tf.reduce_sum(tf.maximum(0., 1. - (highest - rest) / self._rho))
|
|
78
|
+
|
|
79
|
+
second_margin = tf.reduce_sum(tf.clip_by_value(
|
|
80
|
+
tf.reduce_sum(tf.abs((y - y_pred) * self._neg_l[start:end]), axis=1) - self._second_margin[start:end],
|
|
81
|
+
0., float('inf')))
|
|
82
|
+
|
|
83
|
+
return pred_margin + self._alpha * label_margin + \
|
|
84
|
+
self._beta * second_margin + self._gamma * self._l2_reg(self._model)
|
|
85
|
+
|
|
86
|
+
def _before_train(self):
|
|
87
|
+
temp = tf.math.top_k(self._y, k=self._n_outputs)[1]
|
|
88
|
+
self._highest = temp[:, 0:1]
|
|
89
|
+
self._rest = temp[:, 1:]
|
|
90
|
+
|
|
91
|
+
temp = tf.math.top_k(tf.gather(self._y, self._rest, axis=1, batch_dims=1), k=2)[0]
|
|
92
|
+
self._second_margin = temp[:, 0] - temp[:, 1]
|
|
93
|
+
|
|
94
|
+
self._l = tf.one_hot(tf.reshape(self._highest, -1), self._n_outputs)
|
|
95
|
+
self._neg_l = tf.where(tf.equal(self._l, 0.), 1., 0.)
|
|
96
|
+
|
|
97
|
+
def _get_default_model(self):
|
|
98
|
+
return self.get_2layer_model(self._n_features, self._n_outputs)
|
|
99
|
+
|
|
100
|
+
def fit(self, X, y, alpha=1e-2, beta=1e-2, gamma=1e-6, rho=1e-2, **kwargs):
|
|
101
|
+
self._alpha = alpha
|
|
102
|
+
self._beta = beta
|
|
103
|
+
self._gamma = gamma
|
|
104
|
+
self._rho = rho
|
|
105
|
+
return super().fit(X, y, **kwargs)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from qpsolvers import solve_qp
|
|
4
|
+
|
|
5
|
+
from pyldl.algorithms.base import BaseLDL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IncomLDL(BaseLDL):
|
|
9
|
+
"""IncomLDL is proposed in paper Incomplete Label Distribution Learning.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def svt(A, tau):
|
|
14
|
+
U, S, VT = np.linalg.svd(A, full_matrices=False)
|
|
15
|
+
S_thresh = np.maximum(S - tau, 0)
|
|
16
|
+
return U @ np.diag(S_thresh) @ VT
|
|
17
|
+
|
|
18
|
+
def _update_Z(self):
|
|
19
|
+
A = self._X @ self._W + self._V / self._rho
|
|
20
|
+
tau = self._alpha / self._rho
|
|
21
|
+
self._Z = self.svt(A, tau)
|
|
22
|
+
|
|
23
|
+
def _update_W(self):
|
|
24
|
+
|
|
25
|
+
G = -np.eye(self._n_outputs, dtype=np.float64)
|
|
26
|
+
h = np.zeros((self._n_outputs, 1), dtype=np.float64)
|
|
27
|
+
A = np.ones((1, self._n_outputs), dtype=np.float64)
|
|
28
|
+
b = np.array([1.], dtype=np.float64)
|
|
29
|
+
|
|
30
|
+
M = np.zeros_like(self._y)
|
|
31
|
+
|
|
32
|
+
for i in range(self._X.shape[0]):
|
|
33
|
+
P = np.diag((1 + self._rho) * self._mask[i] + self._rho * (1 - self._mask[i])).astype(np.float64)
|
|
34
|
+
ql = (self._V[i] - self._y[i] * self._mask[i] - self._rho * self._Z[i]) * self._mask[i]
|
|
35
|
+
qr = (self._V[i] - self._rho * self._Z[i]) * (1 - self._mask[i])
|
|
36
|
+
q = np.transpose(ql + qr).astype(np.float64)
|
|
37
|
+
M[i] = solve_qp(P, q, G, h, A, b, solver='quadprog')
|
|
38
|
+
|
|
39
|
+
self._W = np.linalg.pinv(np.transpose(self._X) @ self._X) @ np.transpose(self._X) @ M
|
|
40
|
+
|
|
41
|
+
def _update_V(self):
|
|
42
|
+
self._V = self._V + self._rho * (self._X @ self._W - self._Z)
|
|
43
|
+
|
|
44
|
+
def fit(self, X, y, mask, alpha=1e-3, rho=1., max_iterations=100):
|
|
45
|
+
super().fit(X, y)
|
|
46
|
+
self._alpha = alpha
|
|
47
|
+
self._rho = rho
|
|
48
|
+
self._mask = np.where(mask, 0., 1.)
|
|
49
|
+
self._W = np.ones((self._n_features, self._n_outputs))
|
|
50
|
+
self._Z = np.ones((self._X.shape[0], self._n_outputs))
|
|
51
|
+
self._V = np.ones((self._X.shape[0], self._n_outputs))
|
|
52
|
+
for _ in range(max_iterations):
|
|
53
|
+
self._update_W()
|
|
54
|
+
self._update_Z()
|
|
55
|
+
self._update_V()
|
|
56
|
+
|
|
57
|
+
def predict(self, X):
|
|
58
|
+
return X @ self._W
|