Posted at
CocoaDay 6

[swift]線形代数

More than 1 year has passed since last update.

自分の長期的な課題は数式処理と神経回路網だ。後者については、過去何度か挑戦しているが、最近の深層学習ブームのおかげで情報と道具が充実してきたので、またまた、挑戦する。

Accelerate Framework。以前は、CPUの演算アクセラレータを利用する手段でしたが、徐々に数値計算関連のものが追加されていて、今になって分かるのだが、神経回路網関連のものが徐々に用意されている。最上位はCoreMLということになると思うが自分で実装したいということで、線形代数関連を選択する。


BNNS

ニューラルネットワーク

Quadrature

積分

Basic Linear Algebra Subprograms (BLAS)

線形代数

Sparse Solvers


CBLASを利用した例が以下だ。

let kSize: Int32 = 15

let kSizeSize: Int = Int(kSize * kSize)
typealias FloatPointer = UnsafeMutablePointer
var matAns = FloatPointer.allocate(capacity: kSizeSize)
var mat1 = FloatPointer.allocate(capacity: kSizeSize)
var mat2 = FloatPointer.allocate(capacity: kSizeSize)
let p = unsafeBitCast(matAns, to: UnsafeMutablePointer.self)
cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
kSize, kSize, kSize, 1, mat1, kSize, mat2, kSize, 0, p, kSize);
matAns.deallocate(capacity: kSizeSize)

これは辛いがしょうがないと諦めていたが、Developers.IOの記事で、la_object_tを知った。

Developers.IOの記事で紹介されているデバッグ出力用のコードは、古いSwiftのものなので、今時点のものに更新した。

extension la_object_t {

public var rows: UInt {
return UInt(la_matrix_rows(self))
}

public var cols: UInt {
return UInt(la_matrix_cols(self))
}

public var toArray: [Double] {
var arrayBuf = [Double](repeating: 0.0, count: Int(rows * cols))
let status = la_matrix_to_double_buffer(&arrayBuf, cols, self)
return arrayBuf
}

public var matrix: [[Double]] {
var matrix = [[Double]]()
for row in 1...rows {
let firstCol = Int(cols * (row - 1))
let lastCol = Int(cols * row - 1)
let partCols = Array(toArray[firstCol...lastCol])
matrix.append(partCols)
}
return matrix
}

public var matrixDescription: String {
return matrix.reduce("")
{(acc, rowVals) in
acc +
rowVals.reduce(""){(ac, colVal) in ac + "\(colVal) "} +
"\n"
}
}
}

BLASを直接利用する場合、行列のメモリ配列をC言語の二次元配列なのか、Fortranなのかがあるが、la_object_tだと以下のとおり。

var matABuf: [Double] =

[1, 2, 3,
4, 5, 6,
7, 8, 9]
let matA = la_matrix_from_double_buffer(matABuf,
3, /* 行数 */
3, /* 列数 */
3, /* 改行ごとにメモリバッファをスライドさせる幅 */
la_hint_t(LA_NO_HINT),
la_attribute_t(LA_DEFAULT_ATTRIBUTES))
print(matA.matrixDescription)

以下は単位行列。

let matE = la_identity_matrix(3, la_scalar_type_t(LA_SCALAR_TYPE_DOUBLE), la_attribute_t(LA_DEFAULT_ATTRIBUTES))

print(matE.matrixDescription)

これを掛けてみる。

let matT = la_elementwise_product(matA, matE)

print(matT.matrixDescription)


1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0

1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0

1.0 0.0 0.0
0.0 5.0 0.0
0.0 0.0 9.0

なんか計算できた。

関連情報

[iOS 8] Accelerate.Frameworkに加わった新たな線形代数ライブラリ


BLAS


Cocoa Advent Calendar 2017


Cocoa勉強会 BUKURO.swift (connpass)


Cocoa勉強会 BUKURO.swift (ATND)


Cocoa勉強会 BUKURO.swift (Peatix)

【Cocoa練習帳】

http://www.bitz.co.jp/weblog/


http://ameblo.jp/bitz/(ミラー・サイト)


Qiita