聚类算法基于无监督学习,集不需要任何训练数据,聚类算法针对一个没有标注的实例集合,对所有实例分组。这里介绍两类算法,一个是层次聚类,一个是K均值聚类,主要差别在目标函数不同。
层次聚类分为两种:一种以分层的方式建立分组,另一种以聚合聚类。当迭代收敛时停止运算。层次聚类之间主要是代价函数不同cost(Ci,Cj),计算出所有的簇对代价后,选出合并代价最低的两个簇。
代价函数:单连同方法,cost(Ci,Cj)=min{dist(Xi,Xj)|Xi属于Ci,Xj属于Cj},通常利用欧几里德距离公式
全连通方法:cost(Ci,Cj)=max{dist(Xi,Xj)}
平均连通方法:cost(Ci,Cj)=所有实力代价对的平均值
平均组连通:通过衡量一个簇的质心间距离公式cost(Ci,Cj)=dist(pi,pj),了解质心计算公式;所有点求平均。
华德法:基于方差的统计性质,一个数字集的的方差衡量数字的分散程度,该方法尝试对下滑方差的中和,所有的成员都最小的分散在簇的质心周围。代价函数:如果将簇i和簇j合并起来的簇内方差。
另一类:
K均值函数:参见本博客中的K均值算法
K平均算法实例(Java):根据足球联赛表现排名成绩,输出每个国家水平
---------------------------------------------------
15
zhongguo 50 50 9
riben 28 9 4
hanguo 17 15 3
yilang 25 40 5
shate 28 40 2
yilake 50 50 1
kataer 50 40 9
aliandian 50 40 9
wuzhibiekeshitan 40 40 5
taiguo 50 50 9
yuenan 50 50 5
aman 50 50 9
balin 40 40 9
chaoxian 40 32 17
yinni 50 50 9
--------------------------------------------
第一行代表国家数量,其余每行表示国家名和三年的排名成绩,选择K=3,并且国家中第一梯队为:日本,第二梯队:巴林;第三梯队:泰国
代码如下:
///第一部分实体类
public class DataObject {
double m1;
double m2;
double m3;
public DataObject(double m1,double m2,double m3) {
// TODO Auto-generated constructor stub
this.m1=m1;
this.m2=m2;
this.m3=m3;
}
}
//第二部分核心主类
public class KmeansData {
private static double costFunction(List<Integer> list, DataObject[] data,
int i) {
double sum1, sum2, sum3;
// dist代价函数公式:(Xi-Pj)*(Xi-Pj)--与向量内积平方成正比
// 类别一质心
sum1 = sum2 = sum3 = 0;
for (Integer integer : list) {
sum1 += data[integer].m1;
sum2 += data[integer].m2;
sum3 += data[integer].m3;
}
sum1 /= list.size();
sum2 /= list.size();
sum3 /= list.size();
double dist1 = Math.pow((data[i].m1 - sum1), 2)
+ Math.pow((data[i].m2 - sum2), 2)
+ Math.pow((data[i].m3 - sum3), 2);
return dist1;
}
public static void main(String[] args) {
DataObject[] data;
int m1, m2, m3;
int class1 = 1;
int class2 = 12;
int class3 = 9;
// 不能创建列表数组
List<Integer> list1 = new ArrayList<Integer>();
list1.add(class1);
List<Integer> list2 = new ArrayList<Integer>();
list2.add(class2);
List<Integer> list3 = new ArrayList<Integer>();
list3.add(class3);
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int numb = scanner.nextInt();
data = new DataObject[numb];
// 国家名
String[] countryName = new String[numb];
for (int i = 0; i < numb; i++) {
countryName[i] = scanner.next();
m1 = scanner.nextInt();
m2 = scanner.nextInt();
m3 = scanner.nextInt();
data[i] = new DataObject(m1 / 50.0, m2 / 50.0, m3 / 50.0);
}
for (int i = 0; i < data.length; i++) {
double dist1 = costFunction(list1, data, i);
double dist2 = costFunction(list2, data, i);
double dist3 = costFunction(list3, data, i);
double min = Math.min(dist1, dist2);
min = Math.min(min, dist3);
if (min == dist1) {
if (list1.size() == 1 && list1.get(0) == i)
continue;
list1.add(i);
} else if (min == dist2) {
if (list2.size() == 1 && list2.get(0) == i)
continue;
list2.add(i);
} else {
if (list3.size() == 1 && list3.get(0) == i)
continue;
list3.add(i);
}
}
System.out.println("亚洲一流水平国家:");
for (Integer integer : list1) {
System.out.print(countryName[integer]+" , ");
}
System.out.println("
亚洲二流水平国家");
for (Integer integer : list2) {
System.out.print(countryName[integer]+" , ");
}
System.out.println("
亚洲三流水平国家");
for (Integer integer : list3) {
System.out.print(countryName[integer]+" , ");
}
}
}
}
输出结果:
亚洲一流水平国家:
riben , hanguo ,
亚洲二流水平国家
balin , yilang , shate , wuzhibiekeshitan , balin , chaoxian ,
亚洲三流水平国家
taiguo , zhongguo , yilake , kataer , aliandian , taiguo , yuenan , aman , yinni ,