kmean算法C++实现
kmean均值算法是一种最常见的聚类算法。算法实现简单,效果也比较好。kmean算法把n个对象划分成指定的k个簇,每个簇中所有对象的均值的平均值为该簇的聚点(中心)。
k均值算法有如下五个步骤:
- 随机生成最初始k个簇心。可以从样本中随机选择,也可以根据样本中每个特征的取值特点随机生成。
- 对每个样本计算到每个簇心的欧式距离,将样本划分到欧氏距离最小的簇心(聚点)。
- 对划分到同一个簇心(聚点)的样本计算平均值,用均值更新簇心(聚点)
- 若某些簇心(聚点)发生变化,转到2;若所有的聚点都没有变化,转5
- 输出划分结果
#include <vector>
#include <cassert>
#include <iostream>
#include <cmath>
#include <fstream>
#include <climits>
#include <ctime>
#include <iomanip> using namespace std;
namespace terse {
class Kmeans {
private:
vector<vector<double>> m_dataSet;
int m_k;
vector<int> m_clusterResult; // result of cluster
vector<vector<double>> m_cluserCent; //center of k clusters private:
vector<string> split(const string& s, string pattern) {
vector<string> res;
size_t start = ;
size_t end = ;
while (start < s.size()) {
end = s.find_first_of(pattern, start);
if (end == string::npos) {
res.push_back(s.substr(start, end - start - ));
return res;
}
res.push_back(s.substr(start, end - start));
start = end + ;
}
return res;
} void loadDataSet(const char* fileName) {
ifstream dataFile(fileName);
if (!dataFile.is_open()) {
cerr << "open file " << fileName << "failed!\n";
return;
}
string tmpstr;
vector<double> data;
while (!dataFile.eof()) {
data.clear();
tmpstr.clear();
getline(dataFile, tmpstr);
vector<string> tmp = split(tmpstr, ",");
for (string str : tmp) {
data.push_back(stod(str));
}
this->m_dataSet.push_back(data);
}
dataFile.close();
} //compute Euclidean distance of two vector
double distEclud(vector<double>& v1, vector<double>& v2) {
assert(v1.size() == v2.size());
double dist = ;
for (size_t i = ; i < v1.size(); i++) {
dist += (v1[i] - v2[i]) * (v1[i] - v2[i]);
}
return sqrt(dist);
} void generateRandCent() {
int numOfFeats = this->m_dataSet[].size();
size_t numOfSamples = this->m_dataSet.size(); //first:min second:max
vector<pair<double, double>> minMaxOfFeat(numOfFeats);
for (int i = ; i < numOfFeats; i++) {
minMaxOfFeat[i].first = this->m_dataSet[][i];
minMaxOfFeat[i].second = this->m_dataSet[][i];
}
for (size_t i = ; i < numOfSamples; i++) {
for (int j = ; j < numOfFeats; j++) {
if (this->m_dataSet[i][j] > minMaxOfFeat[j].second) {
minMaxOfFeat[j].second = this->m_dataSet[i][j];
}
if (this->m_dataSet[i][j] < minMaxOfFeat[j].first) {
minMaxOfFeat[j].first = this->m_dataSet[i][j];
}
}
}
srand(time(NULL));
for (int i = ; i < this->m_k; i++) {
for (int j = ; j < numOfFeats; j++) {
this->m_cluserCent[i][j] = minMaxOfFeat[j].first
+ (minMaxOfFeat[j].second - minMaxOfFeat[j].first)
* (rand() / (double) RAND_MAX);
}
} } void printClusterCent(int iter) {
int m = this->m_cluserCent.size();
int n = this->m_cluserCent[].size();
cout << "iter = " << iter;
for (int i = ; i < m; i++) {
cout << " {";
for (int j = ; j < n; j++) {
cout << this->m_cluserCent[i][j] << ",";
}
cout << "};";
}
cout << endl;
} void writeResult(const char* fileName = "res.txt") {
ofstream fout(fileName);
if (!fout.is_open()) {
cerr << "open file " << fileName << "failed!";
return;
}
for (size_t i = ; i < this->m_dataSet.size(); i++) {
for (size_t j = ; j < this->m_dataSet[].size(); j++) {
fout << this->m_dataSet[i][j] << "\t";
}
fout << setprecision() << this->m_clusterResult[i] << "\n";
}
fout.close();
} public:
Kmeans(int k, const char* fileName) {
this->m_k = k;
this->loadDataSet(fileName);
this->m_clusterResult.reserve(this->m_dataSet.size());
this->m_cluserCent = vector<vector<double>>(k,
vector<double>(this->m_dataSet[].size()));
generateRandCent();
} Kmeans(int k, vector<vector<double>>& data) {
this->m_k = k;
this->m_dataSet = data;
this->m_clusterResult.reserve(this->m_dataSet.size());
this->m_cluserCent = vector<vector<double>>(k,
vector<double>(this->m_dataSet[].size()));
generateRandCent();
} //verbose = 1,printClusterCent();
void kmeansCluster(int verbose = ) {
int iter = ;
bool isClusterChanged = true;
while (isClusterChanged) {
isClusterChanged = false;
//step 1: find the nearest centroid of each point
int numOfFeats = this->m_dataSet[].size();
size_t numOfSamples = this->m_dataSet.size();
for (size_t i = ; i < numOfSamples; i++) {
int minIndex = -;
double minDist = INT_MAX;
for (int j = ; j < this->m_k; j++) {
double dist = distEclud(this->m_cluserCent[j],
m_dataSet[i]);
if (dist < minDist) {
minDist = dist;
minIndex = j;
}
}
if (m_clusterResult[i] != minIndex) {
isClusterChanged = true;
m_clusterResult[i] = minIndex;
}
} //step 2: update cluster center
vector<size_t> cnt(this->m_k, );
this->m_cluserCent = vector<vector<double>>(this->m_k,
vector<double>(numOfFeats, 0.0));
for (size_t i = ; i < numOfSamples; i++) {
for (int j = ; j < numOfFeats; j++) {
this->m_cluserCent[this->m_clusterResult[i]][j] +=
this->m_dataSet[i][j];
}
cnt[this->m_clusterResult[i]]++;
}
// mean of the vector belong to a cluster
for (int i = ; i < this->m_k; i++) {
for (int j = ; j < numOfFeats; j++) {
this->m_cluserCent[i][j] /= cnt[i];
}
}
if (verbose)
printClusterCent(iter++);
}
writeResult();
}
}; }; int main(){
terse::Kmeans kmeans(,"datafile.txt");
kmeans.kmeansCluster();
return ;
}
/*namespace terse*/
kmean算法C++实现的更多相关文章
- <转>与EM相关的两个算法-K-mean算法以及混合高斯模型
转自http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006924.html http://www.cnblogs.com/jerrylead/ ...
- EM相关两个算法 k-mean算法和混合高斯模型
转自http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006924.html http://www.cnblogs.com/jerrylead/ ...
- 机器学习课程-第8周-聚类(Clustering)—K-Mean算法
1. 聚类(Clustering) 1.1 无监督学习: 简介 在一个典型的监督学习中,我们有一个有标签的训练集,我们的目标是找到能够区分正样本和负样本的决策边界,在这里的监督学习中,我们有一系列标签 ...
- K-Means聚类算法原理
K-Means算法是无监督的聚类算法,它实现起来比较简单,聚类效果也不错,因此应用很广泛.K-Means算法有大量的变体,本文就从最传统的K-Means算法讲起,在其基础上讲述K-Means的优化变体 ...
- 学习OpenCV——Kmean(C++)
从前也练习使用过OpenCV的Kmean算法,但是那版本低,而且也是基于C的开发.这两天由于造论文的需要把它重新翻出来在研究一下C++,发现有了些改进 kmeans C++: doublekmeans ...
- 运用三角不等式加速Kmeans聚类算法
运用三角不等式加速Kmeans聚类算法 引言:最近在刷<数据挖掘导论>,第九章, 9.5.1小节有提到,可以用三角不等式,减少不必要的距离计算,从而达到加速聚类算法的目的.这在超大数据量的 ...
- MLlib--PIC算法
转载请标明出处http://www.cnblogs.com/haozhengfei/p/82c3ef86303321055eb10f7e100eb84b.html PIC算法 幂迭代聚类 ...
- ML: 聚类算法-K均值聚类
基于划分方法聚类算法R包: K-均值聚类(K-means) stats::kmeans().fpc::kmeansruns() K-中心点聚类(K-Medoids) ...
- K-SVD算法
它与K-mean算法原理上是类似的: K-mean 算法: (之前写过:http://www.cnblogs.com/yinheyi/p/6132362.html) 对于初始化的类别中心,可以看作初化 ...
随机推荐
- springmvc 孔浩 hibernate
以上为项目文件 用到的jar包:http://pan.baidu.com/s/1kT1Rsqj 1. model-User 2. beans.xml-去哪些包中找annotation:查找相应的实体类 ...
- 在每页(分页)报表中重复显示标题 - SQL Server Reporting Service (SSRS)
问题描述 TFS系统提供多种报表,有图表(Chart).Web面板(Dashboard).SharePoint面板.Excel报表,SQL Server Reporting Serivce(SSRS) ...
- java 集合stream操作
分组 Map<Integer, List<T>> group = List.stream().collect(Collectors.groupingBy(T::getField ...
- RabbitMQ基础入门篇
下载安装 Erlang RabbitMQ 启动RabbitMQ管理平台插件 DOS下进入到安装目录\sbin,执行以下命令 rabbitmq-plugins enable rabbitmq_manag ...
- .net Framework使用之 MongoDB
新建Helper using MongoDB.Bson; using MongoDB.Driver; using System; using System.Collections.Generic; u ...
- .NET Core 玩一玩 Ocelot API网关
.net 这几年国内确实不好过. 很多都选择转行.不过.net Core跨平台 开源之后 .社区的生态在慢慢建立.往好的趋势发展. 对于坚守在.NET战线的开发者来说 是个挺不错的消息. 特别是微软 ...
- Console命令,让js调试更简单
一.显示信息的命令 console.log("normal"); // 用于输出普通信息 console.info("information"); // 用于输 ...
- 【2019年OCP新题】OCP题库更新出现大量新题-11
11.Your database is in archivelog mode. You want to disable archiving for the database. Examine thes ...
- jzoj4424
20%:暴力枚舉每一條邊有沒有被選到,然後使用并查集判斷聯通性 這樣子有20分,但是我考試寫掛了所以1分也沒有 100%:這道題2000的數據範圍,使用指數級搜索會tle,需要更加好的方法 這道題中, ...
- spring boot 使用application.properties 进行外部配置
application.properties大家都不陌生,我们在开发的时候,经常使用它来配置一些可以手动修改而且不用编译的变量,这样的作用在于,打成war包或者jar用于生产环境时,我们可以手动修改环 ...