This repository contains a revised implementation of Line Space Clustering (LSC) and a separate benchmark script for testing it on synthetic and real datasets.
Please view the original paper for an introduction. The implementation clusters rows of a data matrix by treating each row as an ordered 1D profile over feature index and than using that in a combined distance function.
lsc.py— the main LSC implementation containing theLSC(...)functiontest_lsc_benchmark.py— standalone benchmark script for evaluating LSC against baseline clustering methodsbasic_run.py— just a basic run of the algorithmsynthetic_bench.py— extra test for real world mimicking data (generated by an LLM)
If your main algorithm file is not named lsc.py, either rename it or pass its module name explicitly when running the benchmark.
NOTE: This new version has the same algorithm logic but has been updated to have better performance and to be more robust. Compared with the earlier algorithm, this version makes the clustering procedure more internally consistent:
- it standardizes the input data
- it optionally smooths each row with a Savitzky–Golay filter
- it computes fast DTW distances between rows
- it computes Manhattan (L1) distances between rows
- it normalizes both distance matrices before combining them
- it uses a weighted combined distance
- it performs k-medoids-style clustering
- it uses medoid-based seeding for initialization
- it repairs empty clusters with medoid repair instead of random replacement
Good use cases:
- time series segments
- ordered signal profiles
- spectra
- depth or position-based measurements
Poor use cases:
- ordinary tabular data with unrelated columns
- one-hot encoded features
- feature sets where column order is arbitrary
The benchmark script includes extra tests on non-sequential tabular data specifically to stress-test this limitation.
Install the following Python packages:
pip install numpy scipy scikit-learn matplotlib tqdm fastdtwnumpyscipyscikit-learnmatplotlibtqdmfastdtw- standard library modules such as
argparse,csv,json,time, andpathlib
Python 3.9+ is recommended.
project_folder/
├── lsc.py
├── test_lsc_benchmark.py
└── README_LSC.md
The main algorithm entry point is:
cluster_labels, cluster_centers = LSC(
data,
num_clusters=5,
alpha=0.5,
smoothing=True,
max_iterations=100,
random_state=42,
visualize=False,
show_progress=True
)A NumPy array of shape (n_samples, n_features).
- rows = samples
- columns = ordered features
Number of clusters to form.
Weight for combining DTW and Manhattan distances:
alpha = 1.0→ pure DTWalpha = 0.0→ pure Manhattan distance0 < alpha < 1→ weighted mixture
Because both distance matrices are normalized before combination, alpha has a meaningful effect.
Whether to apply Savitzky–Golay smoothing row-wise before clustering.
Set this to True when neighboring feature positions should vary smoothly.
Set it to False if smoothing may distort meaningful sharp changes.
Maximum number of medoid-update iterations.
Random seed for reproducibility.
If True, the function plots:
- the initial line space
- the clustered line space with medoid representatives
If True, the function gives:
- estimate (shown in loading bar) for the run time of the algorithm
A 1D NumPy array of cluster assignments for each sample.
The final medoid representatives in the scaled and optionally smoothed line space.
These are not automatically transformed back into the original raw feature scale.
If your lsc.py file contains a test block such as:
if __name__ == "__main__":
...then run:
python lsc.pyBasic usage:
python test_lsc_benchmark.py --module lsc --func LSCThis tells the benchmark script to import:
- module:
lsc - function:
LSC
Example: if your algorithm is in my_lsc_impl.py, run:
python test_lsc_benchmark.py --module my_lsc_impl --func LSCpython test_lsc_benchmark.py \
--module lsc \
--func LSC \
--alpha 0.5 \
--max-iterations 100 \
--random-state 42 \
--synthetic-samples 300 \
--synthetic-features 64 \
--synthetic-clusters 5 \
--outdir benchmark_outputs--module— Python module containing theLSCfunction--func— function name to import--alpha— DTW/L1 weighting--max-iterations— maximum clustering iterations--random-state— seed for reproducibility--synthetic-samples— synthetic benchmark sample count--synthetic-features— synthetic benchmark feature count--synthetic-clusters— synthetic benchmark cluster count--outdir— output folder for CSV and JSON results
The benchmark script reports:
Noise levels:
- 1.0
- 2.0
- 3.0
- 5.0
- 10.0
- Iris
- Wine
- Breast cancer dataset
- Iris with permuted feature order
- Wine with permuted feature order
These extra tests help check how sensitive the method is to non-sequential tabular data.
Compares performance with smoothing enabled and disabled.
Reports local runtime over a grid of sample counts and feature counts.
The benchmark reports the following clustering metrics:
- ARI
- AMI
- Homogeneity
- Completeness
- V-measure
- Silhouette
- Runtime in seconds
The benchmark writes results into the directory given by --outdir.
Expected files include:
synthetic_results.csvreal_world_results.csvextra_nonsequential_results.csvsmoothing_ablation.csvruntime_sweep.csvall_primary_rows.csvbenchmark_manifest.json
Set:
alpha=1.0Set:
alpha=0.0You can lower:
- number of samples
- number of features
- number of clusters
max_iterations
DTW is very computationally expensive because all pairwise distances are computed.
Use the extra permuted-feature tests in the benchmark script. If performance drops strongly after column permutation, that indicates the algorithm depends on meaningful feature order of your data.
Your algorithm file is not named lsc.py, or you are not running the command from the correct folder.
Fix:
- rename the file to
lsc.py, or - pass the correct module name with
--module, or - run the command from the folder containing the file