0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【反省会】クラス分類するとき名義尺度と間隔尺度の概念を失念していた【初心者あるある?】

Last updated at Posted at 2019-03-03

先日、初めてクラス分類に一人で挑戦した時の記事
【機械学習】自動車の性能を分類してみる

大変な間違いをしていることに気づきました
それは名義尺度(または順序尺度)と間隔尺度の概念です

おそらくほとんどの人にとっては常識的過ぎて失笑ものだと思いますが、記録として

#1. 4つの尺度
統計学では変数をその性質に応じて4つの尺度、「名義尺度」「順序尺度」「間隔尺度」「比例尺度」に分類します

  • 名義尺度
    いわゆる文字列
  • 順序尺度
    よくアンケートで見る(1.大変そう思う 2.そう思う 3.どちらでもない 4.そう思わない)のような順序に大小の関係があるもの ※間隔には意味がない!!!
  • 間隔尺度
    目盛が等間隔になっているもので、その間隔に意味があるもの
  • 比例尺度
    0が原点であり、間隔と比率に意味があるもの
    詳細は1-4. 変数の尺度

#2. 尺度の種類をガン無視していた
昨日の私

3.文字列の変換
とりあえず文字列をすべて数値に置換しました

df['class']=df['class'].apply(lambda x:1 if x=='unacc' else(2 if x=='acc' else(3 if x=='good' else 4)))
df['buying']=df['buying'].apply(lambda x:1 if x=='low' else(2 if x=='med' else(3 if x=='high' else 4)))
df['maint']=df['maint'].apply(lambda x:1 if x=='low' else(2 if x=='med' else(3 if x=='high' else 4)))
df['doors'][df['doors']=='5more']=5
df['persons'][df['persons']=='more']=5
df['lug_boot']=df['lug_boot'].apply(lambda x:1 if x=='small' else(2 if x=='med' else 3))
df['safety']=df['safety'].apply(lambda x:1 if x=='low' else(2 if x=='med' else 3))

>特徴量idは不要なので削除してから出力

>| index | class | buying | maint | doors | persons | lug_boot | safety |
|-------|-------|--------|-------|-------|---------|----------|--------|
| 0     | 1     | 1      | 2     | 3     | 2       | 1        | 1      |
| 1     | 2     | 1      | 3     | 3     | 5       | 1        | 2      |
| 2     | 1     | 4      | 3     | 5     | 2       | 1        | 2      |
| 3     | 2     | 3      | 3     | 3     | 5       | 3        | 2      |
| 4     | 1     | 3      | 3     | 3     | 2       | 2        | 3      |

**これはデータをちゃんと変換したようだが、名義尺度文字列を名義尺度数字に置き換えただけで全く意味がない**
→クラスごとに0,1の変数に変換し、説明変数として用いる必要がある。いわゆるダミー変数です

#3. ダミー変数 OneHotEncoding
```py
from sklearn.preprocessing import OneHotEncoder
maint=df['maint'].values.reshape(-1,1)
maint_enc=OneHotEncoder().fit_transform(maint).toarray()
doors=df['doors'].values.reshape(-1,1)
doors_enc=OneHotEncoder().fit_transform(doors).toarray()
persons=df['persons'].values.reshape(-1,1)
persons_enc=OneHotEncoder().fit_transform(persons).toarray()
lug_boot=df['lug_boot'].values.reshape(-1,1)
lug_boot_enc=OneHotEncoder().fit_transform(lug_boot).toarray()

こんな感じでやるとダミー変数になります
これを結合して見やすくデータフレーム化すると

- 0 1 2 3 4 5 6 7 8 9 ... 11 12 13 14 15 16 17 18 19 20
0 0 1 0 0 0 0 1 0 0 1 ... 0 1 0 0 0 0 1 0 1 0
1 0 1 0 0 1 0 0 0 0 1 ... 0 0 0 1 0 0 1 0 0 1
2 0 0 0 1 1 0 0 0 0 0 ... 1 1 0 0 0 0 1 0 0 1
3 1 0 0 0 1 0 0 0 0 1 ... 0 0 0 1 1 0 0 0 0 1
4 1 0 0 0 1 0 0 0 0 1 ... 0 1 0 0 0 1 0 1 0 0
こんな感じになります
次元が一気に増えました。カラム名をしっかり設定すればより見やすくなります
これで準備完了です

このデータをStratified-k-Foldで分割して前回と同様に分類し、識別率を評価します
無題.png
なんか微妙ですね。むしろ前回より下がった気がします。
そこでGoogle先生に尋ねてみると2つの要因が浮かびました

#4.ダミー変数を使用しないほうがいいケース
ダミー変数の作り方と注意点について

数値に大小の連続性がある場合はダミー変数にしないようが良いと言われています。

例えば最終学歴のカテゴリがあり、1.中学、2.高校、3.専門(高専)、4.大学、5.大学院と定義されているカテゴリがあったとします。数値が大きくなれば大きくなるほど高学歴となるため、一般的には年収が高くなる傾向がありあす。その場合、最終学歴の数値の大小と年収には関連性は存在することになります。しかし、ここで最終学歴をダミー変数にした場合は独立したパラメータとなってしまうので、最終学歴と年収の関連性は薄くなってしまいます。

このように数値に大小の連続性がある場合はダミー変数にしないようが良いケースもあると言われています。

なるほど
今回のデータには車に乗れる人の数(persons)と車についているドアの数(doors)がありますがこれに該当しそう
Bad Request
しかしグラフで確認してみると(なぜか画像が貼れない)あまり関連性はなさそう

#5. 多重共線性
ダミー変数を使うと変数が大量に増えることがあります
そして0,1で区別した両者には強い相関関係があるため、分析結果に悪影響をもたらすことがあるそう
そこで意図的に次元を削除する必要がある

今回はダミー変数化したそれぞれの特徴量のうちの先頭を削除しました

#6.結果
4と5で上げたことを考慮し再分類
無題.png
うーん。改善したとは言えません

次に4で挙げた2変数のうちあまり相関関係がみられなかったdoorsを再びダミー変数に
無題.png
改悪でした

#7. 結論

  • データの尺度に気を付けるのは非常に大事で、このデータは比例なのか間隔なのかなど常に意識すること!!!
  • 結局あまりうまくいかない
  • もう少しダミー変数のうまい使い方を勉強しなくてはいけません
0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?