C#实现K-MEDOIDS聚类算法
1、任意选取K个对象作为初始聚类中心(O1,O2,…Oi…Ok)。
2)将余下的对象分到各个类中去(该对象与哪一个聚类中心最近就被分配到哪一个聚类簇中);
3)对于每个类(Oi)中,顺序选取一个Or,重复步骤2,计算用Or代替Oi后的误差E=各个点到其对应的中心点欧式距离之和。选择E最小的那个Or来代替Oi。
4)重复步骤3,直到K个medoids固定下来。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; namespace K_medoids
{
class Program
{
/// <summary>
/// 程序文本数据文件应位于同一文件夹下
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var path = string.Empty;
int k = 0;
try
{
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, args[0]);//数据文件路径
k = Convert.ToInt32(args[1]);
}
catch (Exception)
{
Console.Write("参数错误");
return;
}
var reader=new StreamReader(path,Encoding.Default);
var indivadulStr =reader.ReadLine().Trim();//每一行数据的字符串形式
var stanStr= System.Text.RegularExpressions.Regex.Replace(indivadulStr, @" +", " ");
var firstData=stanStr.Split(' ');//第一行数据
var realIndivadul = new Indivaduls();//数据结构体
var db = new List<Indivaduls>();//存放所有数据
foreach (var s in firstData)
{
realIndivadul.Numbers.Add(Convert.ToDouble(s));
}
db.Add(realIndivadul);
while ((indivadulStr=reader.ReadLine())!=null)
{
var stringNumber = indivadulStr.Trim().Split(' ');
var doubleNumber = stringNumber.Select(Convert.ToDouble).ToList();
db.Add(new Indivaduls(){Numbers =doubleNumber});
} var initialCenters = new List<Indivaduls>();//聚类初始中心个体
var gap = db.Count/k + 1;
for (int i = 0; i < k; i++)
{
initialCenters.Add(db[i*gap]);
}
var result=Pam(db, initialCenters);
foreach (var crow in result)
{
foreach (var number in crow.CenterPoint.Numbers)
{
Console.Write(number+"\0");
}
Console.Write("\r\n");
foreach (var point in crow.CrowsPoint)
{
foreach (var number in point.Numbers)
{
Console.Write(number+"\0");
}
Console.Write("\r\n");
}
Console.WriteLine("========================");
}
Console.ReadKey(); }
/// <summary>
///
/// </summary>
/// <param name="indivadulses"></param>
/// <param name="centerPoints"></param>
/// <returns>聚类结果 簇</returns>
public static List<Crows> Pam(List<Indivaduls> indivadulses,List<Indivaduls> centerPoints )
{
var firstCrows = K_medoids(indivadulses, centerPoints); var resultCenterPoints = new List<Indivaduls>();//存放结果中心点
for (int i = 0; i < firstCrows.Count; i++)//循环每一个簇
{
resultCenterPoints.Add(firstCrows[i].CenterPoint);
var oldOtherCrows =new List<Crows>();
oldOtherCrows.AddRange(firstCrows);
oldOtherCrows.RemoveAt(i); var oldDiff = AbsoluteDiff(firstCrows[i], oldOtherCrows); var count=firstCrows[i].CrowsPoint.Count;
for (int j = 0; j < count; j++)//循环每一个簇中的非中心点个体
{
//var otherCrowsss = new List<Crows>();//除去要替换的中心点所在的簇 其他簇
//otherCrowsss.AddRange(firstCrows);
//otherCrowsss.RemoveAt(i); var newCenterPoints = new List<Indivaduls>();//新的中心点集合
newCenterPoints.AddRange(centerPoints);
newCenterPoints.RemoveAt(i);
newCenterPoints.Add(firstCrows[i].CrowsPoint[j]); var newOtherCrowsCenterPoints = new List<Indivaduls>();//新的除变化点所在簇的中心 的其他中心点
newOtherCrowsCenterPoints.AddRange(centerPoints);
newOtherCrowsCenterPoints.RemoveAt(i); var newCrows = K_medoids(indivadulses,newCenterPoints); //替换点后 新的聚类簇 var newOtherCrows = new List<Crows>();
var newCrow = new Crows(); foreach (var crow in newCrows)
{
if (newOtherCrowsCenterPoints.MyContains(crow.CenterPoint))
{
newOtherCrows.Add(crow);
}
else
{
newCrow = crow;
}
}
var newDiff = AbsoluteDiff(newCrow,newOtherCrows);
if (newDiff < oldDiff)
{
resultCenterPoints[i] = newCrow.CenterPoint;
oldDiff = newDiff;
} } }
var resultCrows= K_medoids(indivadulses, resultCenterPoints);
return resultCrows;
}
/// <summary>
/// 单次聚类
/// </summary>
/// <param name="indivadulses">待聚类个体,包括了中心点</param>
/// <param name="centerPoints">中心点个体</param>
/// <returns>聚类结果</returns>
public static List<Crows> K_medoids(List<Indivaduls> indivadulses,List<Indivaduls> centerPoints)
{
var resultCrows = new List<Crows>();//聚类结果 簇集合
var indivadulsCount = indivadulses.Count;//待分配个体的个数,包括了中心点
for (var i = 0; i < centerPoints.Count; i++)
{
resultCrows.Add(new Crows() { CenterPoint = centerPoints[i] });
}
for (int i = 0; i < indivadulsCount; i++)
{
if (!centerPoints.MyContains(indivadulses[i]))
{
int myNumber = 0;//要将这个点归类到 序号为0的resultCrows中
var firstDic = P2PDistance(indivadulses[i], resultCrows[0].CenterPoint);//该点与第一个中心的距离
for (int j = 1; j < resultCrows.Count; j++)
{
var otherDic = P2PDistance(indivadulses[i], resultCrows[j].CenterPoint);
if (otherDic < firstDic)
{
firstDic = otherDic;
myNumber = j;
}
}
resultCrows[myNumber].CrowsPoint.Add(indivadulses[i]);
}
}
return resultCrows;
}
/// <summary>
/// 对于已经完成一次聚类后的某一个点center计算绝对误差
/// </summary>
/// <param name="centerCrow">要计算绝对误差的中心点群簇</param>
/// <param name="otherPoints">除中心点群簇外的其他群簇</param>
public static double AbsoluteDiff(Crows centerCrow,List<Crows> otherPoints )
{
var countCrows = otherPoints.Count;
var distance = Distance(centerCrow);
for (var i = 0; i < countCrows; i++)
{
distance += Distance(otherPoints[i]);
}
return distance;
}
/// <summary>
/// 计算群簇中各个点距离中心点的欧式距离
/// </summary>
/// <param name="crow">群簇</param>
/// <returns>欧式距离</returns>
public static double Distance(Crows crow)
{
var pointCount = crow.CrowsPoint.Count;//非中心点的个数
var distance = 0.0;//总距离
for (var i = 0; i < pointCount; i++)
{
distance += P2PDistance(crow.CenterPoint, crow.CrowsPoint[i]);
}
return distance;
}
/// <summary>
/// 两点间欧式距离
/// </summary>
/// <param name="p1">点p1</param>
/// <param name="p2">点p2</param>
/// <returns></returns>
public static double P2PDistance(Indivaduls p1,Indivaduls p2)
{
if (p1.Numbers.Count != p2.Numbers.Count || p1.Numbers.Count == 0)
{
throw new Exception();
}
var dimension = p1.Numbers.Count;
var result = 0.0;
for (var i = 0; i < dimension; i++)
{
result += (p1.Numbers[i] - p2.Numbers[i])*(p1.Numbers[i] - p2.Numbers[i]);
}
return Math.Sqrt(result);
} }
/// <summary>
/// 一个点个体
/// </summary>
public class Indivaduls
{
public List<double> Numbers;
public Indivaduls()
{
this.Numbers=new List<double>();
}
public bool MyEquals(Indivaduls obj)
{
if (obj.Numbers.Count != this.Numbers.Count)
return false;
for (int i = 0; i < Numbers.Count; i++)
{
if (this.Numbers[i] != obj.Numbers[i])
return false;
}
return true;
}
}
/// <summary>
/// 一个聚类簇
/// </summary>
public class Crows
{
public Crows()
{
this.CrowsPoint=new List<Indivaduls>();
this.CenterPoint=new Indivaduls();
}
public List<Indivaduls> CrowsPoint;//簇中除中心点外的其他个体点
public Indivaduls CenterPoint;//聚类簇中心点
}
public static class ExpandList
{
/// <summary>
/// 扩展方法、判断该集合中是否存在point个体
/// </summary>
/// <param name="indivadulses"></param>
/// <param name="point"></param>
/// <returns></returns>
public static bool MyContains(this List<Indivaduls> indivadulses,Indivaduls point)
{
foreach (var indivadulse in indivadulses)
{
if (point.MyEquals(indivadulse))
return true;
}
return false;
}
}
}
C#实现K-MEDOIDS聚类算法的更多相关文章
- k均值聚类算法原理和(TensorFlow)实现
顾名思义,k均值聚类是一种对数据进行聚类的技术,即将数据分割成指定数量的几个类,揭示数据的内在性质及规律. 我们知道,在机器学习中,有三种不同的学习模式:监督学习.无监督学习和强化学习: 监督学习,也 ...
- K均值聚类算法
k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个 ...
- 机器学习实战---K均值聚类算法
一:一般K均值聚类算法实现 (一)导入数据 import numpy as np import matplotlib.pyplot as plt def loadDataSet(filename): ...
- 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)
其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...
- K均值聚类算法的MATLAB实现
1.K-均值聚类法的概述 之前在参加数学建模的过程中用到过这种聚类方法,但是当时只是简单知道了在matlab中如何调用工具箱进行聚类,并不是特别清楚它的原理.最近因为在学模式识别,又重新接触了这 ...
- 聚类之K均值聚类和EM算法
这篇博客整理K均值聚类的内容,包括: 1.K均值聚类的原理: 2.初始类中心的选择和类别数K的确定: 3.K均值聚类和EM算法.高斯混合模型的关系. 一.K均值聚类的原理 K均值聚类(K-means) ...
- FCM聚类算法介绍
FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小.模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则 ...
- 机器学习实战5:k-means聚类:二分k均值聚类+地理位置聚簇实例
k-均值聚类是非监督学习的一种,输入必须指定聚簇中心个数k.k均值是基于相似度的聚类,为没有标签的一簇实例分为一类. 一 经典的k-均值聚类 思路: 1 随机创建k个质心(k必须指定,二维的很容易确定 ...
- 转载: scikit-learn学习之K-means聚类算法与 Mini Batch K-Means算法
版权声明:<—— 本文为作者呕心沥血打造,若要转载,请注明出处@http://blog.csdn.net/gamer_gyt <—— 目录(?)[+] ================== ...
- 机器学习理论与实战(十)K均值聚类和二分K均值聚类
接下来就要说下无监督机器学习方法,所谓无监督机器学习前面也说过,就是没有标签的情况,对样本数据进行聚类分析.关联性分析等.主要包括K均值聚类(K-means clustering)和关联分析,这两大类 ...
随机推荐
- 9个让人印象深刻的网站 JS 视觉效果
网页设计已经提升到一个整体新的水平,Flash 渐渐失去了地位,逐渐被 HTML/JavaScript/CSS 所超越,而且一样可以实现出 Flash 复杂的特效. 本文介绍 8 个让人印象深刻的网站 ...
- MarkdownPad2 Pro v2.4.2.29969 专业中文破解版完美支持table表格语法
在网上搞了半天,终于搞定了支持table简写语法的markdown软件. 下载地址:http://download.csdn.net/detail/wang_jun_hua/8180717 下载包内含 ...
- CSS3-3D制作案例分析实战
一.前言 上一节,介绍了基础的CSS3 3D动画原理实现,也举了一个小小的例子来演示,但是有朋友跟我私信说想看看一些关于CSS3 3D的实例,所以在这里为了满足一下大家的需求,同时也为了以后能够更好的 ...
- 对.net技术组件的分析和选择
.net很庞杂,学习最忌讳什么?为了学而学,而不是为了用而学.我们不是为了成为教师,所以不要成为书呆子,不要成为"博士",要从庞杂的技术群中选择自己需要的内容进行学习. 如果不加选 ...
- Windows操作系统组策略应用全攻略
作者:佚名出处:IT专家网论坛2007-07-23 13:31 一.什么是组策略 (一)组策略有什么用? 说到组策略,就不得不提注册表.注册表是Windows系统中保存系统.应用软件配置的数据库,随着 ...
- C#嵌入dll到资源释放的问题
有些程序运行的时候,可能调用外部的dll,用户使用时可能会不小心丢失这些dll,导致程序无法正常运行,因此可以考虑将这些dll嵌入到资源中,启动时自动释放.对于托管的dll,我们可以用打包软件合成一个 ...
- 安裝 14.04.1 Ubuntu 到 Lenovo thinkpad t460p
在 Lenovo Thinkpad T460p 安裝 ubuntu, BIOS 需要做一些設定, 沒設定的現象:不斷地停在 usb disk 設定 可以 使用 usb disk install 了!
- 入门Webpack,看这篇就够了
来源于:http://www.jianshu.com/p/42e11515c10f 写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有 ...
- javaScript获取url中的参数
var urlTools = { //获取RUL参数值 getUrlParam: function(name) { /*?videoId=identification */ var params = ...
- noip2016十连测round1
A:String Master 题目:所谓最长公共子串,比如串 A:"abcde",串 B:"jcdkl",则它们的最长公共子串为串 "cd" ...