使用马氏距离作为距离度量函数的c++ kmeans聚类算法代码
时间: 2023-09-20 15:14:54 浏览: 142
kmeans聚类c++代码
4星 · 用户满意度95%
以下是使用马氏距离作为距离度量函数的 C++ K-means 聚类算法的示例代码:
```cpp
#include <iostream>
#include <vector>
#include <cmath>
// 计算两个向量之间的马氏距离
double mahalanobisDistance(const std::vector<double>& vec1, const std::vector<double>& vec2) {
if (vec1.size() != vec2.size()) {
throw std::runtime_error("Vector dimensions do not match");
}
double distance = 0.0;
for (size_t i = 0; i < vec1.size(); ++i) {
distance += pow(vec1[i] - vec2[i], 2);
}
return sqrt(distance);
}
// K-means 聚类算法
std::vector<int> kMeansClustering(const std::vector<std::vector<double>>& data, int k) {
if (k <= 0 || k > data.size()) {
throw std::runtime_error("Invalid number of clusters");
}
std::vector<int> clusterLabels(data.size(), -1); // 聚类标签,初始化为-1
std::vector<std::vector<double>> centroids(k); // 聚类中心
// 随机选择初始聚类中心
std::vector<int> selectedCentroids;
for (int i = 0; i < k; ++i) {
int randIndex = rand() % data.size();
while (std::find(selectedCentroids.begin(), selectedCentroids.end(), randIndex) != selectedCentroids.end()) {
randIndex = rand() % data.size();
}
selectedCentroids.push_back(randIndex);
centroids[i] = data[randIndex];
}
bool isChanged = true;
while (isChanged) {
isChanged = false;
// 分配样本到最近的聚类中心
for (size_t i = 0; i < data.size(); ++i) {
double minDistance = std::numeric_limits<double>::max();
int minCluster = -1;
for (int j = 0; j < k; ++j) {
double distance = mahalanobisDistance(data[i], centroids[j]);
if (distance < minDistance) {
minDistance = distance;
minCluster = j;
}
}
if (clusterLabels[i] != minCluster) {
clusterLabels[i] = minCluster;
isChanged = true;
}
}
// 更新聚类中心
std::vector<int> clusterSizes(k, 0);
std::vector<std::vector<double>> newCentroids(k, std::vector<double>(data[0].size(), 0.0));
for (size_t i = 0; i < data.size(); ++i) {
int cluster = clusterLabels[i];
clusterSizes[cluster]++;
for (size_t j = 0; j < data[i].size(); ++j) {
newCentroids[cluster][j] += data[i][j];
}
}
for (int i = 0; i < k; ++i) {
if (clusterSizes[i] > 0) {
for (size_t j = 0; j < newCentroids[i].size(); ++j) {
newCentroids[i][j] /= clusterSizes[i];
}
}
}
// 判断是否需要继续迭代
for (int i = 0; i < k; ++i) {
if (mahalanobisDistance(centroids[i], newCentroids[i]) > 1e-6) {
isChanged = true;
centroids[i] = newCentroids[i];
}
}
}
return clusterLabels;
}
int main() {
// 示例数据
std::vector<std::vector<double>> data = {
{1.0, 2.0},
{2.0, 1.0},
{4.0, 5.0},
{5.0, 4.0},
{10.0, 12.0},
{12.0, 10.0}
};
int k = 2; // 聚类数目
std::vector<int> clusterLabels = kMeansClustering(data, k);
// 打印聚类结果
for (size_t i = 0; i < data.size(); ++i) {
std::cout << "Data point (" << data[i][0] << ", " << data[i][1] << ") belongs to cluster " << clusterLabels[i] << std::endl;
}
return 0;
}
```
这是一个简单的 K-means 聚类算法的示例代码,其中使用马氏距离作为距离度量函数来计算样本之间的距离。你可以根据需要修改示例数据和聚类数目。请注意,此代码仅供参考,实际使用时可能需要进行优化和适应特定需求的修改。
阅读全文