我知道RDD是不可变的,因此它们的值无法改变,但我看到以下行为:
我为FuzzyCMeans(https://github.com/salexln/FinalProject_FCM)算法编写了一个实现,现在我正在测试它,所以我运行以下示例:
import org.apache.spark.mllib.clustering.FuzzyCMeans
import org.apache.spark.mllib.linalg.Vectors
val data = sc.textFile("/home/development/myPrjects/R/butterfly/butterfly.txt")
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()
> parsedData: org.apache.spark.rdd.RDD[org.apache.spark.mllib.linalg.Vector] = MapPartitionsRDD[2] at map at <console>:31
val numClusters = 2
val numIterations = 20
parsedData.foreach{ point => println(point) }
> [0.0,-8.0]
[-3.0,-2.0]
[-3.0,0.0]
[-3.0,2.0]
[-2.0,-1.0]
[-2.0,0.0]
[-2.0,1.0]
[-1.0,0.0]
[0.0,0.0]
[1.0,0.0]
[2.0,-1.0]
[2.0,0.0]
[2.0,1.0]
[3.0,-2.0]
[3.0,0.0]
[3.0,2.0]
[0.0,8.0]
val clusters = FuzzyCMeans.train(parsedData, numClusters, numIteration
parsedData.foreach{ point => println(point) }
>
[0.0,-0.4803333185624595]
[-0.1811743096972924,-0.12078287313152826]
[-0.06638890786148487,0.0]
[-0.04005925925925929,0.02670617283950619]
[-0.12193263222069807,-0.060966316110349035]
[-0.0512,0.0]
[NaN,NaN]
[-0.049382716049382706,0.0]
[NaN,NaN]
[0.006830134553650707,0.0]
[0.05120000000000002,-0.02560000000000001]
[0.04755220304297078,0.0]
[0.06581619798335057,0.03290809899167529]
[0.12010867103812725,-0.0800724473587515]
[0.10946638900458144,0.0]
[0.14814814814814817,0.09876543209876545]
[0.0,0.49119985188436205]
但是,这怎么可能是我的方法改变了不可变的RDD?
BTW,列车方法的签名如下:
train(数据:RDD [Vector],clusters:Int,maxIterations:Int)
答案 0 :(得分:3)
您正在做的事情在the docs:
中有详细描述打印RDD的元素
另一种常见习语是试图打印出RDD的元素 使用rdd.foreach(println)或rdd.map(println)。在一台机器上 这将生成预期的输出并打印所有RDD 元素。但是,在集群模式下,调用stdout的输出 执行者现在正在写执行者的标准,而不是 关于驱动程序的那个,所以驱动程序上的stdout不会显示这些!至 打印驱动程序上的所有元素,可以使用collect()方法 首先将RDD带到驱动程序节点: rdd.collect()。的foreach(的println)。这可能会导致驱动程序耗尽 但是,因为collect()将整个RDD提取到a 单机;如果你只需要打印一些RDD元素,a 更安全的方法是使用take():rdd.take(100).foreach(println)。
因此,由于数据可以在节点之间迁移,因此无法保证foreach
的相同输出。 RDD是不可变的,但您应该以适当的方式提取数据,因为您没有在您的节点上拥有整个RDD。
另一个可能的问题(在您使用不可变向量时不是这种情况)在Point
iself中使用可变数据,这是完全错误的,因此您将失去所有保证 - RDD
本身仍然是不可改变的。
答案 1 :(得分:0)
为了使RDD完全不可变,其内容也应该是不可变的:
scala> val m = Array.fill(2, 2)(0)
m: Array[Array[Int]] = Array(Array(0, 0), Array(0, 0))
scala> val rdd = sc.parallelize(m)
rdd: org.apache.spark.rdd.RDD[Array[Int]] = ParallelCollectionRDD[1]
at parallelize at <console>:23
scala> rdd.collect()
res6: Array[Array[Int]] = Array(Array(0, 0), Array(0, 0))
scala> m(0)(1) = 2
scala> rdd.collect()
res8: Array[Array[Int]] = Array(Array(0, 2), Array(0, 0))
因为数组是可变的,我可以改变它,因此RDD用新数据更新