将DataFrame与MLlib一起使用

时间:2015-03-31 20:17:58

标签: apache-spark apache-spark-mllib

让我们说我有一个DataFrame(我从HDFS上的csv读入),我想通过MLlib训练一些算法。如何将行转换为LabeledPoints或在此数据集上使用MLlib?

3 个答案:

答案 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 = ...)

让我们说你想要使用xz。您可以将它们拉出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(" ")}"
      }