過去幾天我一直在嘗試撰寫自己的 k 均值演算法,但遇到了障礙。當我試圖找到集群中點的平均位置來移動質心時,我得到一個零分割錯誤(注意:這不會在 k = 2 時發生,只有在 k = 3 時才會發生,但總是當 k >= 4 時發生)。我試圖通過確保每個質心從資料集中的一個點開始來解決這個問題,這樣它的集群中總是至少有一個點,但它沒有作業。我還重新排列了計數器等,但同樣,它不起作用。我已經沒有想法了,不知道為什么這個錯誤仍然發生。我很確定問題來自這些函式之一(編輯:添加了所有代碼和完整的錯誤訊息):
import random
import math
import matplotlib.pyplot as plt
class Kmeans:
def __init__(self, K, dataset, centroids, sorting):
self.K = K
self.dataset = dataset
self.centroids = centroids
self.sorting = sorting
def initializeCentroids(self):
usedPoints = [random.choice(data_set)]
self.centroids = []
for q in range(self.K):
pointSelected = False
while not pointSelected:
m = random.choice(data_set)
print(m)
print(usedPoints)
distance = math.sqrt(abs(((m[0] - usedPoints[len(usedPoints) - 1][0]) ** 2) (m[1] - usedPoints[len(usedPoints) - 1][1]) ** 2))
if usedPoints.count(m) == 0 and distance > 50:
self.centroids.append(list(m))
usedPoints.append(m)
pointSelected = True
return self.centroids
def calcDistance(self):
self.sorting = []
for w in self.dataset:
distances = []
counter = -1
for centr in self.centroids:
counter = 1
distances.append(math.sqrt(abs((((w[0] - centr[0]) ** 2) (w[1] - centr[1]) ** 2))))
for x in range(len(distances)):
if len(distances) > 1:
print(distances)
if distances[0] > distances[1]:
distances.pop(0)
else:
distances.pop(1)
counter -= 1
print(counter)
self.sorting.insert(0, [w, counter, distances[0]])
return self.sorting
# not done
def find_ME(self):
counter2 = 0
for r in self.centroids:
for t in self.sorting:
nums = []
if t[1] == counter2:
nums.append(t[2])
population = len(nums)
error = sum(nums) / population
def reassignCentroids(self):
counter3 = 0
for r in self.centroids:
positionsX = []
positionsY = []
for t in self.sorting:
if t[1] == counter3:
positionsX.append(t[0][0])
positionsY.append(t[0][1])
population = len(positionsY)
print(population)
print(self.sorting)
r[0] = sum(positionsX) / population
r[1] = sum(positionsY) / population
counter3 = 1
return self.centroids
def checkSimilar(self, prevList):
list1 = []
list2 = []
for u in prevList:
list1.append(u[1])
for i in self.sorting:
list2.append(i[1])
print(i)
if list2 == list1:
return True
else:
return False
k = 3
data_set = [(1, 1), (1, 2), (1, 3), (2, 3), (50, 52), (48, 50), (47, 60), (112, 90), (120, 100), (108, 130), (102, 121), (43, 51), (0, 1)]
attempt = Kmeans(k, data_set, [], [])
attempt.initializeCentroids()
xvals = []
yvals = []
sortCompare = []
maxIterations = 100000
# plots
for p in data_set:
xvals.append(p[0])
yvals.append(p[1])
running = True
zeroError = True
while running:
attempt.calcDistance()
sortCompare = attempt.sorting
print(sortCompare, "thisss")
attempt.reassignCentroids()
attempt.calcDistance()
attempt.reassignCentroids()
boolVal = attempt.checkSimilar(sortCompare)
if boolVal or maxIterations <= 0:
xs = []
ys = []
for y in attempt.centroids:
xs.append(y[0])
ys.append(y[1])
plt.scatter(xs, ys)
running = False
else:
sortCompare = []
maxIterations -= 1
print(attempt.sorting)
print(attempt.centroids)
plt.scatter(xvals, yvals)
plt.show()
完整錯誤:回溯(最近一次通話):檔案“C:/Users/Jack Cramer/PycharmProjects/kmeans/main.py”,第 117 行,在嘗試.reassignCentroids() 檔案“C:/Users/Jack Cramer/PycharmProjects /kmeans/main.py", line 73, in reassignCentroids r[0] = sum(positionsX)/population ZeroDivisionError: 除以零
如果您知道為什么會這樣,請告訴我,謝謝您的建議。
uj5u.com熱心網友回復:
正如@thierry-lathuille 指出的那樣,錯誤發生在reassignCentroids除以population零時。 population設定為 的長度positionsY,因此我們需要查看哪些場景導致positionsY沒有元素。
positionsY將其值附加在值的回圈內t in self.sorting。僅當counter3(范圍從 0 到 K-1)匹配時才會附加值t[1]。所以如果有一個值,counter3其中沒有一個t[1]值是相等的,我們就會得到錯誤。為了幫助除錯,我在回圈中添加了一些列印陳述句
print(f"{counter3=}")
for t in self.sorting:
print(f"{t[1]=}")
if t[1] == counter3:
positionsX.append(t[0][0])
positionsY.append(t[0][1])
用 運行幾次k=2,我看到它t[1]是 0 或 1,這不會崩潰,如您所見。但是,上升到k=3,有時我會t[1]等于 0、1 或 2,但有時它僅等于 0 或 1。這意味著將沒有匹配項,您將除以零。上升到k=4,我們應該t[1]等于 0、1、2 或 3,但是在多次重新啟動后我沒有看到任何 3。
從背景關系來看,我猜它t[1]代表給定資料點最接近的集群。根據您的輸入,肉眼看來有三個點簇
因此您的代碼自然有三個預測的簇趨向于它們應該在的位置,因此如果您嘗試預測 4 個簇,您將始終崩潰。如果您只嘗試預測 3 個集群,您可能會走運,并且您預測的集群之一不是最接近任何點的。即使k=2在某些初始化中出錯,我也不會感到驚訝,但在實踐中肯定很少見。
我認為您需要先問問自己,當k高于實際集群數量時,您想看到什么行為。其次,您需要確定在沒有任何資料點最接近集群時如何更新集群的位置。一個快速的解決方法是什么都不做 if population == 0,盡管這可能不會給出你想要的行為。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/399330.html
