CreateMLでiOSイケメン分類器をつくる。ドラッグ&ドロップのみ。

#ディープラーニングをかんたんにできるCreateML
<img width="300" alt="IMG_0574.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/241dee96-2958-2004-7228-5d8e5b3d2e3a.jpeg">
数学などの専門知識は不要です。
AppleのツールCreateMLで、あなたも簡単にディープラーニングのモデルを学習させることができます。
そして、そのモデルはiOSアプリでつかうことができます。

#データをあつめましょう
##トレーニング・データ
イケメンの画像１００枚と、イケメンではない画像１００枚をあつめました。
そして、それらをフォルダわけしました。
<img width="300" alt="スクリーンショット 2020-07-21 5.18.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7d68a1da-eec2-1da4-a516-f10386b01d90.png">
イケメンフォルダ
<img width="300" alt="スクリーンショット 2020-07-21 5.19.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/53993a6a-5e93-30bb-e1c9-f165c0970175.png">
イケメンじゃないフォルダ
<img width="300" alt="スクリーンショット 2020-07-21 5.18.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/afb0f70b-9c18-10e7-8562-5e55be41f1e6.png">
##テスティング・データ
トレーニング・データと同じフォルダ構成で、テスティング・データのフォルダもつくります。
イケメン、イケメンじゃない、10枚ずつです。
トレーニング・データに含まれない画像を用意する必要があります。
分類の子フォルダ名（この場合、「ikemen」と「ikemennot」）はトレーニング・データと同じであることが要求されます。
<img width="300" alt="スクリーンショット 2020-07-21 5.37.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/3fb92bc3-0c71-fb8b-687a-dcfe28297d44.png">


#CreateMLを起動
XcodeをControllキーを押しながらクリック、そしてOpenDeveloperTools、CreateMLを選択。
<img width="600" alt="スクリーンショット 2020-07-21 5.27.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4c6e19ed-dc42-95d4-7800-77b9d840dfed.png">
CreateMLのメニューからImage Classification（画像分類）を選びます。
<img width="600" alt="スクリーンショット 2020-07-21 5.30.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/8602dddd-210f-46ae-f808-b55b91075d0d.png">
それから、好きなプロジェクト名を入力します。
#CreatMLで画像分類モデルを学習させる

Training DataとTesting Dataの＋ボタンをクリックして、用意したフォルダを指定します。
<img width="600" alt="スクリーンショット 2020-07-21 5.34.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c9601088-be31-084d-f436-e797d2274b00.png">

それから、▶️Trainボタンを押すと学習が開始されます。
<img width="600" alt="スクリーンショット 2020-07-21 6.10.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/ef7e5ad6-7aad-997d-241e-d7b9ba4f2ab9.png">

あっという間に終わります。
<img width="600" alt="スクリーンショット 2020-07-21 5.45.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/48bff441-7260-484e-3abe-60041f5c7cab.png">

テスティング・データでテストした結果を表示してくれます。
<img width="600" alt="スクリーンショット 2020-07-21 5.46.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/8c04f3fd-aeda-a3f2-2283-53cf4a7b6d77.png">
イケメンのPrecision89%、Recall80%。
モデルがイケメンと予測した画像の89%が正解。
イケメン画像の80%がイケメンと予測されました。

Previewを選択してオリジナル画像をドロップすると、その画像でテストできます。
![スクリーンショット 2022-07-18 2.28.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7e2a71b7-709e-a813-7086-1e71c604c5f5.png)
99%の確信でイケメンではない、と予測されました。
#モデルをiOSモバイルアプリでつかう
##mlmodelをゲット
Outputタブを選択すると、学習したモデルが表示されます。
これはCoreMLモデル形式です。
Getボタンを押して、モデルを保存します。
<img width="600" alt="スクリーンショット 2020-07-21 6.01.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0006d383-9d9f-e255-42f3-8d300090937c.png">
保存されたモデルを、Xcodeプロジェクトにドラッグ＆ドロップします。
<img width="1133" alt="スクリーンショット 2020-07-21 6.07.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0f5a0c5a-45a4-a266-9bbf-6053832ebed1.png">
##Visionフレームワークでモデルをつかう
Visionフレームワークでmlmodelを手軽に使えます。
VNCoreMLRequestで、CoreMLモデルの推論リクエストをつくります。

```swift:ViewController.swift
func setupVision() -> NSError? {
        // Setup Vision parts
        let error: NSError! = nil
        
        guard let modelURL = Bundle.main.url(forResource: "ikemenclasifier 1", withExtension: "mlmodelc") else {
            return NSError(domain: "VisionObjectRecognitionViewController", code: -1, userInfo: [NSLocalizedDescriptionKey: "Model file is missing"])
        }
        do {
            let visionModel = try VNCoreMLModel(for: MLModel(contentsOf: modelURL))
            let objectRecognition = VNCoreMLRequest(model: visionModel, completionHandler: { (request, error) in
                DispatchQueue.main.async(execute: {
                    // perform all the UI updates on the main queue
                    if let results = request.results {
                        self.mlCompletion(results)
                    }
                })
            })
            self.mlRequest = [objectRecognition]
        } catch let error as NSError {
            print("Model loading went wrong: \(error)")
        }
               return error
    }
```

VNImageRequestHandlerを使って、用意した画像でCoreMLリクエストを実行します。

```swift:ViewController.swift
let imageRequestHandler = VNImageRequestHandler(ciImage: image, orientation: exifOrientation, options: [:])
            do {
                try imageRequestHandler.perform(self.mlRequest)
            } catch {
                print(error)
            }
```

リクエストは結果をVNClassificationObservationとして返します。
identifierは結果の分類名です。それは、データのフォルダ名と同じになります。この場合、「ikemen」か「ikemennot」です。
confidenceはパーセンテージの確信度です。

```swift:ViewController.swift
    func mlCompletion(_ results: [Any])  {
        guard let observation = results.first as? VNClassificationObservation else {
            print("its not ml observation")
            return
        }
        print(observation.identifier,observation.confidence)
        if observation.identifier == "ikemen" {
            resultLabel.text = "イケメン\n\(floor(observation.confidence * 100))"
            ikemenCount += 1
        } else {
            resultLabel.text = "イケメンではない\n\(floor(observation.confidence * 100))"
        }
    }
```
<img width="300" alt="IMG_0574.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/241dee96-2958-2004-7228-5d8e5b3d2e3a.jpeg">

##実際のアプリはこちら
GitHubにアプリ置いときます。
https://github.com/john-rocky/HandsomeClassifier

ぼくのTwitterをフォローしてください。お願いします。
https://twitter.com/JackdeS11

お仕事のご依頼をこのメールにお願いします。
rockyshikoku@gmail.com

あと、Looks Good For Me(わるくないね）、押してください。
　　　　　　　　ここです　↓
チャオ🐣！