在有黑人,白人,黄种人的种群中,分类器开始对他们分类,可能根据他们的皮肤颜色,鼻子高低,头发颜色等一些属性来对他们聚类,分类器训练完成,但不知道他们是不是叫黑人,白人,黄种人,只知道有这么三个簇,当让分类器再次区分一个人他是那一类,分类器会根据这个人的特征跟哪一个簇中的人的特征相似而把这个人分到那个簇中,但是并不会明白这个人叫什么人种。
java代码:全部代码:linkhttps://gitee.com/NicoleSqualo/csdn-case-code.git
package kmeans;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
//import weka.core.Instances;
import weka.core.Instances;
public class kmeans_demo {
public static final int MANHATTAN = 0;
public static final int EUCLIDEAN = 1;
public int distanceMeasure = EUCLIDEAN;
public static final Random random = new Random();
public static Instances dataset;
int numClusters = 2;
static int[][] clusters;
//初始化数据
public kmeans_demo(String paraFilename) {
dataset=null;
try {
//文件阅读器中放入文件
FileReader fileReader=new FileReader(paraFilename);
try {
//文件中的数据放入dataset变量中
dataset=new Instances(fileReader);
fileReader.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
///没有这个文件
System.out.println("Cannot read the file: " + paraFilename + "rn" + e);
System.exit(0);
e.printStackTrace();
}
}
public void setNumClusters(int paraNumClusters) {
numClusters=paraNumClusters;
}
public static int[] getRandomIndices(int paraLength) {
//打乱后数组的下标数组 的 指向相应的数组的下标
int []resultIndices=new int[paraLength];
//1.初始化resultIndices
for(int i=0;i tempDistance) {
tempNearestDistance = tempDistance;
tempNearestCenter = j;
}
}
//把该对象化为tempNearestCenter簇
tempClusterArray[i] = tempNearestCenter;
}
//Step 2.2 Mean. Find new centers.找簇
//tempClusterLengths是大小为簇长度的数组
int[] tempClusterLengths = new int[numClusters];
//tempClusterLengths初始化全为0
Arrays.fill(tempClusterLengths, 0);
//新的簇的中心,第一维指哪个簇,第二维指哪个属性
double[][] tempNewCenters = new double[numClusters][dataset.numAttributes() - 1];
for (int i = 0; i < dataset.numInstances(); i++) {//所有点
for (int j = 0; j < tempNewCenters[0].length; j++) {//属性数目
//求各个簇的新的簇中心,要将各个簇所有对象的属性的平均值,这一步是对各个属性求和过程
tempNewCenters[tempClusterArray[i]][j] += dataset.instance(i).value(j);
} // Of for j
//分在该簇中的数据量加1
tempClusterLengths[tempClusterArray[i]]++;
} // Of for i
// Step 2.3 Now average现在求平均值
for (int i = 0; i < tempNewCenters.length; i++) {//簇中心数
for (int j = 0; j < tempNewCenters[0].length; j++) {//簇中心的属性
//求簇中心属性j的平均值,更新簇中心
tempNewCenters[i][j] /= tempClusterLengths[i];
} // Of for j
} // Of for i
//更新簇中心
tempCenters = tempNewCenters;
System.out.println("新的簇中心的属性为:n");
for (int i = 0; i < tempNewCenters.length; i++) {//簇中心数
for (int j = 0; j < tempNewCenters[0].length; j++) {//簇中心的属性
System.out.print(tempNewCenters[i][j]+"t");
} // Of for j
System.out.println("n");
} // Of for i
// Step 3. Form clusters.构建簇
//簇,第一维指哪个簇,第二维指簇中对象下标
clusters = new int[numClusters][];
//计数器,记录每个每个簇中分的对象
int[] tempCounters = new int[numClusters];
//给簇clusters分配空间,clusters的一维是表示哪个簇, 二维是表示那个簇中对象下标
for (int i = 0; i < numClusters; i++) {
clusters[i] = new int[tempClusterLengths[i]];
} // Of for i
//
for (int i = 0; i < tempClusterArray.length; i++) {//簇的数目
// clusters中的元素指向dataset原始数据的下标为i的元素
clusters[tempClusterArray[i]][tempCounters[tempClusterArray[i]]] = i;
// 该簇中的元素+1
tempCounters[tempClusterArray[i]]++;
} // Of for i
}
}
public static void testClustering() {
//读取数据
kmeans_demo tempKMeans=new kmeans_demo("D:\eclipse\java项目文件\csdn_days\src\kmeans\iris.arff");
//设置要分为3个簇
tempKMeans.setNumClusters(3);
//开始根据距离,把所有数据分为3个簇
tempKMeans.clustering();
// for(int i=0;i
最后的簇中心为:
簇中心的属性为:
6.87027027027027 3.0864864864864856 5.745945945945945 2.089189189189189
5.005999999999999 3.4180000000000006 1.464 0.2439999999999999
5.904761904761906 2.7460317460317465 4.412698412698414 1.4333333333333336
python代码,可视化结果
全部代码:linkhttps://gitee.com/NicoleSqualo/csdn-case-code.git
import matplotlib as plt
import pandas as pd
import random
import numpy as np
from pandocfilters import Math
from matplotlib import pyplot as plt
class KMeans():
def __init__(self,FileName):
'''
获取聚类数据
:param FileName: 文件名
'''
# 用pandas读表
self.dataset=pd.read_csv(FileName,header=0,sep=",",encoding="utf-8")
print(self.dataset)
# print(self.dataset.loc[0][0:len(self.dataset.columns)-1])
# print(self.dataset.loc[0][0])
#设置聚类的时候用的距离公式
self.MANHATTAN = 0#曼哈顿距离公式
self.EUCLIDEAN = 1;#欧式距离公式
self.distanceMeasure = self.EUCLIDEAN#默认是欧式距离公式
#初始化最小距离
self.minDistance=1000
def initCluster(self,num):
'''
初始化分类的簇
:param num: 设置要分成的簇数
:return:
'''
self.clusterNum=num
def ClusterCenter(self):
'''
随机生成要进行分类的簇中心
:return:
'''
# 簇中心,储存dataset中的的下标
self.clusterCenterIndexArray=[]
# dataset数据的长度
datasetLen = len(self.dataset)
random.seed(1)
# 当簇中心没有达到要求的簇中心数目的时候继续循环,保证有clusterNum个不同的簇中心
while len(self.clusterCenterIndexArray)
得到的簇中心为:
#得到的簇中心为
[[4.8825 3.125 1.68 0.325 ]
[6.32105263 2.89894737 4.98947368 1.71052632]
[5.38 3.84666667 1.50666667 0.28666667]]
对于‘sepalwidth’单个属性的投影,对比图如下:
在‘sepalwidth’这个属性的范围中,目标分为三类簇,sepalwidth在一定范围分别为一个簇。
这里需要注意的是:对于target图和predict图中,每个图分得的三个簇不知道标签值,就是他们对应的y轴上的值并不代表他们都是标签为簇0,而是代表他们各个分的一块区域,terget图和predict图可能分得的根据的标签是不同,这体现了kmeans只能区分出不同的类,但是并不说明这一类的具体标签,所以target和predict不能以标签是否对的上而判断它分类结果的好坏,应该看看哪些对象划分到一起判断聚类结果。



