我是Spark + Scala的新手,仍然在发展我的直觉。我有一个包含许多数据样本的文件。每2048行代表一个新样本。我试图将每个样本转换为一个向量,然后运行k-means聚类算法。数据文件如下所示:
123.34 800.18
456.123 23.16
...
当我玩一小部分数据时,我会从文件中创建一个RDD,如下所示:
val fileData = sc.textFile("hdfs://path/to/file.txt")
然后使用以下代码创建向量:
val freqLineCount = 2048
val numSamples = 200
val freqPowers = fileData.map( _.split(" ")(1).toDouble )
val allFreqs = freqPowers.take(numSamples*freqLineCount).grouped(freqLineCount)
val lotsOfVecs = allFreqs.map(spec => Vectors.dense(spec) ).toArray
val lotsOfVecsRDD = sc.parallelize( lotsOfVecs ).cache()
val numClusters = 2
val numIterations = 2
val clusters = KMeans.train(lotsOfVecsRDD, numClusters, numIterations)
这里的关键是我可以在一个字符串数组上调用.grouped
并返回一个包含连续2048值的数组数组。然后,转换为向量并通过KMeans训练算法运行它是微不足道的。
我正在尝试在更大的数据集上运行此代码并遇到java.lang.OutOfMemoryError: Java heap space
错误。大概是因为我在我的freqPowers变量上调用了take
方法,然后对该数据执行了一些操作。
我将如何实现在此数据集上运行KMeans的目标,并牢记
每个数据样本在文件中每2048行发生一次(因此该文件应按顺序进行解析)
此代码需要在分布式群集上运行
我不需要耗尽内存:)
提前致谢
答案 0 :(得分:1)
您可以执行以下操作:
val freqLineCount = 2048
val freqPowers = fileData.flatMap(_.split(" ")(1).toDouble)
// Replacement of your current code.
val groupedRDD = freqPowers.zipWithIndex().groupBy(_._2 / freqLineCount)
val vectorRDD = groupedRDD.map(grouped => Vectors.dense(grouped._2.map(_._1).toArray))
val numClusters = 2
val numIterations = 2
val clusters = KMeans.train(vectorRDD, numClusters, numIterations)
替换代码使用zipWithIndex()
和long的除法将RDD元素分组为freqLineCount
块。分组后,所讨论的元素被提取到它们的实际向量中。