Repository: ElementAI/baal
Pull request #22 (2019-11-07 16:38:43)

Fix doc
## Summary:

### Features:


## Checklist:

* [ ] Your code is documented (To validate this, add your module to `tests/documentation_test.py`).
* [ ] Your code is tested with unit tests.
* [ ] You moved your Issue to the PR state.



Patch:
diff --git a/docs/conf.py b/docs/conf.py
index cf326f3..60d3d9e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -55,7 +55,7 @@ extensions = [
 
 # We need to mock these packages to compile without deps.
 autodoc_mock_imports = ["PIL", "tqdm", "structlog", "torch", "torchvision", "numpy", "sklearn",
-                        "scipy"]
+                        "scipy", "baal.utils.cuda_utils"]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
diff --git a/docs/literature/images/dim/fig3.png b/docs/literature/images/dmi/fig3.png
similarity index 100%
rename from docs/literature/images/dim/fig3.png
rename to docs/literature/images/dmi/fig3.png
diff --git a/src/baal/active/heuristics/heuristics.py b/src/baal/active/heuristics/heuristics.py
index 58db028..87c1eed 100644
--- a/src/baal/active/heuristics/heuristics.py
+++ b/src/baal/active/heuristics/heuristics.py
@@ -1,6 +1,6 @@
-from functools import wraps as _wraps
 import types
 import warnings
+from functools import wraps as _wraps
 
 import numpy as np
 import scipy.stats
@@ -25,6 +25,7 @@ def _shuffle_subset(data: np.ndarray, shuffle_prop: float) -> np.ndarray:
 def singlepass(fn):
     """
     Will take the mean of the iterations if needed.
+
     Args:
         fn (Callable): Heuristic function.
 
@@ -44,7 +45,15 @@ def singlepass(fn):
 
 
 def requireprobs(fn):
-    """Will convert logits to probs if needed"""
+    """
+    Will convert logits to probs if needed.
+
+    Args:
+        fn (Fn): Function that takes logits as input to wraps.
+
+    Returns:
+        Wrapper function
+    """
 
     @_wraps(fn)
     def wrapper(self, probabilities):
@@ -58,7 +67,8 @@ def requireprobs(fn):
 
 
 class AbstractHeuristic:
-    """Abstract class that defines a Heuristic.
+    """
+    Abstract class that defines a Heuristic.
 
     Args:
         shuffle_prop (float): shuffle proportion.
@@ -77,6 +87,7 @@ class AbstractHeuristic:
     def compute_score(self, predictions):
         """
         Compute the score according to the heuristic.
+
         Args:
             predictions (ndarray): Array of predictions
 
@@ -88,9 +99,13 @@ class AbstractHeuristic:
     def get_uncertainties_generator(self, predictions):
         """
         Compute the score according to the heuristic.
+
         Args:
             predictions (Iterable): Generator of predictions
 
+        Raises:
+            ValueError if the generator is empty.
+
         Returns:
             Array of scores.
         """
@@ -102,7 +117,16 @@ class AbstractHeuristic:
         return np.concatenate(acc)
 
     def get_uncertainties(self, predictions):
-        """Get the uncertainties"""
+        """
+        Get the uncertainties.
+
+        Args:
+            predictions (ndarray): Array of predictions
+
+        Returns:
+            Array of uncertainties
+
+        """
         if isinstance(predictions, Tensor):
             predictions = predictions.numpy()
         scores = self.compute_score(predictions)
@@ -114,7 +138,16 @@ class AbstractHeuristic:
         return scores
 
     def get_ranks(self, predictions):
-        """Rank the predictions according to their uncertainties."""
+        """
+        Rank the predictions according to their uncertainties.
+
+        Args:
+            predictions (ndarray): [batch_size, C, ..., Iterations]
+
+        Returns:
+            Ranked index according to the uncertainty (highest to lowes).
+
+        """
         if isinstance(predictions, types.GeneratorType):
             scores = self.get_uncertainties_generator(predictions)
         else:
@@ -135,7 +168,15 @@ class AbstractHeuristic:
 
 
 class BALD(AbstractHeuristic):
-    """Sort by the highest acquisition function value.
+    """
+    Sort by the highest acquisition function value.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+
+
     References:
         https://arxiv.org/abs/1703.02910
     """
@@ -147,6 +188,15 @@ class BALD(AbstractHeuristic):
 
     @requireprobs
     def compute_score(self, predictions):
+        """
+        Compute the score according to the heuristic.
+
+        Args:
+            predictions (ndarray): Array of predictions
+
+        Returns:
+            Array of scores.
+        """
         assert predictions.ndim >= 3
         # [n_sample, n_class, ..., n_iterations]
 
@@ -163,6 +213,12 @@ class BatchBALD(BALD):
     """
     Implementation of BatchBALD.
 
+    Args:
+        num_samples (int): Number of samples to select. (min 2*the amount of samples you want)
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+
     References:
         https://arxiv.org/abs/1906.08158
 
@@ -196,6 +252,15 @@ class BatchBALD(BALD):
 
     @requireprobs
     def compute_score(self, predictions):
+        """
+        Compute the score according to the heuristic.
+
+        Args:
+            predictions (ndarray): Array of predictions
+
+        Returns:
+            Array of scores.
+        """
         MAX_SELECTED = 16000
         MIN_SPREAD = 0.1
         COUNT = 0
@@ -227,7 +292,19 @@ class BatchBALD(BALD):
         return np.array(history)
 
     def get_ranks(self, predictions):
-        """Rank the predictions according to their uncertainties."""
+        """
+        Rank the predictions according to their uncertainties.
+
+        Args:
+            predictions (ndarray): [batch_size, C, ..., Iterations]
+
+        Returns:
+            Ranked index according to the uncertainty (highest to lowest).
+
+        Raises:
+            ValueError if predictions is a generator.
+
+        """
         if isinstance(predictions, types.GeneratorType):
             raise ValueError("BatchBALD doesn't support generators.")
 
@@ -239,7 +316,14 @@ class BatchBALD(BALD):
 
 
 class Variance(AbstractHeuristic):
-    """Sort by the highest variance"""
+    """
+    Sort by the highest variance.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reduction='mean'):
         _help = "Need to reduce the output from [n_sample, n_class] to [n_sample]"
@@ -254,7 +338,14 @@ class Variance(AbstractHeuristic):
 
 
 class Entropy(AbstractHeuristic):
-    """Sort by the highest entropy"""
+    """
+    Sort by the highest entropy.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reduction='none'):
         super().__init__(
@@ -268,8 +359,15 @@ class Entropy(AbstractHeuristic):
 
 
 class Margin(AbstractHeuristic):
-    """Sort by the lowest margin, i.e. the difference between the most confident class and
-    the second most confident class."""
+    """
+    Sort by the lowest margin, i.e. the difference between the most confident class and
+    the second most confident class.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reduction='none'):
         super().__init__(
@@ -284,7 +382,14 @@ class Margin(AbstractHeuristic):
 
 
 class Certainty(AbstractHeuristic):
-    """Sort by the lowest certainty"""
+    """
+    Sort by the lowest certainty.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reduction (Union[str, callable]): function that aggregates the results.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reduction='none'):
         super().__init__(
@@ -297,7 +402,13 @@ class Certainty(AbstractHeuristic):
 
 
 class Random(AbstractHeuristic):
-    """Random heuristic."""
+    """Random heuristic.
+
+    Args:
+        shuffle_prop (float): UNUSED
+        threshold (Optional[Float]): UNUSED
+        reduction (Union[str, callable]): UNUSED.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reduction='none'):
         super().__init__(1.0, threshold, False)
@@ -311,7 +422,13 @@ class Random(AbstractHeuristic):
 
 
 class Precomputed(AbstractHeuristic):
-    """Precomputed heuristics"""
+    """Precomputed heuristics.
+
+    Args:
+        shuffle_prop (float): Amount of noise to put in the ranking. Helps with selection bias.
+        threshold (Optional[Float]): Will ignore sample if the maximum prob is below this.
+        reverse (Bool): Sort from lowest to highest if False.
+    """
 
     def __init__(self, shuffle_prop=0.0, threshold=None, reverse=False):
         super().__init__(shuffle_prop, threshold, reverse=reverse)
diff --git a/src/baal/utils/metrics.py b/src/baal/utils/metrics.py
index d472cbf..021943d 100644
--- a/src/baal/utils/metrics.py
+++ b/src/baal/utils/metrics.py
@@ -22,12 +22,12 @@ class Metrics(object):
         self.result = torch.FloatTensor()
 
     def reset(self):
-        """reset the private values of the class"""
+        """Reset the private values of the class."""
         raise NotImplementedError
 
     def update(self, output=None, target=None):
-        """main calculation of the metric which updated the
-        private values respectively.
+        """
+        Main calculation of the metric which updated the private values respectively.
 
         Args:
             output (tensor): predictions of model


Test patch:
diff --git a/tests/documentation_test.py b/tests/documentation_test.py
index e229756..908d499 100644
--- a/tests/documentation_test.py
+++ b/tests/documentation_test.py
@@ -7,6 +7,8 @@ from itertools import compress
 import pytest
 
 modules = ['baal', 'baal.active', 'baal.bayesian',
+           'baal.active.heuristics', 'baal.active.active_loop',
+           'baal.active.dataset', 'baal.active.file_dataset',
            'baal.utils.metrics', 'baal.utils.cuda_utils']
 # We do not force these functions to be compliant.
 accepted_name = ['set_logger_config']
@@ -58,9 +60,9 @@ def handle_function(name, member):
 def assert_doc_style(name, member, doc, args):
     lines = doc.split("\n")
     first_line = lines[0 if len(args) == 0 else 1]
-    if len(first_line.strip()) == 0:
+    if len(args) > 0 and len(lines[0]) != 0:
         raise ValueError(
-            "{} the documentation should be on the first line.".format(member),
+            "{} the documentation should start on the first line.".format(member),
             member.__module__)
     if first_line.strip()[-1] != '.':
         raise ValueError("{} first line should end with a '.'".format(member),