Your Distance Matrix Calculation
You wrote the code (I summarize it for the Distance Matrix):
K = 3;
n = size(mX, 1);
d = size(mX, 2); %<! Number of dimensions per sample
mC = mX(randperm(n, K), :);
% mD = repmat(mX, 1, 1, K) - reshape(mC, 1, n, K); %<! Your code, Will fail because of reshape
mD = sum((reshape(mX, n, 1, d) - reshape(mC.', 1, K, d)) .^ 2, 3); %<! Correctly with no `repmat()`
The reason it won't work is the reshaping operation you're doing.
The number of elements in mC
is K x d
while your reshape()
should keep the number of elements.
In the following I gave you a code snippet how to calculate the matrix mD
efficiently.
K-Means
To calculate the distance you shouldn't use repmat()
which will allocate new memory.
To calculate the Distance Matrix with the 3rd dimension and broadcasting you should do something like:
mD = sum((reshape(mA, numVarA, 1, varDim) - reshape(mB.', 1, numVarB, varDim)) .^ 2, 3);
But a faster way would be:
mD = sum(mA .^ 2).' - (2 * mA.' * mB) + sum(mB .^ 2);
Which utilizes the fast the Matrix Multiplication is probably the most optimized algorithm and that:
$$ {\left\| \boldsymbol{x} - \boldsymbol{y} \right\|}_{2}^{2} = \boldsymbol{x}^{T} \boldsymbol{x} - 2 \boldsymbol{x}^{T} \boldsymbol{y} + \boldsymbol{y}^{T} \boldsymbol{y} $$
For you to have a reference of K-Means algorithm with support for any Distance Function I created a function and ran it on your data:
It will converge very fast for that data:
I also created a small benchmark for various algorithm to compute the Euclidean Squared Distance Matrix.
The first test was between 3 approaches to calculate the distance between a single set of vectors (For example given by a single matrix):
The second test I compared 2 Row / Column variations of the algorithm above:
The Row / Column variations means I test the algorithm in 2 cases:
- Row Variation - Each data sample is a row in the data matrix (Like your data).
- Column Variation - Each data sample is a column in the data matrix (In MATLAB it means the sample is contiguous in memory).
As can be seen, it is always better to have data in the column variation.
Remark: Pay attention that the Squared Euclidean Distance doesn't obey the Triangle Inequality which is a requirement for a Metric. It is used for computational efficiency as it doesn't change the K-Means algorithm results compared to Euclidean Distance (The L2 Norm based distance).
The MATLAB Code is accessible in my StackExchange Code Review Q254186 GitHub Repository.
Remark: The K-Means algorithm, as a non convex optimization, is sensitive to the initialization. In the above code I used random initialization - randomly choosing samples form data to be the initial centroids. There are better approaches out there (See K-Means++ as an example for a more robust initialization).
MAT
orCSV
file? I will give a reference code for it. \$\endgroup\$