【kaggle①】初心者がタイタニック号の生存予測モデル(Titanic: Machine Learning from Disaster)をやってみる(Titanic概要 ~ データ確認)
昨今取り沙汰されているkaggleに初挑戦してみました~
今回は、初心者向けのTitanicの生存率推定の精度を上げようと挑戦してみた過程を書き残します。
このタスクを通して、日頃は得意なデータや解析手法、機械学習手法しか扱っていなかった自分を戒め、いろいろやってみた経過を書いておきます。
結果
結果からすると、17/06/11 時点で
・精度は、78.974%
・順位は、1777位タイ / 7082 teams
みたいです。
精度は80% over / 順位は3桁目指したいですね。
しかも1人正しく判定できるか否かで全然順位が変わるので、この当たりはかなりひしめき合ってますね。
Kaggleとは
Kaggleとは、世界最大レベルの機械学習コンペティションプラットフォームで、最近ではgoogleに買収されたことが話題となりました。
Kaggleは企業や研究者がデータを投稿し、世界中の統計家やデータ分析家がその最適モデルを競い合う、予測モデリング及び分析手法関連プラットフォーム及びその運営会社である。
「Kaggle」『フリー百科事典 ウィキペディア日本語版』より。
"最終更新 2016年9月1日 (木) 03:17" UTC
URL: https://ja.wikipedia.org/wiki/Kaggle
Titanic : Machine Learning from Disasterとは
In this challenge, we ask you to complete the analysis of what sorts of people were likely to survive. In particular, we ask you to apply the tools of machine learning to predict which passengers survived the tragedy.
『Titanic: Machine Learning from Disaster | Kaggle』より。
URL: https://www.kaggle.com/c/titanic
大雑把にいうと、タイタニック号の乗客の情報から傾向を見つけて、彼ら生存率を推定するタスクです。
具体的に、データセットは、train.csv(train用) / test.csv(submit用) の2つが存在し、
test.csvは、Survivedのみ情報が欠落しているため、これを推定して、KaggleサーバーにSubmitするというのがゴールになります。
データセットの詳細は次に。
0.環境とソースコード
私の環境は次の通り。
・Python 3.4.3 |Anaconda 2.3.0 (64-bit)| (default, Mar 6 2015, 12:06:10) [MSC v.1600 64 bit (AMD64)] on win32
(・お好みでseaborn)
・IPython notebookで作業
1.モジュールロード
よく使うのものは早めにコールしておきます。
#load module import csv import pandas as pd %matplotlib inline import matplotlib.pylab as plt import seaborn as sns # it's up to you import numpy as np sns.set_style("whitegrid")
【機械学習】超雑メモ2 (サポートベクターマシン(SVM)、決定木(Decision Tree))
サポートベクターマシン(SVM)
- ハイパーパラメータはグリッドサーチで最適解を求める
- [python] from sklearn.grid_search import GridSearchCV が便利
【Python】【Webアプリ】flaskで外部公開できないとき
flaskを使っていてウェブアプリを作成時に気づいたことの書き留め
何故か外部公開できない。。。
from flask import Flask, render_template, request app = Flask(__name__) .... if __name__ == "__main__": app.run(port=9999)
host設定が必要でした!
from flask import Flask, render_template, request app = Flask(__name__) .... if __name__ == "__main__": app.run(host='0.0.0.0', port=9999)
これでも繋げない場合はファイアウォールとかかな
【Android】ファイル 書き出し(保存)、追記、エラー時(Java.illegalArgumentException : File contains a path separator) 対策
android アプリにおけるjava実装で忘れやすいことをメモメモ
ファイル 書き出し(保存)、追記、エラー時(Java.illegalArgumentException : xxx contains a path separator) 対策について、実装例を上げていきます。
まず、ファイル 書き出し(保存)、追記について下記。
// 新規ファイルとしてファイル保存 // MODE_PRIVATE : 実装しているアプリのみからアクセス可能 public void writeTextToFile(String fileName, String text) { FileOutputStream fos = null; try { fos = openFileOutput(fileName, Context.MODE_PRIVATE); fos.write(text.getBytes()); } catch (IOException e) { e.printStackTrace(); } } // 既存ファイルへ追記保存 // MODE_APPEND :追記モード public void appendTextToFile(String fileName, String text) { FileOutputStream fos = null; try { fos = openFileOutput(fileName, Context.MODE_PRIVATE|Context.MODE_APPEND); fos .write(text.getBytes()); } catch (IOException e) { e.printStackTrace(); } }
これで実行時エラー(Java.illegalArgumentException : File xxx contains a path separator)が起きる場合がある
ローカル領域へ直保存する場合は問題ないが、ディレクトリ構造を持つ場合、このエラーが発生する
このエラーはFileOutputStreamインスタンスを次に修正すれば対応可能
// 新規ファイルとしてファイル保存 public void writeTextToFile(String fileName, String text) { FileOutputStream fos = null; try { //fos = openFileOutput(fileName, Context.MODE_PRIVATE); fos = new FileOutputStream(new File(fileName)); fos.write(text.getBytes()); } catch (IOException e) { e.printStackTrace(); } } // 既存ファイルへ追記保存 public void appendTextToFile(String fileName, String text) { FileOutputStream fos = null; try { //fos = openFileOutput(fileName, Context.MODE_PRIVATE|Context.MODE_APPEND); fos = new FileOutputStream(new File(fileName), true); fos .write(text.getBytes()); } catch (IOException e) { e.printStackTrace(); } }
追記モードの設定は、FileOutputStreamの第2引数=trueで設定可能
ちなみに、追記モードはtextに改行コードを入れないと素直に文字が追加される
AndroidManifest.xmlのパーミッション設定は忘れずに。
<manifest ...> ... <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
【 opencv 基礎知識 3】 異常検知アプリ作成!③ -フレーム間差分の二値化、二値変化率の認識、画像保存、検知枠の設定-
このお題目は2年前に完遂していたにも関わらず、纏めないまま放置されていたので思い出しも兼ねて書きます!
以前はC++で書いていましたが、pythonで書くと短期作業で実装できるので切り替えました。
環境は次の通り。
- windows 8.1
- python3 (anaconda3-2.3.0)
- cv2
これの続き
motojapan.hateblo.jp
今回のスクリプトでできることは、画像のような感じで、
認識エリアを設定して、その範囲に動きがあればカメラのシャッターを切るといったものです。
例えば、コルクに認識エリアを設定して、(Escキーで決定)
持っていこうとすると犯行現場が撮影される!って感じです。(逮捕!!)
おさらい(カメラ起動/終了とグレースケール画像取得)
pythonで書くとこんな感じです。
def get_gray_frame(cap, size=DEFAULT_SIZE, flip=FLIP): res, frame = cap.read() if size is not None and len(size) == 2: frame = cv2.resize(frame, size) if flip is True: frame = frame[:,::-1] gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) return gray def start_preview(device_id = DEVICE_ID): #init camera device cap = cv2.VideoCapture(device_id) while True: start = time.time() # get frame #frame = get_frame(cap) frame = get_gray_frame(cap) # display frame cv2.imshow('camera preview', frame) if cv2.waitKey(1) == 27: # wait 1msec / finish by ESC key break elapsed_time = time.time() - start sys.stdout.write('elapsed_time {:3.3f} [s] \r'.format(1 / elapsed_time)) sys.stdout.flush() # destroy window cv2.destroyAllWindows() #release camera device cap.release()
大事なところは、
1. cv2.VideoCaptureでカメラ起動、cap.release()でカメラ終了
2. cv2.VideoCaptureは引数にDEVICE_IDを設定
これはPCにWebカメラが2つ以上あった時に、DEVICE_ID=0, DEVICE_ID=1, , , のように設定します。
3. cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)でグレースケール化
ちなみに、グレースケール化したframeの中はこのような感じ
array([[139, 139, 139, ..., 165, 165, 165], [139, 139, 138, ..., 164, 164, 164], [138, 137, 136, ..., 164, 164, 164], ..., [ 63, 63, 63, ..., 103, 102, 100], [ 64, 63, 63, ..., 103, 101, 100], [ 63, 63, 63, ..., 102, 100, 99]], dtype=uint8)
フレーム間差分の二値化
これはcv2が便利な関数(cv2.absdiff/cv2.threshold)を準備しているので是非使います。
def detector(cap, detect_rect): detect = False prev_frame = None crt_frame = None while True: start = time.time() # get frame #frame = get_frame(cap) crt_frame = get_gray_frame(cap) if prev_frame is not None: # diff frame diff_frame = cv2.absdiff(crt_frame, prev_frame) # binary frame diff_b_frame = cv2.threshold(diff_frame, 50, 255, cv2.THRESH_BINARY)[1] cv2.imshow('processing preview', diff_b_frame) detect, ratio = check_detect(diff_b_frame, detect_rect) if detect: # destroy window cv2.destroyAllWindows() return crt_frame # display frame cv2.imshow('camera preview', crt_frame) if cv2.waitKey(250) == 27: # wait 250 msec / finish by ESC key break prev_frame = crt_frame elapsed_time = time.time() - start sys.stdout.write('elapsed_time {:3.3f} [s] \r'.format(1 / elapsed_time)) sys.stdout.flush() # destroy window cv2.destroyAllWindows() return None
特に
diff_frame = cv2.absdiff(crt_frame, prev_frame)
2枚のグレースケール輝度差を出力
diff_b_frame = cv2.threshold(diff_frame, 50, 255, cv2.THRESH_BINARY)[1]
グレースケール画像を2値化 (0 or 255)
(慣れていれば別ですが)これを使わず自力で書くといろいろと考慮することが発生するので、使えるものはどんどん使う。
(arrayの引き算をするにしていも dtype=uint8であるし、0-255に納めなきゃいけないし、、)
二値変化率の認識
ここまでくればあとは何をトリガーにframeを保存するかだけです。
今回は二値の変化率が一定の閾値を超えたかどうかで判断しています。
(例えば0.2)
def check_detect(b_frame, detect_rect): detect_rect.modify() window = b_frame[detect_rect.y : detect_rect.y + detect_rect.h, detect_rect.x : detect_rect.x + detect_rect.w] #check change ratio of binary values ratio = np.mean(window) / 255 if ratio > 0.2: return True, ratio return False, ratio
ポイントはこれ
ratio = np.mean(window) / 255
numpy.meanによる平均値を使いますが、二値化は0 or 255なので、255で割って0 ~ 1の範囲に収めます。
windowは検知エリアのフレーム情報です。
画像保存
検知エリアをつける場合はcv2.rectangleなどで検知エリアを書き込みます。
※ただし、今回はすべてグレースケールへ落とし込んでいるので、(255, 255, 255) -> (255, 255, 0) としても枠は白です。
# save image if initial_img is not None: save_image('./save', '0_initial_image_with_rect.png', initial_img) if detect_img is not None: save_image('./save', '1_detect_image.png', detect_img) cv2.rectangle(detect_img, (detect_rect.x, detect_rect.y), (detect_rect.x + detect_rect.w, detect_rect.y + detect_rect.h), (255, 255, 255), 2) save_image('./save', '2_detect_image_with_rect.png', detect_img)
検知枠の設定
最初に設定するものを最後に説明することになりましたが、cv2.setMouseCallbackを使ってマウス操作で検知枠を設定します。
class Rect: def __init__(self, x, y, w, h): self.x = x self.y = y self.w = w self.h = h def modify(self): if self.w < 0: self.w *= -1 self.x -= self.w if self.h < 0: self.h *= -1 self.y -= self.h class Meta: def __init__(self, window_name, img, rect): self.img = img self.img_bk =np.copy(img) self.rect = rect self.window_name = window_name def mouse_event(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: param.img = np.copy(param.img_bk) param.rect.x = x param.rect.y = y if event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON: param.img = np.copy(param.img_bk) param.rect.w = x - param.rect.x param.rect.h = y - param.rect.y cv2.rectangle(param.img, (param.rect.x, param.rect.y), (param.rect.x + param.rect.w, param.rect.y + param.rect.h), (255, 255, 255), 2) cv2.imshow(param.window_name, param.img) if event == cv2.EVENT_LBUTTONUP: param.img = np.copy(param.img_bk) param.rect.w = x - param.rect.x param.rect.h = y - param.rect.y cv2.rectangle(param.img, (param.rect.x, param.rect.y), (param.rect.x + param.rect.w, param.rect.y + param.rect.h), (255, 255, 255), 2) cv2.imshow(param.window_name, param.img) def configure_detect_rectangle(cap): crt_frame = get_gray_frame(cap) window_name = 'configure detect rectangle' detect_rect = Rect(0, 0, 0, 0) meta = Meta(window_name, crt_frame, detect_rect) cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) cv2.setMouseCallback(window_name, mouse_event, meta) cv2.imshow(window_name, crt_frame) while True: if cv2.waitKey(1) == 27: # wait 1msec / finish by ESC key break cv2.destroyAllWindows() return detect_rect, meta.img
大事なところだけ抜粋すると、この辺です。
param.img = np.copy(param.img_bk)
cv2.rectangleは第一引数のframeに直接書き込みます。
なので検知枠はドラックをしていると常に書き込まれ続けて、大量の四角形が画像に書かれてしまいます。
pythonの場合、primitive以外の型は、(=)オペレータで渡すと、shallowコピーになるので、np.copyでリフレッシュが必要。
(もっといいやり方あったら是非教えてください)
おわりに
ふぅ、終わましたね。
私の場合、昔ロードバイクのタイヤだけ盗まれるという珍事件に巻き込まれたこともあり、
2年前はロードバイクに検知枠をつけて異常があった時にメールが届くようにしていました。(写真付き)
使い方は様々でよいかと思います。(悪用はダメ)
最近だったらSlack経由で通知するとか。
ソースコードはgithubにおいてあるのでこちらからどうぞ。
github.com
【AWS】http サーバーを立てて、Webページを公開する
前回に引き続き、今回はhttpサーバーを立てて、適当なWebページを公開
index.html作成、配置
$ sudo emacs /var/www/html/index.html
<html> <head> <title>AWS http service!</title> </head> <body> <h1>Hello, EC2</h1> Hello EC2! </body> </html>
セキュリティグループ設定
前回同様、セキュリティグループ設定を行う
今回はポート番号:80
確認
クライアントPCのブラウザから次を確認
http://<パブリック IP>
するとこんな感じの画面で確認できました
OK