Apache spark 将RDD转换为kmeans的有效输入

Apache spark 将RDD转换为kmeans的有效输入,apache-spark,pyspark,k-means,apache-spark-mllib,tf-idf,Apache Spark,Pyspark,K Means,Apache Spark Mllib,Tf Idf,我正在使用包含csv文件的目录的spark mllib算法计算TF和IDF,代码如下: 导入argparse 从操作系统导入系统 参数解析 parser=argparse.ArgumentParserdescription='在的目录上运行TF/IDF 文本文档 parser.add_argument-i,-input,help=HDFS中的输入, 必需=真 parser.add_argument-o,'-output',help=HDFS中的输出, 必需=真 parser.add_argume

我正在使用包含csv文件的目录的spark mllib算法计算TF和IDF,代码如下:

导入argparse 从操作系统导入系统 参数解析 parser=argparse.ArgumentParserdescription='在的目录上运行TF/IDF 文本文档 parser.add_argument-i,-input,help=HDFS中的输入, 必需=真 parser.add_argument-o,'-output',help=HDFS中的输出, 必需=真 parser.add_argument-mdf,'-min_document_frequency',默认值=1 args=parser.parse_args docs_dir=args.input d_out=hdfs://master:54310/ +参数输出 min_df=intargs.min_文件频率 进口火花再生材料 从pyspark导入SparkContext 从pyspark.mllib.feature导入哈希 从pyspark.mllib.feature导入IDF sc=SparkContextappName=TF-IDF 每行加载一个文档。 documents=sc.textFiledocs\u dir.maplambda title\u text: 标题\文本[1]。拆分 hashingTF=hashingTF tf=哈希函数 以色列国防军 idf=idf.F tfidf=idf.TF printfidf.collect 拯救 tfidf.saveastextfield\u out 使用

printfidf.collect 我得到这个输出:

[SparseVector1048576,{812399:4.3307},SparseVector1048576,{411697: 0.0066},SparseVector1048576,{411697:0.0066},SparseVector1048576, {411697:0.0066},SparSevector 1048576,{411697:0.0066}。。。。 我还测试了KMeans mllib算法:

来自未来导入打印功能 导入系统 将numpy作为np导入 从pyspark导入SparkContext 从pyspark.mllib.clustering导入KMeans 运行次数=4 定义解析向量行: 返回np.array[floatx代表行中的x.split'] 如果uuuu name uuuuu==\uuuuuuuu main\uuuuuuuu: 如果lensys.argv!=3: printUsage:kmeans,file=sys.stderr 出口-1 sc=SparkContextappName=KMeans lines=sc.textFilesys.argv[1] data=lines.mapparseVector k=intsys.argv[2] 模型=KMeans.traindata,k,运行 打印最终中心:+strmodel.clusterCenters 打印总成本:+strmodel.computeCostdata sc.停止 使用此示例测试用例

0.0 0.0 0.0 0.1 0.1 0.1 0.2 0.2 0.2 9.0 9.0 9.0 9.1 9.1 9.1 9.2 9.2 9.2 而且效果很好

现在我想在KMeans算法中应用上面tfidf的rdd输出,但我不知道如何像上面的示例文本那样转换rdd,或者如何在KMeans算法中正确分割rdd以正常工作

这件事我真的需要一些帮助

更新

我真正的问题是如何从这样的文本文件中读取输入并将其应用于KMeans mllib

1048576,[155412,857472,756332],[1.75642010278,2.41857747478,1.97365255252] 1048576,[159196,323305,501636],[2.98856378408,1.63863706713,2.44956728334] 1048576,[135312,847543,743411],[1.42412015238,1.58759872958,2.01237484818] 更新2

我一点也不确定,但我认为我需要从上面的向量到下面的数组,以便将其直接应用于KMeans mllib算法

1.75642010278 2.41857747478 1.97365255252 2.98856378408 1.63863706713 2.44956728334 1.42412015238 1.58759872958 2.01237484818
IDF的输出是SparseVector的数据帧。KMeans将向量作为稀疏或密集的输入,因此,不需要进行任何转换。您应该能够直接使用IDF的输出列作为KMeans的输入

如果在运行TFIDF和KMeans之间需要将数据保存到磁盘,我建议通过dataframe API将其保存为csv

首先使用行转换为数据帧:

无需导入即可进行转换的另一种方法:

df = tfidf.map(lambda x: (x, )).toDF(["features"])
转换后,将数据框保存为拼花文件:

df.write.parquet('/path/to/save/file')
要读取数据,只需使用:

from pyspark.sql import SQLContext
sqlContext = SQLContext(sc)

df = sqlContext.read.parquet('/path/to/file')

# converting from dataframe into an RDD[Vector]
data = df.rdd.map(list)
如果您在任何情况下需要从保存为字符串的向量转换,也可以这样做。以下是一些示例代码:

from pyspark.mllib.linalg import Vectors, VectorUDT
from pyspark.sql.functions import udf

df = sc.parallelize(["(7,[1,2,4],[1,1,1])"]).toDF(["features"])

parse = udf(lambda s: Vectors.parse(s), VectorUDT())
df.select(parse("features"))
首先创建一个具有相同格式的示例数据框。然后使用UDF将字符串解析为向量。如果您想要rdd而不是数据框,请使用上面从拼花地板读取部分的代码进行转换

但是,IDF的输出非常稀疏。向量的长度为1048576,其中只有一个值超过1。KMeans不会给出任何有趣的结果

我建议您改为研究。它将为每个单词提供一个更紧凑的向量,对这些向量进行聚类将更有意义。使用此方法,您可以收到一个单词到其向量表示的映射,该映射可用于聚类

from pyspark.mllib.linalg import Vectors, VectorUDT
from pyspark.sql.functions import udf

df = sc.parallelize(["(7,[1,2,4],[1,1,1])"]).toDF(["features"])

parse = udf(lambda s: Vectors.parse(s), VectorUDT())
df.select(parse("features"))