完成实验的过程学习下聚类分析算法
内容图片如无法查看请前往原站点访问:http://taoblog421.cn/posts/27782ca8/
参考文章:https://developer.ibm.com/zh/articles/ba-1607-clustering-algorithm/
1、分类和聚类
监督学习与非监督学习
生活例子:
高中或者初中阶段,同学们三五成群,比如看小说的几个人一伙,玩魔方的几个人一伙,上网的几个人一伙…,这个过程老师一般是不知道的,也就是没有老师进行监督,称为非监督学习,聚类算法是非监督学习的算法。
高三的时候,有些老师会采取什么学习小组政策,擅长不同学科的同学组成互帮互助学习小组,这个过程是老师监督下完成的,称为监督学习,分类算法是监督学习的算法
数据分类是根据已有的分类标准对数据划分为不同的类别,类别数和分类的标准都是已知的。而聚类则相反,需要根据数据提取属性,按照属性进行分组,每个组之间的数据是相似的,显然组内的相似性越高,组间的相异性越高,聚类的效果越好
2、K均值算法
2.1 基础知识
k均值算法为聚类算法中最基础也最重要的算法,对绝大多数数据有效,但是不能处理异型簇
- 随机的取 k 个点作为 k 个初始质心;
- 计算其他点到这个 k 个质心的距离;
- 如果某个点 p 离第 n 个质心的距离更近,则该点属于 cluster n,并对其打标签,标注 point p.label=n,其中 n<=k;
- 计算同一 cluster 中,也就是相同 label 的点向量的平均值,作为新的质心;
- 迭代至所有质心都不变化为止,即算法结束。
K值的估计
对于k的值必须提前知道,这也是kmeans算法的一个缺点,对于k值有多种估计方法,这里使用平均直径法来估计
就是首先视所有的点为一个大的整体 cluster,计算所有点之间距离的平均值作为该 cluster 的平均直径。选择初始质心的时候,先选择最远的两个点,接下来从这最两个点开始,与这最两个点距离都很远的点(远的程度为,该点到之前选择的最远的两个点的距离都大于整体 cluster 的平均直径)可视为新发现的质心,否则不视之为质心。这样就可以得到质心的数量
2.2 代码实现
测试数据 kmeans.txt
1,1
2,1
1,2
2,2
6,1
6,2
7,1
7,2
1,5
1,6
2,5
2,6
6,5
6,6
7,5
7,6
代码实现(java):
文本读取工具类:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 读取.txt文件工具类
* @author: zyb
* @date: 2020/10/13 15:47
*/
public class FileRead {
public static void main(String[] args) {
String filePath = "文件所在路径/文件名";
List<String> list = FileRead.read(filePath);
for (String s : list) {
System.out.println(s);
}
}
public static List<String> read(String filePath){
FileInputStream inputStream = null;
BufferedReader bufferedReader = null;
List<String> data = new ArrayList<String>();
try {
inputStream = new FileInputStream(filePath);
//设置inputStreamReader的构造方法并创建对象设置编码方式为gbk(编码格式可自行切换)
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"gbk"));
String str = null;
while((str = bufferedReader.readLine()) != null)
{
data.add(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return data;
}
}
Kmeans.java:
import java.util.*;
/**
* @Author liaotao
* @Date 2020/12/29 16:28
* 实现kmeans算法
*/
public class Kmeans {
// 节点列表
private static List<Node> nodeList;
// 质心
private static Map<Integer,Node> centroid;
public static void main(String[] args) {
nodeList = getNodeListByPath("g:/kmeans.txt");
centroid = computeK(nodeList);
doIteration();
printResult();
}
/**
* 输出聚类结果
*/
public static void printResult() {
for (Node node : nodeList) {
System.out.println(Arrays.toString(node.getAttributes()) + "belongs to cluster " <