最近在编写代码时需要用到矩阵的操作,发现scala中关于矩阵的操作并不多(也许是有但是我还没不知道?欢迎了解人士帮忙科普),需要用到类似矩阵的cholesky分解(这是什么鬼我也不是很懂)还有矩阵求逆等,少部分逻辑比较简单的矩阵操作还能靠自己来实现,复杂的就只能求助调用matlab方法了。但是发现scala调用matlab中的方法的时候参数的传递和返回值的接收是一个问题。在此,将最近个人摸索出来的方法简单介绍一下,参数接收是没问题了,但是总是感觉效率不高,有了解此类问题其它处理办法的希望能告知一二!
首先,我是通过hdfs获取数据,我是将矩阵用文档形式存在txt等文档中,通过hdfs读取的时候用的sc.textFile("XXXXX"),因为读取方式是按行读取的,所以需要对读取到的数据进行处理 处理代码:
val transData = data.flatMap(_.split(" ")).map(_.toDouble).collect()
通过上述分解得到的transData是Array(Double)类型的,可以直接传递给matlab,实验过matlab暂时不支持Spark中的RDD数据类型,所以才有此处的数据处理。
然后再调用matlab中的方法:
val N = new MWNumericArray(2,MWClassID.DOUBLE)
val T = new MatrixOps().Chol(1,transData,N,N)
通过这个调用,可以得到初步返回结果,但是返回结果是Array[AnyRef]类型的数组,通过查看编译后的matlab对应的Java源码可以发现数组中存储的数据是依据matlab调用方法返回结果个数和调用方法时第一个传递的Int类型的参数而定的,例如在matlab源码中返回结果是(X,Y,Z),而在scala端调用方法时是new MatrixOps().Chol(2,transData,N,N),则返回结果的Array[AnyRef]中存储的就是X和Y,而且其实具体的X和Y虽然是AnyRef类型,但是存储是类似与String类型,而且数据之间会有许多空格,所以这只是未经过处理的初步结果,不可以直接使用,需要进行进一步处理。将它转化为一个Double类型的数组,个人处理代码如下:
val test = T.apply(0).toString.split(" ")
val finalArrs = for(i<- 0 to test.length-1 if !test.apply(i).equals("")&&test.apply(i)!=null)yield test.apply(i).toDouble
通过上述操作,就可通过hdfs读取一个文档中的矩阵信息,然后传递给matlab,通过调用matlab中的方法然后对数据进行处理之后再得到Double类型的数组。