Scala - 使用zipped方法处理2个List

1
2
3
4
5
6
// 2个List生成Map
val baselineMap = (featureList, baseline).zipped.toMap

// 2个List的值依次配对计算,生成List
val Si = (baseline, curline).zipped.map(_ + _)
val chisA = (baseline, EAi).zipped.map((d, e) => 1.0 * (d - e) * (d - e) / e)

zipped将两List的元素,依次生成一个Tuple,交给后续处理。

Spark - 使用RDD为DataFrame增加Column

1
2
3
4
5
val newRdd = featureDf.rdd.map(r => Row.fromSeq(r.toSeq :+ KpiChiSquareThreshold.calChiSquareValue(baseline, r.toSeq.toList.asInstanceOf[List[Long]])))
val newSchema = StructType(featureDf.schema.fields :+ StructField("chi2", DoubleType, true))
val spark = SparkSession.builder().appName("any").getOrCreate()
val sqlContext = spark.sqlContext
featureDf = sqlContext.createDataFrame(newRdd, newSchema)

Spark - DataFrame UDF使用多个col

1
2
3
4
5
6
7
8
9
10
11
12
val calUdf = udf((r: Row) => {
val chi2 = KpiChiSquareThreshold.calChiSquareValue(baseline, r.toSeq.toList.asInstanceOf[List[Long]])
if (chi2 > kpiChiSquareThr)
(1, Math.abs(chi2 - kpiChiSquareThr), if (Math.abs(chi2 - kpiChiSquareThr) / kpiChiSquareThr > 1) 1.0 else Math.abs(chi2 - kpiChiSquareThr) / kpiChiSquareThr)
else
(0, 0.0, 0.0)
})
df = df.withColumn("detect", calUdf(struct(featureList.map(f => col(f)): _*)))
.withColumn($(outputCol), col("detect._1"))
.withColumn($(absDevCol), col("detect._2"))
.withColumn($(relDevCol), col("detect._3"))
.drop("detect")

Local Outlier Factor

  • K邻近距离(k-distance):在距离数据点$p$最近的几个点中,第$k$个最近的点跟点$p$之间的距离称为点$p$的K邻近距离,记为$\text{k-distance}(p)$。
  • 可达距离(rechability distance):可达距离的定义跟K邻近距离是相关的,给定参数$k$时,数据点$p$到数据点$o$的可达距离为“数据点$o$的K邻近距离”和“数据点$p$与点$o$之间的直接距离”的最大值。即,$$\begin{aligned} \text{reach_dist}_{k}(p,o) = \max\{\text{k-distance}(o),d(p,o)\} \end{aligned}$$
  • 局部可达密度(local rechability density):局部可达密度的定义是基于可达距离的。对于数据点$p$,与其距离小于等于$\text{k-distance}(p)$的数据点称为它的k近邻(k-nearest-neighbor),记为$N_k(p)$。数据点$p$的局部可达密度,为它与k近邻的平均可达距离的倒数,即,$$\begin{aligned} \text{lrd}_{k}(p) = 1 / \frac{\sum_{o\in{N_{k}(p)}}\text{reach_dist}_{k}(p,o)}{|N_k(p)|} \end{aligned}$$
  • 局部异常因子(local outlier factor):根据局部可达密度的定义,如果一个数据点跟其他点比较疏远的话,那么显然它的局部可达密度就小。但LOF算法衡量一个数据点的异常程度,并不是看它的绝对局部密度,而是看它跟周围邻近的数据点的相对密度。这样做的好处是可以允许数据分布不均匀、密度不同的情况。局部异常因子即是用局部相对密度来定义的。数据点$p$的局部相对密度(局部异常因子)为点$p$的k近邻的平均局部可达密度,跟数据点$p$的局部可达密度的比值,即,$$\begin{aligned} \text{LOF}_{k}(p) = \frac{\sum_{o\in{N_k(p)}}\frac{\text{lrd}_k(o)}{\text{lrd}_k(p)}}{|N_{k}(p)|} = \frac{\sum_{o\in{N_{k}(p)}}\text{lrd}_k(o)}{|N_{k}(p)|}/\text{lrd}_k(p) \end{aligned}$$

根据局部异常因子的定义,如果数据点$p$的LOF得分在1附近,表明数据点p的局部密度跟它的邻居们差不多;如果数据点$p$的LOF得分小于1,表明数据点$p$处在一个相对密集的区域,不像是一个异常点;如果数据点$p$的LOF得分远大于1,表明数据点$p$跟其他点比较疏远,很有可能是一个异常点。