Skip to content

Commit 7eceaa4

Browse files
authored
[MRG] Fix numpy versions problems (#411)
* add new empty line at the end of python file in tslearn/clustering/__init.py * Empty commit * Upgrade numpy * Upgrade numpy with --ignore-installed * Upgrade numpy with --ignore-installed before scikit-learn install * Specify numpy version 1.22 for Numba compatibility * Correct numpy version 1.22 instead of 0.22 * Use numpy version 1.21.6 for Python 3.7 compatibility * Try to unspecify scikit-learn version * Empty commit * Remove commented lines * Try to install numpy before requirements * Specify scikit-learn==1.0 * Add --upgrade option for requirements. * Add eager option for requirements install. * Install numpy==1.22 for Python 3.8 adn 3.9 only (for linux). * Remove tests on Python 3.7 for now (on linux) * Fix error in writing numpy==1.22 * Install scikit-learn==1.0 before reading the requirements * Back to the main branch of tslearn * Add numpy.import_array() after cimport numpy * Replace cython files (.pyx) by usual python files (.py) * Remove cython from requirements and setup file * Use numba in python files which where previously written in cython * Change prange into range for loop with reversed index * Remove reversed order in loop for numba nopython compatibility * Correct dtype error * Remove useless variables and vectorize some for loops * Define forgotten variable * Specify float dtype of a matrix * Add docstrings * Temporarily comment jit decorator to focus on other sources of code errors. * Correct indice error in for loop. * Add necessary for loop. * Add jit decorators. * Try to change np.float64 to float in type checks for Python 3.7 compatibility. * Comment assert dtype == np.float64 to solve Python 3.7 error * Update macOS-10.15 to macOS-12 in azure-pipelines.yml * Add input variable types in jit decorator * Add type signature in git decorators of cycc.py * Add type signature in jit decorator of functions of cysax.py * Correct input type in jit decorator * Correct input type in jit decorator of cydist_sax function * Try intp input type in jit decorator of function cydist_sax * Try to use typeof for type inference in jit decorator of function cydist_sax * Try to use typeof array for type inference in jit decorator of function cydist_sax * Use typeof array for type inference in jit decorator of function cydist_1d_sax * Use typeof array for type inference in jit decorator of function inv_transform_sax * Solve np.linalg.norm problem in cycc.py for use of nopython mode in jit decorated functions * Use nopython mode in jit decorated functions of cysax.py and soft_dtw_fast.py * Add parallel option in jit decorators in files cycc.py and cysax.py * Add parallel option in jit decorator of function _jacobian_product_sq_euc * Delete useless white space to restart the continuous integration tests * Add fastmath option in jit decorators * Simplify arrays in Numba typeof for type induction in jit decorators * Add parallel option in jit decorators of functions _soft_dtw and _soft_dtw_grad (also removed prange from these functions) * Use range in decreasing order in function _soft_dtw_grad * Modify loop structure in funtion cdist_normalized_cc to use Numba prange * Correct docstring error in normalized_cc function * Add void as output type in jit decorator of functions _soft_dtw, _soft_dtw_grad and _jacobian_product_sq_euc * Remove comments in file cycc.py * Remove comments in file cysax.py * Remove comments in file soft_dtw_fast.py * Remove unused imports * Remove signatures (input and output types) in jit decorators * Empty commit * Vectorize a for loop in function inv_transform_sax * Restore previous code formulation in function gamma_soft_dtw
1 parent 37660ee commit 7eceaa4

13 files changed

+543
-437
lines changed

azure-pipelines.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ jobs:
2626
inputs:
2727
versionSpec: '$(python.version)'
2828
displayName: 'Use Python $(python.version)'
29-
29+
3030
- script: |
3131
set -xe
3232
python --version
3333
python -m pip install --upgrade pip
3434
python -m pip install -r requirements.txt
3535
displayName: 'Install dependencies'
36-
36+
3737
- script: |
3838
set -xe
3939
python -m pip install -e .
4040
displayName: 'Install tslearn'
41-
41+
4242
- script: |
4343
set -xe
4444
python -m pip install pytest pytest-azurepipelines
4545
python -m pip install scikit-learn==1.0
46-
python -m pytest -v tslearn/ --doctest-modules;
46+
python -m pytest -v tslearn/ --doctest-modules
4747
displayName: 'Test'
4848
4949

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[build-system]
2-
requires = ["setuptools", "wheel", "numpy", "Cython"]
2+
requires = ["setuptools", "wheel", "numpy"]

requirements.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
Cython
21
numpy
32
numba
43
scipy

requirements_build.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
Cython
21
numpy
32
numba
43
scipy

requirements_nocast.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
Cython
21
numpy
32
numba
43
scipy

setup.py

-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from codecs import open
33
import numpy
44
import os
5-
from Cython.Build import cythonize
65

76
# thanks Pipy for handling markdown now
87
ROOT = os.path.abspath(os.path.dirname(__file__))
@@ -33,8 +32,6 @@
3332
"License :: BSD-2-Clause"
3433
],
3534
include_dirs=[numpy.get_include()],
36-
ext_modules=cythonize("tslearn/metrics/*.pyx",
37-
include_path=[numpy.get_include()]),
3835
packages=find_packages(),
3936
package_data={"tslearn": [".cached_datasets/Trace.npz"]},
4037
install_requires=['numpy', 'scipy', 'scikit-learn', 'Cython', 'numba',

tslearn/metrics/cycc.py

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
STUFF_cycc = "cycc"
2+
3+
import numpy as np
4+
from numba import njit, objmode, prange
5+
6+
__author__ = "Romain Tavenard romain.tavenard[at]univ-rennes2.fr"
7+
8+
9+
@njit(parallel=True, fastmath=True)
10+
def normalized_cc(s1, s2, norm1=-1.0, norm2=-1.0):
11+
"""Normalize cc.
12+
13+
Parameters
14+
----------
15+
s1 : array-like, shape=[sz, d], dtype=float64
16+
s2 : array-like, shape=[sz, d], dtype=float64
17+
norm1 : float64, default=-1.0
18+
norm2 : float64, default=-1.0
19+
20+
Returns
21+
-------
22+
norm_cc : array-like, shape=[2 * sz - 1], dtype=float64
23+
"""
24+
assert s1.shape[1] == s2.shape[1]
25+
sz = s1.shape[0]
26+
n_bits = 1 + int(np.log2(2 * sz - 1))
27+
fft_sz = 2**n_bits
28+
29+
if norm1 < 0.0:
30+
norm1 = np.linalg.norm(s1)
31+
if norm2 < 0.0:
32+
norm2 = np.linalg.norm(s2)
33+
34+
denom = norm1 * norm2
35+
if denom < 1e-9: # To avoid NaNs
36+
denom = np.inf
37+
38+
with objmode(cc="float64[:, :]"):
39+
cc = np.real(
40+
np.fft.ifft(
41+
np.fft.fft(s1, fft_sz, axis=0)
42+
* np.conj(np.fft.fft(s2, fft_sz, axis=0)),
43+
axis=0,
44+
)
45+
)
46+
cc = np.vstack((cc[-(sz - 1) :], cc[:sz]))
47+
norm_cc = np.real(cc).sum(axis=-1) / denom
48+
return norm_cc
49+
50+
51+
@njit(parallel=True, fastmath=True)
52+
def cdist_normalized_cc(dataset1, dataset2, norms1, norms2, self_similarity):
53+
"""Compute the distance matrix between two time series dataset.
54+
55+
Parameters
56+
----------
57+
dataset1 : array-like, shape=[n_ts1, sz, d], dtype=float64
58+
dataset2 : array-like, shape=[n_ts2, sz, d], dtype=float64
59+
norms1 : array-like, shape=[n_ts1], dtype=float64
60+
norms2 : array-like, shape=[n_ts2], dtype=float64
61+
self_similarity : bool
62+
63+
Returns
64+
-------
65+
dists : array-like, shape=[n_ts1, n_ts2], dtype=float64
66+
"""
67+
n_ts1, sz, d = dataset1.shape
68+
n_ts2 = dataset2.shape[0]
69+
assert d == dataset2.shape[2]
70+
dists = np.zeros((n_ts1, n_ts2))
71+
72+
if (norms1 < 0.0).any():
73+
for i_ts1 in prange(n_ts1):
74+
norms1[i_ts1] = np.linalg.norm(dataset1[i_ts1, ...])
75+
if (norms2 < 0.0).any():
76+
for i_ts2 in prange(n_ts2):
77+
norms2[i_ts2] = np.linalg.norm(dataset2[i_ts2, ...])
78+
if self_similarity:
79+
for i in prange(1, n_ts1):
80+
for j in range(i):
81+
dists[i, j] = normalized_cc(
82+
dataset1[i], dataset2[j], norm1=norms1[i], norm2=norms2[j]
83+
).max()
84+
dists += dists.T
85+
else:
86+
for i in prange(n_ts1):
87+
for j in range(n_ts2):
88+
dists[i, j] = normalized_cc(
89+
dataset1[i], dataset2[j], norm1=norms1[i], norm2=norms2[j]
90+
).max()
91+
return dists
92+
93+
94+
@njit(parallel=True, fastmath=True)
95+
def y_shifted_sbd_vec(ref_ts, dataset, norm_ref, norms_dataset):
96+
"""Shift a time series dataset w.r.t. a time series of reference.
97+
98+
Parameters
99+
----------
100+
ref_ts : array-like, shape=[sz, d], dtype=float64
101+
Time series of reference.
102+
dataset : array-like, shape=[n_ts, sz, d], dtype=float64
103+
Time series dataset.
104+
norm_ref : float64
105+
norms_dataset : array-like, shape=[n_ts], dtype=float64
106+
Norms of the time series dataset.
107+
108+
Returns
109+
-------
110+
dataset_shifted : array-like, shape=[n_ts, sz, d], dtype=float64
111+
"""
112+
n_ts = dataset.shape[0]
113+
sz = dataset.shape[1]
114+
d = dataset.shape[2]
115+
assert sz == ref_ts.shape[0] and d == ref_ts.shape[1]
116+
dataset_shifted = np.zeros((n_ts, sz, d))
117+
118+
if norm_ref < 0:
119+
norm_ref = np.linalg.norm(ref_ts)
120+
if (norms_dataset < 0.0).any():
121+
for i_ts in prange(n_ts):
122+
norms_dataset[i_ts] = np.linalg.norm(dataset[i_ts, ...])
123+
124+
for i in prange(n_ts):
125+
cc = normalized_cc(ref_ts, dataset[i], norm1=norm_ref, norm2=norms_dataset[i])
126+
idx = np.argmax(cc)
127+
shift = idx - sz
128+
if shift > 0:
129+
dataset_shifted[i, shift:] = dataset[i, :-shift, :]
130+
elif shift < 0:
131+
dataset_shifted[i, :shift] = dataset[i, -shift:, :]
132+
else:
133+
dataset_shifted[i] = dataset[i]
134+
135+
return dataset_shifted

tslearn/metrics/cycc.pyx

-96
This file was deleted.

0 commit comments

Comments
 (0)