Multi-Knee Detection¶
By default, KneeLocator returns the first knee point found (offline mode). To detect all knee points in a curve, use online mode.
Online vs. Offline Mode¶
Offline Mode (default)¶
With online=False (the default), KneeLocator stops at the first knee detected:
import numpy as np
from kneed import KneeLocator
np.random.seed(23)
x = range(1, 1001)
y = sorted(np.random.gamma(0.5, 1.0, 1000), reverse=True)
kl = KneeLocator(x, y, curve="convex", direction="decreasing", online=False)
print(kl.knee) # Returns the first knee found
Online Mode¶
With online=True, the algorithm scans the entire curve, collecting all knee points and "correcting" previous detections as it goes. The final kl.knee value is the last (most significant) knee found:
kl = KneeLocator(x, y, curve="convex", direction="decreasing", online=True)
print(kl.knee) # Returns the last (corrected) knee found
Accessing All Knees¶
When using online mode, all detected knee points are available via the all_knees attributes:
kl = KneeLocator(x, y, curve="convex", direction="decreasing", online=True)
# x values of all detected knees
print(kl.all_knees) # set of x values
print(kl.all_knees_y) # list of corresponding y values
# Normalized values
print(kl.all_norm_knees) # set of normalized x values
print(kl.all_norm_knees_y) # list of normalized y values
Note
The all_knees attribute is a set, so knee values are unique but unordered. The all_knees_y attribute is a list that preserves the order of detection.
Elbow Aliases¶
If you prefer "elbow" terminology, equivalent properties are available:
kl.all_elbows # same as kl.all_knees
kl.all_elbows_y # same as kl.all_knees_y
kl.all_norm_elbows # same as kl.all_norm_knees
kl.all_norm_elbows_y # same as kl.all_norm_knees_y
Example: Bumpy Curve¶
Curves with multiple local maxima in the difference curve produce multiple knee points:
from kneed import DataGenerator, KneeLocator
x, y = DataGenerator.bumpy()
kl = KneeLocator(x, y, curve="concave", direction="increasing", online=True)
print(f"Primary knee: {kl.knee}")
print(f"All knees: {sorted(kl.all_knees)}")
print(f"Number of knees found: {len(kl.all_knees)}")
When to Use Online Mode¶
| Scenario | Mode |
|---|---|
| Need just the first/most obvious knee | Offline (online=False) |
| Want to find the most significant knee | Online (online=True) |
| Need all knee points in a bumpy curve | Online (online=True), read all_knees |
| Performance-sensitive applications | Offline (stops early) |