-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from gmrukwa/develop
Release v2.5.5 introduces: - pipeline saving - fixes for SpectralClustering - EXIMS feature selector
- Loading branch information
Showing
17 changed files
with
439 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
__version__ = '2.5.4' | ||
__version__ = '2.5.5' | ||
|
||
from ._summary import plot, reject_split | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from ._sklearn import EximsSelector |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
from functools import partial | ||
from multiprocessing import Pool | ||
from typing import Callable, Tuple | ||
|
||
import numpy as np | ||
from tqdm import tqdm | ||
|
||
from divik.feature_selection._exims._structness import structness | ||
|
||
|
||
class pipe: | ||
def __init__(self, *functions): | ||
self.functions = functions | ||
|
||
def __call__(self, *args, **kwargs): | ||
result = self.functions[0](*args, **kwargs) | ||
for func in self.functions[1:]: | ||
result = func(result) | ||
return result | ||
|
||
|
||
def progress_bar(description: str=None): | ||
return partial(tqdm, desc=description) | ||
|
||
|
||
def pmap(func, collection, **kwargs): | ||
with Pool() as pool: | ||
return pool.map(func, collection, **kwargs) | ||
|
||
|
||
def apply(func, collection): | ||
return [func(element) for element in collection] | ||
|
||
|
||
def for_each(func, lazy: bool=True, parallel: bool=False, **kwargs): | ||
if parallel: | ||
return partial(pmap, func, **kwargs) | ||
if lazy: | ||
return partial(map, func) | ||
else: | ||
return partial(apply, func) | ||
|
||
|
||
def as_image(data: np.ndarray, x: np.ndarray, y: np.ndarray, default=-1) -> \ | ||
np.ndarray: | ||
x, y = x.astype(int), y.astype(int) | ||
translated_x, translated_y = x - np.min(x), y - np.min(y) | ||
rows, columns = int(np.max(translated_y) + 1), int(np.max(translated_x) + 1) | ||
if len(data.shape) < 2: | ||
data = data.reshape((data.shape[0], 1)) | ||
cube = default * np.ones((rows, columns, data.shape[1])) | ||
cube[translated_y, translated_x] = data | ||
return cube | ||
|
||
|
||
_IGNORED = -1 | ||
_Feature = np.ndarray | ||
_Structness = float | ||
_FeatureProcessor = Callable[[_Feature], Tuple[_Structness, _Structness]] | ||
_remove_channel_dimension = partial(np.squeeze, axis=2) | ||
|
||
|
||
def _feature_processor(x: np.ndarray, y: np.ndarray) -> _FeatureProcessor: | ||
# noinspection PyTypeChecker | ||
return pipe( | ||
partial(as_image, x=x, y=y, default=_IGNORED), | ||
_remove_channel_dimension, | ||
partial(structness, ignored=[_IGNORED]) | ||
) | ||
|
||
|
||
def _normalize_columns(matrix) -> np.ndarray: | ||
matrix = np.array(matrix, dtype=float) | ||
matrix += np.finfo(float).eps | ||
assert len(matrix.shape) == 2 | ||
return matrix / np.max(matrix, axis=0) | ||
|
||
|
||
_as_features = np.transpose | ||
_normalize_structness_by_kind = _normalize_columns | ||
_sumarize_structness_by_feature = pipe(partial(np.sum, axis=1), np.ravel) | ||
FeaturesStructness = np.ndarray | ||
_StructnessEstimator = Callable[[np.ndarray], FeaturesStructness] | ||
|
||
|
||
def _estimator(structness_: _FeatureProcessor) -> _StructnessEstimator: | ||
# noinspection PyTypeChecker | ||
return pipe( | ||
_as_features, | ||
progress_bar('feature structness'), | ||
for_each(structness_, parallel=True), | ||
_normalize_structness_by_kind, | ||
_sumarize_structness_by_feature | ||
) | ||
|
||
|
||
def exims(data: np.ndarray, x: np.ndarray, y: np.ndarray) -> FeaturesStructness: | ||
structness_estimator = _estimator(_feature_processor(x, y)) | ||
return structness_estimator(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import numpy as np | ||
|
||
|
||
def quantile(values, quantiles): | ||
"""Compute MATLAB-alike quantiles | ||
Arguments: | ||
values - (np.ndarray) Input array or object that can be converted to an | ||
array. | ||
quantiles - (float, np.ndarray) float in range of [0,1] (or sequence | ||
of floats). Quantile to compute, which must be between 0 and 1 | ||
inclusive. | ||
location of first element as a quantile -> 0.5 / n | ||
location of last element as a quantile -> (n - 0.5) / n | ||
^ | ||
| (n-0.5) / n 1.0 | ||
1.0 ----------------|---| | ||
| / | ||
| / | ||
| / | ||
| / <- this is how quantiles look in MATLAB | ||
| / | ||
| / | ||
| / | ||
| / | ||
0.0 ----|---|-------------> | ||
| 0.0 0.5 / n | ||
y = ax + b | ||
0 = a * 0.5 / n + b <- 0th element is treated as 0.5 / n quantile | ||
1 = a * (n - 0.5) / n + b <- last element is treated as (n - 0.5) / n quantile | ||
a = n / (n - 1) | ||
b = - 0.5 / (n - 1) | ||
""" | ||
values = np.array(values) | ||
n = float(values.size) | ||
a = n / (n - 1) | ||
b = - 0.5 / (n - 1) | ||
quantiles = np.array(quantiles) | ||
matlab_alike_quantiles = np.clip(a * quantiles + b, a_min=0.0, a_max=1.0) | ||
return np.percentile(values, q=100. * matlab_alike_quantiles) | ||
|
||
|
||
def n_quantiles(values, N, unbiased=True, backend=quantile): | ||
return backend(values, np.arange(1, N+1, dtype=float) / (N + int(unbiased))) | ||
|
||
|
||
def iqr(values, rng=(25, 75)): | ||
q1, q3 = quantile(values, .01 * np.array(rng)) | ||
return q3 - q1 |
Oops, something went wrong.