トップ «前の日記(2017-11-25) 最新 次の日記(2017-11-27)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|

2017-11-26 [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 

なんか計算できた。

_ 【Cocoa練習帳】

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

トップ «前の日記(2017-11-25) 最新 次の日記(2017-11-27)» 編集