読者です 読者をやめる 読者になる 読者になる

理科系の備忘録

Linux/Ubuntu/Mac/Emacs/Computer vision/Robotics

skimageでランダムフォレスト

import pandas as pd
import numpy as np
import csv as csv
from sklearn.ensemble import RandomForestClassifier
#訓練データの読み込み
train_df = pd.read_csv("train.csv", header=0)
train_df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
# Sexをダミー変数に変換(female = 0, Male = 1)してGenderカラムを追加
train_df["Gender"] = train_df["Sex"].map( {"female": 0, "male": 1} ).astype(int)
train_df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 1
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 0
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 0
# 年齢が欠損している(NaN)ものを抽出
train_df.loc[ train_df.Age.isnull() ].head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
5 6 0 3 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q 1
17 18 1 2 Williams, Mr. Charles Eugene male NaN 0 0 244373 13.0000 NaN S 1
19 20 1 3 Masselmani, Mrs. Fatima female NaN 0 0 2649 7.2250 NaN C 0
# 年齢の欠損値は、年齢の平均値で補完する
median_age = train_df["Age"].dropna().median() # 年齢がNaNの行をドロップしてメディアンをとる
if len(train_df.Age[ train_df.Age.isnull() ]) > 0: # NaN行が1つ上あるなら
    train_df.loc[ (train_df.Age.isnull()), "Age"] = median_age
# 学習に必要無い列を削除する
train_df = train_df.drop(["Name", "Ticket", "Sex", "SibSp", "Parch", "Fare", "Cabin", "Embarked","PassengerId"], axis=1) 
train_df.head(3)
Survived Pclass Age Gender
0 0 3 22.0 1
1 1 1 38.0 0
2 1 3 26.0 0
#テストデータの読み込み, Sexをダミー変数に変換
test_df = pd.read_csv("test.csv", header=0)
test_df["Gender"] = test_df["Sex"].map( {"female": 0, "male": 1} ).astype(int)
test_df.head(3)
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q 1
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S 0
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q 1
# 年齢の欠損値は、年齢の平均値で補完する
median_age = test_df["Age"].dropna().median()
if len(test_df.Age[ test_df.Age.isnull() ]) > 0:
    test_df.loc[ (test_df.Age.isnull()), "Age"] = median_age
# テストデータのPassengerId列を退避させ、テストデータの不要な列を削除する
ids = test_df["PassengerId"].values
test_df = test_df.drop(["Name", "Ticket", "Sex", "SibSp", "Parch", "Fare", "Cabin", "Embarked","PassengerId"], axis=1) 
test_df.head(3)
Pclass Age Gender
0 3 34.5 1
1 3 47.0 0
2 2 62.0 1
#ランダムフォレストで予測
train_data = train_df.values
test_data = test_df.values
model = RandomForestClassifier(n_estimators=100)
output = model.fit(train_data[0::,1::], train_data[0::,0]).predict(test_data).astype(int)
#結果を"titanic_submit.csv"として書き出す
submit_file = open("titanic_submit.csv", "w")
file_object = csv.writer(submit_file)
file_object.writerow(["PassengerId","Survived"])
file_object.writerows(zip(ids, output))
submit_file.close()

import pandas as pd
import numpy as np
import csv as csv
from sklearn.ensemble import RandomForestClassifier
#訓練データの読み込み
train_df = pd.read_csv("train.csv", header=0)
train_df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
# Sexをダミー変数に変換(female = 0, Male = 1)してGenderカラムを追加
train_df["Gender"] = train_df["Sex"].map( {"female": 0, "male": 1} ).astype(int)
train_df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 1
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 0
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 0
# 年齢が欠損している(NaN)ものを抽出
train_df.loc[ train_df.Age.isnull() ].head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
5 6 0 3 Moran, Mr. James male NaN 0 0 330877 8.4583 NaN Q 1
17 18 1 2 Williams, Mr. Charles Eugene male NaN 0 0 244373 13.0000 NaN S 1
19 20 1 3 Masselmani, Mrs. Fatima female NaN 0 0 2649 7.2250 NaN C 0
# 年齢の欠損値は、年齢の平均値で補完する
median_age = train_df["Age"].dropna().median() # 年齢がNaNの行をドロップしてメディアンをとる
if len(train_df.Age[ train_df.Age.isnull() ]) > 0: # NaN行が1つ上あるなら
    train_df.loc[ (train_df.Age.isnull()), "Age"] = median_age
# 学習に必要無い列を削除する
train_df = train_df.drop(["Name", "Ticket", "Sex", "SibSp", "Parch", "Fare", "Cabin", "Embarked","PassengerId"], axis=1) 
train_df.head(3)
Survived Pclass Age Gender
0 0 3 22.0 1
1 1 1 38.0 0
2 1 3 26.0 0
#テストデータの読み込み, Sexをダミー変数に変換
test_df = pd.read_csv("test.csv", header=0)
test_df["Gender"] = test_df["Sex"].map( {"female": 0, "male": 1} ).astype(int)
test_df.head(3)
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Gender
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q 1
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S 0
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q 1
# 年齢の欠損値は、年齢の平均値で補完する
median_age = test_df["Age"].dropna().median()
if len(test_df.Age[ test_df.Age.isnull() ]) > 0:
    test_df.loc[ (test_df.Age.isnull()), "Age"] = median_age
# テストデータのPassengerId列を退避させ、テストデータの不要な列を削除する
ids = test_df["PassengerId"].values
test_df = test_df.drop(["Name", "Ticket", "Sex", "SibSp", "Parch", "Fare", "Cabin", "Embarked","PassengerId"], axis=1) 
test_df.head(3)
Pclass Age Gender
0 3 34.5 1
1 3 47.0 0
2 2 62.0 1
#ランダムフォレストで予測
train_data = train_df.values
test_data = test_df.values
model = RandomForestClassifier(n_estimators=100)
output = model.fit(train_data[0::,1::], train_data[0::,0]).predict(test_data).astype(int)
#結果を"titanic_submit.csv"として書き出す
submit_file = open("titanic_submit.csv", "w")
file_object = csv.writer(submit_file)
file_object.writerow(["PassengerId","Survived"])
file_object.writerows(zip(ids, output))
submit_file.close()

セルオートマトンによる渋滞シミュレーション

はじめに

年末年始に渋滞学という本を読んだ。
車の渋滞だけではなく、緊急時の避難や蟻の行列、通信についても書かれていて勉強になった。

渋滞学 (新潮選書)

渋滞学 (新潮選書)

渋滞とセルオートマトン

交通をモデル化して解析することを交通流解析と呼ぶ。交通流モデルは連続モデルと離散モデルに分けられ、連続モデルでは最適速度過程がよく用いられる。離散モデルでは、セルオートマトンがよく用いられており、「渋滞学」でもこれについて説明されていた。

続きを読む

シェルスクリプトで可変長データを読み取る

はじめに

こんなデータに出くわした。data.txtとする。

1, hoge, foo, bar, piyo, [ID: 1; a; b; c; d;ID: 2; a; b; c; d;ID: 3; a; b; c; d;ID: 4; a; b; c; d;ID: 5; a; b; c; d;]
2, hoge, foo, bar, piyo, [ID: 1; a; b; c; d;]
3, hoge, foo, bar, piyo, [ID: 1; a; b; c; d;ID: 2; a; b; c; d;ID: 3; a; b; c; d;]
4, hoge, foo, bar, piyo, [ID: 1; a; b; c; d;ID: 2; a; b; c; d;]

[]で囲まれた部分が可変長のデータになっている。可変長部分から'b'だけを取り出して、縦1列に並べたい。

1   b
2   b
3   b
4   b
5   b
1   b
1   b
2   b
3   b
1   b
2   b

今回一回限りのデータ処理だったので、久々にシェルで遊ぶことにした。以下は考えた順番通りのメモ。もっといい方法はあると思うが。

実践

下ごしらえとしてawkで[ ]の部分だけを取り出す。[ ]の中と外でセパレータが違うのでありがたい。
簡単のため、最初の1行だけで処理を考える。

head -1 data.txt | awk -F ',' '{print $6}'
[ID: 1; a; b; c; d;ID: 2; a; b; c; d;ID: 3; a; b; c; d;ID: 4; a; b; c; d;ID: 5; a; b; c; d;]

awkでforを回すことも考えた。しかし今回は先に試した別の方法がうまく機能した。

head -1 awk -F, '{print $6}' | tr "ID:" "\nID:" | awk -F ';' 'NR>1{print $3}'

'ID'を検索して、'ID'が見つかるたびに改行する。すると

 [
ID 1; a; b; c; d;
ID 2; a; b; c; d;
ID 3; a; b; c; d;
ID 4; a; b; c; d;
ID 5; a; b; c; d;]

と複数の行であらわされた!あとは各行について、awkで'b'を取り出すだけだ。1行目は'['が邪魔なのでNR>1で回避しておく。

最後に、元データの各行についてこれを実行すればいいから、head -1 の部分をwhile readに変更して1行ずつ読み取るようにした。

cat data.txt | while read LINE;
do
    echo $LINE | awk -F, '{print $6}' | tr "ID:" "\nID:" | awk -F ';' 'NR>1{print $3}' | cat -n;
done
1   b
2   b
3   b
4   b
5   b
1   b
1   b
2   b
3   b
1   b
2   b

ついでに

一応関数化してみる。'cat -' で標準入力を受けられるものにした。

read_multi_frame(){
    cat - |
	awk -F, '{print $6}' |
	tr "ID:" "\nID:" |
	awk -F ';' 'NR>1{print $3}'
}
cat data.txt | while read LINE;
do
    echo $LINE | read_multi_frame | cat -n;
done

以上。

Git bashでSolarized Color

f:id:kenbell1988:20170115175537j:plain
Solarizedのdarkが大好き。
Solarized - Ethan Schoonover


自分が使うPCのターミナル(とEmacs)をすべてsolarized darkにすることで環境の差を小さくし、
会社にいながら家にいるような気持ちでリラックスしてPCに向き合える。*1

WindowsのPCにはGit bash(mintty)をインストールして、ここでシェルを書いたりコマンドを実行したりしている。
.bashrcに以下2行を書いて、対応するファイルを以下のように作ってホームディレクトリに転がしておけば、それでOK。

*1:家にいながら会社にいるような気持ちにもなる。

続きを読む

jediによるpythonコード補完 with Emacs on Windows

f:id:kenbell1988:20170122114754g:plain

背景

年始なのでEmacsの設定を見直すことにした。大学時代に作った環境をずっと使っていたが、あれからpackage.elによるパッケージ管理が主流となり、自分の環境が時代遅れのものとなっていた。(auto-completeよりはcompany-modeがいいとか)

pythonのコーディング環境はipythonで満足していたが、Emacsでも関数の補完やヘルプの表示がしたくなったので、パッケージをインストールした。インストールするパッケージはjedi。

jediとは

github.com

pythonの静的解析ライブラリで、コードの補完などに利用できる。色々なエディタで使うことができ、当然Emacsでも利用できる。

続きを読む

線分と平面の交点を求める

線分の両端点(a, b)と平面の法線ベクトル(nv)と平面上の任意の点(p)から、線分と平面の交点を求めるC++のプログラム。

線分abと平面の交点が線分abを内分する点となることから交点の座標を計算する。

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>

using namespace std;

cv::Mat Intersect3D(
		 cv::Mat& nv, // 平面の法線ベクトル cv::Mat(3,1)
		 cv::Mat& p,  // 平面上の任意の1点  cv::Mat(3,1)
		 cv::Mat& a,  // 線分の端点         cv::Mat(3,1)
		 cv::Mat& b   // 線分の端点         cv::Mat(3,1)
		 ){
  
  // 返り値
  cv::Mat ret = (cv::Mat_<double>(3,1) << 0,0,0);

  // ベクトルの準備
  cv::Mat pa, pb; // p->a, p->bのベクトル
  pa = a - p;
  pb = b - p;

  // 内積計算
  double dot_a = pa.dot(nv); // paベクトルと法線ベクトルの内積
  double dot_b = pb.dot(nv); // pbベクトルと法線ベクトルの内積
 
  // 内積が0の場合交点がなく、直線が平面に含まれる
  double MIN_DOT_TH = 0.000001;
  if( fabs(dot_a) < MIN_DOT_TH ){dot_a = 0;}
  if( fabs(dot_b) < MIN_DOT_TH ){dot_b = 0;}
  
  // 交点なし
  if( dot_a==0 && dot_b==0){
    return ret; // [0,0,0]'で返す
  }

  // 交点なし
  if( dot_a*dot_b > 0 ){
    return ret; // [0,0,0]'で返す
  }

  // 交点あり
  cv::Mat ab = b - a;
  double ratio = fabs(dot_a) / (fabs(dot_a) + fabs(dot_b) );
  ret = a + ab * (ratio);

  return ret; // 計算結果を返す
}



int main(int argc, char *argv[]){

  cv::Mat a  = (cv::Mat_<double>(3,1) << 0,0, 0); // 端点1
  cv::Mat b  = (cv::Mat_<double>(3,1) << 2,2,-2); // 端点2
  cv::Mat p  = (cv::Mat_<double>(3,1) << 0,0,-1); // 平面上の点
  cv::Mat nv = (cv::Mat_<double>(3,1) << 0,0, 1); // 法線ベクトル
  cv::Mat c = Intersect3D(nv, p, a, b); // 交点

  cout << "result: " << c << endl;
  
  return 0;
}