筋肉で解決しないために。

日々出会うモノに対する考察をしたり、主に以下のテーマに関して書いています。 データサイエンス/人工知能/AI/機械学習/DeepLearning/Python//数学/統計学/統計処理

プレゼン入門1_プレゼンを作り始める前に

f:id:watarumon:20180809230139p:plain

こんにちは、ワタルです。

読むだけでプレゼンが上手くなるプレゼン入門講座をはじめることにしました。

はじめに

実は私、学生時代から学会発表などでプレゼン発表する機会が多く、その経験からビジネスプレゼン大会(1000人規模)で優勝したことがあったりして、人前でプレゼンすることに苦手意識があまりなく、むしろ得意だと思っているところで。

そのため自分自身のための言語化や整理も兼ねて、どんな風に考えてプレゼン作っているかをまとめてみようかなと思います。

少しでも皆さんのプレゼンに貢献できたら嬉しいです。
ちなみにcoconalaでプレゼン資料添削もやってるので、良かったらお仕事ください。
エントリの最後にリンク載せておきます。

プレゼン入門シリーズの構成

今の所、このプレゼン入門シリーズは全10回くらいを想定しています。

第1,2回目 作り始める前にすること

第3,4回目 図の作り方、色の使い方等、デザインについて

第5,6回目 おすすめPower Pointショートカットについて

第7,8回目 細々としたテクニック

第9,10回目 話し方、立ち振る舞い、発表練習について

この様な内容を各2エントリくらいずつかなと思っています。
もちろん書き進める中で変わることはあるかもしれません。

それでは、よろしくお願いします。

このエントリの目的

このエントリでは、私が"資料を作り始める前に必ず行うべき"だと考えていることについてまとめています。

プレゼンをしなければいけない状況になった時、なんとなく資料を作り始めるのは絶対に無しです。 時間ばかりかかって、何を伝えたいのかわからないモノが出来上がります。

私はこうして出来上がった資料は、他人の時間も奪うので"不法投棄された悪臭を放つゴミ"だと考えています。
やめましょう、不法投棄は。

さらに、そういう適当に資料を作る人に限って発表練習すらせずに出てくるから、
発表もまとまってなかったりして、さらに世界の生産性を下げることになります。

少し言い過ぎましたが、
そう言った状況を避けるために、"資料を作り始める前に必ず行うべき"ことを知っていただくことが、このエントリの目的です。


漫画「SLAM DUNK」で例えている部分が多くあります。
読んでいない方にとってわかりにくかったらすみません。
SLAM DUNK」はおもしろいので読んでおいた方が良いと思います。

対象者・目的・内容・順序を考える

その"資料を作り始める前に必ずすべきこと"とは、対象者・目的・内容・順序を考えると言うことです。
ひとつずついきます。

f:id:watarumon:20180809121529p:plain

対象者を考える

まずは、対象者を考えるということについて。

対象者とは、言い換えると、そのプレゼンの受け手、聴者のことです。

対象者を考えるということは、
聴くのは、誰で、どんな状況でそのプレゼンを行うのかを考えるということにほかなりません。

例えば以下の様なことを考えます。
大人数?少人数?
場所は広い?狭い?
資料を配ってのプレゼン?投影?
年齢は?役職は?性格は?
思考や知識のレベルは?などです。

極端なことを言うと、
小学生に専門用語を使っても伝わらないと言うこと、大学教授に基礎から話しても冗長になるだけということ。
この様なことです。

漫画「SLAM DUNK」で例える

漫画「SLAM DUNK」で例えると、海南大付属高校との試合において、
赤木は、マネージャーの彩子に対し、「いいからテーピングだ!」と発言する印象的なシーンがあります。

一般的な人に「いいからテーピングだ!」と言っても、
「テーピングってなに?」「テーピングって何かの検査のこと?」「もう試合には出ないって意味なのかな。。」
などとわけのわからないことになりそうですが、

「テーピングとはどんなものか。」「どんな効果があるか」を理解しているマネージャーの彩子に対しては、
「いいからテーピングだ!」という最小限の言葉で、相手に行動まで促させることに成功しています。

対象者を考えることは、全く時間を要しませんが、
少なくともこの様なことを回避することができるというメリットがあります。

さらに次の目的を考えるときに非常に役に立ちます。

まとめです。

f:id:watarumon:20180809121549p:plain

目的を考える

次は、目的を考えるということについて。

目的を言い換えると、
そのプレゼンを受けた相手に、プレゼン終了後にどんな行動をしてほしいか、ということになります。

つまり、誰に、何を、どうしてほしいのか。ということです。
具体的を書くと、

  • セミナーに来たお客さんに、この商品を、購入してほしい。

  • 山田部長に、この企画を、承認してほしい。

  • 学生に、この講義を、理解してほしい。

  • マネージャーの彩子に、テーピングを、してほしい。

稚拙な例になってしまいましたが、このような感じです。

そして、この様にプレゼン資料に入れてしまいましょう。
プレゼン冒頭で宣言することをお勧めします。

f:id:watarumon:20180809122008p:plain

これをしっかり明言するだけで、もう迷いません。
登壇者と聴者は、伝え/伝えられようとする共同体の様になります。

その行動に必要な情報を説明すればいいし、聴者は行動に必要な部分だけ聞けば良くなり、話が格段に伝わりやすくなります。

プレゼンは、登壇者が伝えたいことを説明して、聴者が登壇者の意図を想像する様な連想ゲームではありません。
始めから答えを言うべきです。

まとめです。

f:id:watarumon:20180809122036p:plain

内容を考える

次は、内容を考えるということ。 ここまで話してきた通り、プレゼンの目的は、プレゼン終了後にどんな行動をしてほしいか、に尽きます。

必然的に、内容は、
対象者が行動するために必要な情報になります。
私は、以下の項目について埋める形で考えています。

目的概要理由まとめ

  • 目的とは、プレゼン終了後にどんな行動をしてほしいか

  • 概要とは、その企画概要

  • 理由とは、その企画の詳細やメリデメ

  • まとめとは、目的や概要のまとめになります。

漫画「SLAM DUNK」で例える

プレゼンを漫画「SLAM DUNK」における「いいからテーピングだ!」で例えると、

目的:
マネージャーの彩子に、テーピングを、してほしい。

概要:
テーピングによる治療箇所の詳細、テーピング材の詳細、締め切り日時

理由:
①テーピングで固めないとプレーできない現状

②自分がプレーすることによるメリット
(→牧 紳一の脅威について)

③自分がプレーすることによるデメリット
(→自身の骨が折れてもいい、歩けなくなってもいいと考えているため、デメリットは無視できる)

まとめ:
理由の一覧+「いいからテーピングだ!」

この様な感じでしょうか。
まとめます。

f:id:watarumon:20180809123259p:plain

順序を考える

最後に順序についてです。

プレゼンにおける順序は2種類あります。
結論を先に置くか、後に置くかです。

多くの場合で結論を先にすべきだと思いますが、長めの講演などでは結論を後に置いた方が効果的な場合もあります。

メリデメをまとめておきます。

f:id:watarumon:20180809223038p:plain

漫画「SLAM DUNK」で例える

結論を先に置く場合:
「いいからテーピングだ!」 → なぜなら...

結論を後に置く場合:
「皆さんは私がこの試合に懸ける気持ちをご存知でしょうか?」 → 「1年生の時からずっと全国制覇を...」 → 「いいからテーピングだ!」

この様になります。

まとめ

最後に、このエントリをまとめておきます。

f:id:watarumon:20180809224029p:plain

第1回目は以上です。

次回もよろしくお願いします。

coconalaでプレゼン資料添削もやってるので、良かったらお仕事くださいね!

coconala.com

このブログと僕について

こんにちは、ワタルです。

最近はじめましての機会が多いので、プロフィールエントリを書いておこうと思いまして。

 

 

自己紹介

f:id:watarumon:20180724214903p:image

わたるもん、25歳
元ソシャゲ廃人
現データサイエンティスト兼会社員
東大修士

 

趣味は、スプラトゥーン
好きな色は、MONSTERのみどり色。
好きな音は、シャンパンを開けるときのポンって音。

 

東京都在住で、新橋有楽町銀座日本橋あたりによくいます。
良かったらご飯行きましょう。ツイッターから連絡もらえればすぐ行っちゃうかも。

 

Twitter

 

フォローお願いします~~

 

 


このブログについて

結論から書くと、データ分析/機械学習ポートフォリオ兼勉強ノートとして、このブログを始めました。

 

機械学習を始めたきっかけを書くと、

 

 

同僚「線形代数教えて!」
僕「いいよ。なに勉強してるの?」
同僚「機械学習
僕(機械学習?)
僕(機械学習っておもしろ!)

こんな感じ。

 

勉強を進めるうちに、どんどん心が機械学習に向いていて、さらにさらに勉強中であります。

 

このブログのもうひとつ目的があります、これはすごくふわふわした理由なんだけど。笑
なんとなくブログってネット上の自宅みたいなイメージを持っていて、昔からブログを作りたいなーと思っていたことです。この場所からもコミュニティが生まれたらいいなと思っています。はてなのコメントでもツイッターでも声をかけてもらえるととても嬉しいです。
全て返信しますのでお気軽にどうぞ。

 

この前、機械学習BBQに誘ってもらって今度行くんだけど、
もくもく会とか勉強会とか誘って頂ければなんでも行くと思います。
新しいコミュニティに行くのは好きなので。

 

あ、9月Pycon_JP2018も行くよ。

 


経験とかスキルとか

・ビジネスプレゼン大会(1000人規模)で、「空を人々が自由に飛び交う世界を作る」というアイデアで優勝。
  → coconalaでプレゼン資料添削もやってるので、良かったらお仕事ください。プレゼンには自信ありです。

coconala.com

 

・CAD/After effects/Photoshop/Illustrator/Adobe Illustrator Drawは一通り使えます。
  → LINEスタンプも販売してたので良かったら買ってね~~。

 

store.line.me

 

プログラミング言語


Javascript(正確にはgoogle app script。)
  → Webスクレイピング、メール自動配信、自動カレンダー追加とか実装したことあります。
    
Python(kaggleで遊べる程度にはできます。)

 

・Interactive Data Language "IDL" (だれもこの言語知らないでしょ笑)
  → 科学技術計算でよく使われるデータ分析用プログラミング言語で、研究室時代に実験データ解析に使ってました。


ちなみにソシャゲ経歴


パズドラ(ランク上位0.0003%、ランキングダンジョン18大会連続最上位入賞経験有り、もう引退したけど課金額は100万円超えてると思います。)
・shadowverse(月間ランキング世界8位)

 

おわりに


とりあえず、以上です。
また気が向いたら昔ばなしでも書こうかなと思ってます。
質問箱もあるからよろしくーー

peing.net

決定木とランダムフォレスト分類/回帰の実装と可視化

こんにちは、ワタルです。

はじめに

このエントリでは、サンプルデータを作成し、そのデータを持って決定木とランダムフォレストの実装と可視化をしてみます。

決定木分類をとてもかんたんに説明すると、 ある条件に対してYes or No のように分けて決めていくことでそのサンプルを分類する方法です。

また、ランダムフォレスト(Random forests)は、アンサンブル学習法と呼ばれる学習法の一つです。 アンサンブル学習法とは、いくつかの分類器を集めて構成する学習法のことを指します。 決定木を集めたアンサンブル学習法なので、ランダムフォレストと呼ばれるわけです。

より詳しい説明はこちらを参考にして見てください。 画像もこちらから引用しています。

Enchanted Random Forest – Towards Data Science

f:id:watarumon:20180717171310p:plain

また、コードはこちらを参考にさせていただいております。

Lec86_決定木とランダムフォレスト

それでは実際にコードを書いていきます。

目的とタスク設定

なにごとも、目的とタスクの整理は重要です。

サンプルデータの作成をタスク1 とします。

次に、決定木のみの実装とその可視化をタスク2とします。

次に、ランダムフォレストによる多クラス分類の実装とその可視化をタスク3とします。

最後に、ランダムフォレストによる回帰の実装とその可視化をタスク4とします。

さて、タスク1から始めます。

おまじない

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

タスク1

まずはサンプルデータを生成します。

#make_blobsをimportします
from sklearn.datasets import make_blobs

#500の要素
#4つの中心、つまり4つのグループを作る
#再現性のためにrandom_stateを指定
#cluster_stdはばらつき具合
X, y = make_blobs(n_samples=500, centers=4,
                  random_state=7, cluster_std=2.4)

#生成したデータのプロット
plt.figure(figsize=(10,10))
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='jet')
#引数cとcmapは色のため、sはプロット点の大きさ指定です

>>>

f:id:watarumon:20180717172518p:plain

このサンプルデータに対して、分類を実装していきます。

タスク2

次に決定木分類を実装し、可視化します

#決定木分類のインポート
from sklearn.tree import DecisionTreeClassifier

#決定木の可視化
def visualize_tree(classifier, X, y, boundaries=True,xlim=None, ylim=None):

    # fitを使ったモデルの構築
    classifier.fit(X, y)
    
    #軸を自動調整
    if xlim is None:
        xlim = (X[:, 0].min() - 0.1, X[:, 0].max() + 0.1)
    if ylim is None:
        ylim = (X[:, 1].min() - 0.1, X[:, 1].max() + 0.1)

    x_min, x_max = xlim
    y_min, y_max = ylim
    
    
    #meshgridをつくります。
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100),
                         np.linspace(y_min, y_max, 100))
    
    #分類器の予測をZとして保存
    Z = classifier.predict(np.c_[xx.ravel(), yy.ravel()])
    #np.ravel関数は配列の一次元化、np.c_は配列の結合を行っています

    #meshgridを使って、整形します。
    Z = Z.reshape(xx.shape)
    
    #分類ごとに色を付けます。
    plt.figure(figsize=(10,10))
    plt.pcolormesh(xx, yy, Z, alpha=0.2, cmap='jet')
    #xx,yyの座標について、Zで色分けをしています。alphaは色の薄さです
    
    #訓練データのオーバープロット
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='jet')
    
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)        
    
    #境界線をプロットする関数をつくります
    def plot_boundaries(i, xlim, ylim):
        if i < 0:
            return

        tree = classifier.tree_
        
        #境界を描画
        if tree.feature[i] == 0:
            plt.plot([tree.threshold[i], tree.threshold[i]], ylim, '-k')
            plot_boundaries(tree.children_left[i],
                            [xlim[0], tree.threshold[i]], ylim)
            plot_boundaries(tree.children_right[i],
                            [tree.threshold[i], xlim[1]], ylim)
        
        elif tree.feature[i] == 1:
            plt.plot(xlim, [tree.threshold[i], tree.threshold[i]], '-k')
            plot_boundaries(tree.children_left[i], xlim,
                            [ylim[0], tree.threshold[i]])
            plot_boundaries(tree.children_right[i], xlim,
                            [tree.threshold[i], ylim[1]])
    
    if boundaries:
        plot_boundaries(0, plt.xlim(), plt.ylim())
#インスタンスを作り、上記のvisualize_tree関数内のモデルに代入します
clf = DecisionTreeClassifier(max_depth=2,random_state=0)
visualize_tree(clf,X,y)

>>>

f:id:watarumon:20180717171435p:plain

垂直が①番目、水平が②番目の順に、決定木分類がされていることがわかります。

深さ2の分類では水色のプロットが全く上手く分類できていないことも見て取れます。

もっと深くして試してみます。

#深さ4にしてみます
clf = DecisionTreeClassifier(max_depth=4,random_state=0)

visualize_tree(clf,X,y)

f:id:watarumon:20180717171448p:plain

#深さ10にしてみます。
clf = DecisionTreeClassifier(max_depth=10,random_state=0)

visualize_tree(clf,X,y)

f:id:watarumon:20180717171501p:plain

だいぶごちゃごちゃしてしまいました。 感覚的に見ても、上手く分類できていないプロットはいくつかあり、過学習を起こしてそうな個所も見受けられます。

そこで、アンサンブル学習法である、ランダムフォレストを試してみます。

ランダムフォレストは、学習データの一部をランダムに選んで、決定木を作るという行動を繰り返す手法です。

タスク3

#ランダムフォレスト分類をインポートします
from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(n_estimators=100,random_state=0)
#n_estimatorsは、作る木の数です。

# 境界線を書かないようにします。
visualize_tree(clf,X,y,boundaries=False)

f:id:watarumon:20180717171517p:plain

水色の左側のプロットでは、過学習が起きている様な分類結果が見て取れますが、 決定木分類よりは高い精度であることが見て取れます。

最後に、ランダムフォレスト回帰を実装してみます。

タスク4

線形回帰では、回帰曲線を描くのが困難なサンプルデータを作成し、ランダムフォレスト回帰を実装してみます。

まずは2種類のsin波とランダム関数から生成したノイズからなるダミーデータを生成します。

#ランダムフォレスト回帰をインポートします
from sklearn.ensemble import RandomForestRegressor

x = 10 * np.random.rand(100)

def sin_model(x, sigma=0.2):   
    noise = sigma * np.random.randn(len(x))
    return np.sin(5 * x) + np.sin(0.5 * x) + noise

y = sin_model(x)

# Plotします。
plt.figure(figsize=(16,8))
plt.errorbar(x, y, 0.1, fmt='o')
#Xを用意します。
xfit = np.linspace(0, 10, 1000)

#回帰モデルを用意します。
rfr = RandomForestRegressor(100)

#モデルを学習させます。
rfr.fit(x[:, None], y)

#予測値を計算します。
yfit = rfr.predict(xfit[:, None])

#回帰の目指している実際の曲線を描くための値をつくります
ytrue = sin_model(xfit, 0)

#Plotします
plt.figure(figsize=(16,8))

plt.errorbar(x, y, 0.1, fmt='o')

plt.plot(xfit, yfit, '-r');
plt.plot(xfit, ytrue, '-b', alpha=0.5);

>>>

f:id:watarumon:20180717171536p:plain

青が実際の値で、赤が予測値になります。

線形回帰では、ただ、山なりな曲線しか描けなそうなデータに対して、ランダムフォレスト回帰は有効な方法であることを確かめることができました。

さいごに

今回は、サンプルデータを作成し、そのデータに対して決定木分類の実装と可視化、ランダムフォレスト分類と回帰の実装と可視化を行いました。

また、ランダムフォレスト回帰では、線形回帰では、回帰曲線を描くのが困難そうデータに対して、有効な方法であることを確認出来ました。

お疲れ様でした!

それじゃー、また。

ナイーブベイズ分類をIrisデータセットへの実装

こんにちは、ワタルです。

はじめに

このエントリでは、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、ナイーブベイズ分類を実装してみます。 サンプルデータは、Iris(アヤメ)という植物のデータで、3種類のアヤメについて、それぞれ50サンプルのデータに4つの特徴量が含まれています。

ナイーブベイズ分類をとてもかんたんに表現すると、それぞれの分類先に属する確率を計算し、確率が最も大きいクラスにそのサンプルを分類します。

数字は適当ですが、このようなイメージです。 例えば、Aさんがどのクラスに属するが分類してみたいとします。

Aさんが、クラス1に属する確率は70%、クラス2に属する確率は30%、クラス3に属する確率は50%と求めることが出来た時、Aさんはクラス1に属すると出力されます。

数学的な理解は、こちらのページがおすすめです。

第10回 ベイズ確率:機械学習 はじめよう|gihyo.jp … 技術評論社

それでは、実際に実装してみます。

おまじない

import pandas as pd
from pandas import Series,DataFrame

import matplotlib.pyplot as plt
import seaborn as sns

#Gaussian Naive Bayes のためのコード
from sklearn import datasets
from sklearn import metrics
from sklearn.naive_bayes import GaussianNB

Irisデータセットのインポート

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
Y = iris.target

データセットの分割

#データを、テスト用とトレーニング用に分けます。

from sklearn.cross_validation import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=0)

ナイーブベイズ分類にて学習

#インスタンスの作成
model = GaussianNB()

#訓練データで学習
model.fit(X_train,Y_train)

>>>
GaussianNB(priors=None)

予測精度の確認

#分割しておいたテストデータを用いて、精度を確認します
predicted = model.predict(X_test)
expected = Y_test

print(metrics.accuracy_score(expected, predicted))

>>>
1.0

おぉ、1.0になりました。 ついでにお試しとして、データセットの分割具合を変えて、精度スコアを可視化してみましょう。

精度スコアの可視化

predict_score = []

#テストデータを10%から90%まで変化させて、そのスコアを出力します
for size in np.arange(0.1, 1,0.1): 
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=0,test_size = size)
    model = GaussianNB()
    model.fit(X_train,Y_train)
    predicted = model.predict(X_test)
    expected = Y_test
    predict_score.append(metrics.accuracy_score(expected, predicted))
X_test_size = np.arange(0.1, 1,0.1)
df_score = DataFrame(predict_score,columns=['predict_score'],index=X_test_size)
df_score

>>>
    predict_score
0.1    0.933333
0.2    0.966667
0.3    1.000000
0.4    0.933333
0.5    0.946667
0.6    0.944444
0.7    0.933962
0.8    0.933333
0.9    0.948148
#プロットします
plt.plot(X_test_size,predict_score,color = 'b')
plt.ylim(0.92,1.01)
plt.xlabel("test_size")
plt.ylabel("predict_score")
plt.xticks( np.arange(0.0, 1.0, 0.1) )
plt.hlines([1], 0, 1, linestyles="dashed")

plt.show()

>>>

f:id:watarumon:20180713152426p:plain

訓練データは多ければ多いほどよいわけではないことを体験することができましたね。

さいごに

今回は、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、ナイーブベイズ分類を実装し、テストデータの分け方によって精度が変わる事を確認してみました。

お疲れ様でした!

それじゃー、また。

SVM(Support Vector Machines)による他クラス分類の実装と可視化

はじめに

このエントリでは、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、SVM(Support Vector Machines)を実装してみます。 サンプルデータは、Iris(アヤメ)という植物のデータで、3種類のアヤメについて、それぞれ50サンプルのデータに4つの特徴量が含まれています。

おまじない

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

Irisデータセットのインポート

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
Y = iris.target

データセットの分割

from sklearn.cross_validation import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=3)  
#test_sizeを指定しないと0.25になります

モデル生成

今回は、SVCにおける4つのkernelを用いて、それぞれの精度を出して比較してみます。

from sklearn.svm import SVC

model_linear = SVC(kernel = 'linear')
model_poly = SVC(kernel = 'poly')
model_rbf = SVC(kernel = 'rbf')#kernelを指定しない時のデフォルトです
model_sigmoid = SVC(kernel = 'sigmoid')

モデルに学習させる

#それぞれのモデルを学習させます
model_linear.fit(X_train,Y_train)
model_poly.fit(X_train,Y_train)
model_rbf.fit(X_train,Y_train)
model_sigmoid.fit(X_train,Y_train)

>>>
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='sigmoid',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
#これはsigmoidのときの出力です

モデルの精度確認

テストデータを入れて、モデルの精度を確認します

from sklearn import metrics

predicted_linear = model_linear.predict(X_test)
expected_linear = Y_test
print(metrics.accuracy_score(expected_linear,predicted_linear))

predicted_poly = model_poly.predict(X_test)
expected_poly = Y_test
print(metrics.accuracy_score(expected_poly,predicted_poly))

predicted_rbf = model_rbf.predict(X_test)
expected_rbf = Y_test
print(metrics.accuracy_score(expected_rbf,predicted_rbf))

predicted_sigmoid = model_sigmoid.predict(X_test)
expected_sigmoid = Y_test
print(metrics.accuracy_score(expected_sigmoid,predicted_sigmoid))

>>>
0.9736842105263158
0.9473684210526315
0.9736842105263158
0.2894736842105263

今回の場合では、rbfとlinearの精度が高くでていることがわかりました。

モデルの可視化

最後に下記サイト、及び公式ドキュメントを参考に、ここまでで行ったモデルの可視化に挑戦してみます http://www.tsjshg.info/udemy/Lec82-83.html

from sklearn import svm

#図示できるのが2次元までなので、変数を2つに絞ります。
X = iris.data[:,:2]
Y = iris.target

#SVMの正則化パラメータ
C = 1.0  

#SVC with a Linear Kernel
svc = svm.SVC(kernel='linear', C=C).fit(X, Y)

#Gaussian Radial Bassis Function
rbf_svc = svm.SVC(kernel='rbf', gamma=0.7, C=C).fit(X, Y)

#SVC with 3rd degree poynomial
poly_svc = svm.SVC(kernel='poly', degree=3, C=C).fit(X, Y)

#SVC Linear
lin_svc = svm.LinearSVC(C=C).fit(X,Y)

#step size
h = 0.02

#X軸の最大最小
x_min=X[:, 0].min() - 1
x_max =X[:, 0].max() + 1

#Y軸の最大最小
y_min = X[:, 1].min() - 1
y_max = X[:, 1].max() + 1

#meshgridを作ります。
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),np.arange(y_min, y_max, h))

titles = ['SVC with linear kernel',
          'LinearSVC (linear kernel)',
          'SVC with RBF kernel',
          'SVC with polynomial (degree 3) kernel']

for i, clf in enumerate((svc, lin_svc, rbf_svc, poly_svc)):
    
#境界線を描画します。
    plt.figure(figsize=(15,15))
    plt.subplot(2, 2, i + 1)
    plt.subplots_adjust(wspace=0.4, hspace=0.4)
    
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    plt.contourf(xx, yy, Z, cmap=plt.cm.terrain, alpha=0.5,linewidths=0)
    plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Dark2)
    
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    plt.xlim(xx.min(), xx.max())
    plt.ylim(yy.min(), yy.max())
    plt.xticks(())
    plt.yticks(())
    plt.title(titles[i])
plt.show()

>>>

f:id:watarumon:20180711154133p:plain

f:id:watarumon:20180711154144p:plain

f:id:watarumon:20180711154154p:plain

f:id:watarumon:20180711154204p:plain

さいごに

今回は、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、SVC(Support Vector Machines)を実装し、4種類のkernelを比較してみました。

お疲れ様でした!

それじゃー、また。

k近傍法やロジスティック回帰を使った多クラス分類の実装

はじめに

このエントリでは、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、ロジスティック回帰を用いた多クラス分類やk近傍法を実装してみます。 サンプルデータは、Iris(アヤメ)という植物のデータで、3種類のアヤメについて、それぞれ50サンプルのデータに4つの特徴量が含まれています。

おまじない

#前処理
import numpy as np
import pandas as pd
from pandas import Series,DataFrame

#可視化
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
%matplotlib inline

#機械学習
from sklearn import linear_model
from sklearn.datasets import load_iris
from sklearn import metrics

目的とタスクの設定

目的とタスクの設定をするために、まずは元データをみてみます。

#データセットのロード
iris = load_iris()

#説明変数をXとする
X = iris.data

#目的変数をYとする
Y = iris.target
X[1:5]

>>>
array([[4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
Y

>>>
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

まずは、可視化するためにXとYをdataframeにして、seabornでプロットしてみようと思います。 これをタスク1と呼ぶことにします。

データの傾向をつかんだところで、ロジスティック回帰を実装してみます。 これをタスク2と呼ぶことにします。

最後に、k近傍法を実装し、適切なkの値について検討を行ってみます。 これをタスク3と呼ぶことにします。

タスク1

#Xをdataframeにし、カラム名をつけます
iris_data = DataFrame(X,columns=['Sepal Length','Sepal Width','Petal Length','Petal Width'])

#Yをdataframeにし、カラム名をつけます
iris_target = DataFrame(Y,columns=['Species'])
#Yの要素を名前に置き換えます
def flower(num):
    ''' 数字を受け取って、対応する名前を返します。'''
    if num == 0:
        return 'Setosa'
    elif num == 1:
        return 'Veriscolour'
    else:
        return 'Virginica'

iris_target['Species'] = iris_target['Species'].apply(flower)
iris_target.head()

>>>
Species
0  Setosa
1  Setosa
2  Setosa
3  Setosa
4  Setosa
#XとYをまとめます
iris = pd.concat([iris_data,iris_target],axis=1)
iris.head()

>>>
    Sepal Length    Sepal Width Petal Length    Petal Width Species
0  5.1    3.5    1.4    0.2    Setosa
1  4.9    3.0    1.4    0.2    Setosa
2  4.7    3.2    1.3    0.2    Setosa
3  4.6    3.1    1.5    0.2    Setosa
4  5.0    3.6    1.4    0.2    Setosa

ここまでで、可視化の前処理が終わりました。 プロットします。

sns.pairplot(iris,hue='Species')

>>>

f:id:watarumon:20180711132955p:plain

Setosaは最も特徴的な目的変数であることが見て取れます。

タスク2

ロジスティック回帰を実装します。

#ロジスティック回帰のインスタンスを作成
logreg = LogisticRegression()

#データを訓練データとテストデータに分割します。この場合ではテストが全体の40%になるようにしています。
#再現性のため引数random_stateを設定しています。実際の機械学習では用いないことが多いです。
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.4,random_state=3)

#訓練データを使って学習させます。
logreg.fit(X_train, Y_train)

テストデータを用いて、モデルの精度を確認します。

Y_pred = logreg.predict(X_test)

# 精度を比較してみます
print(metrics.accuracy_score(Y_test,Y_pred)

>>>
0.933333333333

60%の訓練データ、40%がテストデータにて、ロジスティック回帰でモデルを作成した場合では、93%の精度が得られました。

タスク3

k近傍法によるモデルを実装し、適切なkの値について検討を行ってみます。

from sklearn.neighbors import KNeighborsClassifier

#k=1のとき、つまりもっとも近いサンプルの分類がその分類と等しいと予測するモデルです
#インスタンスを作ります
knn = KNeighborsClassifier(n_neighbors = 1)

#訓練データを使って学習させます
knn.fit(X_train,Y_train)

#テストデータで予測をします
Y_pred = knn.predict(X_test)

#精度を調べてみます
print(metrics.accuracy_score(Y_test,Y_pred))

>>>
0.9666666666666667

最後に、kの値を任意に変化させてプロットすることで、適切なkの値について検討してみます。

k_range = range(1, 90)
accuracy = []

for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, Y_train)
    Y_pred = knn.predict(X_test)
    accuracy.append(metrics.accuracy_score(Y_test, Y_pred))
print (type(accuracy))
print (type(k_range))

>>>
<class 'list'>
<class 'range'>

kの変化をk_rangeに、精度の変化をaccuracyというlistにすることができました。

plt.plot(k_range, accuracy)
plt.xlabel('K')
plt.ylabel('Testing Accuracy')

>>>

f:id:watarumon:20180711133007p:plain

値を確認してみます。

df = DataFrame(accuracy,columns=['accuracy'],index=k_range)
df[50:60]

>>>
    accuracy
51 0.850000
52 0.850000
53 0.850000
54 0.900000
55 0.833333
56 0.850000
57 0.816667
58 0.500000
59 0.500000
60 0.500000

今回の訓練データとテストデータの分け方では、k=57とk=58に大きな差があることがわかりました。

さいごに

今回は、機械学習のサンプルデータとしてよく用いられるIrisのデータに対して、ロジスティック回帰を用いた多クラス分類やk近傍法を実装することができました。

お疲れ様でした!

それじゃー、また。

どんな妻が不倫しやすいかをロジスティック回帰してみた。

はじめに

このエントリでは、Statsmodelsの一部として提供されているサンプルデータを用いてロジスティック回帰を実装してみます。 サンプルデータは、1974年に行われた、女性に対して不倫の有無を聞いた調査です。 http://www.statsmodels.org/stable/datasets/generated/fair.html

おまじない

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import math

#プロット
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
%matplotlib inline

#機械学習
from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import train_test_split
from sklearn import metrics
import statsmodels.api as sm

サンプルデータのインポート

df = sm.datasets.fair.load_pandas().data

データの概要を引用しておきます。

Number of observations: 6366 Number of variables: 9 Variable name definitions:

rate_marriage : How rate marriage, 1 = very poor, 2 = poor, 3 = fair, 4 = good, 5 = very good

age : Age

yrs_married : No. years married. Interval approximations. See original paper for detailed explanation.

children : No. children

religious : How relgious, 1 = not, 2 = mildly, 3 = fairly, 4 = strongly

educ : Level of education, 9 = grade school, 12 = high school, 14 = some college, 16 = college graduate, 17 = some graduate school, 20 = advanced degree

occupation : 1 = student, 2 = farming, agriculture; semi-skilled, or unskilled worker; 3 = white-colloar; 4 = teacher counselor social worker, nurse; artist, writers; technician, skilled worker, 5 = managerial, administrative, business, 6 = professional with advanced degree

occupation_husb : Husband's occupation. Same as occupation.

affairs : measure of time spent in extramarital affairs

df.head()
>>>

f:id:watarumon:20180709202346p:plain

データ概要と目的の整理(タスクの設定)

まず今回の目的は、ある諸データが与えられたとき、その人が不倫をしているかどうかを求めることのできるモデルの作成です。

そのため、データセットのaffairsは不倫をしている時間を表しているので、まずはこれを0と1で表現するように処理が必要です。これをタスク1と呼ぶことにします。

次に、数字が意味をもっていないものを処理してあげる必要があります。 そのカラムはoccupationとoccupation_husbです。 これは、数字を職業を表す記号として使用されているので、0と1で表現できるような何らかの処理が必要であります。 これをタスク2と呼ぶことにします。

タスク1の処理

まずは、タスク1から処理をしていきます。 0でない場合に1を返し、その他は0を返す関数をつくります。

def affair_check(x):
    if x != 0:
        return 1
    else:
        return 0

#Had_Affairという新しいカラムをつくります
df['Had_Affair'] = df['affairs'].apply(affair_check)

df.head()
>>>

f:id:watarumon:20180709202416p:plain

これで、affairsを0と1で表現することができました。

タスク2の処理

次にタスク2を処理していきます。

今回は、occupation(職業)のカテゴリが6種類あることより、列を6列作り、それぞれにマッチしていれば、1を返すことで、0と1で表現することとしたいと思います。 これは、pandas.get_dummies()関数によって簡単に処理することができます。 pandas.get_dummies()関数は、機械学習の前処理としてよく使われる手法です。

#ダミー変数に展開します。
occ_dummies = pd.get_dummies(df['occupation'])
hus_occ_dummies = pd.get_dummies(df['occupation_husb'])

#カラムに名前を付けます。
occ_dummies.columns = ['occ1','occ2','occ3','occ4','occ5','occ6']
hus_occ_dummies.columns = ['hocc1','hocc2','hocc3','hocc4','hocc5','hocc6']

#表示します
occ_dummies.head()

>>>

f:id:watarumon:20180709202520p:plain

状況整理(タスクの設定)

ここまでで、タスク1とタスク2を処理することができました。 次は、ダミー変数を用いたので、多重共線性を考慮しつつ、ここまで処理したdataframeを合体させたいと思います。 これを、タスク3と呼ぶことにします。

その次に、ロジスティックモデルにはめこめるように、説明変数をXというdataframeに、目的変数をYというnumpyarrayに処理しようと思います。 これをタスク4とと呼ぶことにします。

その後、目的のモデルを作成し、そのスコアを求めることをタスク5と呼ぶことにします。

最後に簡単にそのスコアの妥当性を検討します。 これをこれをタスク6と呼ぶことにします。

タスク3

ダミー変数を用いたので、多重共線性を考慮しつつ、ここまで処理したdataframeを合体させたいと思います。

多重共線性については、こちらのページが概要を理解するにはわかりやすかったです。 http://heartland.geocities.jp/ecodata222/ed/edj1-2-1-2-1.html

#occupationと、目的変数「Had_Affair」を削除します。
X = df.drop(['occupation','occupation_husb','Had_Affair','affairs'],axis=1)

#ダミー変数のDataFrameを繋げます。
dummies = pd.concat([occ_dummies,hus_occ_dummies],axis=1)

#Xとdummiesを繋げます。
X = pd.concat([X,dummies],axis=1)

#多重共線性を考慮して、occ1とhocc1を落とします。
X = X.drop('occ1',axis=1)
X = X.drop('hocc1',axis=1)
X.head()

>>>

f:id:watarumon:20180709202605p:plain

タスク4

タスク3で説明変数Xはやってしまいましたね。 目的変数Yをつくります。

Y = df.Had_Affair

#1次元のarrayにしておきます
Y = np.ravel(Y)
Y

タスク5

目的のモデルを作成し、そのスコアを求めます。

#LogisticRegressionクラスのインスタンスを作ります。
log_model = LogisticRegression()

#モデルを作ります。
log_model.fit(X,Y)

#モデルのスコア
log_model.score(X,Y)

>>>
0.7258875274897895

およそ73%一致のモデルを作成できました!

タスク6

簡単にこのスコアの妥当性を検討します。

まず、この問題は2値問題なので、例えば常に0と予想するモデルを作ったとして、その精度スコアと比べてみます。

Y.mean()

>>>
0.3224945020420987

68%の精度スコアということがわかります。この値よりは、先ほどのモデルの73%の方が高いことがわかります。

次に、sklearn.cross_validationで検証してみます。

#テストデータに分割
X_train, X_test, Y_train, Y_test = train_test_split(X, Y)

# 新しいモデルを作ります。
log_model2 = LogisticRegression()
log_model2.fit(X_train, Y_train)

# テスト用データを使って、予測。
class_predict = log_model2.predict(X_test)

# 精度スコアを出力。
print(metrics.accuracy_score(Y_test,class_predict))

>>>
0.7374371859296482

約73%の精度を得ました。すべてのデータを使ったときとおよそ同じ結果が得られました。

結論

どの変数が予測に寄与しているかを可視化してみます。

coeff_df = DataFrame([X.columns, log_model.coef_[0]]).T
plt.figure(figsize=(15,5))
sns.barplot(x=coeff_df[0], y=coeff_df[1])

f:id:watarumon:20180709201740p:plain

これを見ると、結婚生活が豊かなほど、宗教観が強いほど不倫しにくく、 逆に、結婚年月が長くなるほど、不倫率が上がる様です。

職業の面で言うと、夫の職業によって妻の不倫率はあまり変化なく、 3 = white-colloar、 5 = managerial,administrative, business, 6 = professional with advanced degree これらの、ホワイトカラー、経営者、実業家、高学歴専門職の様な人が不倫をしやすいことが示唆されます。

お金もステータスもある人が不倫しやすいって考えると、妥当かもしれませんね。

今回は、Statsmodelsの一部として提供されているサンプルデータを用いてロジスティック回帰を実装してみました。 お疲れ様でした!

それじゃー、また。