[swift]線形代数

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

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

<dl>
        <dt>BNNS</dt>
                <dd>ニューラルネットワーク</dd>
        <dt>Quadrature</dt>
                <dd>積分</dd>
        <dt>Basic Linear Algebra Subprograms (BLAS)</dt>
                <dd>線形代数</dd>
        <dt> Sparse Solvers </dt>
                <dd></dd>
</dl>

<p>CBLASを利用した例が以下だ。</p>

<pre><code>let kSize: Int32 = 15
let kSizeSize: Int = Int(kSize * kSize)
typealias FloatPointer = UnsafeMutablePointer<Float>
var matAns = FloatPointer.allocate(capacity: kSizeSize)
var mat1 = FloatPointer.allocate(capacity: kSizeSize)
var mat2 = FloatPointer.allocate(capacity: kSizeSize)
let p = unsafeBitCast(matAns, to: UnsafeMutablePointer<Float>.self)
cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
            kSize, kSize, kSize, 1, mat1, kSize, mat2, kSize, 0, p, kSize);
matAns.deallocate(capacity: kSizeSize)
</code></pre>

<p>これは辛いがしょうがないと諦めていたが、Developers.IOの<a href="https://dev.classmethod.jp/references/ios-8-accelerate-framework/">記事</a>で、la_object_tを知った。</p>

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

<pre><code>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"
        }
    }
}
</code></pre>

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

<pre><code>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)
</code></pre>

<p>以下は単位行列。</p>

<pre><code>let matE = la_identity_matrix(3, la_scalar_type_t(LA_SCALAR_TYPE_DOUBLE), la_attribute_t(LA_DEFAULT_ATTRIBUTES))
print(matE.matrixDescription)
</code></pre>

<p>これを掛けてみる。</p>

<pre><code>let matT = la_elementwise_product(matA, matE)
print(matT.matrixDescription)
</code></pre>

<pre><code>
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 
</code></pre>

<p>なんか計算できた。</p>

関連情報
<a href="https://dev.classmethod.jp/references/ios-8-accelerate-framework/">[iOS 8] Accelerate.Frameworkに加わった新たな線形代数ライブラリ</a><br />
<a href="https://developer.apple.com/documentation/accelerate/blas">BLAS</a><br />
<a href="https://qiita.com/advent-calendar/2017/cocoa">Cocoa Advent Calendar 2017</a><br />
<a href="https://cocoa-kanto.connpass.com">Cocoa勉強会 BUKURO.swift (connpass)</a><br />
<a href="https://atnd.org/groups/cocoa-study">Cocoa勉強会 BUKURO.swift (ATND)</a><br />
<a href="http://cocoa-study.peatix.com">Cocoa勉強会 BUKURO.swift (Peatix)</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk>note</a><br />
<a href="https://qiita.com/m_yukio>Qiita</a><br />