Spark 线性代数库 Breeze API 详解

Posted 小帆的帆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spark 线性代数库 Breeze API 详解相关的知识,希望对你有一定的参考价值。

转载请标明出处:小帆的帆的专栏

运算

加,减,乘,除

向量与向量

  • 加:+
  • 减:-
  • 乘::*
  • 除::/

规则1:乘除前面,加冒号;单独的乘号和除号分别表示点积和线性求解
规则2:累加效果,加等号

import breeze.linalg.DenseVector

object Test 
  def main(args: Array[String]) 
    val v1 = DenseVector(1.0, 2.0, 3.0, 4.0)
    val v2 = DenseVector(0.5, 0.5, 0.5, 0.5)
    // DenseVector(1.5, 2.5, 3.5, 4.5)
    println("\\nv1 + v2 : ")
    println(v1 + v2)

    // DenseVector(0.5, 1.5, 2.5, 3.5)
    println("\\nv1 - v2 : ")
    println(v1 - v2)

    // DenseVector(0.5, 1.0, 1.5, 2.0)
    println("\\nv1 :* v2 : ")
    // 规则1:乘号前面多了冒号
    println(v1 :* v2)

    // DenseVector(2.0, 4.0, 6.0, 8.0)
    println("\\nv1 :/ v2 : ")
    // 规则1:除号前面多了冒号
    println(v1 :/ v2)

    // 但是v1 和 v2并没有改变
    // DenseVector(1.0, 2.0, 3.0, 4.0)
    println("\\nv1 : ")
    println(v1)

    // DenseVector(0.5, 0.5, 0.5, 0.5)
    println("\\nv2 : ")
    println(v2)

    // 规则2
    // 如果想把最后的结果保存到v1上,需要加等号
    // DenseVector(1.5, 2.5, 3.5, 4.5)
    println("\\nv1 += v2 : ")
    println(v1 += v2)

    // DenseVector(1.0, 2.0, 3.0, 4.0)
    println("\\nv1 -= v2 : ")
    println(v1 -= v2)

    // DenseVector(0.5, 1.0, 1.5, 2.0)
    println("\\nv1 :*= v2 : ")
    // 注意:乘号前面多了冒号
    println(v1 :*= v2)

    // DenseVector(1.0, 2.0, 3.0, 4.0)
    println("\\nv1 :/= v2 : ")
    // 注意:除号前面多了冒号
    println(v1 :/= v2)
  

矩阵与矩阵

跟向量与向量完全一样

  • 加:+
  • 减:-
  • 乘::*
  • 除::/

规则1:乘除前面,加冒号;单独的乘号和除号分别表示点积和线性求解
规则2:累加效果,加等号

import breeze.linalg.DenseMatrix

object Test1 
  def main(args: Array[String]) 
    val m1 = DenseMatrix((1.0, 2.0), (3.0, 4.0))
    val m2 = DenseMatrix((0.5, 0.5), (0.5, 0.5))

    /**
      * 1.5  2.5  
      * 3.5  4.5
      */
    println("\\nm1 + m2 : ")
    println(m1 + m2)

    /**
      * 0.5  1.5  
      * 2.5  3.5  
      */
    println("\\nm1 - m2 : ")
    println(m1 - m2)

    /**
      * 0.5  1.0  
      * 1.5  2.0  
      */
    println("\\nm1 :* m2 : ")
    // 注意:乘号前面多了冒号
    println(m1 :* m2)

    /**
      * 2.0  4.0  
      * 6.0  8.0  
      */
    println("\\nm1 :/ m2 : ")
    // 注意:除号前面多了冒号
    println(m1 :/ m2)

    // 但是m1 和 m2并没有改变
    /**
      * 1.0  2.0  
      * 3.0  4.0  
      */
    println("\\nm1 : ")
    println(m1)

    /**
      * 0.5  0.5  
      * 0.5  0.5  
      */
    println("\\nm2 : ")
    println(m2)

    // 如果想把最后的结果保存到m1上,需要加等号
    /**
      * 1.5  2.5  
      * 3.5  4.5
      */
    println("\\nm1 += m2 : ")
    println(m1 += m2)

    /**
      * 1.0  2.0  
      * 3.0  4.0  
      */
    println("\\nm1 -= m2 : ")
    println(m1 -= m2)

    /**
      * 0.5  1.0  
      * 1.5  2.0  
      */
    println("\\nm1 :*= m2 : ")
    // 注意:乘号前面多了冒号
    println(m1 :*= m2)

    /**
      * 1.0  2.0  
      * 3.0  4.0  
      */
    println("\\nm1 :/= m2 : ")
    // 注意:除号前面多了冒号
    println(m1 :/= m2)
  

矩阵或向量与数值

  • 加:+
  • 减:-
  • 乘:*
  • 除:/

规则1:累加效果,加等号

注意:乘除号前不需要冒号,因为没有矩阵与数值的点积等计算

import breeze.linalg.DenseMatrix, DenseVector

object Test1 
  def main(args: Array[String]) 
    val v1 = DenseVector(1.0, 2.0, 3.0, 4.0)

    // DenseVector(1.5, 2.5, 3.5, 4.5)
    println("v1 + 0.5 : ")
    println(v1 + 0.5)

    // DenseVector(0.5, 1.5, 2.5, 3.5)
    println("\\nv1 - 0.5 : ")
    println(v1 - 0.5)

    // DenseVector(0.5, 1.0, 1.5, 2.0)
    println("\\nv1 * 0.5 : ")
    println(v1 * 0.5)

    // DenseVector(2.0, 4.0, 6.0, 8.0)
    println("\\nv1 / 0.5 : ")
    println(v1 / 0.5)

    // v1依然不变
    // DenseVector(1.0, 2.0, 3.0, 4.0)
    println("\\nv1 : ")
    println(v1)

    // DenseVector(1.5, 2.5, 3.5, 4.5)
    println("\\nv1 += 0.5 : ")
    println(v1 += 0.5)

    // DenseVector(1.0, 2.0, 3.0, 4.0)
    println("\\nv1 -= 0.5 : ")
    println(v1 -= 0.5)

    // DenseVector(0.5, 1.0, 1.5, 2.0)
    println("\\nv1 *= 0.5 : ")
    println(v1 *= 0.5)

    // DenseVector(5.0, 10.0, 15.0, 20.0)
    println("\\nv1 /= 0.1 : ")
    println(v1 /= 0.1)

    // DenseVector(5.0, 10.0, 15.0, 20.0)
    println("\\nv1 : ")
    println(v1)

    val m1 = DenseMatrix((1.0, 2.0), (3.0, 4.0))

    /**
      * 1.5  2.5  
      * 3.5  4.5  
      */
    println("m1 + 0.5 : ")
    println(m1 + 0.5)

    /**
      * 0.5  1.5  
      * 2.5  3.5  
      */
    println("\\nm1 - 0.5 : ")
    println(m1 - 0.5)

    /**
      * 0.5  1.0  
      * 1.5  2.0  
      */
    println("\\nm1 * 0.5 : ")
    println(m1 * 0.5)

    /**
      * 2.0  4.0  
      * 6.0  8.0  
      */
    println("\\nm1 / 0.5 : ")
    println(m1 / 0.5)

    // m1依然不变
    /**
      * 1.0  2.0  
      * 3.0  4.0  
      */
    println("\\nm1 : ")
    println(m1)

    /**
      * 1.5  2.5  
      * 3.5  4.5  
      */
    println("\\nm1 += 0.5 : ")
    println(m1 += 0.5)

    /**
      * 1.0  2.0  
      * 3.0  4.0  
      */
    println("\\nm1 -= 0.5 : ")
    println(m1 -= 0.5)

    /**
      * 0.5  1.0  
      * 1.5  2.0  
      */
    println("\\nm1 *= 0.5 : ")
    println(m1 *= 0.5)

    /**
      * 5.0   10.0  
      * 15.0  20.0 
      */
    println("\\nm1 /= 0.1 : ")
    println(m1 /= 0.1)

    /**
      * 5.0   10.0  
      * 15.0  20.0  
      */
    println("\\nm1 : ")
    println(m1)
  

矩阵与向量

  • 加:+
  • 减:-
  • 乘::*
  • 除::/

规则1:乘除前面,加冒号;单独的乘号和除号分别表示点积和线性求解
规则2:累加效果,加等号
规则3:必须有星号
规则4:星号在左,逐行;星号在右,逐列;与向量是列向量还是行向量无关
规则5:向量必须是列向量

import breeze.linalg.*, DenseMatrix, DenseVector

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    val v1 = DenseVector(1.0, 2.0)
    //    val v1 = DenseVector(1.0, 2.0).t // 运行时异常,规则5,向量必须是列向量
    //    val v1 = DenseVector(1.0, 2.0).t.t // 正确,如果是一个列向量,需要转换成行向量

    // 规则4: 星号在左,逐行;星号在右,逐列
    println("-------------星号在左边,就逐行操作-----------------")

    /**
      * 2.0  4.0
      * 4.0  6.0
      */
    println("\\nm1(*, ::) + v1 : ")
    println(m1(*, ::) + v1)

    /**
      * 0.0  0.0
      * 2.0  2.0
      */
    println("\\nm1(*, ::) - v1 : ")
    println(m1(*, ::) - v1)

    //    规则1: 乘除前面,加冒号

    /**
      * 1.0  4.0
      * 3.0  8.0
      */
    println("\\nm1(*, ::) :* v1 : ")
    println(m1(*, ::) :* v1)

    /**
      * 1.0  1.0
      * 3.0  2.0
      */
    println("\\nm1(*, ::) :/ v1 : ")
    println(m1(*, ::) :/ v1)

    println("-------------星号在右边,就逐列操作-----------------")

    /**
      * 2.0  3.0
      * 5.0  6.0
      */
    println("\\nm1(::, *) + v1 : ")
    println(m1(::, *) + v1)

    /**
      * 0.0  1.0
      * 1.0  2.0
      */
    println("\\nm1(::, *) - v1 : ")
    println(m1(::, *) - v1)

    /**
      * 1.0  2.0
      * 6.0  8.0
      */
    println("\\nm1(::, *) :* v1 : ")
    println(m1(::, *) :* v1)

    /**
      * 1.0  2.0
      * 1.5  2.0
      */
    println("\\nm1(::, *) :/ v1 : ")
    println(m1(::, *) :/ v1)

    // 无论星号在哪,m1都不会改变
    println("-------------规则2: 累加效果,加等号-----------------")

    // 下面以整除为例,注意星号的位置,一个在左,一个在右

    /**
      * 1.0  2.0
      * 3.0  4.0
      */
    println("\\nm1 : ")
    println(m1)

    /**
      * BroadcastedRows(1.0  4.0
      * 3.0  8.0  )
      */
    println("\\nm1(*, ::) :*= v1 : ")
    println(m1(*, ::) :*= v1)

    /**
      * 1.0  4.0
      * 3.0  8.0
      */
    println("\\nm1 : ")
    println(m1)

    /**
      * BroadcastedColumns(1.0  4.0
      * 1.5  4.0  )
      */
    println("\\nm1(::, *) :/= v1 : ")
    println(m1(::, *) :/= v1)

    /**
      * 1.0  4.0
      * 1.5  4.0
      */
    println("\\nm1 : ")
    println(m1)
  

函数

统计

求和

import breeze.linalg.Axis, DenseMatrix, sum

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    // Axis._0 纵向
    // 4.0  6.0
    println(sum(m1, Axis._0))

    // Axis._1 横向
    // 3.0 7.0
    println(sum(m1, Axis._1))
  

均值

import breeze.linalg.Axis, DenseMatrix
import breeze.stats.mean

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    // Axis._0 纵向
    // 4.0  6.0
    println(mean(m1, Axis._0))

    // Axis._1 横向
    // 1.5  3.5
    println(mean(m1, Axis._1))
  

方差和标准差

import breeze.linalg.Axis, DenseMatrix
import breeze.stats.stddev, variance

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    // Axis._0 纵向
    // 2.0  2.0 
    println(variance(m1, Axis._0))

    // Axis._1 横向
    // 0.5, 0.5
    println(variance(m1, Axis._1))

    // Axis._0 纵向
    // 2.0  2.0 
    println(stddev(m1, Axis._0))

    // Axis._1 横向
    // 0.5, 0.5
    println(stddev(m1, Axis._1))
  

N次方和开方

import breeze.linalg.DenseMatrix
import breeze.numerics.pow, sqrt

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    /**
      * 1.0  4.0
      * 9.0  16.0
      */
    println(pow(m1, 2))

    /**
      * 1.0   8.0   
      * 27.0  64.0  
      */
    println(pow(m1, 3))

    /**
      * 1.0                 1.4142135623730951  
      * 1.7320508075688772  2.0  
      */
    println(sqrt(m1))
  

E和log

import breeze.linalg.DenseMatrix
import breeze.numerics.exp, log, log10, log1p

object Test1 
  def main(args: Array[String]) 

    val m1 = DenseMatrix(
      (1.0, 2.0),
      (3.0, 4.0)
    )

    /**
      * 2.718281828459045   7.38905609893065
      * 20.085536923187668  54.598150033144236
      */
    // e = 2.718281828459045
    println(exp(m1))

    /**
      * 0.0                 0.6931471805599453
      * 1.0986122886681098  1.3862943611198906
      */
    // 以e为底
    println(log(m1))

    /**
      * 0.0                  0.3010299956639812  
      * 0.47712125471966244  0.6020599913279624  
      */
    // 以10为底
    println(log10(m1))

    /**
      * 0.6931471805599453  1.0986122886681096  
      * 1.3862943611198906  1.6094379124341003  
      */
    // 以e为底
    // log1p() 以返回 log(1 + x),甚至当 x 的值接近零也能计算出准确结果。
    println(log1p(m1))
  

三角

  • sin, sinh, asin, asinh
  • cos, cosh, acos, acosh
  • tan, tanh, atan, atanh
  • atan2
  • sinc(x) == sin(x)/x
  • sincpi(x) == sinc(x * Pi)

取整

import breeze.linalg.DenseVector
import breeze.numerics._

object Test1 
  def main(args: Array[String]) 
    val a = DenseVector(1.4, 0.5, -2.3)

    // 四舍五入
    println(round(a))

    // 向上取整
    println(ceil(a))

    // 向下取整
    println(floor(a))

    // 大于0,为1;小于0,为-1
    println(signum(a))

    // 绝对值
    println(abs(a))
  

示例

模拟逻辑回归

利用Breze进行,归一化,添加截距项,预测

import breeze.linalg._
import breeze.numerics._
import breeze.stats._

object Work2 
  def main(args: Array[String]) 

    // 随机产生数据
    //    val featuresMatrix = DenseMatrix.rand[Double](3, 3)
    //    val labelMatrix = DenseMatrix.rand[Double](3, 1)

    // 测试数据
    val featuresMatrix = DenseMatrix(
      (1.0, 2.0, 3.0),
      (4.0, 5.0, 6.0),
      (7.0, 8.0, 9.0)
    )

    val labelMatrix = DenseMatrix(
      1.0,
      1.0,
      0.0
    )

    // 均值
    // DenseVector(4.0, 5.0, 6.0)
    val featuresMean = mean(featuresMatrix(::, *)).toDenseVector
    println("均值:")
    println(featuresMean)

    // 标准差
    // DenseVector(3.0, 3.0, 3.0)
    val featuresStddev = stddev(featuresMatrix(::, *)).toDenseVector
    println("\\n标准差:")
    println(featuresStddev)

    // 减去均值
    /**
      * -3.0  -3.0  -3.0
      * 0.0   0.0   0.0
      * 3.0   3.0   3.0
      */
    featuresMatrix(*, ::) -= featuresMean
    println("\\n减去均值:")
    println(featuresMatrix)

    // 除以标准差
    /**
      * -1.0  -1.0  -1.0
      * 0.0   0.0   0.0
      * 1.0   1.0   1.0
      */
    featuresMatrix(*, ::) /= featuresStddev
    println("\\n除以标准差:")
    println(featuresMatrix)

    // 生成截距
    /**
      * 1.0
      * 1.0
      * 1.0
      */
    val intercept = DenseMatrix.ones[Double](featuresMatrix.rows, 1)
    println("\\n截距:")
    println(intercept)

    // 拼接成为最终的训练集
    /**
      * 1.0  -1.0  -1.0  -1.0
      * 1.0  0.0   0.0   0.0
      * 1.0  1.0   1.0   1.0
      */
    val train = DenseMatrix.horzcat(intercept, featuresMatrix)
    println("\\n训练集:")
    println(train)

    // 参数
    // 为方便检查结果,这里全部设置为1
    /**
      * 1.0
      * 1.0
      * 1.0
      * 1.0
      */
    val w = new DenseMatrix(4, 1, Array(1.0, 1.0, 1.0, 1.0))
    //    val w = DenseMatrix.rand[Double](4, 1) // 随机生成, 一定要指定类型
    println("\\n参数:")
    println(w)

    /**
      * -2.0
      * 1.0
      * 4.0
      */
    // 随机生成w时,如果没有指定类型,A的计算结果虽然不会有错,但是后面将无法计算,除非通过asInstanceOf进行类型转换
    // 如果w指定了类型,那么在idea中,转换语句会是灰色的,意思是这句话没有作用,可以不写
    val A = (train * w).asInstanceOf[DenseMatrix[Double]]
    println("\\nA:")
    println(A)

    /**
      * 0.11920292202211755
      * 0.7310585786300049
      * 0.9820137900379085
      */
    // Sigmoid函数
    val probability = 1.0 / (exp(A * -1.0) + 1.0)
    println("\\nprobability:")
    println(probability)

    /**
      * MSE : 0.6041613548425021
      */
    val MSE = mean(pow(probability - labelMatrix, 2))
    println("\\nMSE:")
    println(MSE)

    /**
      * RMSE : 0.777278170825929
      */
    val RMSE = sqrt(MSE)
    println("\\nRMSE:")
    println(RMSE)
  

参考

Quickstart
Linear Algebra Cheat Sheet
炼数成金-黄美灵老师的Spark MLlib 机器学习算法与源码解析课程

以上是关于Spark 线性代数库 Breeze API 详解的主要内容,如果未能解决你的问题,请参考以下文章

Scala 的矩阵运算

Spark MLlib数据类型

Spark MLlib数据类型

Spark MLlib数据类型

Spark MLlib之使用Breeze操作矩阵向量

spark-mllib 密集向量和稀疏向量