From 9829bc59b4a0e7a73eda3238d58e66051b02f8d1 Mon Sep 17 00:00:00 2001
From: Dominique Benielli <dominique.benielli@lis-lab.fr>
Date: Wed, 25 Mar 2020 19:06:24 +0100
Subject: [PATCH] copyright + bug fix compute alpha

---
 VERSION                                     |   2 +
 copyright.py                                |   2 +-
 copyrightstamp.txt                          |   2 +-
 examples/usecase/plot_usecase_exampleMKL.py |   2 -
 license.txt                                 |   2 +-
 multimodal/__init__.py                      |   2 +-
 multimodal/boosting/cumbo.py                |  14 +--
 multimodal/boosting/mumbo.py                |  11 ++-
 multimodal/kernels/mvml.py                  |   2 +-
 multimodal/tests/data/digit.py              |  62 ++++++++++++
 multimodal/tests/data/digit_y.npy           | Bin 14504 -> 0 bytes
 setup.py                                    | 104 +++++++++++++++++++-
 12 files changed, 185 insertions(+), 20 deletions(-)
 create mode 100644 VERSION
 create mode 100644 multimodal/tests/data/digit.py
 delete mode 100644 multimodal/tests/data/digit_y.npy

diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..1578b44
--- /dev/null
+++ b/VERSION
@@ -0,0 +1,2 @@
+multimodal:0.0.dev0
+
diff --git a/copyright.py b/copyright.py
index dcf2f20..76c97d1 100644
--- a/copyright.py
+++ b/copyright.py
@@ -50,7 +50,7 @@ def getStamp(date, iw_version):
     """ Return the corrected formated stamp """
     stamp = open("copyrightstamp.txt").read()
     stamp = stamp.replace("DATE", date)
-    stamp = stamp.replace("IW_VERSION", iw_version)
+    stamp = stamp.replace("MULTIMODAL_VERSION", multimodal_version)
     stamp = stamp.replace('\n', '\n# ')
     stamp = "# " + stamp
     stamp = stamp.replace("# \n", "#\n")
diff --git a/copyrightstamp.txt b/copyrightstamp.txt
index 64f2083..b3d76ec 100644
--- a/copyrightstamp.txt
+++ b/copyrightstamp.txt
@@ -34,7 +34,7 @@ Version:
 Licence:
 -------
 
-License: LGPLv3+
+License: New BSD License
 
 
 ######### COPYRIGHT #########
diff --git a/examples/usecase/plot_usecase_exampleMKL.py b/examples/usecase/plot_usecase_exampleMKL.py
index 27d6fbf..600c566 100644
--- a/examples/usecase/plot_usecase_exampleMKL.py
+++ b/examples/usecase/plot_usecase_exampleMKL.py
@@ -19,7 +19,6 @@ from sklearn.tree import DecisionTreeClassifier
 from multimodal.datasets.base import load_dict, save_dict
 from multimodal.tests.data.get_dataset_path import get_dataset_path
 from multimodal.datasets.data_sample import MultiModalArray
-from multimodal.kernels.mvml import MVML
 from multimodal.kernels.lpMKL import MKL
 
 import numpy as np
@@ -50,7 +49,6 @@ if __name__ == '__main__':
     # file = get_dataset_path("digit_histogram.npy")
     file = get_dataset_path("digit_col_grad.npy")
     y = np.load(get_dataset_path("digit_y.npy"))
-    base_estimator = DecisionTreeClassifier(max_depth=4)
     dic_digit = load_dict(file)
     XX =MultiModalArray(dic_digit)
     X_train, X_test, y_train, y_test = train_test_split(XX, y)
diff --git a/license.txt b/license.txt
index 1011e46..54ead26 100644
--- a/license.txt
+++ b/license.txt
@@ -1,6 +1,6 @@
 New BSD License
 
-Copyright (c) 2020-15-01, The scit-multimodallearn developers.
+Copyright (c) 2020-15-01, The scikit-multimodallearn developers.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/multimodal/__init__.py b/multimodal/__init__.py
index 1ff9679..e851e58 100644
--- a/multimodal/__init__.py
+++ b/multimodal/__init__.py
@@ -1 +1 @@
-__version__ = '0.0.dev0'
+__version__ = "0.0.dev0"
diff --git a/multimodal/boosting/cumbo.py b/multimodal/boosting/cumbo.py
index 158c9ca..175a9cf 100644
--- a/multimodal/boosting/cumbo.py
+++ b/multimodal/boosting/cumbo.py
@@ -311,16 +311,16 @@ class MuCumboClassifier(BaseEnsemble, ClassifierMixin, UBoosting):
         zeta2 = zeta**2
         def F(x=None, z=None):
             if x is None:
-                # l'algorithme fonctionne de manière itérative
-                # il faut choisir un x initial, c'est ce qu'on fait ici
+                # iteratif algo
+                # choice x initial
                 return 0, matrix(1.0, (n_view*m, 1))
             if min(x) < 0.0:
-                return None   # cas impossible
-            # ici commence le code qui définit ce qu'est une itération
-            f = sum(matrix(coef * exp( matrix(zeta * x.T))   ))
-            Df = matrix(np.sum( zeta * coef * exp(matrix( zeta * x.T ) ), axis=0 )).T # -(x**-1).T
+                return None   # impossible
+            # begin iteration
+            f = sum(matrix(coef * exp( matrix(zeta * x.T))))
+            Df = matrix(np.sum( zeta * coef * exp(matrix( zeta * x.T)), axis=0)).T  # -(x**-1).T
             if z is None: return f, Df
-            H = spdiag(z[0] * matrix(np.sum(coef * zeta2 * exp( matrix(zeta* x.T) ), axis= 0))) ## beta**(-2))
+            H = spdiag(z[0] * matrix(np.sum(coef * zeta2 * exp( matrix(zeta* x.T)), axis=0)))  # beta**(-2))
             return f, Df, H
         try:
             solver = solvers.cp(F, A=A, b=b, G=G, h=h, dim={'l':2*n_view*m})['x']
diff --git a/multimodal/boosting/mumbo.py b/multimodal/boosting/mumbo.py
index 23dacff..29cfe52 100644
--- a/multimodal/boosting/mumbo.py
+++ b/multimodal/boosting/mumbo.py
@@ -221,12 +221,19 @@ class MumboClassifier(BaseEnsemble, ClassifierMixin, UBoosting):
 
     def _compute_alphas(self, edges):
         """Compute values of confidence rate alpha given edge values."""
+        dim = edges.shape[0]
         np.where(edges > 1.0, edges, 1.0)
         alphas = 0.5 * np.log((1. + edges) / (1. - edges))
         if np.any(np.isinf(alphas)):
-            alphas[np.where(np.isinf(alphas))[0]] = 1.0
+            if isinstance(alphas, float):
+                alphas = 1.0
+            else:
+                alphas[np.where(np.isinf(alphas))[0]] = 1.0
         if np.any(np.isnan(alphas)):
-            alphas[np.where(np.isnan(alphas))[0]] = 1.0
+            if isinstance(alphas, float):
+                alphas = 1.0
+            else:
+                alphas[np.where(np.isnan(alphas))[0]] = 1.0
         return alphas
 
     def _compute_cost_global(self, label_score_global, best_predicted_classes,
diff --git a/multimodal/kernels/mvml.py b/multimodal/kernels/mvml.py
index d2ce3e9..3365f2c 100644
--- a/multimodal/kernels/mvml.py
+++ b/multimodal/kernels/mvml.py
@@ -613,7 +613,7 @@ class MVML(MKernel, BaseEstimator, ClassifierMixin, RegressorMixin):
 
         return A_new
 
-    def score(self, X, y=None):
+    def score(self, X, y):
         """Return the mean accuracy on the given test data and labels.
 
         Parameters
diff --git a/multimodal/tests/data/digit.py b/multimodal/tests/data/digit.py
new file mode 100644
index 0000000..00f69a3
--- /dev/null
+++ b/multimodal/tests/data/digit.py
@@ -0,0 +1,62 @@
+from sklearn import datasets
+import numpy as np
+import PIL
+import matplotlib.pyplot as plt
+import os
+import matplotlib.pyplot as plt
+from multimodal.datasets.base import load_dict, save_dict
+from multimodal.tests.data.get_dataset_path import get_dataset_path
+from multimodal.datasets.data_sample import MultiModalArray
+from multimodal.kernels.mvml import MVML
+#Load the digits dataset
+digits = datasets.load_digits()
+
+#Display the first digit
+plt.figure(1, figsize=(3, 3))
+plt.imshow(digits.images[-1], cmap=plt.cm.gray_r, interpolation='nearest')
+plt.show()
+colors = digits.data
+gradiant = np.gradient(digits.images, axis=[1,2])
+print(gradiant[0].shape)
+gradiant0 = gradiant[0].reshape(colors.shape[0], colors.shape[1])
+gradiant1 = gradiant[1].reshape(colors.shape[0], colors.shape[1])
+for ind in range(digits.images.shape[0]):
+    ima0 = digits.images[ind, :,:]
+    ima1 = gradiant[0][ind, :,:]
+    ima2 = gradiant[1][ind, :,:]
+    ama_pil0 = PIL.Image.fromarray(ima0, mode=None)
+    ama_pil1 = PIL.Image.fromarray(ima1, mode=None)
+    ama_pil2 = PIL.Image.fromarray(ima2, mode=None)
+    histo_color = np.asarray(ama_pil0.histogram())
+    histo_gradiant0 = np.asarray(ama_pil1.histogram())
+    histo_gradiant1 = np.asarray(ama_pil2.histogram())
+    if ind==0:
+        list_histogram_color = histo_color
+        list_histogram_gradiant0 = histo_gradiant0
+        list_histogram_gradiant1 = histo_gradiant1
+    else:
+        list_histogram_color = np.vstack((list_histogram_color, histo_color))
+        list_histogram_gradiant0 = np.vstack((list_histogram_gradiant0, histo_gradiant0))
+        list_histogram_gradiant1 = np.vstack((list_histogram_gradiant1, histo_gradiant1))
+
+dict_digit = {0: list_histogram_color, 1: list_histogram_gradiant0, 2: list_histogram_gradiant1}
+
+
+print(list_histogram_color.shape)
+print(list_histogram_gradiant0.shape)
+print(list_histogram_gradiant1.shape)
+file = get_dataset_path("digit_histogram.npy")
+save_dict(dict_digit, file)
+
+d2 = load_dict(file)
+
+figure = plt.figure(figsize=(27, 9))
+ax = plt.subplot(2,1,1)
+
+ax.scatter(list_histogram_color[:,3], list_histogram_color[:,4], c=digits.target, edgecolors='k')
+ax = plt.subplot(2,1,2)
+ax.scatter(list_histogram_color[:,0], list_histogram_color[:,1], c=digits.target, edgecolors='k')
+plt.show()
+
+mvml = MVML(lmbda=0.1, eta=1, nystrom_param=0.2)
+mvml.fit(d2, digits.target)
diff --git a/multimodal/tests/data/digit_y.npy b/multimodal/tests/data/digit_y.npy
deleted file mode 100644
index b5588884574d1c89a5d34ece3993af4b532b7191..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 14504
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
HaTp%}0<=3U

diff --git a/setup.py b/setup.py
index 5ec883a..4819398 100644
--- a/setup.py
+++ b/setup.py
@@ -1,15 +1,111 @@
 
-import os
+import os, re
+import shutil
 from setuptools import setup, find_packages
-
+from distutils.command.clean import clean as _clean
+from distutils.dir_util import remove_tree
+from distutils.command.sdist import sdist
 import multimodal
 
+try:
+    import numpy
+except:
+    raise 'Cannot build iw without numpy'
+    sys.exit()
+
+# --------------------------------------------------------------------
+# Clean target redefinition - force clean everything supprimer de la liste '^core\.*$',
+relist = ['^.*~$', '^#.*#$', '^.*\.aux$', '^.*\.pyc$', '^.*\.o$']
+reclean = []
+USE_COPYRIGHT = True
+try:
+    from copyright import writeStamp, eraseStamp
+except ImportError:
+    USE_COPYRIGHT = False
+
+###################
+# Get Multimodal version
+####################
+def get_version():
+    v_text = open('VERSION').read().strip()
+    v_text_formted = '{"' + v_text.replace('\n', '","').replace(':', '":"')
+    v_text_formted += '"}'
+    v_dict = eval(v_text_formted)
+    return v_dict["multimodal"]
+
+########################
+# Set Multimodal __version__
+########################
+def set_version(multimodal_dir, version):
+    filename = os.path.join(multimodal_dir, '__init__.py')
+    buf = ""
+    for line in open(filename, "rb"):
+        if not line.decode("utf8").startswith("__version__ ="):
+            buf += line.decode("utf8")
+    f = open(filename, "wb")
+    f.write(buf.encode("utf8"))
+    f.write(('__version__ = "%s"\n' % version).encode("utf8"))
+
+for restring in relist:
+    reclean.append(re.compile(restring))
+
+
+def wselect(args, dirname, names):
+    for n in names:
+        for rev in reclean:
+            if (rev.match(n)):
+                os.remove("%s/%s" %(dirname, n))
+        break
+
+
+######################
+# Custom clean command
+######################
+class clean(_clean):
+    def walkAndClean(self):
+        os.walk("..", wselect, [])
+        pass
+
+    def run(self):
+        clean.run(self)
+        if os.path.exists('build'):
+            shutil.rmtree('build')
+        for dirpath, dirnames, filenames in os.walk('iw'):
+            for filename in filenames:
+                if (filename.endswith('.so') or
+                        filename.endswith('.pyd') or
+                        filename.endswith('.dll') or
+                        filename.endswith('.pyc')):
+                    os.unlink(os.path.join(dirpath, filename))
+            for dirname in dirnames:
+                if dirname == '__pycache__':
+                    shutil.rmtree(os.path.join(dirpath, dirname))
+
+
+##############################
+# Custom sdist command
+##############################
+class m_sdist(sdist):
+    """ Build source package
+
+    WARNING : The stamping must be done on an default utf8 machine !
+    """
+
+    def run(self):
+        if USE_COPYRIGHT:
+            writeStamp()
+            sdist.run(self)
+            # eraseStamp()
+        else:
+            sdist.run(self)
 
 def setup_package():
     """Setup function"""
 
     name = 'scikit-multimodallearn'
-    version = multimodal.__version__
+    version = get_version()
+    multimodal_dir = 'multimodal'
+    set_version(multimodal_dir, version)
     description = 'A scikit-learn compatible package for multimodal Classifiers'
     here = os.path.abspath(os.path.dirname(__file__))
     with open(os.path.join(here, 'README.rst'), encoding='utf-8') as readme:
@@ -21,7 +117,7 @@ def setup_package():
         'Source': url,
         'Tracker': '{}/issues'.format(url)}
     author = 'Dominique Benielli and Sokol Koço and Florent Jaillet and Riikka Huusari ' \
-             'and Cécile Capponi and Hachem Kadri'
+             'and Baptiste Bauvin and Cécile Capponi and Hachem Kadri'
     author_email = 'contact.dev@lis-lab.fr'
     license = 'newBSD'
     classifiers = [
-- 
GitLab