spark.mllib源码阅读-回归算法1-LinearRegression

Spark实现了三类线性回归方法:

1、LinearRegression:普通线性回归模型

2、LassoRegression:加L1正则化的线性回归

3、RidgeRegression:加L2正则化的线性回归

Spark采用了模型和训练分离定义的方式,模型和模型的迭代计算都很清晰:

如LinearRegressionModel和LinearRegressionWithSGD,LassoModel和LassoWithSGD,RidgeRegressionModel和RidgeRegressionWithSGD。其中Model继承自GeneralizedLinearModel和RegressionModel,为了便于模型的保存和输出,还继承了Saveable、Loader和PMMLExportable类,XXXWithSGD继承自GeneralizedLinearAlgorithm,并实现来模型训练的train方法其通过调用父类GeneralizedLinearAlgorithm的run方法来实现模型参数求解的逻辑。


LinearRegression(普通线性回归模型)

三类线性回归模型的实现都大同小异,在此以普通的线性回归LinearRegressionModel和LinearRegressionWithSGD为例来说明。LinearRegressionModel继承了大量的类,但本身实现比较简单,即覆写来父类的predictPoint、save和load方法。代码简单,在此不述。

RidgeRegressionWithSGD继承了GeneralizedLinearAlgorithm类,其主要实现了一个方法train,并定义来自己的Gradient类型和Updater类型为模型训练做准备,另外train实现了重载:

def train(
    input: RDD[LabeledPoint],
    numIterations: Int,
    stepSize: Double,
    regParam: Double,
    miniBatchFraction: Double,
    initialWeights: Vector): RidgeRegressionModel = {
  new RidgeRegressionWithSGD(stepSize, numIterations, regParam, miniBatchFraction).run(
    input, initialWeights)
}
def train(
    input: RDD[LabeledPoint],
    numIterations: Int,
    stepSize: Double,
    regParam: Double,
    miniBatchFraction: Double): RidgeRegressionModel = {
  new RidgeRegressionWithSGD(stepSize, numIterations, regParam, miniBatchFraction).run(input)
}
def train(
    input: RDD[LabeledPoint],
    numIterations: Int,
    stepSize: Double,
    regParam: Double): RidgeRegressionModel = {
  train(input, numIterations, stepSize, regParam, 1.0)
}
def train(
    input: RDD[LabeledPoint],
    numIterations: Int): RidgeRegressionModel = {
  train(input, numIterations, 1.0, 0.01, 1.0)
}

不同train方法的区别主要是初始化参数值,从这里也可以看到Spark使用来哪些默认的参数值进行模型的初始化。train方法内部调用了父类的run方法。

我们再来看看父类GeneralizedLinearAlgorithm的run方法干来啥?

run方法首先进行了特征值的 Scaling,这里对特征值的方差进行来归一化:

//run方法的特征值Scaling过程
val scaler = if (useFeatureScaling) {
  new StandardScaler(withStd = true, withMean = false).fit(input.map(_.features))
} else {
  null
}

// Prepend an extra variable consisting of all 1.0's for the intercept.
// TODO: Apply feature scaling to the weight vector instead of input data.
val data =
  if (addIntercept) {
    if (useFeatureScaling) {
      input.map(lp => (lp.label, appendBias(scaler.transform(lp.features)))).cache()
    } else {
      input.map(lp => (lp.label, appendBias(lp.features))).cache()
    }
  } else {
    if (useFeatureScaling) {
      input.map(lp => (lp.label, scaler.transform(lp.features))).cache()
    } else {
      input.map(lp => (lp.label, lp.features))
    }
  }

特征值的 Scaling过程是由用户决定是否需要Scaling,一般来说,用户可以在数据预处理的步骤中进行特征值的Scaling,也可以交给Spark在这里进行。关于

为什么要做特征值的Scaling,在知乎上看到的一个图片能很好的说明问题:

没有进过归一化,寻找最优解的过程


经过归一化,把各个特征的尺度控制在相同的范围内:



另外,本人也有3遍介绍归一化的博文:数据预处理之归一化机器学习中的归一化方法时间序列的归一化方法、也可以看看来自知乎的问答,结合具体的机器学习算法,还有很多特定的特征Scaling方法。

说完特征值的Scaling,再回过头来看run方法。run方法除了特征值的Scaling外,还做来一些训练数据的整理、模型参数初始化的过程,之后调用了Optimizer类实例来求解模型参数并在最后调用createModel方法返回一个RegressionModel:

val weightsWithIntercept = optimizer.optimize(data, initialWeightsWithIntercept)
//val intercept = 这里省略了一些代码
//var weights =
createModel(weights, intercept)

总结,Spark模型和训练算法模块分离,对模型应用还是训练来说,都是算法思路清晰、模块算法低耦合的特点,同时,对算法开发人员也比较友好,可以单独实现自己的优化算法或者单独实现上层的模型。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-means 算法是一种无监督学习算法,用于将数据集分成 K 个簇。Spark MLlib 中实现了 K-means 算法,可以用于大规模数据的聚类。 以下是 Spark MLlib 实现 K-means 算法的基本步骤: 1. 加载数据集,将数据集转换为特征向量 2. 初始化 K 个簇的质心 3. 对每个样本,将其分配到距离最近的簇 4. 根据分配结果,重新计算每个簇的质心 5. 重复步骤 3 和 4,直到达到最大迭代次数或收敛 以下是一个简单的代码示例: ```python from pyspark.ml.clustering import KMeans from pyspark.ml.evaluation import ClusteringEvaluator from pyspark.ml.feature import VectorAssembler # 加载数据集 data = spark.read.format("csv").load("path/to/data.csv", header=True, inferSchema=True) # 转换数据集为特征向量 assembler = VectorAssembler(inputCols=data.columns, outputCol="features") dataset = assembler.transform(data) # 初始化 KMeans 模型 kmeans = KMeans().setK(2).setSeed(1) # 训练模型 model = kmeans.fit(dataset) # 输出簇中心点 centers = model.clusterCenters() for center in centers: print(center) # 预测数据集中每个样本所属的簇 predictions = model.transform(dataset) # 评估模型 evaluator = ClusteringEvaluator() silhouette = evaluator.evaluate(predictions) print("Silhouette with squared euclidean distance = " + str(silhouette)) ``` 这里假设数据集已经被加载并且包含两个特征。首先,使用 VectorAssembler 将数据集转换为特征向量。然后,初始化 KMeans 模型并训练它。最后,输出每个簇的中心点和模型评估结果。需要注意的是,这里使用了默认的欧几里得距离作为距离度量。如果需要使用其他距离度量,可以通过设置 distanceMeasure 参数来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值