Swiftで行列を扱うために自作

概要

書籍「ニューラルネットワーク自作入門」をSwiftでコーディング。

書籍はPythonです。
Numpyを使用しています。
Numpyの代わりを自作します。

コード

import Foundation

/// 行列
struct Matrix {
    var matrix:[[Double]] = []

    func description() {
        for r in 0..<matrix.count {
            print("\(r) : \(matrix[r])")
        }
    }
    
    static func rand(rows:Int, colums:Int) -> Matrix {
        var createMatrix = Matrix()
        createMatrix.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: rows), count: colums)
        for r in 0..<rows {
            for c in 0..<colums {
                createMatrix.matrix[r] = Double.random(in: 0...1)
            }
        }
        return createMatrix
    }
    
    /// 行列の内積
    /// - parameter left: 左辺(行列)
    /// - parameter right: 右辺(行列)
    /// - returns: 結果(行列)
    static func dot(left:Matrix, right:Matrix) -> Matrix {
        var result = Matrix()
        result.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: right.matrix[0].count), count: right.matrix.count)
        for rresult in 0..<result.matrix.count {
            for cresult in 0..<result.matrix[rresult].count {
                var sum = 0.0
                for rright in 0..<right.matrix.count {
                    sum = sum + (right.matrix[rright][cresult] * left.matrix[rresult][rright])
                }
                result.matrix[rresult][cresult] = sum
            }
        }
        return result
    }
    
    /// 行列の転置
    /// - parameter input: 行列
    /// - returns: 結果(行列)
    static func transpose(input:Matrix) -> Matrix {
        var result = Matrix()
        result.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: input.matrix.count), count: input.matrix[0].count)
        for r in 0..<input.matrix.count {
            for c in 0..<input.matrix[r].count {
                result.matrix[r] = input.matrix[r]
            }
        }
        return result
    }
    
}

func - (left: Matrix, right: Double) -> Matrix {
    var result = Matrix()
    result.matrix = left.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = result.matrix[r] - right
        }
    }
    return result
}

func - (left: Double, right: Matrix) -> Matrix {
    var result = Matrix()
    result.matrix = right.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = left - result.matrix[r]
        }
    }
    return result
}

func - (left: Matrix, right: Matrix) -> Matrix {
    var result = Matrix()
    result.matrix = left.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = result.matrix[r] - right.matrix[r]
        }
    }
    return result
}

func + (left: Matrix, right: Matrix) -> Matrix {
    var result = Matrix()
    result.matrix = left.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = result.matrix[r] + right.matrix[r]
        }
    }
    return result
}

/// 行列の要素同士の掛け算
/// - parameter left: 左辺(行列)
/// - parameter right: 右辺(行列)
/// - returns: 結果(行列)
func * (left: Matrix, right: Matrix) -> Matrix {
    var result = Matrix()
    result.matrix = left.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = result.matrix[r] * right.matrix[r]
        }
    }
    return result
}

/// 行列の要素同士の掛け算
/// - parameter left: 左辺(数値)
/// - parameter right: 右辺(行列)
/// - returns: 結果(行列)
func * (left: Double, right: Matrix) -> Matrix {
    var result = Matrix()
    result.matrix = right.matrix
    for r in 0..<result.matrix.count {
        for c in 0..<result.matrix[r].count {
            result.matrix[r] = left * result.matrix[r]
        }
    }
    return result
}

example

var a = Matrix()
a.matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
var b = Matrix()
b.matrix = [[1, 2, 3]]
print("転置")
let c = Matrix.transpose(input: b)
print(c.description())

print("内積")
print(Matrix.dot(left: a, right: c).description())

print("行列の要素同士の掛け算")
print((a * a).description())

print("行列の足し算")
print((a + a).description())

print("行列の引き算")
print((a - a).description())
転置
0 : [1.0]
1 : [2.0]
2 : [3.0]
()
内積
0 : [14.0]
1 : [32.0]
2 : [50.0]
()
行列の要素同士の掛け算
0 : [1.0, 4.0, 9.0]
1 : [16.0, 25.0, 36.0]
2 : [49.0, 64.0, 81.0]
()
行列の足し算
0 : [2.0, 4.0, 6.0]
1 : [8.0, 10.0, 12.0]
2 : [14.0, 16.0, 18.0]
()
行列の引き算
0 : [0.0, 0.0, 0.0]
1 : [0.0, 0.0, 0.0]
2 : [0.0, 0.0, 0.0]
()

Action Item

  • 整理
  • 初期化処理
  • class化検討・判断
  • Numpy.random.normal検討
  • パラメータチェック
  • 異常系

memo

SwiftでPythonが使える(ようになる)らしい。
記事「今、僕が一番注目している Swift の新機能について、 iOSDC Japan 2018 で話します」

Swift

Posted by shi-n