import numpy as np
def loadDataSet(fileName):
dataMat = []
fr = open(fileName)
for line in fr.readlines():
curLine = line.strip().split('\t')
fltLine = map(float,curLine)
dataMat.append(fltLine)
return dataMat
def distEclud(vecA,vecB):
return np.sqrt(np.sum(np.power(vecA-vecB,2)))
def randCent(dataSet,k):
n = np.shape(dataSet)[1]
'''
centroids是一个3*2的矩阵,用于存储三个中心点的坐标
'''
centroids = np.mat(np.zeros((k,n)))
for j in range(n):
#统计每一列的最小值
minJ = min(dataSet[:,j])
#每列最大值与最小值的差值
rangeJ = float(max(dataSet[:,j]) - minJ)
#random.rand(k,1) 产生k*1的数组,里面的数据是0~1的浮点型。
array2 = minJ + rangeJ * np.random.rand(k,1)
#转换成k*1矩阵 赋值给centroids
centroids[:,j] = np.mat(array2)
return centroids
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
m = np.shape(dataSet)[0]
y.mat 将二维数组转换成矩阵
clusterAssment = np.mat(np.zeros((m,2)))
createCent找到K个随机中心点坐标
centroids = createCent(dataSet, k)
# print centroids
clusterChanged = True
while clusterChanged:
clusterChanged = False
#遍历80个数据到每个中心点的距离
for i in range(m):
#np.inf float的最大值,无穷大
minDist = np.inf
#当前点属于的类别号
minIndex = -1
#每个样本点到三个中心点的距离
for j in range(k):
返回两点距离的值
distJI = distMeas(centroids[j,:],dataSet[i,:])
if distJI < minDist:
#当前最小距离的值
minDist = distJI
#当前最小值属于哪个聚类
minIndex = j
#有与上次迭代计算的当前点的类别不相同的点
if clusterAssment[i,0] != minIndex:
clusterChanged = True
#将当前点的类别号和最小距离 赋值给clusterAssment的一行
clusterAssment[i,:] = minIndex,minDist
for cent in range(k):
ent[:,0].A==censInClust 取出的是对应是当前遍历cent类别的 所有行数据组成的一个矩阵
ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A==cent)[0]]心点坐标的位置
centroids[cent,:] = np.mean(ptsInClust, axis=0)
#返回 【 当前三个中心点的坐标】 【每个点的类别号,和到当前中心点的最小距离】
return centroids, clusterAssment
if __name__ == '__main__': 80*2的矩阵
dataMat = np.mat(loadDataSet('./testSet.txt'))
k=3
centroids, clusterAssment =
kMeans(dataMat, k, distMeas=distEclud, createCent=randCent)
print centroids
print clusterAssment
对于分类结果,可以抽样数据使用matplotlib检验数据的分布情况。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
#建立12*12新的图像
plt.figure(figsize=(12, 12))
n_samples = 1500
random_state = 170
'''
make_blobs函数是为聚类产生数据集 , 产生一个数据集和相应的标签
n_samples:表示数据样本点个数,默认值100
n_features:表示数据的维度,特征,默认值是2
centers:产生数据的中心点,默认值3个
shuffle :洗乱,默认值是True
random_state:官网解释是随机生成器的种子
'''
#x返回的是向量化的数据点,y返回的是对应数据的类别号
x,y = make_blobs(n_samples=n_samples, random_state=random_state)
#使用KMeans去聚类,返回聚好的类别集合,聚合成几类
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(x)
#subplot 绘制多个子图,221 等价于2,2,1 表示两行两列的子图中的第一个
plt.subplot(221)
#scatter 绘制散点图
plt.scatter(x[:, 0], x[:, 1], c=y_pred)
plt.title("kmeans01")
transformation = [[ 0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
#numpy.dot 矩阵相乘
X_aniso = np.dot(x, transformation)
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso)
plt.subplot(222)
plt.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
plt.title("kmeans02")
#vstack 是合并矩阵,将y=0类别的取出500行,y=1类别的取出100行,y=2类别的取出10行
X_filtered = np.vstack((x[y == 0][:500], x[y == 1][:100], x[y == 2][:10]))
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_filtered)
plt.subplot(223)
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("kmeans03")
dataMat = []
fr = open("testSet.txt","r")
for line in fr.readlines():
if line.strip() <> "":
curLine = line.strip().split('\t')
fltLine = map(float,curLine)
dataMat.append(fltLine)
dataMat = np.array(dataMat)
y_pred = KMeans(n_clusters=4, random_state=random_state).fit_predict(dataMat)
plt.subplot(224)
plt.scatter(dataMat[:,0], dataMat[:, 1], c=y_pred)
plt.title("kmeans04")
plt.savefig("./kmeans.png")
plt.show()
object KMeans {
def main(args: Array[String]) {
//1 构建Spark对象
val conf = new SparkConf().setAppName("KMeans").setMaster("local")
val sc = new SparkContext(conf)
// 读取样本数据1,格式为LIBSVM format
val data = sc.textFile("kmeans_data.txt")
val parsedData = data.map(s => Vectors.dense(s.split(' ')
.map(_.toDouble))).cache()
val numClusters = 4
val numIterations = 100
val model = new KMeans().
//设置聚类的类数
setK(numClusters).
//设置找中心点最大的迭代次数
setMaxIterations(numIterations).
run(parsedData)
//四个中心点的坐标
val centers = model.clusterCenters
val k = model.k
centers.foreach(println)
println(k)
//保存模型
// model.save(sc, "./Kmeans_model")
//加载模型
val sameModel = KMeansModel.load(sc, "./Kmeans_model")
println(sameModel.predict(Vectors.dense(1,1,1)))
val sqlContext = new SQLContext(sc)
sqlContext.read.parquet("./Kmeans_model/data").show()
}
}
给Kmeans指定中心点坐标:
object KMeans2 {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("KMeans2").setMaster("local")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(List(
Vectors.dense(Array(-0.1, 0.0, 0.0)),
Vectors.dense(Array(9.0, 9.0, 9.0)),
Vectors.dense(Array(3.0, 2.0, 1.0))))
//指定文件 kmeans_data.txt 中的六个点为中心点坐标。
val centroids: Array[Vector] = sc.textFile("kmeans_data.txt")
.map(_.split(" ").map(_.toDouble))
.map(Vectors.dense(_))
.collect()
val model = new KMeansModel(clusterCenters=centroids)
println("聚类个数 = "+model.k)
//模型中心点
model.clusterCenters.foreach { println }
//预测指定的三条数据
val result = model.predict(rdd)
result.collect().foreach(println(_))
}
}