Skip to main content

Your First Clustering Iteration

This guide will walk you through adding data points, defining centroids, and running the clustering algorithm to see real-time results.
1

Add Data Points

Start by adding some data points to cluster. You have two options:Option 1: Manual Entry
  1. In the Add Point section (left side), enter X and Y coordinates
  2. Click the Add Point button
  3. Repeat to add multiple points
// Example points you might add:
// Point 1: (10, 20)
// Point 2: (15, 18)
// Point 3: (50, 60)
// Point 4: (55, 65)
Option 2: Random GenerationClick the Random Point button to automatically generate a random point with coordinates between -100 and 100:
// From src/utils/CMeans.ts:178-188
export function generateRandomPoints(n: number) {
    const points = [];
    for (let i = 0; i < n; i++) {
        const point = {
            x: Math.floor(Math.random() * 201) - 100,
            y: Math.floor(Math.random() * 201) - 100,
        };
        points.push(point);
    }
    return points as Point[];
}
Add at least 4-6 points to see meaningful clustering behavior.
2

Define Initial Centroids

Now add centroids that will serve as the initial cluster centers:
  1. In the Add Centroid section (right side), enter X and Y coordinates
  2. Click the Add Centroid button
  3. Add 2-3 centroids to create distinct clusters
// Example centroids:
// Centroid 1: (12, 19)  // Near the first group of points
// Centroid 2: (52, 62)  // Near the second group of points
The number of centroids determines the number of clusters (k). For your first try, use 2-3 centroids.
3

Observe the Initial State

After adding points and centroids, you’ll see:
  • Points Table: Lists all your data points with coordinates (4 decimal places)
  • Centroids Table: Shows your initial centroid positions
  • Scatter Plot: Visualizes points and centroids on a Chart.js graph
  • Cost Function: Displays as 0.0000 before the first iteration
  • Distance Matrix: Empty until you iterate
  • Membership Matrix: Empty until you iterate
4

Run the First Iteration

Click the Iterate button to execute one step of the fuzzy C-Means algorithm.Behind the scenes, the useCMeans hook executes:
// From src/utils/useCmeans.ts:38-50
const onIterate = () => {
    if (newCentroids.length <= 0) {
        notification.error({
            message: 'Error',
            description: 'There are not enough points or centroids to start an iteration of the algorithm!',
            duration: 3,
            placement: 'bottomLeft'
        });
        return
    }

    setCentroids(newCentroids); // Update the centroids
};
The algorithm performs these calculations:
  1. Distance Matrix: Calculates Euclidean distance between each point and centroid
  2. Membership Matrix: Computes fuzzy membership values (soft assignment)
  3. New Centroids: Recalculates centroid positions based on weighted membership
  4. Cost Function: Sums the weighted squared distances
The default algorithm is fuzzy C-Means with fuzzification parameter m=2. This is set in src/App.tsx:16.
5

Analyze the Results

After the first iteration, examine the updated interface:Distance MatrixShows Euclidean distances calculated by:
// From src/utils/CMeans.ts:32-35
export const euclidianDistance = (pointA: Point, pointB: Point) => {
    const distance = Math.sqrt(
        Math.pow((pointA.x - pointB.x), 2) + Math.pow((pointA.y - pointB.y), 2)
    );
    return distance;
}
Membership MatrixFor fuzzy C-Means, values are continuous (0 to 1) representing partial membership:
// From src/utils/FuzzyCmeans.ts:22-31
for (let k = 0; k < distanceMatrix.length; k++) {
    if (distanceMatrix[k][j] !== 0) {
        clusterSum += Math.pow(
            (distanceMatrix[i][j] / distanceMatrix[k][j]), 
            2 / (fuzzyParameter - 1)
        );
    }
}
const membershipValue = clusterSum !== 0 ? 1 / clusterSum : 1;
Updated Scatter PlotPoints are now color-coded by their dominant cluster membership, and centroids have moved to new positions.Cost FunctionThe cost function shows the total clustering error:
// From src/utils/FuzzyCmeans.ts:79-92
export const getFuzzyCostValues = (distanceMatrix: number[][], membershipMatrix: number[][], fuzzyParameter: number): number[] => {
    const costValues: number[] = [];
    for (let i = 0; i < distanceMatrix.length; i++) {
        let costValue = 0;
        for (let j = 0; j < distanceMatrix[0].length; j++) {
            costValue += Math.pow(membershipMatrix[i][j], fuzzyParameter) * Math.pow(distanceMatrix[i][j], 2);
        }
        costValues.push(costValue);
    }
    return costValues;
}
6

Continue Iterating

Keep clicking Iterate to run additional iterations. Watch for:
  • Centroid movement: Centroids shift toward the center of their clusters
  • Decreasing cost: The cost function should decrease with each iteration
  • Stabilization: Eventually, centroids stop moving and the cost plateaus (convergence)
Typical convergence takes 5-15 iterations depending on your data and initial centroid positions.
7

Reset and Experiment

Click the Reset button to clear all points and centroids:
// From src/utils/useCmeans.ts:52-55
const onReset = () => {
    setCentroids([]);
    setPoints([]);
};
Try different scenarios:
  • More clusters (add 4-5 centroids)
  • Different point distributions
  • Comparing crisp vs. fuzzy behavior (requires code modification in src/App.tsx:16)

Understanding the Algorithm Flow

The useCMeans hook orchestrates the entire clustering process:
// From src/utils/useCmeans.ts:18-28
const cMeansFunction = useMemo(() => {
    return algorithm === 'fuzzy' ? fuzzyCMeans : CMeans;
}, [algorithm]);

const {
    distanceMatrix,
    membershipMatrix,
    newCentroids,
    costValues,
    costFunction,
} = useMemo(() => cMeansFunction(points, centroids), [cMeansFunction, points, centroids]);
Each iteration updates the state, triggering React to re-render all matrices, charts, and tables with fresh data.

Crisp vs. Fuzzy Comparison

Crisp C-Means (Hard Clustering)

  • Membership: Binary (0 or 1) - each point belongs to exactly one cluster
  • Centroid Update: Simple mean of assigned points
  • Use Case: When clusters are well-separated and non-overlapping
// From src/utils/CMeans.ts:92-114
export const getNewCentroids = (points: Point[], membershipMatrix: number[][]) => {
    const newCentroids = [];
    for (let i = 0; i < membershipMatrix.length; i++) {
        let sumaX = 0;
        let sumaY = 0;
        let cardinalidad = 0;

        for (let j = 0; j < membershipMatrix[0].length; j++) {
            if (membershipMatrix[i][j] == 1) {
                sumaX += points[j].x;
                sumaY += points[j].y;
                cardinalidad++;
            }
        }
        const x = sumaX / cardinalidad;
        const y = sumaY / cardinalidad;

        if (cardinalidad !== 0) {
            newCentroids.push({ x, y });
        }
    }
    return newCentroids;
}

Fuzzy C-Means (Soft Clustering)

  • Membership: Continuous (0 to 1) - points can partially belong to multiple clusters
  • Centroid Update: Weighted mean using membership degrees raised to power m
  • Use Case: When clusters overlap or boundaries are unclear
// From src/utils/FuzzyCmeans.ts:47-68
export const getNewFuzzyCentroids = (points: Point[], membershipMatrix: number[][], fuzzyParameter: number): Point[] => {
    const newCentroids: Point[] = [];
    for (let i = 0; i < membershipMatrix.length; i++) {
        let membershipx = 0;
        let membershipy = 0;
        let membership = 0;
        for (let j = 0; j < membershipMatrix[0].length; j++) {
            const squareMembership = Math.pow(membershipMatrix[i][j], fuzzyParameter);
            membership += squareMembership;
            membershipx += squareMembership * points[j].x;
            membershipy += squareMembership * points[j].y;
        }
        const x = membershipx / membership;
        const y = membershipy / membership;

        newCentroids.push({ x, y });
    }
    return newCentroids;
}

Common Patterns and Tips

Achieving Good Convergence

  1. Initial Centroids: Place them in different regions of your data space
  2. Sufficient Points: Use at least 3-4 points per cluster
  3. Iterations: Run until the cost function change is minimal (< 0.01)

Monitoring Convergence

Watch the cost function displayed at the top of the interface:
// From src/App.tsx:40
<h2 className="text-xl font-semibold">Cost Function: {costFunction.toFixed(4) ?? 0}</h2>
When the cost stops decreasing significantly between iterations, the algorithm has converged.

Handling Edge Cases

If you see an error notification:
“There are not enough points or centroids to start an iteration of the algorithm!”
This means you need to add at least one point and one centroid before clicking Iterate.

Next Steps

Now that you understand the basics:
  • Explore the detailed algorithm implementations in the API Reference
  • Learn about component architecture in the Components section
  • Customize the fuzzification parameter or add algorithm switching in the Advanced Usage guide

Build docs developers (and LLMs) love