← All Posts
Deep Learning · Data Imbalance in Deep Learning · Class Imbalance and Resampling

ADASYN

ADASYN allocates more synthetic rows to minority examples surrounded by the other class. It then generates those rows by interpolating toward minority neighbors, using the movement introduced in SMOTE.

The new idea is the allocation rule: where should the extra training rows come from? We will follow four minority examples through neighbor counting, budget allocation and generation. This chapter describes imbalanced-learn’s ADASYN implementation; code and rounding details are optional.

First count neighbors from both classes

Imagine 14 training rows with two numeric features: ten majority rows labeled 0, and four minority rows labeled 1. Name the minority examples A, B, C and D. For each one, find the two closest other training rows using Euclidean distance. The seed itself is excluded.

A, B and C form a small groupMinority points A at 0,0; B at 1,0; C at 0,1. Majority m1 at 1.4,0 and m2 at 0,1.4 lie close to B and C.
D has majority neighbors nearbyMinority point D at 10,0 lies between majority points m3 at 9.5,0 and m4 at 10.5,0.
Blue circles are minority rows; orange crosses are majority rows. The panels show separate regions with the same scale. Six farther majority rows are omitted here and included in the Python dataset below; none enters these two-neighbor lists.
SeedTwo nearest other rowsMajority fraction
AB, C0 / 2 = 0
Bm1, A1 / 2 = 0.5
Cm2, A1 / 2 = 0.5
Dm3, m42 / 2 = 1

Call the majority count for seed $i$ $d_i$, and the number of neighbors $k$. Its local majority fraction, $r_i$, is simply

$$r_i=\frac{d_i}{k}.$$

D gets the largest score because all its nearby rows have the other label. A gets zero because its nearest neighbors share its label. This is a neighborhood heuristic for difficulty: it does not measure a trained classifier’s loss, and a score of 1 does not prove that D’s label is wrong.

Turn those fractions into shares of a budget

Suppose we request six additional minority rows, intending to raise their count from four to ten. The local fractions add up to 2. Dividing each by 2 gives budget shares of 0%, 25%, 25% and 50% for A, B, C and D.

Write $G$ for the requested number of additional rows. For each seed, $w_i$ is its budget share and $u_i$ is its quota before rounding. The sum below runs over all minority seeds:

$$w_i=\frac{r_i}{\sum_j r_j},\qquad u_i=G w_i.$$

At G = 6, the quotas are 0, 1.5, 1.5 and 3. D receives twice B’s quota. A produces no synthetic rows as a seed, but the original A row remains and can still serve as another seed’s interpolation neighbor.

Allocate the same budget across four seeds
SeedShareQuotaWhole rows
A0%0.000
B25%1.502
C25%1.502
D50%3.003
Request: 6 additional rows, for a final minority count of 10. Rounding produces 7 additional rows, for an actual minority count of 11.
The neighborhood shares stay fixed. Move the budget to see that rounding each seed’s quota separately need not preserve the requested total. At G = 1, every quota rounds to zero and the library raises an error.
Why can a requested count of 10 produce 11?

The implementation applies numpy.rint to each quota independently. It rounds to the nearest integer, choosing the even integer at an exact halfway point: 0.5 becomes 0; 1.5 becomes 2. Thus our quotas become [0, 2, 2, 3], totaling seven new rows. No later adjustment forces the total back to six.

This is an implementation detail, not a new learning principle. Check actual output counts when comparing runs. A dictionary such as sampling_strategy={1: 10} requests a final count of ten for class 1; the ADASYN allocation may return a nearby count.

A different neighbor search chooses the generation direction

Once the quotas are allocated, the implementation fits its neighbor search on the minority rows only. For each seed’s assigned rows, it randomly selects one of that seed’s k minority neighbors and moves a shared random fraction along the segment. The synthetic label is 1.

01All training classes → allocationHow many of the seed’s nearby rows have the other label? Use that fraction to allocate the generation budget.
02Minority class only → generationWhich same-class row should be the other parent? Choose a neighbor and use the SMOTE interpolation step.
Two searches answer different questions. A nearby majority row influences the quota but does not become an interpolation parent. The original observations are retained.

For D, the first search finds majority rows m3 and m4, each only 0.5 away. The second search finds minority rows B and A, at distances 9 and 10. Its synthetic rows can therefore stretch across long segments. “Many opposite-class neighbors” does not imply “good nearby minority parents.”

This is the assumption to inspect: extra rows may emphasize a useful class boundary, but they may also amplify an isolated or mislabeled example. Neither the neighbor count nor the assigned label establishes the true class of every interpolated point. The SMOTE validity discussion covers feature constraints and categorical alternatives.

Recognize when the allocation is undefined or unhelpful

For multiclass data, the library scores each selected class against all other labels, then generates within that class. This extends the same two-search idea; “other labels” replaces “majority” in the count.

ADASYN supplies a candidate training distribution, not evidence of improved performance. Compare it with no resampling, class weights and basic SMOTE under the same evaluation protocol. Choose from validation results and operational needs, rather than from how balanced the resulting row counts look.

References and further reading