k-means asks for a number of clusters, $k$, chosen in advance, and finds $k$ centroids that minimise the total squared distance from each point to its nearest centroid. It iterates: assign every point to its nearest centroid, recompute each centroid as the mean of its assigned points, repeat until the assignments stop changing.
- Choose $k$ and initialise $k$ centroids (
k-means++in scikit-learn picks good starting points automatically). - Assign every point to its nearest centroid.
- Move each centroid to the mean of the points now assigned to it.
- Repeat steps 2 and 3 until assignments stop changing (or a maximum iteration count is reached).
kmeans_network_flows.py
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
# flow_features: packets/second, mean packet size, flow duration, ...
scaled = StandardScaler().fit_transform(flow_features)
kmeans = KMeans(n_clusters=3, n_init=10, random_state=3)
labels = kmeans.fit_predict(scaled)
Caution: k-Means Needs k, and Needs Scaled Features
k-means has two sharp edges. First, you must choose $k$ in advance; choosing it badly (too few, too many) produces clusters that do not correspond to anything meaningful. Second, k-means uses raw Euclidean distance, so a feature measured in the thousands (bytes transferred) will dominate a feature measured in single digits (TCP flags set) unless every feature is standardised first, exactly as StandardScaler does above.

