マイナスから始める機械学習入門2 Bluemixで遊ぶ
WatsonとBluemixとは?
ガチでコードを書き始める前に、IBMのWatsonで感覚を掴んでみたいと思います。
Watsonとは、専門家の思考パターンを学習させて意思決定に役立てるものです。
人の脳をコードで再現するAI(人工知能)とは異なるため「人工知能」ではない、というのがIBMの見解のようです。
IBMはWatsonを「自然言語を理解・学習し人間の意思決定を支援する"コグニティブ・コンピューティング・システム(Cognitive Computing System)"」と定義しています。
「コグニティブ」というのが、専門家の思考パターンですね。
このWatsonを使って様々なアプリを作るために必要なのが、Bluemix。
Bluemixは簡単にアプリを作るためのフレームワークと、Web上でアプリを実行させるための実行環境です。
こちらのサンプルから分かるように、
- Arduinoで室温を計ってWeb上でその変化をグラフ化する
- Twitterボットをつくる
- 質問応答システムを作成
- Twitterを分析してユーザーの性格を知る
- 脳波でラジコンを動かす
- Oculusの位置データを取得する
などがあります。
脳波でラジコンを動かしたり、Oculusの位置データを取得するのはローカル環境でもできます。
が、いざセンサのデータをネットを介して受け取ったり処理したりとなるとけっこうメンドくさいので、こういうのは有難いです。
この中でも、Twitterボットや質問応答システムにWatsonが使われています。
いきなりWatsonを使うのも良いのですが、実行環境であるBluemixのことも知っていないといけないので、まずはBluemixのセットアップからやっていきましょう。
Bluemixのセットアップ
アプリをBluemix上(クラウド上)で作成する(「Hello world」の表示)
ローカル環境でコードを書くのがベターだと思われますが、ブロックを組み合わせることでコードを書かずにアプリを作成できる「Node-RED」と組み合わせて使うこともあるかと思いますので、ひとまずはBluemix上でコードを書いていくことにします。
どうもSafariではなくGoogleChorme等でやったほうがいいみたいです。一部Flash使ってるんでしょうか。
- ダッシュボードから、「アプリの作成」を選び「WEB」をクリック
- 「SDK for Node.js」をクリック(上記のサンプルでもNode.jsを使用しているものが多いため)
- 続行をクリックして、アプリ名をつける(英語推奨・他ユーザと名前が被っているとNG)
- 少し待って、「アプリは稼働しています」の表示が出たら「GIT」をクリック
- ダッシュボードに戻り、作成されたアプリのアイコンをクリックする
- 「概要」を選択し、「GITの追加」をクリック
- 適当にIDを入力して、利用条件にチェックを入れたら「作成」を押す
- 続行を押していき、閉じるを押す
- アプリの「概要」をクリックすると右上に「コードの編集」のボタンがあるので、それをクリック
- アプリ名が書かれた左側のウィンドウから「public」→「index.html」をクリック
- 右側にコードが表示されるので、h1タグの中身を変えてみる(Hi there!から例えばHello world!)
- 「ファイル」メニュー→「保存」で保存する
- 再生ボタンのようなアイコン(ワークスペース・コンテンツを使用したアプリケーションのデプロイ)をクリックしてOKを押して、実行する
- 少し待ってアプリケーション名の左隣にあるボタンが緑色になったら、再生ボタンのようなアイコンの右2つ隣の矢印がついているアイコン(アプリケーションURLを開く)をクリック
- 変更が適用されて、アプリが実行されているのを確認できる
これが基本のようですね。次からはNode-REDをやってみたいと思います。
マイナスから始める機械学習入門1 Pythonを使えるようにする
あるプロジェクトで必要にかられて機械学習に手を出すことになりましたので、メモ代わりに。
【対象】
- ProcessingやoFでコードを書いたことはあるが、ライブラリを自分で作ったことはない
- 機械学習なにそれおいしいの?
- 日本人だから英語わからんし
- 微積?ベクトル?使わないから忘れた。線形代数って習った気がするけど何だっけ?
- 本とか買いたいけど、かけられるお金がそんなにあるわけじゃない・・・できるだけネットで済ませたい
な、ある意味でマイナスからのスタートです。私はこれ+SwiftやObjective-Cをちょっとだけ書いたレベルです。
機械学習とは?
簡単に一言でいえば、「データからパターンやルールなどを自動的に学習して、予測や分類を行ってくれるもの」でしょうか。
株価予想や積雪量予想などのコードを上げて下さっている方もみえますね。
http://qiita.com/hiroeorz@github/items/a7907bb3dd6f4e407ffd
大きく分けて、「教師あり学習」「教師なし学習」があります。
教師あり学習とは?
「これを入力したらこれを出力しなさい」という例をいくつかマシンに教えます。
そして、新しい入力が来たときに正しい出力がされるような仕組み(関数)を作ります。
分かりやすい例がメールの迷惑メールフィルタですね。
「これは迷惑メール」「これは重要なメールだよ」「これは恋人からのメールだよ」などと教えてあげることで、次から自動で分類してくれます。
教師なし学習とは?
教師なし学習では「これは迷惑メール」「これは迷惑メールじゃないよ」というお手本がありません。
データからパターンやルール、特徴を読み取ってデータを処理します。
理論は追い追い見ていくとして、まず機械学習に関するコードを書くために必要な言語、Pythonから見ていくことにします。
Pythonとは?
オブジェクト指向言語で、Google Appなどでも使われているようです。
Python開発環境インストール方法(Mac)
後から細々としたことを行う必要が出てきますが、ひとまず簡単に開発環境を整えてPythonのお勉強からスタートしたいと思います。
- ここにアクセスし、http://qiita.com/ms-rock/items/6e4498a5963f3d9c4a67 3.xのバージョンをダウンロードする
- ダウンロードされたパッケージをダブルクリックしてインストール
- ここから https://www.jetbrains.com/pycharm/download/ 開発環境「PyCharm」をダウンロードする。Communityで良いと思います
- ダウンロードされたパッケージをダブルクリックしてインストール
- PyCharmをダブルクリックして起動、「I do not have a previous version of PyCharm …」を選択してOKを押す
- 「Create a new project」を押して、新しいプロジェクトを作成する
- 名前を英語でつけるとPyCharmが起動する
- 左側のウィンドウに表示されているプロジェクト名のところ(フォルダアイコンのとなり)を右クリックして、「New」→「Python File」を選択して名前を英語でつける
- 右側のウィンドウにコードを書いて保存して、Runボタンを押す。例えば、print("Hello World!")
- 最初に実行したときは実行するファイルを選択する画面が出てくるので、先ほどつけたファイル名を選択する
Preferenceから、Editor→General→Appearanceを選択し、以下の項目をONにしておくと使いやすいかと思われます。
- 行番号を表示 Show line number
- メソッドの区切り線 Show method separators
- 空白の表示 Show whitespaces
wiki系テーマ「WP Knowledge Base Theme」のカスタマイズについて
近接センサを使う
iPhoneの前カメラ付近にある近接センサに手や顔などを近づけるとアクションが起こるものです。
どうやら近接センサが物体を検知しているときは、デフォルトで画面が真っ暗になるようです。
しかも相当手を近づけないと反応しないので、距離を測ることができず使いどころが難しいかもしれません。
import UIKit class ViewController: UIViewController { @IBOutlet weak var sencerLabel: UILabel! @IBAction func sencerStop(sender: AnyObject) { //近接センサーのOFF myDevice.proximityMonitoringEnabled = false //近接センサーの監視を解除 NSNotificationCenter.defaultCenter().removeObserver(self, name:UIDeviceProximityStateDidChangeNotification, object: nil) } //UIDeviceクラスを呼ぶ let myDevice: UIDevice = UIDevice.currentDevice() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //近接センサーのON myDevice.proximityMonitoringEnabled = true //近接センサーの通知設定 NSNotificationCenter.defaultCenter() .addObserver( self, selector: "sencerAction:", name: "UIDeviceProximityStateDidChangeNotification", object: nil ) //近接センサーを通知する NSNotificationCenter.defaultCenter() .postNotificationName( "UIDeviceProximityStateDidChangeNotification", object: nil ) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //近接センサの処理 func sencerAction(notification: NSNotification){ if myDevice.proximityState == true { //近づいた時 print("近づいた"); sencerLabel.text = "近づいた" }else{ //離れた時 print("離れた"); sencerLabel.text = "離れた" } } }
配列を検索する
配列にフィルタをかけたい場合は、こうなります。
let array = ["愛知", "北海道", "東京"] //北という文字が該当する場合 let arPredicate = NSPredicate(format: "self contains[c] '北'") //その要素を抜き出しなさい let arArray = (array as NSArray).filteredArrayUsingPredicate(arPredicate) println(arArray)
また、配列をplistに書いた場合は以下となります。
1.Supporting Filesを右クリックして、Property Listsを選択
2.RootのTypeをDictionaryからArrayに変える
3.Rootの右にある+ボタンを押してデータ追加
をした状態で、
// プロジェクトに保存されたプロパティリストのパスを取得する let filePath = NSBundle.mainBundle().pathForResource("sample", ofType: "plist") // データをプロパティリストから読み込む var array = NSArray(contentsOfFile: filePath!)! //NSArrayをArrayに変換 var arr: [String] = array as! [String] //Arrayを文字列に変換 let str = arr.reduce("") { $0 + String($1) } switch str.lowercaseString as NSString { case let str1 where str1.rangeOfString("名古屋").length != 0: println("あるよ") case let str1 where str1.rangeOfString("北海道").length != 0: println("さらにあるよ") default: println("ないよ") }
となります。
上記は条件分岐を使っていますが、単純にplistの該当データを抜き出したい場合は、
// プロジェクトに保存されたプロパティリストのパスを取得する let filePath = NSBundle.mainBundle().pathForResource("sample", ofType: "plist") // データをプロパティリストから読み込む var array = NSArray(contentsOfFile: filePath!)! //NSArrayをArrayに変換 var arr: [String] = array as! [String] //北という文字が該当する場合 let arPredicate = NSPredicate(format: "self contains[c] '北'") //その要素を抜き出しなさい let arArray = (arr as NSArray).filteredArrayUsingPredicate(arPredicate) println(arArray)
となります。
ランダムなタイミングで何かする・ランダムな間隔で何かする
ランダムなタイミングで何かすることと、ランダムな間隔で何かするというコードを書いてみました。
ランダムな間隔で何かする、のほうはわりと力技で、他に良い方法がある気がします。
まずランダムなタイミングで何かする。例えば、ボタンを押してからランダムなタイミングでイベントが起こるみたいな例です。
ボタンを設置しておいてから、結びつけておきます。
@IBAction func timeBtn(sender: AnyObject) { //0-30秒ランダム let random = arc4random() % 30 var doubleRandomNum: Double = Double(random) //遅らせる処理 let delay = doubleRandomNum * Double(NSEC_PER_SEC) var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), { println( "ザ・ワールド" ) }) }
ランダムな間隔で何かするのほうです。1秒ごとにランダムな数値を吐き出し、条件分岐で処理を行わせることで
ランダムな間隔で文字を出力しています。
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //1秒ごとにupdate()の中身を繰り返し処理を行う var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("update"), userInfo: nil, repeats: true) } func update() { //0から10までのランダムな数値を出力=0から10秒までのランダムな時間を出力 let random2 = arc4random() % 10 switch random2 { //2秒のとき case 2: println("承太郎「そして時は動き出す」") //5秒のとき case 5: println("ディオ「そして時は動き出す」") default: //どこにも当てはまらない場合の処理、必ず書く break } }
しゃべらせつつ口パクアニメーション
Siriにしゃべらせつつ口パクアニメーションを同期させるのを試してみました。
とはいっても、母音に合わせてアニメーションの口を変える・・・などということはしていません(汗
本来はまばたきは目が開いている画像・半目の画像・閉じてる画像の3枚が良いのですが、サンプルで作ったものは人間キャラのアニメーションでは
なかったので、2枚にしてあります。
また、目を開いた状態・半目・閉じた状態の3つのアニメーションのタイミングを個々に細かく記述することが難しかったため、
力技でやっています。
いい方法があればご教授ください。
目を開いた状態・半目・閉じた状態のアニメーションを作る場合は、開いた状態が2秒・半目が0.1秒・閉じた状態が0.1秒くらいです。
なので今回は開いた状態が2秒・閉じた状態が0.2秒にしています。
準備:
1.まばたき用の静止画2枚(目が開いてる画像と閉じてる画像)・口パク静止画(口開けた画像と閉じた画像)を用意し、Imageviewを配置
2.AVFoundationのフレームワークを読み込ませておく
import UIKit import AVFoundation //SpeechSynthesizerクラス var talker = AVSpeechSynthesizer() class ViewController: UIViewController,AVSpeechSynthesizerDelegate { //Siriにしゃべらせる準備 var talker = AVSpeechSynthesizer() @IBOutlet weak var eyesOnPict: UIImageView! @IBOutlet weak var mousePict: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //まばたきアニメーション 開いた状態が2秒・閉じた状態が0.2秒 //アニメーション画像の準備 var imgArray:[UIImage!] = [ UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormalZzz.png")] //アニメーション画像の設定 eyesOnPict.animationImages = imgArray //アニメーション全体の秒数 eyesOnPict.animationDuration = 2.2 //繰り返しは無限にするため0をセット eyesOnPict.animationRepeatCount = 0 //アニメーションスタート eyesOnPict.startAnimating() talker.delegate = self //口パクアニメーション //画像の準備 var imgArray2:[UIImage!] = [ UIImage(named: "mouse1.png"), UIImage(named: "mouse2.png")] //アニメーション画像の設定 mousePict.animationImages = imgArray2 //アニメーション全体の秒数 mousePict.animationDuration = 0.8 //繰り返しは無限にするため0をセット mousePict.animationRepeatCount = 0 speakBig() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func prefersStatusBarHidden() -> Bool { return true } //おしゃべりがスタートしたらどうするか func speechSynthesizer(synthesizer: AVSpeechSynthesizer!, didStartSpeechUtterance utterance: AVSpeechUtterance!) { //アニメーションスタート mousePict.startAnimating() } //おしゃべりが終わったらどうするか func speechSynthesizer(synthesizer: AVSpeechSynthesizer!, didFinishSpeechUtterance utterance: AVSpeechUtterance!) { // アニメーション終了 mousePict.stopAnimating() } func speakBig() { let speak1 = AVSpeechUtterance(string:"結局テクノロジーの歴史は欲の歴史なんだよねえ") // 言語を日本に設定 speak1.voice = AVSpeechSynthesisVoice(language: "ja-JP") //しゃべる速度 数値が大きくなるほど早い speak1.rate = 0.2 //声の高さ 数値が大きくなるほど高い speak1.pitchMultiplier = 0.4 // 実行 talker.speakUtterance(speak1) } }