让我们说我有一个DataFrame(我从HDFS上的csv读入),我想通过MLlib训练一些算法。如何将行转换为LabeledPoints或在此数据集上使用MLlib?
答案 0 :(得分:5)
假设您正在使用Scala:
让我们说你获得DataFrame
如下:
val results : DataFrame = sqlContext.sql(...)
第1步:调用results.printSchema()
- 这不仅会向您展示DataFrame中的列和(这很重要)他们的订单,还会显示Spark SQL认为的类型。一旦你看到这个输出,事情变得不那么神秘了。
第2步:从RDD[Row]
中获取DataFrame
:
val rows: RDD[Row] = results.rdd
第3步:现在只需要从各行中提取您感兴趣的任何字段。为此,您需要知道每个字段的基于0的位置及其类型,幸运的是,您在上面的步骤1中获得了所有这些。例如,
让我们说你做了SELECT x, y, z, w FROM ...
并打印了架构
root
|-- x double (nullable = ...)
|-- y string (nullable = ...)
|-- z integer (nullable = ...)
|-- w binary (nullable = ...)
让我们说你想要使用x
和z
。您可以将它们拉出RDD[(Double, Integer)]
,如下所示:
rows.map(row => {
// x has position 0 and type double
// z has position 2 and type integer
(row.getDouble(0), row.getInt(2))
})
从这里开始,您只需使用Core Spark来创建相关的MLlib对象。如果您的SQL返回数组类型的列,事情会变得复杂一些,在这种情况下,您必须为该列调用getList(...)
。
答案 1 :(得分:2)
假设您正在使用JAVA(Spark版本1.6.2):
以下是使用DataFrame进行机器学习的JAVA代码的简单示例。
它加载具有以下结构的JSON,
[{“label”:1,“att2”:5.037089672359123,“att1”:2.4100883023159456},...]
将数据拆分为培训和测试,
此外,根据official documentation,自当前版本2.0.0起,MLlib的“基于DataFrame的API是主要API”。因此,您可以使用DataFrame找到几个示例。
代码:
SparkConf conf = new SparkConf().setAppName("MyApp").setMaster("local[2]");
SparkContext sc = new SparkContext(conf);
String path = "F:\\SparkApp\\test.json";
String outputPath = "F:\\SparkApp\\justTest";
System.setProperty("hadoop.home.dir", "C:\\winutils\\");
SQLContext sqlContext = new org.apache.spark.sql.SQLContext(sc);
DataFrame df = sqlContext.read().json(path);
df.registerTempTable("tmp");
DataFrame newDF = df.sqlContext().sql("SELECT att1, att2, label FROM tmp");
DataFrame dataFixed = newDF.withColumn("label", newDF.col("label").cast("Double"));
VectorAssembler assembler = new VectorAssembler().setInputCols(new String[]{"att1", "att2"}).setOutputCol("features");
StringIndexer indexer = new StringIndexer().setInputCol("label").setOutputCol("labelIndexed");
// Split the data into training and test
DataFrame[] splits = dataFixed.randomSplit(new double[] {0.7, 0.3});
DataFrame trainingData = splits[0];
DataFrame testData = splits[1];
DecisionTreeClassifier dt = new DecisionTreeClassifier().setLabelCol("labelIndexed").setFeaturesCol("features");
Pipeline pipeline = new Pipeline().setStages(new PipelineStage[] {assembler, indexer, dt});
// Train model
PipelineModel model = pipeline.fit(trainingData);
// Make predictions
DataFrame predictions = model.transform(testData);
predictions.rdd().coalesce(1,true,null).saveAsTextFile("justPlay.txt" +System.currentTimeMillis());
答案 2 :(得分:0)
基于RDD的Mllib即将被弃用,因此您应该使用基于DataFrame的Mllib。
通常,这些MLlib api的输入是一个DataFrame,其中包含2列-标签和功能。有多种方法可以构建此DataFrame-底层api,例如org.apache.spark.mllib.linalg。{Vector,Vectors},org.apache.spark.mllib.regression.LabeledPoint,org.apache.spark.mllib.linalg 。{Matrix,Matrices}等。它们都采用特征和标签的数字值。 可以使用org.apache.spark.ml.feature。{Word2Vec,Word2VecModel}将单词转换为向量。本文档介绍了更多内容-https://spark.apache.org/docs/latest/mllib-data-types.html
创建带有标签和功能的输入数据框后,实例化MLlib api,然后将DataFrame传递给“ fit”函数以获取模型,然后在模型上调用“ transform”或“ predict”函数以获取结果。
示例-
培训文件看起来像-
<numeric label> <a string separated by space>
//Build word vector
val trainingData = spark.read.parquet(<path to training file>)
val sampleDataDf = trainingData
.map { r =>
val s = r.getAs[String]("value").split(" ")
val label = s.head.toDouble
val feature = s.tail
(label, feature)
}.toDF("lable","feature_words")
val word2Vec = new Word2Vec()
.setInputCol("feature_words")
.setOutputCol("feature_vectors")
.setMinCount(0)
.setMaxIter(10)
//build word2Vector model
val model = word2Vec.fit(sampleDataDf)
//convert training text data to vector and labels
val wVectors = model.transform(sampleDataDf)
//train LinearSVM model
val svmAlgorithm = new LinearSVC()
.setFeaturesCol("feature_vectors")
.setMaxIter(100)
.setLabelCol("lable")
.setRegParam(0.01)
.setThreshold(0.5)
.fit(wVectors) //use word vectors created
//Predict new data, same format as training data containing words
val predictionData = spark.read.parquet(<path to prediction file>)
val pDataDf = predictionData
.map { r =>
val s = r.getAs[String]("value").split(" ")
val label = s.head.toDouble
val feature = s.tail
(label, feature)
}.toDF("lable","feature_words")
val pVectors = model.transform(pDataDf)
val predictionlResult = pVectors.map{ r =>
val s = r.getAs[Seq[String]]("feature_words")
val v = r.getAs[Vector]("feature_vectors")
val c = svmAlgorithm.predict(v) // predict using trained SVM
s"$c ${s.mkString(" ")}"
}