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 full-size slide

  2. !
    ػցֶशೖ໳

    View full-size slide

  3. !
    ෼ྨʢ Classifica)on ʣ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  17. y = -1.78 x + 11.1

    View full-size slide

  18. ௚ઢͰ෼ྨ

    View full-size slide

  19. ௚ઢͰ෼ྨ

    View full-size slide

  20. ͜Μͳσʔλͩͱʁ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  23. ௚ઢͷࣜͰ͸ແཧ

    View full-size slide

  24. ΑΓෳࡶͳ͕ࣜඞཁ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. !
    ൚Խʢ Generaliza*on ʣ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  55. ಛ௃ྔ͕ 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  60. ࣍ݩͱஅ໘

    View full-size slide

  61. ࣍ݩͱஅ໘

    View full-size slide

  62. ࣍ݩͱஅ໘

    View full-size slide

  63. ࣍ݩͱஅ໘

    View full-size slide

  64. !
    ௒ۂ໘ʢ Hypersurface ʣ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  68. 4 ࣍ݩۭ࣌ؒͷஅ໘

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  78. 8 × 8 = 64 ըૉ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  86. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  87. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  88. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  89. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  90. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  91. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  104. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  113. 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 full-size slide

  114. 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 full-size slide

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

    View full-size slide

  116. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  117. खॻ͖਺ࣈͷ෼ྨʢ 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 full-size slide

  118. ࣮ߦͷ༷ࢠ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  125. 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 full-size slide

  126. ෼ྨثͷੜ੒
    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 full-size slide

  127. 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 full-size slide

  128. Ϙλϯ͕ԡ͞Εͨͱ͖
    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 full-size slide

  129. ෼ྨثʹ౉͢ೖྗ஋Λੜ੒
    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 full-size slide

  130. ෼ྨ
    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 full-size slide

  131. ݁ՌΛ 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide