1. 程式人生 > >Spark線性代數,繪圖工具入門;scala, java下的Breeze線性代數以及資料繪圖工具breeze-viz入門

Spark線性代數,繪圖工具入門;scala, java下的Breeze線性代數以及資料繪圖工具breeze-viz入門

//官方地址,  https://github.com/scalanlp/breeze/wiki/Quickstar

//由於編輯器的格式原因, 自行拷貝到整合開發環境中除錯格式,  程式碼都可以正確執行

 def breezeTest: Unit ={
    //Vector支援訪問和更新,
 DenseVector是列向量
    val
x = DenseVector.zeros[Double](5) ;//構建一個5維的稠密向量
    SparseVector.zeros[Double](5)//構建稀疏向量,不會給zero分配空間

//Like Numpy, negative indices are supported, 
i<0,我們從後往前插入資料 即 x(i)= x(x.length + i) ;
//因為x支援的下標範圍是[-5,5),所以x(-1)= x(5 -1) = x(4);
 x(-1)= 6 ;
 println("firstx : " + x + "\t size : " + x.length);
 println("-1 index : " + x(-1)) ;
    /**
     *
Unlike Scalala, all Vectors are column vectors. Row vectors are
represented as Transpose[Vector[T]]
     *
     *
使用slicing,使用Range比那些slicing使用任何一個序列(sequence)都快非常多
 3 to 4 是一個Range
     */
    val  range: Range.Inclusive = 3 to 4 ;
 x(3 to 4) := .5
 x(-4)= 2 ;
 println("second  x : " + x) //DenseVector(0.0, 2.0, 0.0, 0.5, 0.5)
   
 //實際上和scala中的slice引數一樣,關鍵是第二引數是until不是 to,slice(start: Int, until: Int)
    val subVector: DenseVector[Double] = x.slice(2, 5) ;
    println("subVector: " + subVector) ;
    
/**
     *
vectorized-set operator := (:=是一個向量化集操作)
     *
The slice operator constructs a read-through and write-through view
of the given elements in the underlying vector.
     *
slice操作 為給定的Vector中資料構建一個  讀通道和寫通道視窗(view),  :=向量化集操作可以為這個  slice操作賦值.
     *
     *
你同時也可以 將 其  賦值到一個大小相容的Vector.
     */
 x(0 to 1) := DenseVector(.6,.5) // DenseVector(0.6, 0.5, 0.0, 0.5, 0.5)
    println("third
x : " + x) ;
    /**
     *
DenseMatrix
     *
密集矩陣可以同樣方式構建(呼叫建構函式),也可以訪問和更新
     */
    val m = DenseMatrix.zeros[Int](5,5) ;
    println("\nfirst m : \n" + m + "\n") ;
    println("將密集矩陣轉換為 密集向量 :" + m.toDenseVector) ;
    //The columns of m can be accessed as DenseVectors, and the rows as DenseMatrices.
    //m的列可以當做是在訪問  列向量DenseVector,行當做 DenseMatrix訪問
    //m(::,1)是訪問列,m(4, ::)訪問下標為4的行向量
    println(s"rows: ${m.rows},  cols: ${m.cols}") ;
    m(::,1):= DenseVector(8, 9, 10, 22, 11) ;//列向量
    println("m(::,1): " + m(::,1)) ;
    m(4,::) := DenseVector(1,2,3,4,5).t  // transpose to match row shape
    println("\nsecondm : \n" + m + "\n") ;
    //此隱士轉換將Double向量轉為Int向量
    implicit val d2I= new OpSet.InPlaceImpl2[DenseVector[Int],DenseVector[Double]] {
      def apply(v: DenseVector[Int], v2: DenseVector[Double]){
        v
:= DenseVector(v2.toArray.map(_.toInt))
      }
    }
    val
mCol0 = DenseVector(0.0, 2.0, 0.0, 4.5, 1.5)
    m(::,
0) := mCol0 ;
    println("\nthird
m : \n" + m + "\n") ;
//
   m := DenseMatrix.zeros[Int](3,3)
//
   java.lang.IllegalArgumentException: requirement failed: Matrices
must have same number of row
    m
:= DenseMatrix.zeros[Int](5,5)
    println("\nfouth
m : \n" + m + "\n") ;
    /**
     *
Sub-matrices can be sliced and updated, and literal matrices can be
specified using a simple tuple-based syntax.
     *
Unlike Scalala, only range slices are supported,
     *
and only the columns (or rows for a transposed matrix) can have a
Range step size different from 1.
     *
子矩陣可以被sliced和更新,使用一個簡單
 基礎元組語法(tuple-based
syntax) 字面量矩陣就能被 特例化.
     *
不像Scalala,
只有range劃分被支援,
{x(0 to 1), x是列向量}
和只有列(或者轉置矩陣的
行)有一個Range
     *
Breeze的行和列都可以用range劃分:
m(0 to 1, 0 to 1)
     */
    m(0
to 1, 0 to 1) := DenseMatrix((3,1),(-1,-2))
    println("\nfifth
m : \n" + m + "\n") ;
    /**
      3
  1   0  0  0
      -1
 -2  0  0  0
      0
  0   0  0  0
      0
  0   0  0  0
      1
  2   3  4  5
    *
    */
    /**
     *
Linear Algebra Cheat-Sheet 列舉了這些操作:
 https://github.com/scalanlp/breeze/wiki/Linear-Algebra-Cheat-Sheet
     *
Matlab或者Numpy相似,
Breeze也支援一系列操作
                                          breeze
          matlab       Numpy
    Elementwise
addition                   a + b          a + b        a + b
    Elementwise
multiplication             a :* b           a .* b         a * b
    Elementwise
comparison                 a :< b           a < b (gives matrix
of 1/0 instead of true/false)      a < b
    Inplace
addition                       a :+= 1.0      a += 1         a += 1 
(內部加)
    Inplace
elementwise multiplication     a :*= 2.0      a *= 2         a *= 2
    Vector
dot product                     a dot b,a.t * b†   dot(a,b)    
dot(a,b)
    Elementwise
sum                      sum(a)           sum(sum(a))  a.sum()
    Elementwise
max                      a.max          max(a)         a.max()
    Elementwise
argmax                     argmax(a)      argmax(a)    a.argmax()
    Ceiling
                             ceil(a)        ceil(a)      ceil(a) 
//向上取整
    Floor
                               floor(a)         floor(a)      
floor(a)
    */
    /**
     *
     *
Broadcasting:
     *
有時候需要應用一個操作到一個矩陣的每一行
或者 列,
作為一個unit
     *
例如:
你可能項計算每一行的均值(可以用於PCA中的均值化操作),或者增加一個vector到每一列
     *
適應一個矩陣以至於  操作能應用到
列式的或者行式的,
稱作廣播broadcasting
;
     *
隱士的做broadcasting,
RNumpy一樣
智慧.
     *
意味著:
如果隨機地(accidentally)新增一個矩陣或者一個向量,
他們不會阻止你 .
     *
In Breeze, 使用 *
去 表明你的意圖(signal
your intent) .
     *
  *意味著 visually(形象化地)喚醒
foreach.
     */
    import
breeze.stats.mean ;
    val
dm = DenseMatrix( (1.0, 2.0, 3.0), (4.0, 5.0, 6.0) )//3個二維向量
    val
res = dm(::, *) + DenseVector(3.0, 4.0) ; //一個二維的列向量
    println("\nfirst
res : \n" + res + "\n") ;
    println(s"rows
: ${dm.rows}, cols: ${dm.cols}") ;
    res(::,
*) := DenseVector(3.0, 4.0) ;
    println("\nsecond
res : \n" + res + "\n") ;
    //dm矩陣每一行的平均值
    val
dmean: DenseVector[Double] = mean(dm(*, ::))
    println("\nfirst
dm : \n" + dm + "\n") ;
    println("dm矩陣每一行的平均值
: " +
dmean) ;
    println("dm矩陣每一列的平均值
: " +
mean(dm(::, *))) ;
 } 


def figure: Unit ={
  /**
   * Breeze-Viz
   * 隨著版本變化, API會有大幅變化,  畢竟沒有matplotlib強大
*
   * Breeze延續了  Scalalaplotting 很多函式, 雖然API有些不同(但有很多 繼承自Scalala).
   * scaladoc文件中 以trait的形式展示在breeze.plot包中.
   * 首先, 畫一些 曲線圖 並儲存, 所有 實際的繪圖工作都是由  非常健全的JFreeChart包完成
*/
val a = new DenseVector[Int](1 to 3 toArray)
  val b = new DenseMatrix[Int](3, 3, 1 to 9 toArray)

  val f = Figure()
  val p = f.subplot(0)
  val x: DenseVector[Double] = linspace(0.0, 1.0)//曲線可畫區間
p += plot(x, x :^ 2.0)
  p += plot(x, x :^ 3.0, '.')
  p.xlabel = "x axis"
p.ylabel = "y axis"
f.saveas("/opt/scala/breeze-viz-ana/lines.png")


  /**
   * subplot增加一個子圖
* 繪製一個直方圖 : 100,000正常分佈 的隨機數 裝入 100 桶中(buckets)
   */
val p2 = f.subplot(2, 1, 1)
  val g = breeze.stats.distributions.Gaussian(0, 1)//高斯分佈
p2 += hist(g.sample(100000), 1000)
  p2.title = "A normal distribution"
p2.xlabel = "x-axis" ;
p2.ylabel = "y-axis[count]"
f.saveas("/opt/scala/breeze-viz-ana/subplots.png")

  val f2 = Figure()
  f2.subplot(0) += image(DenseMatrix.rand(200, 200))
  f2.saveas("/opt/scala/breeze-viz-ana/image.png")
}