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