Matrix Arithmetic in Swift

Matrix Arithmetic in Swift

0b26590a0a8b0f1da140ed5de9b68379?s=128

USAMI Kosuke

May 15, 2019
Tweet

Transcript

  1. ߦྻΛSwiftͰ࣮૷͢Δ USAMI Kosuke Fenrir Inc.

  2. ࣗݾ঺հ • Ӊࠤݟެี • ϑΣϯϦϧגࣜձࣾ • iOS ΞϓϦ։ൃ : Swift

    / C# • ֶੜ࣌୅͸਺ֶઐ߈ • ࠷ۙɺ·ͨগ͠ਅ໘໨ʹ΍Γͩͨ͠
  3. ߦྻͱ͸ • ͜͜Ͱ͍͏ߦྻ͸ɺઢܕ୅਺Ͱग़ͯ͘ΔߦྻʢMatrixʣͷ͜ͱ • ػցֶशͳͲͰ࢖ΘΕΔ͜ͱ͔Βɺ࠷ۙগ͠஫໨͞ΕͯΔ͔΋ ͠Εͳ͍ʁ ஌ΒΜ͚Ͳɻ

  4. ߦྻΛ Swift Ͱ࣮૷ͯ͠ΈΔ • ਺ֶͷ֓೦ΛϓϩάϥϛϯάݴޠͰදݱ͢Δ໨తɿ • ਺ֶͷ֓೦Λཧղ͍ͨ͠ • ϓϩάϥϛϯάݴޠΛཧղ͍ͨ͠ •

    ࠓճ͸࣮༻౓͸͋·Γॏࢹ͠ͳ͍ • طʹ Swift for TensorFlow ͳͲ͕͋Δ
  5. ԿΛ࣮૷͢Δ͔ • ࠓճ͸ɺߦྻͷԋࢉʹண໨ͨ͠ • ଍͠ࢉ / εΧϥʔഒ / ͔͚ࢉ •

    ߦྻʹ͸ɺϕΫτϧΛϕΫτϧʹҠ͢ઢܕࣸ૾Λදݱ͢Δͱ͍ ͏ॏཁͳҙຯ͕͋Δ͕ɺࠓճ͸ѻΘͳ͍ʢͦΕʹ͸ϕΫτϧ΋ ࣮૷͢Δඞཁ͕͋ΔͷͰɾɾɾʣ
  6. ߦྻΛදݱ͢ΔͨΊͷσʔλ • ֤੒෼ͷܕ͸Կ͔ • Կߦ͋Δ͔ / Կྻ͋Δ͔ • XߦYྻͷ੒෼Λऔಘ͢Δ /

    ઃఆ͢Δ • ߦϕΫτϧ / ྻϕΫτϧ
  7. Matrix ϓϩτίϧ protocol MatrixProtocol { associatedtype Scalar: Numeric var rows:

    Int { get } var columns: Int { get } subscript(row: Int, column: Int) -> Scalar { get set } func vector(row: Int) -> [Scalar] func vector(column: Int) -> [Scalar] }
  8. ॳظԽ (1) struct Matrix : MatrixProtocol { typealias Scalar =

    Float private var grid: [Scalar] init(rows: Int, columns: Int, grid: [Scalar]) { self.rows = rows self.columns = columns self.grid = grid } }
  9. ॳظԽ (2) // ΍ͬͺΓɺ͜͏ॻ͖͍ͨΑͶ let a = Matrix(elements: [[1, 2],

    [3, 4]]) struct Matrix { init(elements: [[Scalar]]) { let rows = elements.count let columns = elements.first?.count ?? 0 let grid = elements.flatMap { $0 } self.init(rows: rows, columns: columns, grid: grid) } }
  10. ੒෼ͷऔಘͱઃఆ struct Matrix : MatrixProtocol { subscript(row: Int, column: Int)

    -> Scalar { get { return grid[row * columns + column] } set { grid[row * columns + column] = newValue } } }
  11. ߦϕΫτϧ / ྻϕΫτϧ struct Matrix : MatrixProtocol { func vector(row:

    Int) -> [Scalar] { return (0..<columns).map { self[row, $0] } } func vector(column: Int) -> [Scalar] { return (0..<rows).map { self[$0, column] } } }
  12. ԋࢉͷ࣮૷ • ߦྻͷԋࢉ • ଍͠ࢉ / εΧϥʔഒ / ͔͚ࢉ •

    ͜ΕΒΛఆٛ͢Δϓϩτίϧ͕طʹ͋ΔͳΒ४ڌ͍ͤͨ͞ • ඪ४ͷ API ʹͳΔ΂͋͘Θ͍ͤͨ • ͳ͍৔߹Ͱ΋ɺϓϩτίϧΛఆٛͯ͠४ڌͤ͞ΔΑ͏ʹ͢Δ
  13. ଍͠ࢉͷϓϩτίϧ • AdditiveArithmetic ϓϩτίϧΛ࢖͏ • Swift 5 ͷ AdditiveArithmetic protocol

    ͱ͸Կ͔ ͱ͍͏هࣄΛҎલ Qiita ʹॻ͍ͨ
  14. ଍͠ࢉͷ࣮૷ extension Matrix : AdditiveArithmetic { static func + (lhs:

    Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: lhs.columns, grid: zip(lhs.grid, rhs.grid).map(+)) } static func - (lhs: Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: lhs.columns, grid: zip(lhs.grid, rhs.grid).map(-)) } }
  15. ՝୊ : zero ͸Ͳ͏͢Δʁ protocol AdditiveArithmetic { static var zero:

    Self } • ͢΂ͯͷ੒෼͕ 0 ͷߦྻ͕θϩߦྻͰ͸͋Δͷ͕ͩɾɾɾ • ߦྻͷαΠζʹΑͬͯมΘΔͷͰɺstatic Ͱఆٛͮ͠Β͍ • ݱࡏɺྑ͍ղܾ͕ͳ͍ɾɾɾ
  16. εΧϥʔഒͷϓϩτίϧͷఆٛ • Swift for TensorFlow ʹ͋ΔͷͰͦͷ··ਅࣅ͢Δ protocol VectorNumeric { associatedtype

    Scalar: Numeric static func * (lhs: Scalar, rhs: Self) -> Self static func *= (lhs: inout Self, rhs: Scalar) }
  17. εΧϥʔഒͷ࣮૷ extension Matrix : VectorNumeric { static func * (lhs:

    Scalar, rhs: Matrix) -> Matrix { return Matrix( rows: rhs.rows, columns: rhs.columns, grid: rhs.grid.map { lhs * $0 }) } }
  18. ͔͚ࢉͷϓϩτίϧ • Swift ඪ४ͷ Numeric ͰͲ͏͔ʁ ҎԼͷϓϩύςΟ͕໰୊ protocol Numeric {

    associatedtype Magnitude : Comparable, Numeric var magnitude: Self.Magnitude { get } } • magnitude ͸ઈର஋Λฦ͢ɾɾɾߦྻʹ͸ͳ͍֓೦ • ͕ͨͬͯ͠ɺߦྻ͸ Numeric ͡Όͳ͍
  19. ͔͚ࢉͷϓϩτίϧͷఆٛ • Numeric ͔Β magnitude Λ͸ͣ͢ protocol MultiplicativeArithmetic { static

    func * (lhs: Self, rhs: Self) -> Self static func *= (lhs: inout Self, rhs: Self) }
  20. ͔͚ࢉͷ࣮૷ extension Matrix : MultiplicativeArithmetic { static func * (lhs:

    Matrix, rhs: Matrix) -> Matrix { return Matrix( rows: lhs.rows, columns: rhs.columns, grid: (0..<lhs.rows).flatMap { row in (0..<rhs.columns).map { column in zip(lhs.vector(row: row), rhs.vector(column: column)) .map(*).reduce(0, +) }}) } }
  21. ࠓޙͷ՝୊ • associatedtype ΑΓδΣωϦΫεͷ΄͏͕ྑ͍͔ʁ • ΍ͬͺΓ Numeric ʹ͍͕ͨ͠ʁ • magnitude

    ͸ߦྻ͕ࣜߟ͑ΒΕΔ͕ਖ਼ํߦྻͷΈ • ߦྻΛϕΫτϧʹ࡞༻͍ͤͨ͞ • ͜ͷߦྻΛ਌࿨͢ΔΑ͏ʹϕΫτϧΛఆٛͯ͠΍Δ