Synthetic Data for Clustering Experiments
The program builds a small synthetic data set, creates a k-means clustering model, and trains that model on the data.
Starting With a Complete Program
This article begins with a complete, short program rather than with definitions. The program builds a small synthetic data set, creates a k-means clustering model, and trains that model on the data. Read it once before you go on, and notice which line you expect to be the most important one.
make_blobsgenerates the synthetic points that clustering will work onKMeans(n_clusters=3)creates the model object and records the number of clusters to findkmeans.fit(X)trains the model on the points in X
Three Jobs in One Short Script
The script has three jobs. It obtains data, it builds a model object, and it trains that model. Each job maps to one or two lines. Once you can name the job a line performs, you know which part of the program to inspect when results look wrong.
Reading the script this way means you can answer three questions for any line. Does it create data, create a model, or train the model? Mapping each line to one job turns a short program into three checkpoints. The rest of this article takes each job in turn.
Generating the Data With make_blobs
In this script the data is produced by make_blobs, which returns two things, X and y. The variable X holds the two-dimensional points that the clustering step will work on. The variable y holds a second array. The script stores it, but it never passes y to the clustering step. The clustering model in this script sees only X.
The argument random_state=1 controls the random generation so that the same synthetic points are produced on each run. This is important for debugging. If two runs of the same script disagree, the data was not the cause, because the data is fixed by the seed. You can therefore set the data aside as a suspect when you compare runs.
What KMeans(n_clusters=3) Records
The source describes this step as instantiating the KMeans class and setting the number of clusters you are looking for. In code, that is the single line kmeans = KMeans(n_clusters=3). The class name is KMeans. The keyword argument is n_clusters. The value 3 is the number of clusters the model is asked to find.
Notice what this constructor line does and does not establish. It records the setting that the model should use. It does not yet find any groups. The learning from the data happens in the next step, when fit is called. A learner who expects the object creation line to find the clusters will be surprised, and that surprise is a useful signal that the training step is the place to look.
How fit Uses the Data It Receives
The source states that the fit method is called on the KMeans object, with the data as an argument. The line kmeans.fit(X) therefore has two parts. The first part is the object whose method runs, which is kmeans. The second part is the data that method receives, which is X, the array produced by make_blobs.
kmeans = KMeans(n_clusters=3)The model holds only its setting, n_clusters=3, and has seen no points.
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)The model has been trained on the points in X, so the grouping now comes from the data.
When you trace the script, watch the moment fit runs. Before that line, the model holds only its setting. After it, the model has been trained on the points in X. Any unexpected grouping you see must therefore come from one of three places: the data passed in, the setting given to the constructor, or the training call itself.
Tracing a Result That Does Not Match
When a clustering result does not match what you expected, avoid re-reading the whole script at once. Work through the three jobs in order. The first job whose state differs from your expectation is where the divergence begins.
Two runs disagree
Two runs of the same script give different groupings. Find the first job where the state differs from what you expected.
- 1Check the data
The script calls
make_blobswithrandom_state=1. The seed is fixed, so the points in X should be identical on both runs. The data is not the cause. - 2Check the setting
The constructor should read
KMeans(n_clusters=3). If both runs use the same line, the setting is the same as well. - 3Check the training call
The call should be
kmeans.fit(X). If one run passes a different array, or the call was changed between runs, the training input differs. This is the first job whose state can differ.
With the data and setting confirmed, the divergence begins at the training call. Edit the fit line first to find the difference.
Mistakes When Reading the Script
Common mistake Expecting the constructor line to find the clusters
What it looks likeAssuming that after kmeans = KMeans(n_clusters=3) the model already knows where the groups are.
Why it failsThe constructor only records the setting. No points have been passed to the model yet.
Do this insteadLook for the learning in the fit call, where the data enters the model.
Common mistake Blaming the data when two runs disagree
What it looks likeConcluding that make_blobs generated different points because the grouping changed.
Why it failsThe script fixes the seed with
random_state=1, so the same points are produced on each run.Do this insteadConfirm the data first, then move on to the setting and the training call.
Common mistake Assuming the variable y feeds the clustering step
What it looks likeThinking that the second output of make_blobs is used to form the clusters.
Why it failsThe script stores y but never passes it to the clustering step. The model is trained only on X.
Do this insteadTrace what kmeans.fit receives. Here that is X alone.
Common mistake Re-reading the whole script at once instead of checking the three jobs in order
Practice: Changing the Cluster Count
The model was asked for three clusters, and the data was generated with a fixed random seed. If you changed only the value 3 to a different number, which line of the script would have to be edited, and which of the three jobs would be affected? Write down your answer, then compare it with the trace.
Hints
- Find the only place where the number 3 appears in the script.
- Ask whether the number is part of the data job, the model job, or the training job.
- Remember that the constructor line records the setting and the fit line trains the model.
Key Takeaways
- A short scikit-learn script has three jobs: it obtains data with
make_blobs, builds a model object with KMeans, and trains that model with fit. KMeans(n_clusters=3)records the number of clusters the model should find, but it does not learn any groups until fit is called.kmeans.fit(X)passes the array X to the trained model, and the model's cluster centers and labels come from that training.- When results diverge, check the data, then the setting, then the training call, in that order, to find the first job whose state differs from your expectation.