Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSエンジニアのための、SwiftからPythonのライブラリを使って機械学習する方法 / Machine Learning using Python from Swift for iOS Engineer

iOSエンジニアのための、SwiftからPythonのライブラリを使って機械学習する方法 / Machine Learning using Python from Swift for iOS Engineer

Swift 4.2では他言語のAPIをSwiftから簡単に呼び出せるようになります。これ自体は汎用的な仕組みですが、最大の目的はSwiftからPythonの資産を活用できるようにし、Python並の機械学習を実現することのようです。日々Swiftを書いているiOSエンジニアにとってこれは大きなチャンスです。このトークではiOSエンジニアに向けて、SwiftのコードでPythonのライブラリを使って機械学習する方法を紹介します。

Yuta Koshizawa

September 02, 2018
Tweet

More Decks by Yuta Koshizawa

Other Decks in Programming

Transcript

  1. iOS ΤϯδχΞͷͨΊͷɺ
    Swi$ ͔Β Python ͷϥΠϒϥϦΛ
    ࢖ͬͯػցֶश͢Δํ๏
    Yuta Koshizawa @koher

    View Slide

  2. View Slide

  3. !
    ػցֶशೖ໳

    View Slide

  4. View Slide

  5. !
    ෼ྨʢ Classifica)on ʣ

    View Slide

  6. ྫ: ݂ӷݕࠪʹΑΔഏ͕Μͷ਍அ

    View Slide

  7. ྫ: ݂ӷݕࠪʹΑΔഏ͕Μͷ਍அ
    ݈߁ͳਓͷσʔλ
    ඃݕऀ ID CYFRA (ng/ml) CEA (ng/ml)
    0001 3.0 4.0
    0002 2.8 4.5
    0003 3.1 3.7
    ... ... ...

    View Slide

  8. ྫ: ݂ӷݕࠪʹΑΔഏ͕Μͷ਍அ
    ഏ͕Μͷਓͷσʔλ
    ඃݕऀ ID CYFRA (ng/ml) CEA (ng/ml)
    1001 4.0 6.0
    1002 3.4 7.0
    1003 4.9 4.8
    ... ... ...

    View Slide

  9. ID: 0001, CYFRA: 3.0 ng/ml, CEA: 4.0 ng/ml

    View Slide

  10. ID: 0002, CYFRA: 2.8 ng/ml, CEA: 4.5 ng/ml

    View Slide

  11. ID: 0003, CYFRA: 3.1 ng/ml, CEA: 3.7 ng/ml

    View Slide

  12. ɾɾɾ

    View Slide

  13. ID: 1001, CYFRA: 4.0 ng/ml, CEA: 6.0 ng/ml

    View Slide

  14. ID: 1002, CYFRA: 3.4 ng/ml, CEA: 7.0 ng/ml

    View Slide

  15. ID: 1003, CYFRA: 4.9 ng/ml, CEA: 4.8 ng/ml

    View Slide

  16. ɾɾɾ

    View Slide

  17. ઢͷԼ → ݈߁ɺઢͷ্ → ഏ͕Μ

    View Slide

  18. CYFRA: 3.2 ng/ml, CEA: 3.8 ng/ml

    View Slide

  19. CYFRA: 4.5 ng/ml, CEA: 5.9 ng/ml

    View Slide

  20. ػցֶश
    !
    → ྑͦ͞͏ͳ௚ઢΛܾΊΔ

    View Slide

  21. y = a x + b

    View Slide

  22. y = a x + b

    View Slide

  23. y = a x + b

    View Slide

  24. y = -1.78 x + 11.1

    View Slide

  25. ௚ઢͰ෼ྨ

    View Slide

  26. ௚ઢͰ෼ྨ

    View Slide

  27. ͜Μͳσʔλͩͱʁ

    View Slide

  28. ௚ઢͰ෼ྨ͢Δͷ͸ແཧ͋Γ

    View Slide

  29. ͜ΜͳۂઢͰ෼ྨ͍ͨ͠

    View Slide

  30. ௚ઢͷࣜͰ͸ແཧ

    View Slide

  31. ΑΓෳࡶͳ͕ࣜඞཁ

    View Slide

  32. ෳࡶͳํ͕දݱྗ͕ߴͯ͘ྑ͍ʁ

    View Slide

  33. ͞ΒʹෳࡶͳࣜʹΑΔۂઢ

    View Slide

  34. CYFRA: 3.2 ng/ml, CEA: 4.7 ng/ml

    View Slide

  35. CYFRA: 3.2 ng/ml, CEA: 4.7 ng/ml

    View Slide

  36. !
    ෳࡶͳϞσϧͳΒྑ͍ͱ͍͏Θ͚Ͱ͸ͳ͍

    View Slide

  37. !
    ൚Խʢ Generaliza*on ʣ

    View Slide

  38. ͲͷΑ͏ʹ൚ԽೳྗΛධՁ͢Ε͹Α͍ʁ

    View Slide

  39. !
    !
    ܇࿅σʔλʢ Training data ʣ
    !
    ςετσʔλʢ Test data ʣ
    ʹ෼͚ͯ൚ԽೳྗΛධՁ͢Δɻ

    View Slide

  40. શσʔλ

    View Slide

  41. ܇࿅σʔλ

    View Slide

  42. ܇࿅σʔλΛ࢖ֶͬͯश

    View Slide

  43. ܇࿅σʔλ: ਫ਼౓ 100%

    View Slide

  44. ςετσʔλΛ࢖ͬͯධՁ

    View Slide

  45. ςετσʔλ: ਫ਼౓ 90.0%

    View Slide

  46. ܇࿅σʔλΛ࢖ֶͬͯश

    View Slide

  47. ܇࿅σʔλ: ਫ਼౓ 97.1%

    View Slide

  48. ςετσʔλΛ࢖ͬͯධՁ

    View Slide

  49. ςετσʔλ: ਫ਼౓ 95.8%

    View Slide

  50. ܇࿅σʔλΛ࢖ֶͬͯश

    View Slide

  51. ܇࿅σʔλ: ਫ਼౓ 89.6%

    View Slide

  52. ςετσʔλΛ࢖ͬͯධՁ

    View Slide

  53. ςετσʔλ: ਫ਼౓ 85.8%

    View Slide

  54. View Slide

  55. View Slide

  56. ܇࿅σʔλΛ 10 ഒʹ૿΍ͯ͠ΈΔ

    View Slide

  57. Overfi&ng ͷͱ͖ʢ܇࿅σʔλʣ

    View Slide

  58. Overfi&ng ͷͱ͖ʢ܇࿅σʔλʣ

    View Slide

  59. Overfi&ng ͷͱ͖ʢςετσʔλ: 90.0%ʣ

    View Slide

  60. Overfi&ng ͷͱ͖ʢςετσʔλ: 95.0%ʣ

    View Slide

  61. Underfi'ng ͷͱ͖ʢ܇࿅σʔλʣ

    View Slide

  62. Underfi'ng ͷͱ͖ʢ܇࿅σʔλʣ

    View Slide

  63. Underfi'ng ͷͱ͖ʢςετσʔλ: 85.8%ʣ

    View Slide

  64. Underfi'ng ͷͱ͖ʢςετσʔλ: 85.8%ʣ

    View Slide

  65. !
    !
    ద߹ෆ଍ʢ Underfi(ng ʣ
    !
    ա৒ద߹ʢ Overfi'ng ʣ
    Λ۠ผͯ͠ରԠํ๏Λߟ͑Δ

    View Slide

  66. ಛ௃ྔ͕ 3 ݸ͋Δ৔߹
    ඃݕऀ ID CYFRA (ng/ml) CEA (ng/ml) SCC (ng/ml)
    0001 3.0 4.0 1.1
    0002 2.8 4.5 1.4
    0003 3.1 3.7 0.9
    ... ... ... ...

    View Slide

  67. ಛ௃ྔ͕ 3 ݸ͋Δ৔߹

    View Slide

  68. ಛ௃ྔ͕ 3 ݸ͋Δ৔߹

    View Slide

  69. !
    4 ࣍ݩɾߴ࣍ݩۭؒΛ
    Πϝʔδ͢Δํ๏

    View Slide

  70. ࣍ݩ

    View Slide

  71. ෼ྨͷͨΊʹ͸ۭؒΛ෼ׂ͢Δ

    View Slide

  72. ࣍ݩͱஅ໘

    View Slide

  73. ࣍ݩͱஅ໘

    View Slide

  74. ࣍ݩͱஅ໘

    View Slide

  75. ࣍ݩͱஅ໘

    View Slide

  76. !
    ௒ۂ໘ʢ Hypersurface ʣ

    View Slide

  77. ۂ͕ͬͯͳ͍ͱ͖͸
    !
    ௒ฏ໘ʢ Hyperplane ʣ

    View Slide

  78. !
    ๏ଇੑΛݟ͚ͭग़͢
    N ࣍ݩۭؒ͸ N - 1 ࣍ݩۭؒͰ෼ׂͰ͖Δ

    View Slide

  79. ۭؒʢ 3 ࣍ݩʣ + ࣌ؒʢ 1 ࣍ݩʣ = 4 ࣍ݩʁ

    View Slide

  80. 4 ࣍ݩۭ࣌ؒͷஅ໘

    View Slide

  81. ݱࡏ͸
    4 ࣍ݩۭ࣌ؒΛ
    աڈͱະདྷʹ෼͚Δ௒ฏ໘

    View Slide

  82. !
    4 ࣍ݩ͸ۭ࣌ؒͰߟ͑Δͱ૝૾͠΍͍͢

    View Slide

  83. 2 ࣍ݩۭؒΛۂઢͰ෼͚Δ͜ͱΛߟ͑Δ

    View Slide

  84. 10 × 10 ͷ֨ࢠঢ়ͷσʔλ

    View Slide

  85. 10 × 10 ͷ֨ࢠঢ়ͷσʔλ

    View Slide

  86. ֨ࢠঢ়ͷσʔλͱ࣍ݩ
    • 2 ࣍ݩͩͱ ݅
    • 3 ࣍ݩͩͱ ݅
    • 4 ࣍ݩͩͱ ݅
    • ...
    • 80 ࣍ݩͩͱ ݅

    View Slide

  87. ֨ࢠঢ়ͷσʔλͱ࣍ݩ
    • 2 ࣍ݩͩͱ ݅
    • 3 ࣍ݩͩͱ ݅
    • 4 ࣍ݩͩͱ ݅
    • ...
    • 80 ࣍ݩͩͱ ݅ ← ؍ଌՄೳͳӉ஦ʹ͋Δݪࢠͷ਺

    View Slide

  88. !
    ߴ࣍ݩۭؒ͸ലେ
    ୯७ʹσʔλ݅਺Λ૿΍͢ํ๏Ͱ௅Ήͷ͸ແ๳

    View Slide

  89. खॻ͖਺ࣈͷ෼ྨ 1
    1 h$p:/
    /scikit-learn.org/stable/datasets/index.html#op;cal-recogni;on-of-handwri$en-digits-data-set

    View Slide

  90. 8 × 8 = 64 ըૉ

    View Slide

  91. ೖྗ͸ 64 ࣍ݩͷσʔλ

    View Slide

  92. ߴ࣍ݩۭؒͰͷ෼ྨͷΠϝʔδ

    View Slide

  93. ߴ࣍ݩۭؒͰͷ෼ྨͷΠϝʔδ

    View Slide

  94. ߴ࣍ݩۭؒͰͷ෼ྨͷΠϝʔδ

    View Slide

  95. ߴ࣍ݩۭؒͰͷ෼ྨͷΠϝʔδ

    View Slide

  96. ߴ࣍ݩۭؒͰͷ෼ྨͷΠϝʔδ

    View Slide

  97. !
    ߴ࣍ݩͰ͸ઢܗϞσϧ΋༗༻

    View Slide

  98. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  99. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  100. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  101. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  102. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  103. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  104. खॻ͖਺ࣈͷ෼ྨʢ݁Ռʣ
    train: 0.9925760950259837
    test: 0.9666666666666667

    View Slide

  105. !
    Swi% ͔Βಈతܕ෇ݴޠʹ
    ࿈ܞ͢Δͷʹ͔ܽͤͳ͍৽ػೳ

    View Slide

  106. SE-0195: @dynamicMemberLookup 2
    2 h$ps:/
    /github.com/apple/swi6-evolu9on/blob/master/proposals/0195-dynamic-member-lookup.md

    View Slide

  107. SE-0216: @dynamicCallable 3
    3 h$ps:/
    /github.com/apple/swi6-evolu9on/blob/master/proposals/0216-dynamic-callable.md

    View Slide

  108. ੩తܕ෇ݴޠͱͷ࿈ܞ
    import UIKit
    class ViewController: UIViewController {
    override func viewDidLoad() {
    super.viewDidLoad()
    }
    }

    View Slide

  109. ੩తܕ෇ݴޠͱͷ࿈ܞ
    import UIKit
    class ViewController: UIViewController {
    override func viewDidLoad() {
    super.viewDidLoab() // ίϯύΠϧΤϥʔ
    // ^
    }
    }

    View Slide

  110. ಈతܕ෇ݴޠͱͷ࿈ܞ
    import NumPy
    let a = array([[1, 2], [3, 4]])
    print(a.shape)

    View Slide

  111. ಈతܕ෇ݴޠͱͷ࿈ܞ
    import NumPy
    let a = array([[1, 2], [3, 4]])
    print(a.shabe) // ͜Ε͕ΤϥʔʹͳΔ͔࣮ߦ࣌·ͰΘ͔Βͳ͍
    // ^

    View Slide

  112. ಈతܕ෇ݴޠͱͷ࿈ܞ
    import NumPy
    let a = array([[1, 2], [3, 4]])
    print(a["shape"]) // ͜Μͳײ͕͡ Swift ʹೃછΈͦ͏

    View Slide

  113. ಈతܕ෇ݴޠͱͷ࿈ܞ
    import NumPy
    let a = array([[1, 2], [3, 4]])
    print(a.shape) // Ͱ΋͜͏ॻ͚ͳ͍ͱਏ͍

    View Slide

  114. SE-0195: @dynamicMemberLookup
    _ = foo.bar
    foo.bar = x
    // @dynamicMemberLookup Ͱ↑͕↓ͷγϯλοΫεγϡΨʔʹͳΔ
    _ = foo[dynamicMember: "bar"]
    foo[dynamicMember: "bar"] = x

    View Slide

  115. SE-0195: @dynamicMemberLookup
    @dynamicMemberLookup
    struct Foo {
    subscript(dynamicMember member: String) -> Foo {
    ...
    }
    }

    View Slide

  116. SE-0216: @dynamicCallable
    foo(42, "XYZ")
    foo(a: 42, b: "XYZ")
    // @dynamicCallable Ͱ↑͕↓ͷγϯλοΫεγϡΨʔʹͳΔ
    foo.dynamicallyCall(withArguments: [42, "XYZ"])
    foo.dynamicallyCall(withKeywordArguments: ["a": 42, "b": "XYZ"])

    View Slide

  117. SE-0216: @dynamicCallable
    @dynamicCallable
    struct Foo {
    ...
    @discardableResult
    func dynamicallyCall(withArguments: [FooConvertible]) -> Foo {
    ...
    }
    @discardableResult
    func dynamicallyCall(withKeywordArguments: [String: FooConvertible]) -> Foo {
    ...
    }
    }

    View Slide

  118. Swi$ for TensorFlow 4
    4 h$ps:/
    /medium.com/tensorflow/introducing-swi8-for-tensorflow-b75722c58df0

    View Slide

  119. !
    Swi% ͔Β Python ͷ
    ϥΠϒϥϦΛ࢖͏ํ๏

    View Slide

  120. Python
    import numpy as np
    a = np.array([[1, 2, 3], [4, 5, 6]])
    print(a.shape)

    View Slide

  121. Swi$
    import Python
    let np = Python.import("numpy")
    let a = np.array([[1, 2, 3], [4, 5, 6]])
    print(a.shape)

    View Slide

  122. View Slide

  123. Swi$
    import Python
    let np = Python.import("numpy")
    let a = np.array([[1, 2, 3], [4, 5, 6]])
    print(a.shape)

    View Slide

  124. Swi$
    import Python
    let np: PythonObject = Python.import("numpy")
    let a: PythonObject = np.array([[1, 2, 3], [4, 5, 6]])
    print(a.shape)

    View Slide

  125. PythonObject 5
    @dynamicCallable
    @dynamicMemberLookup
    public struct PythonObject {
    ...
    }
    5 h$ps:/
    /github.com/apple/swi6/blob/tensorflow/stdlib/public/Python/Python.swi6

    View Slide

  126. PythonObject 5
    public extension PythonObject {
    subscript(dynamicMember memberName: String) -> PythonObject {
    get {
    guard let member = checking[dynamicMember: memberName] else {
    fatalError("Could not access PythonObject member '\(memberName)'")
    }
    return member
    }
    nonmutating set {
    let selfObject = ownedPyObject
    defer { Py_DecRef(selfObject) }
    let valueObject = newValue.ownedPyObject
    defer { Py_DecRef(valueObject) }
    if PyObject_SetAttrString(selfObject, memberName, valueObject) == -1 {
    try! throwPythonErrorIfPresent()
    fatalError(...)
    }
    }
    }
    ...
    }
    5 h$ps:/
    /github.com/apple/swi6/blob/tensorflow/stdlib/public/Python/Python.swi6

    View Slide

  127. PythonObject 5
    public extension PythonObject {
    subscript(dynamicMember memberName: String) -> PythonObject {
    get {
    guard let member = checking[dynamicMember: memberName] else {
    fatalError("Could not access PythonObject member '\(memberName)'")
    }
    return member
    }
    nonmutating set {
    let selfObject = ownedPyObject
    defer { Py_DecRef(selfObject) }
    let valueObject = newValue.ownedPyObject
    defer { Py_DecRef(valueObject) }
    if PyObject_SetAttrString(selfObject, memberName, valueObject) == -1 {
    try! throwPythonErrorIfPresent()
    fatalError(...)
    }
    }
    }
    ...
    }
    5 h$ps:/
    /github.com/apple/swi6/blob/tensorflow/stdlib/public/Python/Python.swi6

    View Slide

  128. !
    Swi% ͔Β Python ͷ
    ϥΠϒϥϦΛ࢖ͬͯػցֶश

    View Slide

  129. खॻ͖਺ࣈͷ෼ྨʢ Python ʣ
    # Python
    # scikit-learn ͷؔ਺΍ΫϥεΛ import
    from sklearn.datasets import load_digits
    from sklearn.svm import LinearSVC
    from sklearn.model_selection import train_test_split
    # ֶश
    classifier = LinearSVC()
    dataset = load_digits()
    X_train, X_test, y_train, y_test = \
    train_test_split(dataset["data"], dataset["target"])
    classifier.fit(X_train, y_train)
    # ධՁ
    print(f"train: {classifier.score(X_train, y_train)}")
    print(f"test: {classifier.score(X_test, y_test)}")

    View Slide

  130. खॻ͖਺ࣈͷ෼ྨʢ Swi% ʣ
    import Python
    // scikit-learn ͷؔ਺΍ΫϥεΛ import
    let load_digits = Python.import("sklearn.datasets").load_digits
    let LinearSVC = Python.import("sklearn.svm").LinearSVC
    let train_test_split = Python.import("sklearn.model_selection").train_test_split
    // ֶश
    let classifier = LinearSVC()
    let dataset = load_digits()
    let (X_train, X_test, y_train, y_test)
    = train_test_split(dataset["data"], dataset["target"]).tuple4
    classifier.fit(X_train, y_train)
    // ධՁ
    print("train: \(classifier.score(X_train, y_train))")
    print("test: \(classifier.score(X_test, y_test))")

    View Slide

  131. ࣮ߦͷ༷ࢠ

    View Slide

  132. !
    ϞσϧΛ Core ML ༻ʹ
    ม׵ͯ͠ iOS ΞϓϦͰ࢖͏

    View Slide

  133. coremltools 6
    6 h$ps:/
    /github.com/apple/coremltools

    View Slide

  134. Core ML ༻ͷϞσϧΛ࡞੒
    // coremltools ͷ import
    let coremltools = Python.import("coremltools")
    // Ϟσϧͷม׵ͱอଘ
    let coreml_model = coremltools.converters.sklearn
    .convert(classifier)
    coreml_model.save("Digits.mlmodel")

    View Slide

  135. coremltools Λ import
    // coremltools ͷ import
    let coremltools = Python.import("coremltools")
    // Ϟσϧͷม׵ͱอଘ
    let coreml_model = coremltools.converters.sklearn
    .convert(classifier)
    coreml_model.save("Digits.mlmodel")

    View Slide

  136. ϞσϧΛม׵
    // coremltools ͷ import
    let coremltools = Python.import("coremltools")
    // Ϟσϧͷม׵ͱอଘ
    let coreml_model = coremltools.converters.sklearn
    .convert(classifier)
    coreml_model.save("Digits.mlmodel")

    View Slide

  137. ϞσϧΛอଘ
    // coremltools ͷ import
    let coremltools = Python.import("coremltools")
    // Ϟσϧͷม׵ͱอଘ
    let coreml_model = coremltools.converters.sklearn
    .convert(classifier)
    coreml_model.save("Digits.mlmodel")

    View Slide

  138. View Slide

  139. View Slide

  140. iOS ΞϓϦ͔Βม׵ͨ͠ϞσϧΛར༻
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  141. ෼ྨثͷੜ੒
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  142. View Slide

  143. Digits.mlmodel ͔Β෼ྨثͷΫϥε͕ࣗಈੜ੒͞ΕΔ
    class Digits {
    var model: MLModel
    convenience init() { ... }
    func prediction(input: DigitsInput) throws -> DigitsOutput {
    let outFeatures = try model.prediction(from: input)
    let result = DigitsOutput(
    classLabel: outFeatures.featureValue(for: "classLabel")!.int64Value,
    classProbability: outFeatures.featureValue(
    for: "classProbability"
    )!.dictionaryValue as! [Int64 : Double]
    )
    return result
    }
    ...
    }

    View Slide

  144. Ϙλϯ͕ԡ͞Εͨͱ͖
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  145. ෼ྨثʹ౉͢ೖྗ஋Λੜ੒
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  146. ෼ྨ
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  147. ݁ՌΛ UIAlertController Ͱදࣔ
    class ViewController: UIViewController {
    @IBOutlet var canvasView: CanvasView!
    private let classifier = Digits()
    @IBAction func pressClassifyButton(_ button: UIButton) {
    let image = Image(uiImage: canvasView.image).resizedTo(width: 8, height: 8)
    let input = try! MLMultiArray(shape: [8, 8], dataType: .double)
    var pointer = input.dataPointer.bindMemory(to: Double.self, capacity: 8 * 8)
    for pixel in image {
    pointer.pointee = Double(255 - pixel) / 16.0
    pointer += 1
    }
    let result = try! classifier.prediction(input: DigitsInput(input: input))
    let alertController = UIAlertController(title: "\(result.classLabel)", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default) { [weak self] _ in
    self?.canvasView.clear()
    })
    present(alertController, animated: true, completion: nil)
    }
    }

    View Slide

  148. Swi$Digits 7
    7 h$ps:/
    /github.com/koher/swi6-digits

    View Slide

  149. ࣮ࡍͷͱ͜Ζ
    - ϓϩμΫγϣϯ؀ڥͰ࢖͏ͷ͸·ͩා͍
    - ֶश͸ਪ࿦ΑΓ΋ະख़ͳٕज़Λ࢖͍΍͍͢
    - Python Λ஌Βͳͯ͘ྑ͍Θ͚Ͱ͸ͳ͍
    - Swift Ͱ΋ॻ͚ΔॲཧΛ Swift Ͱॻ͚Δͷ͸͏Ε͍͠
    - Swift ͷະདྷΛࠓ͔ΒମݧͰ͖Δ

    View Slide

  150. !
    ࣗ෼ͰֶͿͱ͖ʹ໾ཱͭࢿྉ

    View Slide

  151. Machine Learning | Coursera 8
    8 h$ps:/
    /www.coursera.org/learn/machine-learning

    View Slide

  152. PythonͰ͸͡ΊΔػցֶश 9
    9 h$ps:/
    /www.oreilly.co.jp/books/9784873117980/

    View Slide

  153. ѻΘͳ͔ͬͨτϐοΫ
    -
    !
    ݕূσʔλʢ Validation data ʣ
    -
    !
    લॲཧʢ Preprocessing ʣ
    -
    !
    ਖ਼ଇԽʢ Regularization ʣ
    -
    !
    ަࠩݕূʢ Cross-validation ʣ
    -
    !
    ِཅੑʢ False Positive ʣɺِӄੑʢ False Negative ʣ
    -
    !
    ద߹཰ʢ Precision ʣɺ࠶ݱ཰ʢ Recall ʣɺ
    ɹ F ஋ʢ F-measure ʣ
    - ...

    View Slide

  154. View Slide

  155. Ϟσϧͷબ୒ʹςετσʔλΛར༻ͯ͠
    ਖ਼͘͠ධՁͰ͖͍ͯΔͷ͔ʁ

    View Slide

  156. !
    ݕূσʔλʢ Valida'on data ʣ
    ͰϞσϧΛධՁͯ͠બ୒͠ɺ
    ςετσʔλͰ൚ԽೳྗΛධՁ͢Δ

    View Slide

  157. SE-0195: @dynamicMemberLookup 2
    2 h$ps:/
    /github.com/apple/swi6-evolu9on/blob/master/proposals/0195-dynamic-member-lookup.md

    View Slide

  158. SE-0216: @dynamicCallable 3
    3 h$ps:/
    /github.com/apple/swi6-evolu9on/blob/master/proposals/0216-dynamic-callable.md

    View Slide

  159. Swi$ for TensorFlow 4
    4 h$ps:/
    /medium.com/tensorflow/introducing-swi8-for-tensorflow-b75722c58df0

    View Slide

  160. Swi$ for TensorFlow ͷΠϯετʔϧ 10
    10 h%ps:/
    /github.com/tensorflow/swi8/blob/master/Installa

    View Slide

  161. Xcode 10 beta Λ࢖͏৔߹
    sudo xcode-select -s /Applications/Xcode-beta.app/

    View Slide

  162. Core ML ༻ʹϞσϧΛม׵ 11
    11 h$ps:/
    /developer.apple.com/documenta6on/coreml/conver6ngtrainedmodelstocore_ml

    View Slide

  163. coremltools 6
    6 h$ps:/
    /github.com/apple/coremltools

    View Slide

  164. ͓͠·͍

    View Slide