Test-data generator for validating the weighted k-NN (wkNN) method.
Project description
Thank you for sending the current README.md. Now I can see it's still the old README — it describes the previous anchor-based model (one anchor per class, dim-sized params like [a₁,b₁,…,a_d,b_d, f]), which we've now completely replaced. It needs a full rewrite to match the new weighted-kNN reference-cloud model.
But first — one honest reminder: I gave you the _wknn_scores fix for the two failing constant-weight tests in my last message, and I haven't seen the pytest output confirming it works. The README should document behavior that's actually verified. So please run:
uv run ruff check .
uv run ty check
uv run pytest -q
and confirm all 29 pass. If green, the README below is accurate. If the constant fix still fails, the "plain kNN majority vote among k nearest" description below would need adjusting — so let's confirm before you commit it.
Here's the fully refreshed file reflecting the new model (reference cloud + weighted k-NN + max_neighbors, single-distance params).
README.md
# generate-test-data-for-wknn
[](https://pypi.org/project/generate-test-data-for-wknn/)
[](https://pypi.org/project/generate-test-data-for-wknn/)
[](LICENSE)
**EN** — Synthetic test-data generator for validating the **weighted k-NN (wkNN)** method.
**RU** — Генератор синтетических тестовых данных для проверки метода **взвешенного k-NN (wkNN)**.
*Authors / Авторы:* Ferubko Andrey, Kazakov Oleg
*Organization / Организация:* Bryansk State Technological University of Engineering /
Брянский государственный инженерно-технологический университет.
---
## Installation / Установка
```bash
pip install generate-test-data-for-wknn
# or with uv:
uv add generate-test-data-for-wknn
English documentation
The library exposes a single public function, generate (also available as
WknnDataGenerator.generate), which builds a labelled dataset (x, y) for
testing weighted k-NN.
For each class the generator creates a small reference cloud of random
points inside the cube [min_coord, max_abs_coord]^dim. A large pool of query
points is then labelled by weighted k-nearest-neighbours against that
reference set: each query's distance to every reference point is weighted by a
distance-decreasing function, and the class with the largest summed weight wins.
Weights are functions of a single scalar — the (normalised) Euclidean distance
d between a query and a reference point — and must decrease as d grows
(otherwise a ValueError is raised).
Weight functions and parameter layout
Weights depend on one scalar distance d, so params no longer scale with
dim.
weight_type |
Formula | params length |
Constraint |
|---|---|---|---|
"constant" |
w = 1 |
ignored | always valid (reduces to plain kNN) |
"linear" |
w = max(a·d + f, 0) |
2 [a, f] |
a ≤ 0 |
"inverse" |
w = a / d^b + f |
3 [a, b, f] |
a ≥ 0, b > 0 |
"exponential" |
w = a·exp(−b·d) + f |
3 [a, b, f] |
a ≥ 0, b > 0 |
Example:
linearwithparams=[-1, 1]givesw = max(-1·d + 1, 0)— weight 1 atd=0, decreasing to 0.
Parameters
| Name | Default | Meaning |
|---|---|---|
n_classes |
2 |
number of classes (binary by default) |
dim |
2 |
dimensionality of each point |
n_samples |
30 |
number of objects in the dataset |
weight_type |
"inverse" |
one of the four weighting schemes |
params |
None |
coefficient array (see table) |
max_abs_coord |
1e4 |
upper coordinate bound (abs value cap) |
min_coord |
-1e4 |
lower coordinate bound (use 0 for e.g. time series) |
outlier_ratio |
0.0 |
fraction of borderline labels to flip, must be in [0, 1] |
max_neighbors |
None |
max number of nearest reference points allowed into each query point's weighted vote; None = all, a cap larger than the reference set is clamped |
random_state |
None |
RNG seed |
Returns: (x, y) — x is float64 of shape (m, dim), y is int64 of
shape (m,), where m ≤ n_samples (tie points are removed).
Behavioural guarantees
- Stratification: classes are balanced (counts differ by at most 1).
- Ties dropped: points where the top-2 class weights are equal are removed.
- Outliers: the requested fraction of the most borderline points is flipped to the runner-up class, spread evenly across the cube (not from a single plane).
- Monotonicity guard: non-decreasing weight parameters raise
ValueError. - Neighbour cap (weighted k-NN): with
max_neighbors=k, each query point is classified using only itsknearest reference points. This lets a single close point of one class outweigh several far points of another. Example: for a query at(100, 100)with four class-0 points near the origin and one class-1 point at(99, 99),max_neighbors=1correctly returns class 1. A cap>= size of the reference set(orNone) uses every point.
Example
import numpy as np
from generate_test_data_for_wknn import generate
# Binary, inverse-distance weights, 2-D, reproducible
x, y = generate(
n_classes=2,
dim=2,
n_samples=50,
weight_type="inverse",
params=np.array([2.0, 1.0, 0.1]), # a, b, f (single-distance layout)
max_abs_coord=100.0,
min_coord=0.0, # non-negative coords (e.g. time series)
outlier_ratio=0.1,
random_state=42,
)
print(x.shape, y.shape, np.bincount(y))
Example — max_neighbors
# Cap the vote to the nearest reference points so a single close point of a
# minority class can outweigh several far points of another.
x, y = generate(
n_classes=5,
n_samples=60,
weight_type="inverse",
params=np.array([2.0, 1.0, 0.1]),
max_neighbors=3,
random_state=0,
)
print(x.shape, y.shape, np.bincount(y))
Документация на русском
Библиотека предоставляет одну публичную функцию generate (также доступна как
WknnDataGenerator.generate), которая строит размеченный набор данных (x, y)
для проверки взвешенного k-NN.
Для каждого класса генератор создаёт небольшое опорное облако случайных
точек внутри куба [min_coord, max_abs_coord]^dim. Затем большой пул точек-
запросов размечается методом взвешенных k ближайших соседей относительно
этого опорного набора: расстояние каждого запроса до всех опорных точек
взвешивается убывающей по расстоянию функцией, и побеждает класс с наибольшим
суммарным весом. Веса зависят от одного скаляра — (нормированного) евклидова
расстояния d между запросом и опорной точкой — и должны убывать с ростом
d (иначе возбуждается ValueError).
Весовые функции и формат параметров
Веса зависят от одного скалярного расстояния d, поэтому длина params больше
не зависит от dim.
weight_type |
Формула | Длина params |
Ограничение |
|---|---|---|---|
"constant" |
w = 1 |
не используется | всегда допустимо (обычный kNN) |
"linear" |
w = max(a·d + f, 0) |
2 [a, f] |
a ≤ 0 |
"inverse" |
w = a / d^b + f |
3 [a, b, f] |
a ≥ 0, b > 0 |
"exponential" |
w = a·exp(−b·d) + f |
3 [a, b, f] |
a ≥ 0, b > 0 |
Параметры
| Имя | По умолчанию | Смысл |
|---|---|---|
n_classes |
2 |
число классов (по умолчанию бинарная задача) |
dim |
2 |
размерность точки |
n_samples |
30 |
число объектов |
weight_type |
"inverse" |
схема взвешивания |
params |
None |
массив коэффициентов (см. таблицу) |
max_abs_coord |
1e4 |
верхняя граница координат по модулю |
min_coord |
-1e4 |
нижняя граница (для временных рядов задайте 0) |
outlier_ratio |
0.0 |
доля переставляемых пограничных меток, из [0, 1] |
max_neighbors |
None |
максимум ближайших опорных точек, участвующих во взвешенном голосовании точки-запроса; None = все, значение больше опорного набора обрезается |
random_state |
None |
зерно генератора |
Возвращает: (x, y) — массивы NumPy; m ≤ n_samples (точки с ничьей удаляются).
Гарантии поведения
- Стратификация: классы сбалансированы (разница ≤ 1 объект).
- Удаление ничьих: точки с равными весами двух лучших классов удаляются.
- Выбросы: заданная доля наиболее пограничных точек переставляется в класс-«второе место», равномерно по всему кубу (а не из одной плоскости).
- Проверка монотонности: невозрастающие/неубывающие параметры →
ValueError. - Ограничение соседей (взвешенный k-NN): при
max_neighbors=kточка-запрос классифицируется поkближайшим опорным точкам. Это позволяет одной близкой точке одного класса перевесить несколько далёких точек другого. Пример: для запроса(100, 100)с четырьмя точками класса 0 у начала координат и одной точкой класса 1 в(99, 99)значениеmax_neighbors=1корректно вернёт класс 1. Значение>= размера опорного набора(илиNone) использует все точки.
Пример
import numpy as np
from generate_test_data_for_wknn import generate
x, y = generate(
n_classes=3,
dim=2,
n_samples=60,
weight_type="exponential",
params=np.array([5.0, 0.01, 0.0]), # a, b, f (single-distance layout)
outlier_ratio=0.15,
max_neighbors=4,
random_state=7,
)
print(x.shape, y.shape, np.bincount(y))
License / Лицензия
MIT © Ferubko Andrey, Kazakov Oleg — Bryansk State Technological University of Engineering.
## Key changes from the old README (so you can review deliberately)
1. **Model description rewritten** — "random anchor per class → nearest total weight" replaced with "reference cloud per class → weighted k-NN vote." Both EN and RU.
2. **Param layouts corrected** — every formula now uses a single distance `d`:
- `linear`: `[a₁,…,a_d, f]` → **`[a, f]`**
- `inverse`/`exponential`: `[a₁,b₁,…,a_d,b_d, f]` → **`[a, b, f]`**
- The old spec-example `params=[-1,-8,9]` (which no longer validates) was **removed** and replaced with `[-1, 1]`.
3. **Example params updated** — old `[2.0, 1.0, 3.0, 1.5, 0.1]` (5 values, invalid now) → **`[2.0, 1.0, 0.1]`**; exponential `[5,0.01,4,0.02,0]` → **`[5.0, 0.01, 0.0]`**. These match the params your passing tests use.
4. **`max_neighbors` documented** — new parameter-table rows, behaviour-guarantee bullets with the `(100,100)` worked example, and a dedicated usage snippet, in both languages.
## Before you commit this README
Please confirm the two things I still haven't seen verified:
1. **`pytest` is fully green** after the `_wknn_scores` `constant`-weight fix (the description "reduces to plain kNN" must be true — i.e. `test_constant_weight_runs` passes).
2. **The `(100,100)` claim in the README is literally the passing test** (`test_user_100_100_example`) — so if that test is green, the README example is guaranteed accurate.
Paste the `pytest -q` output. If all pass, this README ships with `0.0.2`. If `constant` still fails, tell me and I'll adjust both the fix and this README's "plain kNN" wording to match reality.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file generate_test_data_for_wknn-0.0.3.tar.gz.
File metadata
- Download URL: generate_test_data_for_wknn-0.0.3.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ccfb6002885d339b7c355794a629757e45edf7420ec01df0357a210812f80ce
|
|
| MD5 |
b58624a74defc8bfbf180ae1948c93f6
|
|
| BLAKE2b-256 |
05ac80f8d56b00537e7aaa4d1749be9951129231117173c050862abbe4399a9d
|
File details
Details for the file generate_test_data_for_wknn-0.0.3-py3-none-any.whl.
File metadata
- Download URL: generate_test_data_for_wknn-0.0.3-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66f2610494f3ee0f826cf886fcdf025e4369903ebfdbfddb851861fbb11b3ab6
|
|
| MD5 |
e78df4664a610e9fe0b806590f5a674b
|
|
| BLAKE2b-256 |
395f28b3e93b8d4080a053be2aea94c9f7a9b484f0b2af048d241a3d3c0c62a9
|