ギークなエンジニアを目指す男

基幹系SIerがWeb系とかネイティブ系の知識を蓄えようとするブログ

MENU

Pythonで決定木とRandomForestを比較してみる。その2(タイタニック生存者予測)

本日はタイタニック生存者予測をRandomForestを用いて行なってみたいと思います。

決定木で行なった記事はこちら

taxa-program.hatenablog.com

コード

モデルを使用するまでの部分は前回と一緒です

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

#トレーニングデータ欠損値処理
train['Fare'] = train['Fare'].fillna(train['Fare'].median())
train['Age'] = train['Age'].fillna(train['Age'].median())
train['Embarked'] = train['Embarked'].fillna('S')

#トレーニングデータカテゴリ変数の変換
train['Sex'] = train['Sex'].apply(lambda x: 1 if x == 'male' else 0)
train['Embarked'] = train['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)

#検証データ欠損値処理
test['Fare'] = test['Fare'].fillna(test['Fare'].median())
test['Age'] = test['Age'].fillna(test['Age'].median())
test['Embarked'] = test['Embarked'].fillna('S')

#検証データカテゴリ変数の変換
test['Sex'] = test['Sex'].apply(lambda x: 1 if x == 'male' else 0)
test['Embarked'] = test['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)


## RandomForest
from sklearn.ensemble import RandomForestClassifier

target = train["Survived"].values
features_one = train[["Pclass", "Sex", "Age", "Fare"]].values

# モデルの作成
clf_RF = RandomForestClassifier(random_state=0)
clf_RF = clf_RF.fit(features_one, target)

# 予測
pred_RF = clf_RF.predict(test_features)

# PassengerIdを取得
PassengerId = np.array(test["PassengerId"]).astype(int)

# my_prediction(予測データ)とPassengerIdをデータフレームへ落とし込む
my_solution = pd.DataFrame(pred, PassengerId, columns = ["Survived"])

# my_tree_one_RF.csvとして書き出し
my_solution.to_csv("my_tree_one_RF.csv", index_label = ["PassengerId"])

ここまででCSVへの書き出し処理は終了です。

Kaggleに提出してみる

今回出力したデータをKaggleへ提出してみます。

f:id:taxa_program:20180521002148p:plain

「0.71291」なので決定木のときと一緒でした。

てっきりRandomForestの方が良いスコアがでると思っていましたが、これは予想外でした。

次は、今回使用しなかった説明変数も学習させて、より良いモデルの作成を行なっていきたいと思います。

Pythonで決定木とRandomForestを比較してみる。その1(タイタニック生存者予測)

今回は、Kaggle初心者向けに公開されているデータセットを使ってタイタニックの生存者予測」Pythonを使って行います。

データセットは下記Kaggleサイトからダウンロードをお願いします。 Titanic: Machine Learning from Disaster | Kaggle

データを傍観してみる

とりあえず必要なライブラリをimportして、データを見てみます。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

# CSVデータの読み込み
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

# データ確認
train.head()

f:id:taxa_program:20180518231858p:plain

# テストデータも確認してみる
test.head()

f:id:taxa_program:20180518232000p:plain

ちなみに各項目はこんな感じです。

  • PassengerId – 乗客識別ユニークID
  • Survived – 生存フラグ(0=死亡、1=生存)
  • Pclass – チケットクラス
  • Name – 乗客の名前
  • Sex – 性別(male=男性、female=女性)
  • Age – 年齢
  • SibSp – タイタニックに同乗している兄弟/配偶者の数
  • parch – タイタニックに同乗している親/子供の数
  • ticket – チケット番号
  • fare – 料金
  • cabin – 客室番号
  • Embarked – 出港地(タイタニックへ乗った港)

試しに、男女の生存者を比較してみましょう。なんとなくですが、女性の方が生き残っていたような記憶があります。

# プロット
sns.countplot('Sex',hue='Survived',data=train)

f:id:taxa_program:20180518232258p:plain

やはり女性の方が生存者が多いようです。

統計情報もみておきましょう。

train.describe()

f:id:taxa_program:20180518232452p:plain

数値データでは、Ageのデータが少し欠損していることがわかります。
ぜひ、testデータの統計情報も確認して見てください。

データセットの欠損データチェック

提供されている(または使う)データセットで100%データが揃っていることは珍しいようです。どこかのデータが欠損してたり、信用性が低いため使えなかったりする場合がほとんどみたい。

前のセクションで、Ageデータが欠損していることはわかりましたが、数値項目以外もまとめてみてみます。

## ataframeの欠損データをisnull()で探して、カラム毎に返す関数
def kesson_table(df): 
        null_val = df.isnull().sum()
        percent = 100 * df.isnull().sum()/len(df)
        kesson_table = pd.concat([null_val, percent], axis=1)
        kesson_table_ren_columns = kesson_table.rename(
        columns = {0 : '欠損数', 1 : '%'})
        return kesson_table_ren_columns
 
kesson_table(train)
kesson_table(test)

f:id:taxa_program:20180518233006p:plain f:id:taxa_program:20180518233020p:plain

左がtrainで右がtestです。「Age」と「Cabin」の2つの項目で欠損が多いことがわかります。

データセットの事前処理

欠損データを放っておくのはあまりよろしくないので、欠損データを代理データに入れ替えます。さらに、文字列カテゴリカルデータを数字へ変換していきます。
今回はCabinの値は使用しないので、その他の欠損値を代理データに入れ替えていきます。

まず「Fare」「Age」ですが、シンプルに train の全データの中央値(Median)を代理として使いましょう。(代理データで何を使うか、どのような処理を加えるかは非常に重要かつ大きな議論ではありますが、ここはシンプルに考えて進めます)

次に「Embarked」(出港地)ですが、こちらも2つだけ欠損データが train に含まれています。他のデータを確認すると「S」が一番多い値でしたので、代理データとして「S」を使いましょう。

#欠損値処理
train['Fare'] = train['Fare'].fillna(train['Fare'].median())
train['Age'] = train['Age'].fillna(train['Age'].median())
train['Embarked'] = train['Embarked'].fillna('S')

# 欠損値の確認
kesson_table(train)

Cabon以外の欠損値がなくなったことがわかるかと思います。 f:id:taxa_program:20180518234636p:plain

次はカテゴリカルデータの文字列を数字に変換しましょう。今回の予想で使う項目で文字列を値として持っているカラムは「Sex」と「Embarked」の2種類となります。Sexは「male」「female」の2つのカテゴリー文字列、Embarkedはは「S」「C」「Q」の3つの文字列となります。これらを数字に変換しましょう。

#カテゴリ変数の変換
train['Sex'] = train['Sex'].apply(lambda x: 1 if x == 'male' else 0)
train['Embarked'] = train['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
# データを表示してみる
train.head(10)

数字に置換されました。 f:id:taxa_program:20180518234922p:plain

testに関しても同様の処理を行います。

#欠損値処理
test['Fare'] = test['Fare'].fillna(test['Fare'].median())
test['Age'] = test['Age'].fillna(test['Age'].median())
test['Embarked'] = test['Embarked'].fillna('S')
#カテゴリ変数の変換
test['Sex'] = test['Sex'].apply(lambda x: 1 if x == 'male' else 0)
test['Embarked'] = test['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)

決定木

scikit-learnから決定木をimportし、モデルを作成していきます。

from sklearn.tree import DecisionTreeClassifier

# トレーニングデータの分割
target = train["Survived"].values
features_one = train[["Pclass", "Sex", "Age", "Fare"]].values

# モデル(決定木の作成)の作成
clf = DecisionTreeClassifier(random_state=0)
clf = clf.fit(features_one, target)

# 「test」の説明変数の値を取得
test_features = test[["Pclass", "Sex", "Age", "Fare"]].values

# 予測と結果の表示
pred = clf.predict(test_features)
print(pred)

f:id:taxa_program:20180519000042p:plain

こんな感じで1と0の羅列が結果として得られました。

Kaggleに投稿してみる

この予測データをCSVへ書き出してKaggleへ投稿してみましょう。
下記のコードでPassengerIdと予測値を取得してCSVファイルを書き出します。

# PassengerIdを取得
PassengerId = np.array(test["PassengerId"]).astype(int)

# my_prediction(予測データ)とPassengerIdをデータフレームへ落とし込む
my_solution = pd.DataFrame(my_prediction, PassengerId, columns = ["Survived"])

# my_tree_one.csvとして書き出し
my_solution.to_csv("my_tree_one.csv", index_label = ["PassengerId"])

結果は・・・

f:id:taxa_program:20180519001513p:plain

結果として「0.71291」のスコアが獲得できました。

Kaggleのスコアはコンペにより異なるようです。(各コンペの「Evaluation」のページに詳細が記載されています)

今回予測を行なったタイタニックのコンペでは予測スコアは単純に「Accuracy(正解率)」が使われていますので、今作った「my_tree_one」は約71.3%の確率で正解を予測できましたということになります。

いかがでしたでしょうか。

次回はもう少し精度をあげる努力をしてみます。

重回帰分析を行なってみたことのまとめ。その2(Python)

前回に引き続き、重回帰分析を行なっていきます。
今回は実際にモデルを作成し、そのモデルを使って訓練→検証をおこないます。

前回記事はこちら

taxa-program.hatenablog.com

  • モデルの構築と検証
  • 訓練データと検証データに分割
  • 家賃の予測
  • 学習して感じたこと

モデルの構築と検証

実際にモデルの構築、検証に関しては3行で終わります。
これはsklearnという魔法のようなライブラリのおかげです。
実際に重回帰分析に使用される数学などは、google先生に聞いてみてください。
気が向いたら、自分が勉強したことを記事にするかもしれません。

さて、前置きが長くなりましたが、下記がコードです。

# ライブラリのimport 今回は重回帰分析で使用する部分のみをimport
from sklearn.linear_model import LinearRegression
# モデルの宣言
model = LinearRegression()
# モデルの学習
model.fit(X,y)
# 検証(決定係数の計算)
model.score(X,y)

これだけです。ちなみに、前回記事を振り返っていただけると分かるのですが、変数Xには説明変数(家の広さ、グレードなど)、yには目的変数(家賃)が格納されています。

さて、これで結果はどのようになったかというと・・・

続きを読む

KaggleにJOINしました。

最近、機械学習のことをWEBで調べることが多くなりましたが、その中で「Kaggle」というキーワードがちらほらあったので、本格的に調べてみました。

Kaggleとは

以下、引用です。

まず呼び方ですが、Kaggleと書いて「カグル」と読みます。日本でも最近は定着してきましたが、Kaggleに参加している方を「カグラー(Kaggler)」とも呼びます。
Kaggleですが、本サイトへ行くと一番上に書かれていますが「The Home of Data Science & Machine Learning」(データサイエンスと機械学習の家)と題されている通り、世界中の機械学習・データサイエンスに携わっている約40万人の方が集まるコミニティーです。
Kaggleでは、企業や政府などの組織とデータ分析のプロであるデータサイエンティスト/機械学習エンジニアを繋げるプラットフォームとなっています。単純なマッチングではなく、Kaggleの最大の目玉とも言える「Competetion(コンペ)」がKaggleの特徴の一つです。
Competition(コンペ)は、企業や政府がコンペ形式(競争形式)で課題を提示し、賞金と引き換えに最も制度の高い分析モデルを買い取るという、最近でいう一種のクラウドファンディングに近いような仕組みとなります。

これは素晴らしいサービスがあったものだ、と喜びました。

早速JOINしてみる

といっても、メールアドレスとパスワードを登録すればすぐです。
これで私もカグラーの仲間入りです。

f:id:taxa_program:20180516203713p:plain Kaggleのチュートリアルも勉強する予定なので、また記事にしたいと思います。

重回帰分析を行なってみたことのまとめ。その1(Python)

今回は重回帰分析で得た知識をつらつら書いていこうと思う。
私、機械学習初心者のため「何言ってんだこいつ」という箇所があるかもしれないが、そこはスルーせずにコメントいただけるととても嬉しい。

今回は賃貸データから家賃を導きだす、ということをモチベーションに機械学習を行なっていく。

  • CSVデータの読み込み
  • 分布の確認
  • 相関関係の確認
  • 説明変数と目的変数の切り分け

CSVデータの読み込み

まずは分析対象のデータの読み込みを行なった。
Pythonには機械学習に必要なライブラリがとても多く(だからML = Pythonということなのだろう)、CSVデータの取り込みもサルでもできる。
(使用しているCSVファイルはこの記事の末尾にアップロード先を記載しています)

import numpy as np
import pandas as pd

# CSVファイルの読み込み
# xNが家賃を決定する項目、yが家賃($)のデータ
df = pd.read_csv('housing.csv')

ここでimportしているライブラリは2つ。
wikipediaから引用させてもらうと以下のようなもの。

  • numpy

    プログラミング言語Pythonにおいて数値計算を効率的に行うための拡張モジュールである。 効率的な数値計算を行うための型付きの多次元配列(例えばベクトルや行列などを表現できる)のサポートをPythonに加えるとともに、それらを操作するための大規模な高水準の数学関数ライブラリを提供する。

  • pandas

    プログラミング言語Pythonにおいて、データ解析を支援する機能を提供するライブラリである。特に、数表および時系列データを操作するためのデータ構造と演算を提供する。

説明が長くなったが、ライブラリさえimportしてしまえば、CSVファイルの取り込みなんぞ1行で書けてしまう。便利な時代だ。

データを見てみるとこんな感じ。

続きを読む

Gitの仕組みを勉強してみた

Gitについて詳しく知ろうと、勉強してみたことの備忘録です。

  • Gitの記録方法
  • Gitの概要
  • Gitのデータについて

Gitの記録方法

Gitはデータをスナップショットとして記録しています。
差分保存だと、マージやブランチする際に結構な時間がかかってしまうようで。

Gitの概要

gitのローカルは下記3つのエリアに別れています。

  • ワークツリー
    ファイルを変更したりする手元の作業場所

  • ステージ
    コミットする変更を準備する場所
    記録したい変更分のみ、ステージに追加する。
    →git addコマンド

  • リポジトリ
    スナップショットを記録しておく場所
    ステージに追加されているものをスナップショットとして保存する
    →git commitコマンド

流れとしては、ワークツリーでファイルを変更してステージに追加。その後、リポジトリにスナップショットとして保存する、といった感じ。

Gitのデータについて

Gitはリポジトリに「圧縮ファイル」「ツリーファイル」「コミットファイル」の3種類のファイルを保持し、これでバージョン管理を行なっています。
下記でそれぞれのファイルについて概要を記しておきます。

続きを読む

Flask で PythonアプリをWEBに公開する

現在作成している、画像識別プログラムをWEBに公開する際の手順です。

※Anacondaのインストール、TensorFlowのインストールは終了していることを前提としています。

python仮装環境の切り替え

下記コマンドで、インストールされてる環境が表示されるので、Flaskをインストールする仮装環境に切り替えを行います。

$ conda info -e

私の場合は tf140 なので、下記のように切り替えます。

$ source activate tf140

Flaskインストール

公式HPはこちらです。
Welcome | Flask (A Python Microframework)

下記コマンドでインストールできます。

$ pip install Flask

FlaskでHello Worldを表示してみる

公式サイトにもあるHelloWordlを表示するプログラムを作成して、実際にブラウザから確認してみます。

続きを読む