Skip to content

KMeans ignores example weights in centroid updates and default initialization #7876

Open

Description

@svick

KMeans accepts an ExampleWeightColumnName, but appears to ignore weight magnitudes during the main training loop and the default K-means|| initialization.

Expected behavior

Centroids should be weighted means of their assigned examples:

centroid = sum(weight * features) / sum(weight)

Initialization should also account for example weights where appropriate.

Actual behavior

Source inspection shows:

  • Centroid updates accumulate unweighted feature vectors and divide by the number of assigned rows.
  • Default K-means|| initialization samples using distance-based weights without incorporating example weights. Its candidate-reduction step also counts rows rather than summing their weights.
  • Explicit K-means++ initialization does use example weights, but the subsequent training loop still computes unweighted centroids.

Consequently, a weight column can affect initialization differently depending on the selected algorithm, without producing weighted centroid updates.

Minimal repro

The following example isolates the centroid calculation by requesting one cluster:

using System;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Trainers;

var mlContext = new MLContext(seed: 1);
var data = mlContext.Data.LoadFromEnumerable(new[]
{
    new Input { Features = new[] { 0f }, Weight = 1f },
    new Input { Features = new[] { 10f }, Weight = 9f }
});

var model = mlContext.Clustering.Trainers.KMeans(
    new KMeansTrainer.Options
    {
        NumberOfClusters = 1,
        ExampleWeightColumnName = nameof(Input.Weight),
        InitializationAlgorithm =
            KMeansTrainer.InitializationAlgorithm.KMeansPlusPlus,
        NumberOfThreads = 1
    }).Fit(data);

VBuffer<float>[] centroids = default;
model.Model.GetClusterCentroids(ref centroids, out _);
Console.WriteLine(centroids[0].GetValues()[0]);

public class Input
{
    [VectorType(1)]
    public float[] Features { get; set; } = new float[1];

    public float Weight { get; set; }
}

Expected centroid: 9, from (1 * 0 + 9 * 10) / (1 + 9).

Source inspection predicts 5, the unweighted mean. This repro has not yet been executed.

Relevant source

Found while improving the weight-column documentation for #6746 in #7875.

Note

This report was drafted with GitHub Copilot assistance.

Activity

  1. added
    bugSomething isn't working
    area-TrainersMachine learning trainers and training APIs
    on Nov 3, 2026
  2. removed
    untriagedNew issue has not been triaged
    on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-TrainersMachine learning trainers and training APIsbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions