title: Does CrossValidator in PySpark distribute the execution?
body: <p>I am playing with Machine Learning in PySpark and am using a RandomForestClassifier. I have used Sklearn till now. I am using CrossValidator to tune the parameters and get the best model. A sample code taken from Spark's website is below.</p>
  
  <p>From what I have been reading, I do not understand whether spark distributes the parameter tuning as well or it is the same as in case of GridSearchCV of Sklearn.</p>
  
  <p>Any help would really appreciated.</p>
  
  <pre><code>from pyspark.ml import Pipeline
  from pyspark.ml.classification import LogisticRegression
  from pyspark.ml.evaluation import BinaryClassificationEvaluator
  from pyspark.ml.feature import HashingTF, Tokenizer
  from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
  
  # Prepare training documents, which are labeled.
  training = spark.createDataFrame([
      (0, "a b c d e spark", 1.0),
      (1, "b d", 0.0),
      (2, "spark f g h", 1.0),
      (3, "hadoop mapreduce", 0.0),
      (4, "b spark who", 1.0),
      (5, "g d a y", 0.0),
      (6, "spark fly", 1.0),
      (7, "was mapreduce", 0.0),
      (8, "e spark program", 1.0),
      (9, "a e c l", 0.0),
      (10, "spark compile", 1.0),
      (11, "hadoop software", 0.0)
  ], ["id", "text", "label"])
  
  # Configure an ML pipeline, which consists of tree stages: tokenizer, hashingTF, and lr.
  tokenizer = Tokenizer(inputCol="text", outputCol="words")
  hashingTF = HashingTF(inputCol=tokenizer.getOutputCol(), outputCol="features")
  lr = LogisticRegression(maxIter=10)
  pipeline = Pipeline(stages=[tokenizer, hashingTF, lr])
  
  # We now treat the Pipeline as an Estimator, wrapping it in a CrossValidator instance.
  # This will allow us to jointly choose parameters for all Pipeline stages.
  # A CrossValidator requires an Estimator, a set of Estimator ParamMaps, and an Evaluator.
  # We use a ParamGridBuilder to construct a grid of parameters to search over.
  # With 3 values for hashingTF.numFeatures and 2 values for lr.regParam,
  # this grid will have 3 x 2 = 6 parameter settings for CrossValidator to choose from.
  paramGrid = ParamGridBuilder() \
      .addGrid(hashingTF.numFeatures, [10, 100, 1000]) \
      .addGrid(lr.regParam, [0.1, 0.01]) \
      .build()
  
  crossval = CrossValidator(estimator=pipeline,
                            estimatorParamMaps=paramGrid,
                            evaluator=BinaryClassificationEvaluator(),
                            numFolds=2)  # use 3+ folds in practice
  
  # Run cross-validation, and choose the best set of parameters.
  cvModel = crossval.fit(training)
  </code></pre>