迁移指南:MLlib(机器学习)

请注意,本迁移指南仅描述 MLlib 特有的内容。在将基于 DataFrame 的 API 的 MLlib 迁移到更高版本时,许多 SQL 迁移的内容也同样适用。请参阅 迁移指南:SQL、Dataset 和 DataFrame

从 MLlib 3.5 升级到 4.0

破坏性变更

没有破坏性变更。

弃用和行为变更

弃用

没有弃用内容。

行为变更

从 MLlib 2.4 升级到 3.0

破坏性变更

弃用和行为变更

弃用

行为变更

从 MLlib 2.2 升级到 2.3

破坏性变更

弃用和行为变更

弃用

行为变更

从 MLlib 2.1 升级到 2.2

破坏性变更

没有破坏性变更。

弃用和行为变更

弃用

没有弃用内容。

行为变更

从 MLlib 2.0 升级到 2.1

破坏性变更

已移除弃用的方法

弃用和行为变更

弃用

行为变更

从 MLlib 1.6 升级到 2.0

破坏性变更

Spark 2.0 中有几项破坏性变更,概述如下。

用于 DataFrame API 的线性代数类

Spark 的线性代数依赖项已被移动到一个新项目 mllib-local(参见 SPARK-13944)。作为此更改的一部分,线性代数类被复制到了一个新的包 spark.ml.linalg 中。spark.ml 中的基于 DataFrame 的 API 现在依赖于 spark.ml.linalg 类,导致了一些破坏性变更,主要是在各个模型类中(完整列表请参见 SPARK-14810)。

注意:spark.mllib 中的基于 RDD 的 API 继续依赖于之前的包 spark.mllib.linalg

转换向量和矩阵

虽然大多数流水线组件支持加载时的向后兼容性,但在 2.0 之前的 Spark 版本中,一些包含向量或矩阵列的现有 DataFrame 和流水线可能需要迁移到新的 spark.ml 向量和矩阵类型。用于将 DataFrame 列从 spark.mllib.linalg 类型转换为 spark.ml.linalg 类型(反之亦然)的工具可以在 spark.mllib.util.MLUtils 中找到。

此外,还有用于转换单个向量和矩阵实例的实用方法。在 mllib.linalg.Vector / mllib.linalg.Matrix 上使用 asML 方法可转换为 ml.linalg 类型,使用 mllib.linalg.Vectors.fromML / mllib.linalg.Matrices.fromML 可转换为 mllib.linalg 类型。

from pyspark.mllib.util import MLUtils

# convert DataFrame columns
convertedVecDF = MLUtils.convertVectorColumnsToML(vecDF)
convertedMatrixDF = MLUtils.convertMatrixColumnsToML(matrixDF)
# convert a single vector or matrix
mlVec = mllibVec.asML()
mlMat = mllibMat.asML()

有关详细信息,请参阅 MLUtils Python 文档

import org.apache.spark.mllib.util.MLUtils

// convert DataFrame columns
val convertedVecDF = MLUtils.convertVectorColumnsToML(vecDF)
val convertedMatrixDF = MLUtils.convertMatrixColumnsToML(matrixDF)
// convert a single vector or matrix
val mlVec: org.apache.spark.ml.linalg.Vector = mllibVec.asML
val mlMat: org.apache.spark.ml.linalg.Matrix = mllibMat.asML

有关详细信息,请参阅 MLUtils Scala 文档

import org.apache.spark.mllib.util.MLUtils;
import org.apache.spark.sql.Dataset;

// convert DataFrame columns
Dataset<Row> convertedVecDF = MLUtils.convertVectorColumnsToML(vecDF);
Dataset<Row> convertedMatrixDF = MLUtils.convertMatrixColumnsToML(matrixDF);
// convert a single vector or matrix
org.apache.spark.ml.linalg.Vector mlVec = mllibVec.asML();
org.apache.spark.ml.linalg.Matrix mlMat = mllibMat.asML();

有关详细信息,请参阅 MLUtils Java 文档

已移除弃用的方法

spark.mllibspark.ml 包中删除了几个已弃用的方法

  • ml.evaluation.BinaryClassificationEvaluator 中的 setScoreCol
  • spark.mlLinearRegressionLogisticRegression 中的 weights
  • mllib.optimization.LBFGS 中的 setMaxNumIterations(标记为 DeveloperApi
  • mllib.rdd.RDDFunctions 中的 treeReducetreeAggregate(这些函数现在直接在 RDD 上可用,此前标记为 DeveloperApi
  • mllib.tree.configuration.Strategy 中的 defaultStrategy
  • mllib.tree.Node 中的 build
  • mllib.util.MLUtils 中的多类 libsvm 加载器和 load/save labeledData 方法

完整的破坏性变更列表可在 SPARK-14810 中找到。

弃用和行为变更

弃用

spark.mllibspark.ml 包中的弃用内容包括

  • SPARK-14984:在 spark.ml.regression.LinearRegressionSummary 中,model 字段已弃用。
  • SPARK-13784:在 spark.ml.regression.RandomForestRegressionModelspark.ml.classification.RandomForestClassificationModel 中,numTrees 参数已弃用,建议改用 getNumTrees 方法。
  • SPARK-13761:在 spark.ml.param.Params 中,validateParams 方法已弃用。我们将重写方法中的所有功能移动到相应的 transformSchema 中。
  • SPARK-14829:在 spark.mllib 包中,LinearRegressionWithSGD, LassoWithSGD, RidgeRegressionWithSGDLogisticRegressionWithSGD 已弃用。我们鼓励用户使用 spark.ml.regression.LinearRegressionspark.ml.classification.LogisticRegression
  • SPARK-14900:在 spark.mllib.evaluation.MulticlassMetrics 中,precision, recallfMeasure 参数已弃用,建议改用 accuracy
  • SPARK-15644:在 spark.ml.util.MLReaderspark.ml.util.MLWriter 中,context 方法已弃用,建议改用 session
  • spark.ml.feature.ChiSqSelectorModel 中,setLabelCol 方法已弃用,因为它未被 ChiSqSelectorModel 使用。

行为变更

spark.mllibspark.ml 包中的行为变更包括

  • SPARK-7780spark.mllib.classification.LogisticRegressionWithLBFGS 现在直接调用 spark.ml.classification.LogisticRegression 进行二分类。这将为 spark.mllib.classification.LogisticRegressionWithLBFGS 引入以下行为变更:
  • 在使用 L1/L2 更新器训练二分类模型时,截距不会被正则化。
  • 如果用户设置不进行正则化,无论是否进行特征缩放,训练都将以相同的收敛速度返回相同的解。
  • SPARK-13429:为了与 spark.ml.classification.LogisticRegression 提供更好且一致的结果,spark.mllib.classification.LogisticRegressionWithLBFGS 的默认值:convergenceTol 已从 1E-4 更改为 1E-6。
  • SPARK-12363:修复了 PowerIterationClustering 的一个 Bug,这很可能会改变其结果。
  • SPARK-13048:如果使用了检查点,使用 EM 优化器的 LDA 默认将保留最后一个检查点。
  • SPARK-12153Word2Vec 现在遵守句子边界。之前,它处理不正确。
  • SPARK-10574:在 spark.mlspark.mllib 中,HashingTF 默认使用 MurmurHash3 作为哈希算法。
  • SPARK-14768:移除了 PySpark ParamexpectedType 参数。
  • SPARK-14931:更改了一些在 Scala 和 Python 的流水线之间不匹配的默认 Param 值。
  • SPARK-13600QuantileDiscretizer 现在使用 spark.sql.DataFrameStatFunctions.approxQuantile 来查找分割点(之前使用自定义抽样逻辑)。对于相同的输入数据和参数,输出的分桶将会不同。

    从 MLlib 1.5 升级到 1.6

    spark.mllibspark.ml 包中没有破坏性的 API 变更,但存在一些弃用和行为变更。

    弃用

    • SPARK-11358:在 spark.mllib.clustering.KMeans 中,runs 参数已弃用。
    • SPARK-10592:在 spark.ml.classification.LogisticRegressionModelspark.ml.regression.LinearRegressionModel 中,weights 字段已弃用,改用新名称 coefficients。这有助于消除与赋予算法的实例(行)“权重”的歧义。

    行为变更

    • SPARK-7770spark.mllib.tree.GradientBoostedTreesvalidationTol 在 1.6 中更改了语义。之前,它是绝对误差变化的阈值。现在,它类似于 GradientDescentconvergenceTol 的行为:对于较大的误差,它使用相对误差(相对于先前的误差);对于较小的误差(< 0.01),它使用绝对误差。
    • SPARK-11069spark.ml.feature.RegexTokenizer:之前,它在标记化之前不会将字符串转换为小写。现在,它默认转换为小写,并提供不转换的选项。这与较简单的 Tokenizer 转换器的行为一致。

    从 MLlib 1.4 升级到 1.5

    spark.mllib 包中,没有破坏性的 API 变更,但有几处行为变更

    • SPARK-9005RegressionMetrics.explainedVariance 返回平均回归平方和。
    • SPARK-8600NaiveBayesModel.labels 变为排序状态。
    • SPARK-3382GradientDescent 具有默认的收敛容差 1e-3,因此迭代可能比 1.4 更早结束。

    spark.ml 包中,存在一项破坏性的 API 变更和一项行为变更

    • SPARK-9268:由于 Scala 编译器错误,Java 的可变参数支持已从 Params.setDefault 中移除。
    • SPARK-10097:添加了 Evaluator.isLargerBetter 来指示指标排序。像 RMSE 这样的指标不再像 1.4 中那样反转符号。

    从 MLlib 1.3 升级到 1.4

    spark.mllib 包中,有几项破坏性变更,但均在 DeveloperApiExperimental API 中

    • 梯度提升树
    • (破坏性变更) Loss.gradient 方法的签名已更改。这仅对为 GBT 编写自定义损失函数的用户有影响。
    • (破坏性变更) case 类 BoostingStrategyapplycopy 方法已更改,原因是对 case 类字段进行了修改。对于使用 BoostingStrategy 设置 GBT 参数的用户,这可能是一个问题。
  • (破坏性变更) LDA.run 的返回值已更改。它现在返回抽象类 LDAModel 而不是具体类 DistributedLDAModel。类型为 LDAModel 的对象仍可强制转换为相应的具体类型,具体取决于优化算法。

    spark.ml 包中,发生了几项重大 API 变更,包括

    • Param 和其他用于指定参数的 API
    • uid 流水线组件的唯一 ID
    • 某些类的重组

    由于 spark.ml API 在 Spark 1.3 中是 Alpha 组件,我们在此不列出所有变更。然而,自 1.4 起 spark.ml 不再是 Alpha 组件,我们将为未来版本提供任何 API 变更的详细信息。

    从 MLlib 1.2 升级到 1.3

    spark.mllib 包中,有几项破坏性变更。第一个变更(在 ALS 中)是唯一一个不在标记为 Alpha 或 Experimental 的组件中的变更。

    • (破坏性变更)ALS 中,无关的方法 solveLeastSquares 已被移除。DeveloperApi 方法 analyzeBlocks 也被移除。
    • (破坏性变更) StandardScalerModel 仍为 Alpha 组件。其中,variance 方法已被 std 方法替换。要计算原 variance 方法返回的列方差值,只需将 std 返回的标准差值平方即可。
    • (破坏性变更) StreamingLinearRegressionWithSGD 仍为 Experimental 组件。其中有两项变更:
    • 移除带参数的构造函数,改用构建器模式,即使用默认构造函数加上参数设置方法。
    • 变量 model 不再是公共的。
  • (破坏性变更) DecisionTree 仍为 Experimental 组件。在它及其相关类中,有几项变更:
  • DecisionTree 中,弃用的类方法 train 已被移除。(对象/静态 train 方法保留。)
  • Strategy 中,checkpointDir 参数已被移除。仍然支持检查点,但检查点目录必须在调用树和树集成训练之前设置。
  • PythonMLlibAPI(Scala/Java 和 Python 之间用于 MLlib 的接口)以前是一个公共 API,但现在是私有的,声明为 private[python]。这从来就不是为了外部使用而设计的。
  • 在线性回归(包括 Lasso 和岭回归)中,平方损失现在除以 2。因此,为了产生与 1.2 中相同的结果,正则化参数需要除以 2,步长需要乘以 2。

    spark.ml 包中,主要的 API 变更来自 Spark SQL。我们在此列出最重要的变更:

    • 旧的 SchemaRDD 已被具有稍作修改的 API 的 DataFrame 取代。spark.ml 中所有曾经使用 SchemaRDD 的算法现在都使用 DataFrame。
    • 在 Spark 1.2 中,我们使用 import sqlContext._(其中 sqlContextSQLContext 的实例)从 LabeledPointRDD 隐式转换为 SchemaRDD。这些隐式转换已被移动,因此我们现在调用 import sqlContext.implicits._
    • 用于 SQL 的 Java API 也相应发生了变化。详情请参阅上述示例和 Spark SQL 编程指南

    其他变更发生在 LogisticRegression

    • scoreCol 输出列(默认值为 “score”)被重命名为 probabilityCol(默认值为 “probability”)。该类型最初是 Double(表示类别 1.0 的概率),但现在是 Vector(表示每个类别的概率,以支持未来的多分类)。
    • 在 Spark 1.2 中,LogisticRegressionModel 不包含截距。在 Spark 1.3 中,它包含截距;但是,由于它使用 spark.mllib.LogisticRegressionWithLBFGS 的默认设置,它将始终为 0.0。使用截距的选项将在未来添加。

    从 MLlib 1.1 升级到 1.2

    MLlib v1.2 中唯一的 API 变更是在 DecisionTree 中,该 API 在 MLlib 1.2 中继续作为实验性 API

    1. (破坏性变更) 分类的 Scala API 采用命名参数指定类别数量。在 MLlib v1.1 中,此参数在 Python 中称为 numClasses,在 Scala 中称为 numClassesForClassification。在 MLlib v1.2 中,名称均设置为 numClasses。此 numClasses 参数通过 Strategy 或通过 DecisionTree 静态 trainClassifiertrainRegressor 方法指定。

    2. (破坏性变更) Node 的 API 发生了变化。这通常不应影响用户代码,除非用户手动构建决策树(而不是使用 trainClassifiertrainRegressor 方法)。树 Node 现在包含更多信息,包括预测标签的概率(用于分类)。

    3. 打印方法的输出已更改。toString (Scala/Java) 和 __repr__ (Python) 方法过去打印完整模型;现在它们打印摘要。对于完整模型,请使用 toDebugString

    Spark 发行版中的示例以及 决策树指南 中的示例已相应更新。

    从 MLlib 1.0 升级到 1.1

    MLlib v1.1 中唯一的 API 变更是在 DecisionTree 中,该 API 在 MLlib 1.1 中继续作为实验性 API

    1. (破坏性变更) 树深度的含义已更改了 1,以匹配 scikit-learnrpart 中的树实现。在 MLlib v1.0 中,深度为 1 的树有 1 个叶节点,深度为 2 的树有 1 个根节点和 2 个叶节点。在 MLlib v1.1 中,深度为 0 的树有 1 个叶节点,深度为 1 的树有 1 个根节点和 2 个叶节点。此深度由 Strategy 中的 maxDepth 参数指定,或通过 DecisionTree 静态 trainClassifiertrainRegressor 方法指定。

    2. (非破坏性变更) 我们建议使用新添加的 trainClassifiertrainRegressor 方法来构建 DecisionTree,而不是使用旧的参数类 Strategy。这些新的训练方法明确区分了分类和回归,并将专门的参数类型替换为简单的 String 类型。

    建议使用的新 trainClassifiertrainRegressor 的示例在 决策树指南 中给出。

    从 MLlib 0.9 升级到 1.0

    在 MLlib v1.0 中,我们以统一的方式支持密集和稀疏输入,这引入了一些破坏性变更。如果您的数据是稀疏的,请以稀疏格式存储,而不是密集格式,以利用存储和计算中的稀疏性。详细信息如下所述。