將地圖上的點進行聚類,安排交通工具抵達這些簇的質心,然後步行到每個簇內地址。
這裏我們直接用給出的文件進行操作,跳過10.4.1節。
添加代碼:
def distSLC(vecA, vecB): # 返回地球表面兩點之間的距離
a = sin(vecA[0,1] * pi / 180) * sin(vecB[0,1] * pi / 180)
b = cos(vecA[0,1] * pi / 180) * cos(vecB[0,1] * pi / 180) * \
cos(pi * (vecB[0,0] - vecA[0,0]) / 180)
return arccos(a + b) * 6371.0
import matplotlib
import matplotlib.pyplot as plt
def clusterClubs(numClust = 5): # 畫圖,參數爲希望得到的簇數目
datList = []
for line in open('places.txt').readlines():
lineArr = line.split('\t')
datList.append([float(lineArr[4]), float(lineArr[3])])
datMat = mat(datList)
myCentroids, clustAssing = biKmeans(datMat, numClust, \
distMeas = distSLC)
fig = plt.figure()
rect = [0.1, 0.1, 0.8, 0.8]
scatterMarkers = ['s', 'o', '^', '8', 'p', \
'd', 'v', 'h', '>', '<']
axprops = dict(xticks = [], yticks = [])
ax0 = fig.add_axes(rect, label = 'ax0', **axprops)
imgP = plt.imread('Portland.png') # imread 基於圖像創建矩陣
ax0.imshow(imgP)
ax1 = fig.add_axes(rect, label = 'ax1', frameon = False)
for i in range(numClust):
ptsInCurrCluster = datMat[nonzero(clustAssing[:,0].A == i)[0],:]
markerStyle = scatterMarkers[i % len(scatterMarkers)] # 使用索引來選擇標記形狀
ax1.scatter(ptsInCurrCluster[:,0].flatten().A[0],\
ptsInCurrCluster[:,1].flatten().A[0],\
marker = markerStyle, s = 90)
ax1.scatter(myCentroids[:,0].flatten().A[0],\
myCentroids[:,1].flatten().A[0], marker = '+', s = 300)
plt.show()
運行代碼:
import kMeans
from numpy import *
kMeans.clusterClubs(5)
得到結果:
==================================================================================
通過修改簇的數目,得到程序運行的效果。
比如4簇:
3簇:
================================================================================================
10.5 小結
聚類是一種無監督的學習方法。所謂無監督學習是指事先並不知道要尋找的內容,即沒有目標變量。聚類將數據點歸到多個簇中,其中相似數據點處於同一簇,而不相似數據點處於不同簇中。聚類中可以使用多種不同的方法計算相似度。
K-均值聚類算法以 k 個隨機質心開始。算法會計算每個點到質心的距離。每個點會被分配到距其最近的簇質心。然後緊接着基於新分配到簇的點更新簇質心。以上過程重複數次,直到質心不再改變。
爲了得到更好地聚類效果,可以使用另一種稱爲二分 k-均值 的聚類算法。該方法首先將所有點作爲一個簇,然後使用 k-均值 算法對其劃分,下一次迭代時,選擇有最大誤差的簇進行劃分。這個過程重複直到 k 個簇創建爲止。