回想專案中遇到的,多商家資訊融合的場景。我們如何把多商家的資訊進行合理的匹配呢?首先想到的是人工匹配和程式匹配相結合。這樣也可以實現,但費心費力,且實際匹配效果很差,如果商家融合資訊呈指數級增長,這樣的方式就太low了。
那如何把這個流程做的智慧型化些呢?我們可以引入機器學習中的聚類,它可以將商家相關屬性進行聚集,並分類。
簇: 所有資料點點集合,簇中物件相似。
質心: 簇中所有點的中心(計算所有點的均值).
採用歐式距離,兩點間直線距離.也可採用其他距離計算(後期會做相應的介紹)
sse 值越小,表示越接近它們的質心.由於代價函式(sse)是非凸函式,所以在運用kmeans演算法時,不能保證收斂到乙個全域性的最優解,我們得到的一般是乙個區域性的最優解。
為了取得比較好的效果,用不同的初始質心執行,得到多個區域性最優解,比較它們的sse,選取sse最小的那個。
#載入資料
def loaddataset(filename):
datamat =
fr = open(filename)
for line in fr.readlines():
curline = line.strip().split('\t')
ftlline = map(float,curline) #資料初始化float型別
return datamat
#歐式距離
def disteclud(veca, vecb):
return sqrt(sum(power(veca -vecb,2)))
# power 樣本點平方((x1-x2)^2+(y1-y2)^2)
# sqrt 求和後開方
#構建k個隨機質心
def randcent(dataset, k):
n = shape(dataset)[1] #獲得列數
centroids = mat(zeros((k,n))) #k行n列的零階矩陣
for j in range(n):
minj = min(dataset[:,j])
rangej = float(max(dataset[:,j]) - minj)
centroids[:,j] = minj + rangej * random.rand(k,1)
return centroids
(1)k-均值
#kmeans
def kmeans(dataset, k, distmeas=disteclud, createcent=randcent):
m = shape(dataset)[0] #樣本數
clusterassment = mat(zeros((m,2))) #獲得m*2矩陣(一列簇分類結果,一列誤差)
centroids = createcent(dataset,k) #初始化k個質心
clusterchanged = true #簇更改標記
while clusterchanged:
clusterchanged = false
#樣本點加入到最近的簇
for i in range(m):
mindist = 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[i,:] = minindex,mindist**2
#每輪結束後調整簇心
for cent in range(k):
if clusterassment[i, 0] != minindex: clusterchanged = true
clusterassment[i, :] = minindex, mindist ** 2 #計算每列平均值
return centroids, clusterassment
(2)二分k-均值
# k:簇個數 distmeas:距離生成器
def bikmeans(dataset, k, distmeas=disteclud):
m = shape(dataset)[0] #資料集矩陣的行數
clusterassment = mat(zeros((m,2)))
centroid0 = mean(dataset, axis=0).tolist()[0] # 建立乙個初始簇
centlist =[centroid0] #create a list with one centroid
for j in range(m): # 計算每個樣本點到初始簇的距離
clusterassment[j,1] = distmeas(mat(centroid0), dataset[j,:])**2
while (len(centlist) < k): # 迭代直到簇的數目等於k
lowestsse = inf
for i in range(len(centlist)):
# 嘗試劃分每一簇
ptsincurrcluster = dataset[nonzero(clusterassment[:,0].a==i)[0],:]
centroidmat, splitclustass = kmeans(ptsincurrcluster, 2, distmeas)
ssesplit = sum(splitclustass[:,1])
# 剩餘資料集的誤差
ssenotsplit = sum(clusterassment[nonzero(clusterassment[:,0].a!=i)[0],1])
# 記錄總誤差最小的那個簇
if (ssesplit + ssenotsplit) < lowestsse:
bestcenttosplit = i
bestnewcents = centroidmat
bestclustass = splitclustass.copy()
lowestsse = ssesplit + ssenotsplit
# 因為二分均值,所以結果簇編號只能是0或1,修改結果簇編號為:原簇號和新增簇號
bestclustass[nonzero(bestclustass[:,0].a == 1)[0],0] = len(centlist)
bestclustass[nonzero(bestclustass[:,0].a == 0)[0],0] = bestcenttosplit
# 更新簇列表centlist和樣本點分配簇結果矩陣clusterassment
centlist[bestcenttosplit] = bestnewcents[0,:].tolist()[0]
clusterassment[nonzero(clusterassment[:,0].a == bestcenttosplit)[0],:]= bestclustass
return mat(centlist), clusterassment;
if __name__=="__main__":
datamat = loaddataset('testset.txt')
randcent(mat(datamat), 3)
#kmeans(mat(datamat),3,disteclud,randcent)
#bikmeans(mat(datamat),3,disteclud)
優點: 容易實現
缺點:可能收斂到區域性最小值, 在大規模資料集上收斂較慢,高維空間有侷限
(1)分析資料
(2)基於變化的演算法:即定義乙個函式,隨著k的改變,認為在正確的k時會產生極值。
(3)基於結構的演算法:即比較類內距離、類間距離以確定k。
(4) 基於一致性矩陣的演算法:即認為在正確的k時,不同次聚類的結果會更加相似
(5)基於層次聚類:即基於合併或**的思想,在一定情況下停止從而獲得k
(6)基於取樣的演算法:即對樣本取樣,分別做聚類;根據這些結果的相似性確定k。
(7)使用canopy method演算法進行初始劃分
(8)使用bic演算法進行初始劃分
目前了解的還比較淺顯,後期將不斷地優化。
聚類演算法 KMeans 機器學習實戰
直接上 coding utf8 time 2018 4 12 下午05 33 author yjfiejd file k means 3.py from numpy import import time import matplotlib.pyplot as plt 1 先定義3個函式,第乙個函式為...
機器學習實戰 層次聚類演算法
層次聚類試圖在不同層次對資料集進行劃分,從而形成樹形的聚類結構。資料集的劃分可採用 自底向上 的聚合策略,也可採用 自頂向下 的分拆策略。層次聚類可以分為凝聚層次聚類和 層次聚類。層次聚類採用的就是 自頂而下 的思想,先將所有的樣本都看作是同乙個簇,然後通過迭代將簇劃分為更小的簇,直到每個簇中只有乙...
機器學習實戰之K Means聚類
俗話說的好 物以類聚,人以群分 今天我們要講的聚類演算法很大程度上可以印證此話。聚類是一種非監督學習,什麼是非監督學習?與之前學習的分類和回歸不同 監督學習 監督學習是有有label標籤的,而非監督學習沒有。我們再回到聚類上,聚類是把相似的物件歸到同一簇中,有點像全自動分類。聚類的應用場景有很多,例...