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

3c031541ed3d92869414857dfef853de?s=47 Yuta Koshizawa
September 02, 2018

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のライブラリを使って機械学習する方法を紹介します。

3c031541ed3d92869414857dfef853de?s=128

Yuta Koshizawa

September 02, 2018
Tweet

Transcript

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

  2. None
  3. ! ػցֶशೖ໳

  4. None
  5. ! ෼ྨʢ Classifica)on ʣ

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

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

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

    4.0 6.0 1002 3.4 7.0 1003 4.9 4.8 ... ... ...
  9. ID: 0001, CYFRA: 3.0 ng/ml, CEA: 4.0 ng/ml

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

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

  12. ɾɾɾ

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

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

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

  16. ɾɾɾ

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

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

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

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

  21. y = a x + b

  22. y = a x + b

  23. y = a x + b

  24. y = -1.78 x + 11.1

  25. ௚ઢͰ෼ྨ

  26. ௚ઢͰ෼ྨ

  27. ͜Μͳσʔλͩͱʁ

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

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

  30. ௚ઢͷࣜͰ͸ແཧ

  31. ΑΓෳࡶͳ͕ࣜඞཁ

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

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

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

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

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

  37. ! ൚Խʢ Generaliza*on ʣ

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

  39. ! ! ܇࿅σʔλʢ Training data ʣ ! ςετσʔλʢ Test data

    ʣ ʹ෼͚ͯ൚ԽೳྗΛධՁ͢Δɻ
  40. શσʔλ

  41. ܇࿅σʔλ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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 ... ... ... ...
  67. ಛ௃ྔ͕ 3 ݸ͋Δ৔߹

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

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

  70. ࣍ݩ

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

  72. ࣍ݩͱஅ໘

  73. ࣍ݩͱஅ໘

  74. ࣍ݩͱஅ໘

  75. ࣍ݩͱஅ໘

  76. ! ௒ۂ໘ʢ Hypersurface ʣ

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

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

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

  80. 4 ࣍ݩۭ࣌ؒͷஅ໘

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

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

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

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

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

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

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

    4 ࣍ݩͩͱ ݅ • ... • 80 ࣍ݩͩͱ ݅ ← ؍ଌՄೳͳӉ஦ʹ͋Δݪࢠͷ਺
  88. ! ߴ࣍ݩۭؒ͸ലେ ୯७ʹσʔλ݅਺Λ૿΍͢ํ๏Ͱ௅Ήͷ͸ແ๳

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

  90. 8 × 8 = 64 ըૉ

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

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

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

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

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

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

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

  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)}")
  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)}")
  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)}")
  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)}")
  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)}")
  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)}")
  104. खॻ͖਺ࣈͷ෼ྨʢ݁Ռʣ train: 0.9925760950259837 test: 0.9666666666666667

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

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

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

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

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

    { super.viewDidLoab() // ίϯύΠϧΤϥʔ // ^ } }
  110. ಈతܕ෇ݴޠͱͷ࿈ܞ import NumPy let a = array([[1, 2], [3, 4]])

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

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

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

    print(a.shape) // Ͱ΋͜͏ॻ͚ͳ͍ͱਏ͍
  114. SE-0195: @dynamicMemberLookup _ = foo.bar foo.bar = x // @dynamicMemberLookup

    Ͱ↑͕↓ͷγϯλοΫεγϡΨʔʹͳΔ _ = foo[dynamicMember: "bar"] foo[dynamicMember: "bar"] = x
  115. SE-0195: @dynamicMemberLookup @dynamicMemberLookup struct Foo { subscript(dynamicMember member: String) ->

    Foo { ... } }
  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"])
  117. SE-0216: @dynamicCallable @dynamicCallable struct Foo { ... @discardableResult func dynamicallyCall(withArguments:

    [FooConvertible]) -> Foo { ... } @discardableResult func dynamicallyCall(withKeywordArguments: [String: FooConvertible]) -> Foo { ... } }
  118. Swi$ for TensorFlow 4 4 h$ps:/ /medium.com/tensorflow/introducing-swi8-for-tensorflow-b75722c58df0

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

  120. Python import numpy as np a = np.array([[1, 2, 3],

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

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

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

    PythonObject = np.array([[1, 2, 3], [4, 5, 6]]) print(a.shape)
  125. PythonObject 5 @dynamicCallable @dynamicMemberLookup public struct PythonObject { ... }

    5 h$ps:/ /github.com/apple/swi6/blob/tensorflow/stdlib/public/Python/Python.swi6
  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
  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
  128. ! Swi% ͔Β Python ͷ ϥΠϒϥϦΛ࢖ͬͯػցֶश

  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)}")
  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))")
  131. ࣮ߦͷ༷ࢠ

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

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

  134. Core ML ༻ͷϞσϧΛ࡞੒ // coremltools ͷ import let coremltools =

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

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

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

    Ϟσϧͷม׵ͱอଘ let coreml_model = coremltools.converters.sklearn .convert(classifier) coreml_model.save("Digits.mlmodel")
  138. None
  139. None
  140. iOS ΞϓϦ͔Βม׵ͨ͠ϞσϧΛར༻ class ViewController: UIViewController { @IBOutlet var canvasView: CanvasView!

    private let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  141. ෼ྨثͷੜ੒ class ViewController: UIViewController { @IBOutlet var canvasView: CanvasView! private

    let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  142. None
  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 } ... }
  144. Ϙλϯ͕ԡ͞Εͨͱ͖ class ViewController: UIViewController { @IBOutlet var canvasView: CanvasView! private

    let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  145. ෼ྨثʹ౉͢ೖྗ஋Λੜ੒ class ViewController: UIViewController { @IBOutlet var canvasView: CanvasView! private

    let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  146. ෼ྨ class ViewController: UIViewController { @IBOutlet var canvasView: CanvasView! private

    let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  147. ݁ՌΛ UIAlertController Ͱදࣔ class ViewController: UIViewController { @IBOutlet var canvasView:

    CanvasView! private let classifier = Digits() @IBAction func pressClassifyButton(_ button: UIButton) { let image = Image<UInt8>(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) } }
  148. Swi$Digits 7 7 h$ps:/ /github.com/koher/swi6-digits

  149. ࣮ࡍͷͱ͜Ζ - ϓϩμΫγϣϯ؀ڥͰ࢖͏ͷ͸·ͩා͍ - ֶश͸ਪ࿦ΑΓ΋ະख़ͳٕज़Λ࢖͍΍͍͢ - Python Λ஌Βͳͯ͘ྑ͍Θ͚Ͱ͸ͳ͍ - Swift

    Ͱ΋ॻ͚ΔॲཧΛ Swift Ͱॻ͚Δͷ͸͏Ε͍͠ - Swift ͷະདྷΛࠓ͔ΒମݧͰ͖Δ
  150. ! ࣗ෼ͰֶͿͱ͖ʹ໾ཱͭࢿྉ

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

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

  153. ѻΘͳ͔ͬͨτϐοΫ - ! ݕূσʔλʢ Validation data ʣ - ! લॲཧʢ

    Preprocessing ʣ - ! ਖ਼ଇԽʢ Regularization ʣ - ! ަࠩݕূʢ Cross-validation ʣ - ! ِཅੑʢ False Positive ʣɺِӄੑʢ False Negative ʣ - ! ద߹཰ʢ Precision ʣɺ࠶ݱ཰ʢ Recall ʣɺ ɹ F ஋ʢ F-measure ʣ - ...
  154. None
  155. Ϟσϧͷબ୒ʹςετσʔλΛར༻ͯ͠ ਖ਼͘͠ධՁͰ͖͍ͯΔͷ͔ʁ

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

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

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

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

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

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

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

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

  164. ͓͠·͍