Skip to content

Commit

Permalink
remove numexpr as a hard dependency (#54)
Browse files Browse the repository at this point in the history
* fix numexpr in densities

* fix doc

* rm else

* fix abs

* fix underflow error

* fix flake8

* fix flake8
  • Loading branch information
pierreablin authored Nov 15, 2024
1 parent a004233 commit 6058e5e
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 118 deletions.
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pip

Otherwise, to install ``picard``, you first need to install its dependencies::

$ pip install numpy matplotlib numexpr scipy
$ pip install numpy matplotlib scipy

Then install Picard with pip::

Expand Down Expand Up @@ -137,9 +137,11 @@ These are the dependencies to use Picard:

* numpy (>=1.8)
* matplotlib (>=1.3)
* numexpr (>= 2.0)
* scipy (>=0.19)

Optionally to get faster computations, you can install

* numexpr (>= 2.0)

These are the dependencies to run the EEG example:

Expand Down
32 changes: 26 additions & 6 deletions picard/densities.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
# License: BSD (3-clause)

import numpy as np
import numexpr as ne

try:
import numexpr as ne
except ImportError:
ne = None
from scipy.optimize import check_grad
from numpy.testing import assert_allclose

Expand Down Expand Up @@ -40,11 +42,18 @@ def __init__(self, params=None):

def log_lik(self, Y):
alpha = self.alpha # noqa
if ne is None:
absY = np.abs(Y)
np.exp(-2. * alpha * absY)
return absY + np.log1p(np.exp(-2. * alpha * absY)) / alpha
return ne.evaluate('abs(Y) + log1p(exp(-2. * alpha * abs(Y))) / alpha')

def score_and_der(self, Y):
alpha = self.alpha
score = ne.evaluate('tanh(alpha * Y)')
if ne is None:
score = np.tanh(alpha * Y)
else:
score = ne.evaluate('tanh(alpha * Y)')
return score, alpha - alpha * score ** 2


Expand All @@ -57,18 +66,29 @@ def __init__(self, params=None):

def log_lik(self, Y):
a = self.alpha # noqa
if ne is None:
return -np.exp(- a * Y ** 2 / 2.) / a
return ne.evaluate('-exp(- a * Y ** 2 / 2.) / a')

def score_and_der(self, Y):
a = self.alpha # noqa
Y_sq = ne.evaluate('Y ** 2') # noqa
K = ne.evaluate('exp(- a / 2. * Y_sq)') # noqa
return ne.evaluate('Y * K'), ne.evaluate('(1- a * Y_sq) * K')
if ne is None:
Y_sq = Y ** 2
K = np.exp(- a / 2. * Y_sq)
return Y * K, (1 - a * Y_sq) * K
else:
Y_sq = ne.evaluate('Y ** 2') # noqa
K = ne.evaluate('exp(- a / 2. * Y_sq)') # noqa
return ne.evaluate('Y * K'), ne.evaluate('(1- a * Y_sq) * K')


class Cube(object):
def log_lik(self, Y):
if ne is None:
return Y ** 4 / 4
return ne.evaluate('Y ** 4 / 4')

def score_and_der(self, Y):
if ne is None:
return Y ** 3, 3 * Y ** 2
return ne.evaluate('Y ** 3'), ne.evaluate('3 * Y ** 2')
2 changes: 1 addition & 1 deletion picard/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def picard(X, fun='tanh', n_components=None, ortho=True, extended=None,
'verbose': verbose, 'ortho': ortho, 'extended': extended,
'covariance': covariance}

with np.errstate(all='raise'): # So code breaks if overflow/Nans
with np.errstate(over='raise', invalid='raise'):
Y, W, infos = core_picard(X1, **kwargs)

del X1
Expand Down
Loading

0 comments on commit 6058e5e

Please sign in to comment.