"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

機械学習の目的変数と説明変数と特徴量のざっくり理解/出現率と外れ値判定のサンプル

f:id:arakan_no_boku:20200329000112p:plain

目次

目的変数と説明変数と特徴量

機械学習における用語です。

目的変数とは、予測対象の変数のことです。

説明変数とは、目的変数を説明することができる変数のことです。

特徴量は説明変数のことです。

例えば、未来の売上げを予測したいとした場合。

目的変数になるのは「過去の売上データ」になるのは直観でもわかります。

そして、その売上に影響をあたえる可能性のある諸々・・例えば、曜日や気温、店舗周辺イベント、セールの有無、広告費、チラシ枚数などなど・・が説明変数/特徴量となります。

ただ、説明変数には、売り上げへの影響が強いものがあれば、弱いものもあります。

まったく関係なさそうなものもあります。

予測精度をあげようと思ったら、あたりまえですけど、売り上げへの影響が強いものにしぼって学習データを作る必要があります。

どの説明変数が使えそうか?

もしくは、どの説明変数がいらないか?

説明変数の中の値で予測精度をさげるようなイレギュラーな値(はずれ値)がはいっていないか?

そんなことを調べて、学習データの精度をあげてやる必要があります。

 

サンプルで使うデータとやること

以下の要領でCSVファイルを読み込んで「t」というDataFrameがある想定です。

train = pd.read_csv('./csvdata/train.csv')

こんなデータを例にします。

f:id:arakan_no_boku:20200516231202p:plain
target列が目的変数です。

他の列は説明変数候補です。

説明変数として有効かどうかは、まだわからないので、説明変数候補に対して分析をかけて、使えそうかどうか「あたりをつける」作業をしてみようというわけです。

あたりをつけるとはどうするか?なのですが。

一番、理解しやすいのは出現率ではないかと思ってます。

つまり、目的変数である「target」が各値になるときに、ある説明変数の値がどれくらいの比率で出現しているか?ってことです。

出現率が高い値があるということは、目的変数の値を決定するのに影響が強い可能性が高いですし、逆なら弱い・・というのは考えやすいです。

まず、それをやってみます。

 

Pandasのcrosstabで出現率をみるサンプル

出現率をみるのに、Pandasの「crosstab」を使います。

pandas.pydata.org

コード例は、以下がインポートされている前提とします。

import pandas as pd

出現率計算1:crosstabでnormalize='columns'

例の「prl」列を説明変数に選んで、目的変数に対する各値の出現率を求めます。

pd.crosstab(index=train['target'], columns=train['brl'], margins=True, normalize='columns')

結果はこんな感じ。

f:id:arakan_no_boku:20200516232336p:plain

brlが「0」の時、「1」の時に、各targetの値ごとの出現率が計算されてます。

各列の縦計は「概ね1.0・・つまり100%」です。

上記は列方向の計が100%になっています。

出現率2:crosstabでnormalize='index'

オプションを「normalize='index'」に変更すると、行方向の計が100%になります。

pd.crosstab(index=train['target'], columns=train['brl'], margins=True, normalize='index')

結果はこう変わります。

f:id:arakan_no_boku:20200516233330p:plain

横計が概ね100%になります。

出現率3:indexとcolumnsを入れ替えてみる

上記はindexに目標変数、columnsに特徴変数を指定しています。

今度は、それを入れ替えてみます。

pd.crosstab(index=train['brl'],columns=train['target'],margins=True,normalize='index')

 そうすると、以下のように横長になります。

f:id:arakan_no_boku:20200520203743p:plain

ブログの画像にすると見づらいですが、実際には、たくさんの項目を並べて表示するので、このほうもよく使います。

出現率4:結果をheatmap(ヒートマップ)で視覚化

crosstabの出力を数字だけだと見づらいときには視覚化します。

出力をprintではなく、左辺のDataFrameに渡し、All列は邪魔なのでdropした後、seabornのheatmap()に渡して表示するだけですけど。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

 

dfheat = pd.crosstab(index=train['target'], columns=train['prl'], margins=True, normalize='columns')
dfheat.drop(['All'], axis=1, inplace=True)
sns.heatmap(dfheat, annot=True)
plt.show()

すると、こういうグラフになって、視覚的に把握しやすい・・かどうかは好みですが・・カッコいいです。 

f:id:arakan_no_boku:20200517004515p:plain

はずれ値にあたりをつける

出現率以外に重要なのは「はずれ値」の把握です。

はずれ値は「他のデータからみて、極端に大きいか小さい値」のことです。

学習データとして使うには、これをみつけて「外れ値=異常値」なのか、「はずれ値だけど異常値ではない」のかを判断しないといけません。

外れ値に判定されたものは学習データからはぶいてやらないと、結果の精度がおちてしまうからです。

どの値がはずれ値なのかを判定する方法にはいくつかあります。

  • スミルノフ・グラブス検定
  • 四分位範囲(IQR)を利用した判定

等です。

今回はシンプルな後者の方法でやります。

四分位範囲(IQR)とは「第3四分位点 - 第1四分位点」で計算します。

それを使って

  • 「第3四分位数から四分位範囲×1.5倍を足した値」以上
  • 「第1四分位数から四分位範囲×1.5倍を引いた値」以下

を外れ値だと判定する方法です。

例にdescribe()で以下のような結果になった列を使います。

f:id:arakan_no_boku:20200517161004p:plain
25%が第一四分位、75%が第三四分位にあたります。

なので、外れ値判定の基準値を求めるのは。

q1 = train['rnd'].describe()['25%']
q3 = train['rnd'].describe()['75%']
iqr = q3 - q1

outlier_min = q1 - (iqr) * 1.5
outlier_max = q3 + (iqr) * 1.5

みたいな感じになります。

上記の例だとoutlier_minは「 -61.5」で、元データのminより小さいので基準値以下の外れ値はありません。

でも、outlier_maxは「142.5」で、maxより小さいので基準値以上の外れ値はあります。

あとは、以下のように基準値以上の外れ値の行を抽出したりして

outmax = train[train['rnd'] >= outlier_max]

あたりをつけ、必要に応じて置き換えたり、行を削除したりすれば、なんとかなりそうな気はします。 

今回はこんなところで。

ではでは。