Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > 人工知能「Swift-Ai」

Swiftで簡単に利用可能な人工知能「Swift-Ai」

人工知能といえば今話題になっているAlphaGoの囲碁で世界チャンピオンの世界最強棋士イ・セドルさんとの戦い。 人工知能が最初の三連勝は衝撃的というか悔しいというか、それでもセドルさんはそのAlphaGoを負かしたりと 壮絶な戦いでした。ここででてくる人工知能ですがGoogleのDeepLeaningを利用した、つまり恐らくですがTensorFlowを 利用していたのではと思われます。

TensorFlowはまだiOS対応していないので人工知能をモバイルで扱うのはまだ先かなと 思っていましたが、Swift-AIという機械学習ライブラリが早速開発されているようで、ニュートラルネットワークや 行列による高速処理等がすでにできるという記事を見つけました。これは試してみる価値ありです!すでに 日本語で解説しているサイト様がありましたが、改めて自分の手で調査してみます。

サンプル画像

参考:Swiftで書かれた人工知能・機械学習ライブラリ「Swift-AI」をiOSで動かしてみるAdd Star
参考:collinhundley/Swift-AI
参考:A.I. and machine learning library written in Swift
参考:グーグルが4億ドルで買収をしたロンドンの人工知能スタートアップ、DeepMind。

やってみた

上記サイトにはサンプルを実行している画面がありましたので、同じように何個かトライしてみます。GithubからソースコードをDLします。

グラフを変えるとその状態に近づいてくるサンプル。生きてるみたい。オーガニックな動きをして人工知能な感じがします

サンプル画像

描いた手文字を認識してくれるサンプル。まだ精度は低そうではありますが、Swiftサラリーマンの顔を描いても 類似した数値を出してくれました。人口知能がどんな反応をするかっていうのも面白いですね

サンプル画像

入力文字を手書き文字で出力してくれるサンプル。これは手書きで既にDB化されたデータを出力しているのかな?

サンプル画像

カスタマイズ

さてまだ人工知能が理解をちゃんとしていない自分にしてはソースをみても理解できないと思うのですが、一度中身をみてみます。 最初のトライとしては日本語のサイトにもあった手書き認識の箇所のソースを見てみます。

どうやらSwift-AIですが現時点(2016年3月)、 フィードフォワードニューラルネットワークと、高速行列演算ライブラリ は完成しているみたい、Genetic Algorithmsというのもかな、、、はて、、、全然意味わかりません。rebuildfmでもひげぽんさんが、人工知能を学ぶなら 数学の行列を理解する必要があるよ、とのことでしたので高校が文系で行列を学ばなかった僕にはさっぱりわかっていません

まずは日本語サイト(shu223さんのはてなライブラリ)を 見本に、手書き文字を数字に認識している例のサンプルがどう動いているかを検証です。

サンプル画像<- これの検証

ソースコードは、、、HandwritingViewController.swiftからみてみましょう

サンプル画像

サンプルにあるように以下のソースコードがviewDidLoadにありました。最初にこれを使ってニュートラルネットワークを用意します


    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = NSBundle.mainBundle().URLForResource("handwriting-ffnn", withExtension: nil)!
        self.network = FFNN.fromFile(url)
        
        self.handwritingView.startPauseButton.addTarget(self, action: "startPause", forControlEvents: .TouchUpInside)
        self.handwritingView.clearButton.addTarget(self, action: "resetTapped", forControlEvents: .TouchUpInside)
        self.handwritingView.infoButton.addTarget(self, action: "infoTapped", forControlEvents: .TouchUpInside)
        
    }
    

はて、、、、このhandwriting-ffnnを読み込んでいるようですが、何なのでしょうか。

サンプル画像

サンプル画像

ファイルサイズも5.7MBのファイル。でかい。こちらが恐らくですがFFNN(ニュートラルネットワークの記憶しているデータなのではと思います),恐らく このサイズが大きくなって経験をつむのでは?と思いました。中は1~10の定義っぽいデータと、それをリンクしているような経験値情報的なものが多数。試しに、、、このファイルを空にしたらもしかしてアホになるのかな、、、、試してみます。

色々やっていると、、、なんだかうまく部分的に削除できなかったので、cp /dev/null で該当ファイルを0バイトにして実行すると、 nullエクセプションでエラー。まぁ、、そうなるかな。経験の部分だけを消して頭が悪くしたかったのですが、時間がきたので断念です。明日は続きから、、、


(2016年3月21日) 仕切り直しで進めます。アホにするために上記のファイルをイジるのは今回は後回しでまずは正規な利用方法を確認します

見本のサイトのように進めていくとHandwritingの手描き認識のページで「手書き文字がどの数字かを判断しているタイミング」は手書きが終わってからタイマー処理でscanImageという以下関数が呼ばれています。その中で以前TensorFlowを読んでいて学んでいたのですが、文字の画像データであっても[配列]で保存するようです、 Excelの行と列で保存するような数学の行列なのでしょうか。

以下、scanImage関数でピクセル部分を配列に保存している箇所です


    private func scanImage() -> [Float]? {
        var pixelsArray = [Float]()
        guard let image = self.handwritingView.canvas.image else {
            return nil
        }
        // Extract drawing from canvas and remove surrounding whitespace
        let croppedImage = self.cropImage(image, toRect: self.boundingBox!)
        // Scale character to max 20px in either dimension
        let scaledImage = self.scaleImageToSize(croppedImage, maxLength: 20)
        // Center character in 28x28 white box
        let character = self.addBorderToImage(scaledImage)
        
        self.handwritingView.imageView.image = character
        
        let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(character.CGImage))
        let data: UnsafePointer = CFDataGetBytePtr(pixelData)
        let bytesPerRow = CGImageGetBytesPerRow(character.CGImage)
        let bytesPerPixel = (CGImageGetBitsPerPixel(character.CGImage) / 8)
        var position = 0
        for _ in 0..<Int(character.size.height) {
            for _ in 0..<Int(character.size.width) {
                let alpha = Float(data[position + 3])
                pixelsArray.append(alpha / 255)
                position += bytesPerPixel
            }
            if position % bytesPerRow != 0 {
                position += (bytesPerRow - (position % bytesPerRow))
            }
        }
        
        return pixelsArray
    }

こちらですが正直ややこしいです。手書きの画像をバイナリ化してそれをpixcel配列に変換して出力しています。 僕が思うに大事なのは最終的に出力する配列を出力する形を覚えることが、機械学習への一歩なのではと考えています。(画像を処理できる数値として保存する)

以下のような感じではないでしょうか?

サンプル画像

右図の黄色マスの部分が色味や色相があれば大きな値になるだけです。

画像を「配列として捉える」という基本的な処理をわかっていないと ハマって行きそうに感じていました。僕は正直最初よくわかっていませんでした、、、、これをすることで機械に画像を効率よく覚えさせる(データとして) 事ができるといった流れなのかと思います。ちなみにGoogleの人工知能TensorFlowであればこちらのページに英語で説明がされています。 手書き数字の認識処理(MINST)が、簡単な雰囲気で記載されているのですが私には最初意味が全くわかっていませんでしたが、やはり配列で保存している ことが書かれています。

さて文字を判断するのはupdate関数というもので実施しているようです


    private func classifyImage() {
        // Extract and resize image from drawing canvas
        guard let imageArray = self.scanImage() else {
            self.clearCanvas()
            return
        }
        do {
            let output = try self.network.update(inputs: imageArray)
            if let (label, confidence) = self.outputToLabel(output) {
                self.updateOutputLabels("\(label)", confidence: "\((confidence * 100).toString(decimalPlaces: 2))%")
            } else {
                self.handwritingView.outputLabel.text = "Error"
            }
        } catch {
            print(error)
        }
        
        // Clear the canvas
        self.clearCanvas()
    }
    

networkオブジェクトのデータ型は最初に宣言したFFNNクラスです。そのupdateに先ほどのバイト配列を入れて更新すると、、、、


Printing description of output:
▿ 10 elements
  - [0] : 4.29226e-08
  - [1] : 6.6781e-06
  - [2] : 0.0671169 { ... }
  - [3] : 0.786305 { ... }
  - [4] : 3.03404e-07 { ... }
  - [5] : 3.8179e-06 { ... }
  - [6] : 3.36246e-10 { ... }
  - [7] : 4.32692e-07 { ... }
  - [8] : 3.47046e-05 { ... }
  - [9] : 0.000136177 { ... }
  

上記のようなそれぞれの数字に対する確率がかえってきます。↑の場合は 3を描いて、その3が78%の確率で合致しているとの結果の数値になります。以下のような感じ

サンプル画像

以上より、このサンプルの手書きサンプルを使うだけであればFFNNクラスを宣言して、そこにバイト配列を入れてupdateする、 だけで認識率がかえってくるようになります。ただ数字で0~9の判断のみですので、それ以外を検証したい(カスタマイズしたい)場合はどうやってやるのでしょうか。 そこまで理解できないと機械学習ニュートラルネットワークを学ぶ意味が無いので、次回は自作して顔認識処理をトライしてみようと思います!そこまで 今やると時間が足りないとのひとまず今日はここまでです。

まとめ

機械学習に関して少しずつですが理解をほんのりとだけですができてきた気がします。。。関係のある本サイトの以下記事もよろしければどうぞ

参考:Swiftサラリーマン: DeepLearningが気になって

(おまけ)行列ってなんだ?と勉強している中でお世話になったサイトです。分かりやすい〜。流石東大生のサイト様です。 おもしろおかしく理解されているからこそ賢いのかなととても関心致しました。。。その中でいつも行と列で混乱していた僕の中では目からうろこの画像がありました、、、

参考:東大生が教えるビジュアル数学

サンプル画像

これ有名な教え方なんですよねキット、、、、これ知らなかったのでいままで何度もうーんと考えていたので感謝感謝です。。。

↓こんな記事もありますよ!

Facebook SDKを試してみる#3(再調査)

SDKのインストーラが起動しても結局frameworkをドラッグドロップしなちゃ追加できない、面倒臭い、と発言してしまったのですが、 どうやらSDKをインストーラにてインストールした場合(SDK4.1)は、importするだけでどうやらSDKが追加できるとかなんとか。

URLエンコードとデコード

サーバとデータのやりとりをしているとURLエンコードしないと文字化けしちゃったりと問題がでる場合があります。 phpのurlencodeやurldecodeと連携させる場合等、Swift側でどうやってエンコードすれば良いかの方法を記載しております

WatchKitでタイマーアプリを作成する。

簡単なアプリを作成しながらAppleWatchを学んでいきます。前回の記事で大まかな動きは理解できましたので、 つぎはAppleWatchとアプリとの連携をタイマー機能を利用して検証していきます
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!