Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

[swift]線形代数

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?