hangscer

scala矩阵运算库-breeze学习与使用

2017/05/15
1
2
3
4
import breeze.linalg._
import breeze.numerics._
import breeze.stats._
import breeze.plot._

breeze库很好用,包括线性代数运算与数据可视化等等.

Plotting Data

折线图与散点图

1
2
3
4
5
6
7
8
val p2=f.subplot(0)
p2 += plot(1 to 100,1 to 100 map(i=>Random.nextInt(i*2)))
p2 += scatter(1 to 100,1 to 100 map(i=>Random.nextInt(i)),radius=>0.5,colors = x=>Color.BLACK)
//散点图
//radius 为点的半径
//colors为点的颜色
p2 += plot(1.0 to 100 by 0.1 ,1.0 to 100 by 0.1 map(15*math.cos(_)+50))
f.saveas("hah.png")


1
2
3
4
5
val f=Figure()
val p2=f.subplot(0)
p2 += hist(1 to 1000 map(i=>Random.nextGaussian()),bins = 100)
//bins越大 图像越精细
f.saveas("hah.png")

新建矩阵

List[List[_]]结构中新建矩阵或直接构建:

1
2
3
val lists=List(List(1,2,3),List(4,5,6))
val v=DenseMatrix(lists:_*)
val v1=DenseMatrix((1,2,3),(4,5,6))

DenseMatrix部分源码为:

1
2
3
4
5
6
7
8
9
10
11
def apply[@specialized(/* Don't remove until SI-8886 is closed*/) R,
@spec(Double, Int, Float, Long) V](rows : R*)(implicit rl : LiteralRow[R,V], man : ClassTag[V], zero: Zero[V]) = {
val nRows = rows.length
val ns = rows.headOption match {
case None => 0
case Some(firstRow) => rl.length(firstRow)
}
val rv = zeros(nRows, ns)
finishLiteral(rv, rl, rows)
rv
}

可以看出多参数的个数即为矩阵的行数.

从csv文件中构建矩阵

利用scala.io.Source工具包一句话即可搞定
代码:

1
def csvtoMatrix(string:String)=DenseMatrix(scala.io.Source.fromFile(string).getLines().toStream.map(str=>str.split(",").map(_.trim.toDouble).toList):_*)

矩阵乘法

1
2
3
4
5
6
7
8
val a=DenseMatrix(
(1,2),
(3,4),
(5,6))
val c=DenseMatrix(
(1,1),
(2,2))
val r=a*c

还有其他矩阵运算,不再赘述

矩阵切片与更新

切片选择数据(底层通过数组驱动,所以index从0开始)
切片的到时不同矩阵对象,但是它们和原来的矩阵共享相同的数组.所以对切片得到的矩阵写数组也会更新原来的矩阵.

1
2
val r:Matrix[Int]=a(0 to 1,0 to 1)
println(r)

更新矩阵

1
2
3
4
5
val r=a(0 to 1,0 to 1)
r := DenseMatrix(
(3,-1),
(-1,-2))
println(a)

PCA降维

调用breeze本身的svd(奇异值分解)和切片等等方法,可以实现PCA算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
object Main extends App {
val sourceData=List(1 to 100 :_*).map(i=>List(i.toDouble,Random.nextInt(i).toDouble))
val data=DenseMatrix(sourceData:_*)
val m=data.rows
val r=(1.0/m)*((data.t)*data)
import svd.SVD
val SVD(u,s,v)=svd(r)
val Ureduce=u(::,0 to 0) //底层使用的是数组,索引从0开始,而不是数学概念里的1开始
val x=Ureduce(0,0)
val y=Ureduce(1,0)
val f=Figure()
val p=f.subplot(0)
p += scatter(sourceData.map(i=>i.head),sourceData.map(_.tail.head),size = _=>1)
p+=plot(-150.0 to 150 by 1.0 map(i=>(i*x,i*y)._1),-150.0 to 150 by 1.0 map(i=>(i*x,i*y)._2))
f.saveas("ha.png")
}


那么问题来了,PCA降维与线性回归的区别在哪里呢?