Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[MRG+1] NMF speed-up for beta_loss = 0 #9277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 5, 2017
Merged

Conversation

hongkahjun
Copy link
Contributor

@hongkahjun hongkahjun commented Jul 4, 2017

Suggestion for speeding up IS divergence in NMF mu update:

WH_safe_X_data **= -1
WH_safe_X_data **= 2

is much faster than

 WH_safe_X_data **= beta_loss - 2

Using line_profiler on ipython to time the lines,

seconds
4363077           WH_safe_X_data **= beta_loss - 2

vs

219524            WH_safe_X_data **= -1
33966             WH_safe_X_data **= 2

test code below:

from sklearn.decomposition.nmf import non_negative_factorization
from sklearn.decomposition.nmf import _multiplicative_update_w
from sklearn.datasets import make_classification
import time
from IPython import get_ipython
import numpy as np

ipython = get_ipython()
np.random.seed(10)
t0 = time.time()
all_samples, all_targets = make_classification(n_samples=1000, n_features=513, n_informative=511,
                                               n_redundant=2, n_repeated=0, n_classes=2,
                                               n_clusters_per_class=1, random_state=0)
all_samples += 5000
ipython.magic(
    "lprun -f _multiplicative_update_w non_negative_factorization(all_samples, n_components=16, solver='mu', beta_loss='itakura-saito', max_iter=100)")

@jnothman
Copy link
Member

jnothman commented Jul 4, 2017 via email

@hongkahjun
Copy link
Contributor Author

hongkahjun commented Jul 5, 2017

Hi

Sorry if I was not clear but

WH_safe_X_data **= -2

yields

4217895     WH_safe_X_data **= -2

Also, not sure why it is much faster, but seems like it has something to do with how numpy calculates powers that are not positive integers.

@jnothman
Copy link
Member

jnothman commented Jul 5, 2017 via email

@hongkahjun
Copy link
Contributor Author

WH_safe_X_data **= -2 yields 4,217,895
while
WH_safe_X_data **= -1 yields 219,524            
WH_safe_X_data **= 2 yields 33,966             

@jnothman
Copy link
Member

jnothman commented Jul 5, 2017 via email

@hongkahjun
Copy link
Contributor Author

Hi,

I am using 1.11.3.

@jnothman
Copy link
Member

jnothman commented Jul 5, 2017 via email

@TomDLT
Copy link
Member

TomDLT commented Jul 5, 2017

Numpy uses different functions for power internally:

  • When the exponent is in {-1, 0, 0.5, 1, 2}, it uses respectively {reciprocal, one_like, sqrt, ~identity, square}.
  • For any other exponent, it uses a much slower routine. This is why a **= 2; a **= -1 is much faster than a **= -2.

A benchmark on a **= b; a **= -1 versus a **= -b gives me (v1.11.3):
figure_1

(Click on details to show the script)

import numpy as np
from time import time
import matplotlib.pyplot as plt

n_points = int(1e6)
power_range = np.arange(0, 4.1, 0.1)
durations = np.zeros((2, power_range.size))

array = np.random.randn(n_points)
np.abs(array, array)

for i, power in enumerate(power_range):
    array_copy = array.copy()
    start = time()
    array_copy **= -power
    durations[0, i] = time() - start

    array_copy = array.copy()
    start = time()
    array_copy **= power
    array_copy **= -1
    durations[1, i] = time() - start


plt.figure(figsize=(10, 4))
ax = plt.gca()
ax.plot(power_range, durations[0], '-o', label='one operation')
ax.plot(power_range, durations[1], '-o', label='two operations')
ax.set(xlabel='power', ylabel='time', title='Elementwise power in Numpy')
ax.legend()
plt.show()

@jnothman
Copy link
Member

jnothman commented Jul 5, 2017 via email

@jnothman
Copy link
Member

jnothman commented Jul 5, 2017

@TomDLT will you report at Numpy?

@hongkahjun
Copy link
Contributor Author

All right, I added a comment stating that code is using numpy's reciprocal function for exponent -1

@@ -545,6 +545,12 @@ def _multiplicative_update_w(X, W, H, beta_loss, l1_reg_W, l2_reg_W, gamma,

if beta_loss == 1:
np.divide(X_data, WH_safe_X_data, out=WH_safe_X_data)
elif beta_loss == 0:
# using numpy's reciprocal function for exponent -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're effectively using np.reciprocal and np.square, you could just do that here...

@jnothman jnothman changed the title [MRG] NMF speed-up for beta_loss = 0 [MRG+1] NMF speed-up for beta_loss = 0 Jul 5, 2017
@jnothman
Copy link
Member

jnothman commented Jul 5, 2017

LGTM

Copy link
Member

@ogrisel ogrisel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for merge once CI is green.

@jnothman jnothman merged commit a8306d4 into scikit-learn:master Jul 5, 2017
@jnothman
Copy link
Member

jnothman commented Jul 5, 2017

Thanks @hongkahjun

massich pushed a commit to massich/scikit-learn that referenced this pull request Jul 13, 2017
dmohns pushed a commit to dmohns/scikit-learn that referenced this pull request Aug 7, 2017
dmohns pushed a commit to dmohns/scikit-learn that referenced this pull request Aug 7, 2017
NelleV pushed a commit to NelleV/scikit-learn that referenced this pull request Aug 11, 2017
paulha pushed a commit to paulha/scikit-learn that referenced this pull request Aug 19, 2017
AishwaryaRK pushed a commit to AishwaryaRK/scikit-learn that referenced this pull request Aug 29, 2017
maskani-moh pushed a commit to maskani-moh/scikit-learn that referenced this pull request Nov 15, 2017
jwjohnson314 pushed a commit to jwjohnson314/scikit-learn that referenced this pull request Dec 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants