我有这个火花程序,我会尝试将其限制在相关部分
# Split by delimiter ,
# If the file is in unicode, we need to convert each value to a float in order to be able to
# treat it as a number
points = sc.textFile(filename).map(lambda line: [float(x) for x in line.split(",")]).persist()
# start with K randomly selected points from the dataset
# A centroid cannot be an actual data point or else the distance measure between a point and
# that centroid will be zero. This leads to an undefined membership value into that centroid.
centroids = points.takeSample(False, K, 34)
#print centroids
# Initialize our new centroids
newCentroids = [[] for k in range(K)]
tempCentroids = []
for centroid in centroids:
tempCentroids.append([centroid[N] + 0.5])
#centroids = sc.broadcast(tempCentroids)
convergence = False
ncm = NCM()
while(not convergence):
memberships = points.map(lambda p : (p, getMemberships([p[N]], centroids.value, m)))
cmax = memberships.map(lambda (p, mus) : (p, getCMax(mus, centroids.value)))
# Memberships
T = cmax.map(lambda (p, c) : (p, getMemberships2([p[N]], centroids.value, m, delta, weight1, weight2, weight3, c)))
I = cmax.map(lambda (p, c) : (p, getIndeterminateMemberships([p[N]], centroids.value, m, delta, weight1, weight2, weight3, c)[0]))
F = cmax.map(lambda (p, c) : (p, getFalseMemberships([p[N]], centroids.value, m, delta, weight1, weight2, weight3, c)[0]))
# Components of new centroids
wTm = T.map(lambda (x, t) : ('onekey', scalarPow(m, scalarMult(weight1, t))))
#print "wTm = " + str(wTm.collect())
print "at first reduce"
sumwTm = wTm.reduceByKey(lambda p1, p2 : addPoints(p1, p2))
#print "sumwTm = " + str(sumwTm.collect())
wTmx = T.map(lambda (x, t) : pointMult([x[N]], scalarPow(m, scalarMult(weight1, t))))
print "adding to cnumerator list"
#print wTmx.collect()
cnumerator = wTmx.flatMap(lambda p: getListComponents(p)).reduceByKey(lambda p1, p2 : p1 + p2).values()
print "collected cnumerator, now printing"
#print "cnumerator = " + str(cnumerator.collect())
#print str(sumwTm.collect())
# Calculate the new centroids
sumwTmCollection = sumwTm.collect()[0][1]
cnumeratorCollection = cnumerator.collect()
#print "sumwTmCollection = " + str(sumwTmCollection)
#cnumeratorCollection =cnumerator.collectAsMap().get(0).items
print "cnumeratorCollection = " + str(cnumeratorCollection)
for i in range(len(newCentroids)):
newCentroids[i] = scalarMult(1 / sumwTmCollection[i], [cnumeratorCollection[i]])
centroids = newCentroids
# Test for convergence
convergence = ncm.test([centroids[N]], [newCentroids[N]], epsilon)
#convergence = True
# Replace our old centroids with the newly found centroids and repeat if convergence not met
# Clear out space for a new set of centroids
newCentroids = [[] for k in range(K)]
此程序在我的本地计算机上运行良好,但是,在独立群集上运行时,它的行为不符合预期。它不一定会抛出错误,但它所做的事情会产生与我在本地计算机上运行时收到的输出不同的输出。群集和3个节点似乎工作正常。我有一种感觉,问题是我不断更新centroids
,这是一个python列表,并且每次都会通过while-loop
进行更改。是否每个节点可能没有该列表的最新副本?我是这么认为所以我尝试使用broadcast variable
,但那些无法更新(只读)。我也尝试使用accumulator
,但这些仅用于累积。我还尝试将python列表保存为hdfs上的文件,以便每个节点都可以访问,但这不能很好地工作。你认为我正确理解了这个问题吗?还有其他可能会发生在这里吗?如何在本地计算机上获得可以正常工作的代码,而不是在群集上?
答案 0 :(得分:4)
感谢您一直以来对这个问题的关注,特别是因为听起来我可以发布更多信息以使您的工作更轻松。这里的问题在
centroids = points.takeSample(False, K, 34)
我没有意识到这一点,但经过短暂的实验后,这个函数每次都会返回相同的输出,尽管我认为这是一个随机样本。只要您使用相同的种子(在这种情况下为34),您将得到相同的RDD作为回报。我的群集上的RDD由于某种原因而不同于返回到本地计算机的RDD。在任何情况下,因为每次都是相同的RDD,我的输出永远不会改变。 "随机"的问题回到我身边的质心是,这些特殊的东西在数学中产生了类似马鞍点的东西,在那里没有找到质心的收敛。答案的这一部分是数学和编程,所以我不会进一步提及它。我在这一点上的真正希望是,如果你想要的话,其他人会得到帮助
centroids = points.takeSample(False, K, 34)
每次调用时都会生成不同的样本,每次都会将种子更改为一些随机数。
我希望这一切都有帮助。我从来没有花太多时间在我的记忆解决方案上。
再次感谢。