[MRG+1] NMF speed-up for beta_loss = 0#9277
Merged
jnothman merged 6 commits intoscikit-learn:masterfrom Jul 5, 2017
Merged
Conversation
Member
|
how does **= -2 compare? it is strange to me that you would need to do two
**= operations to get the speedup.
…On 5 Jul 2017 9:07 am, "hongkahjun" ***@***.***> wrote:
Suggestion for speeding up IS divergence in NMF mu update:
WH_safe_X_data **= -1WH_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_factorizationfrom sklearn.decomposition.nmf import _multiplicative_update_wfrom sklearn.linear_model import LogisticRegressionfrom sklearn.datasets import make_classificationimport timefrom IPython import get_ipythonimport 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)")
------------------------------
You can view, comment on, or merge this pull request online at:
#9277
Commit Summary
- NMF speed-up for beta_loss = 0
- newest update for NMF speed-up for beta_loss = 0
- updated NMF speed-up for beta_loss = 0
- updated NMF speed-up for beta_loss = 0
File Changes
- *M* sklearn/decomposition/nmf.py
<https://github.com/scikit-learn/scikit-learn/pull/9277/files#diff-0>
(11)
Patch Links:
- https://github.com/scikit-learn/scikit-learn/pull/9277.patch
- https://github.com/scikit-learn/scikit-learn/pull/9277.diff
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#9277>, or mute the
thread
<https://github.com/notifications/unsubscribe-auth/AAEz6yAaW5HQ2ohwpEFWVOngTwt7idjPks5sKsWsgaJpZM4ONuom>
.
|
Contributor
Author
|
Hi Sorry if I was not clear but WH_safe_X_data **= -2yields 4217895 WH_safe_X_data **= -2Also, 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. |
Member
|
that seems faster than either option in your original benchmarks, unless
I'm not reading correctly
…On 5 Jul 2017 6:35 pm, "hongkahjun" ***@***.***> wrote:
Hi
Sorry if I was not clear but
WH_safe_X_data **= -2
yields
42178.9 WH_safe_X_data **= -2
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9277 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz60rLm_i4goxIzibbcMwsKEONJ67Cks5sK0rYgaJpZM4ONuom>
.
|
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 |
Member
|
sounds like a numpy issue potentially. what numpy configuration are you
using?
…On 5 Jul 2017 7:05 pm, "hongkahjun" ***@***.***> wrote:
WH_safe_X_data **= -2 yields 4,217,895whileWH_safe_X_data **= -1 yields 219,524 WH_safe_X_data **= 2 yields 33,966
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9277 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz60WvKJl4LYjj6wMULGRUq_VJwvyIks5sK1HHgaJpZM4ONuom>
.
|
Contributor
Author
|
Hi, I am using 1.11.3. |
Member
|
Numpy.show_config()?
And how do those benchmarks look on latest numpy (1.13)?
…On 5 Jul 2017 7:24 pm, "hongkahjun" ***@***.***> wrote:
Hi,
I am using 1.11.3.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9277 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz6x65jlmyBIstFHwAXdziwLuc250rks5sK1Y1gaJpZM4ONuom>
.
|
Member
|
Numpy uses different functions for power internally:
A benchmark on (Click on details to show the script) Detailsimport 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() |
Member
|
Thanks, @TomDLT!
so it sounds we should at least raise an issue at numpy to handle -.5 and
-2.
I'm okay with merging this for now, but I'd appreciate a comment
referencing fast_scalar_power (or the issue one of us is about to create at
numpy).
…On 5 July 2017 at 20:23, Tom Dupré la Tour ***@***.***> wrote:
Numpy uses different functions for power internally
<https://github.com/numpy/numpy/blob/b9e3ac9abb6e435cdf6bbe33e0bc894d6a879a53/numpy/core/src/multiarray/number.c#L464>
:
- 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):
[image: figure_1]
<https://user-images.githubusercontent.com/11065596/27860284-25fff35c-617c-11e7-8607-c07fb1b7aac1.png>
(Click on details to show the script)
import numpy as npfrom time import timeimport 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()
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9277 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEz6840CUZglxqDvaGKWKDCp-973C95ks5sK2QjgaJpZM4ONuom>
.
|
Member
|
@TomDLT will you report at Numpy? |
Contributor
Author
|
All right, I added a comment stating that code is using numpy's reciprocal function for exponent -1 |
jnothman
reviewed
Jul 5, 2017
sklearn/decomposition/nmf.py
Outdated
| 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 |
Member
There was a problem hiding this comment.
If you're effectively using np.reciprocal and np.square, you could just do that here...
Member
|
LGTM |
ogrisel
approved these changes
Jul 5, 2017
Member
ogrisel
left a comment
There was a problem hiding this comment.
+1 for merge once CI is green.
Member
|
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
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Suggestion for speeding up IS divergence in NMF mu update:
is much faster than
Using line_profiler on ipython to time the lines,
test code below: