8
11

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 3 years have passed since last update.

第1回 Google Colaboratoryで始める機械学習のための特徴量エンジニアリング - カウントデータの二値化と離散化

Last updated at Posted at 2020-03-08

はじめに

本記事ではカウントデータに対しての前処理として使用される二値化と離散化について解説しています。本記事は主に「機械学習のための特徴量エンジニアリング」を参考とさせて頂いておりますので、気になる方は是非チェックしてみてください。

また本記事の内容をより詳しくYouTubeで解説しているのでこちらも気になる方はチェックしてみてください。

※本記事で解説するプログラムは全てこちらにあります。

二値化とは

名前の通りターゲットの値を二値にする処理のことです。例えば以下の様な例を考えます。

例
ユーザーにおすすめの曲をレコメンドするシステムを作成したい。
ユーザーが曲を聞いた回数を特徴量として使用したいがどのようにデータを整形すれば良いか?

そこでとあるユーザーのデータを取り出したところ、以下の様なデータであったと仮定します。1列目が曲のID、2列目がその曲を再生した回数です。

image.png

このデータをヒストグラムにすると以下の様になました。

image.png

さてここで、ユーザーにおすすめの曲をリコメンドするためにはユーザーがその曲に興味を持ったのかという情報が重要になります。しかし、上記のままでは20回聞いた曲は、1回しか聞いていない曲しか聞いていない曲の20倍好きという情報をモデルに与えてしまうことになります。そこで一度でも曲を再生していれば興味があると仮定して1度以上再生された曲は1、一回も再生されていない曲は0と二値化しました。こうすることで、曲ごとの差をなくし興味のある曲と興味のない曲に分けることができました。

これをグラフに表すと以下のようになります。

image.png

実装したコードを以下に示します。

binary.py
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

##乱数固定
np.random.seed(100)

##疑似データを生成
data_array = []
for i in range(1, 1000):
  s = np.random.randint(0, i * 10, 10)
  data_array.extend(s)
data_array.extend(np.zeros(9000))
data = pd.DataFrame({'Listen Count': data_array})

data_binary = pd.DataFrame()
##1をかけることでTrue, Falseから1,0に変換
data_binary['Listen Count'] = (data['Listen Count'] > 0) * 1

##離散化とは

固定幅による離散化

離散化を行うことで、連続したデータを同じグループとして扱うことができるので、

  • スケールによる影響を取り除くことができる
  • 外れ値をなくすことができる

というメリットがあります

例えば人の年齢が数値データとして与えられている場合は、0~10をグループ1, 10~20をグループ2....., 80以上をグループ9とすることで全ての年齢をグループに分けることが可能になります。数値データのままでもいいように感じるかもしれませんが、例えば110歳まで生きた人が数人いた場合その大きなデータに引っ張られてしまい、他の要素の影響が小さくなってしまうという問題が発生する場合があります。ですが80歳も110歳も同様に高齢者として同グループにすることで、このような問題を解消することができます。

今回は年齢を10歳ごとに区切りましたが、ライフスタイルに合わせ0~12(幼少期から小学校)をグループ1, 12~17(中高生)をグループ2というようにグループ分けする場合もあります。

また、数値が複数の桁にまたがる場合は、0~9, 10~99, 100~999, といったように10の累乗でグループ分けする場合もあります。

10ごとに区切る場合

discretization.py
import numpy as np

small_counts = np.random.randint(0, 100, 20)
print(small_counts)

print(np.floor_divide(small_counts, 10))

実行結果

image.png

image.png

10の累乗でグループ化する場合

discretization.py
import numpy as np

large_counts = []
for i in range(1, 100, 10):
  tmp = np.random.randint(0, i * 1000, 5)
  large_counts.extend(tmp)

print(np.array(large_counts))
print(np.floor(np.log10(large_counts)))

image.png

image.png

分位数による離散化

固定幅による離散化は非常に便利ですが、例えばカウントデータに大きなギャップがあると、データの入らないグループが複数できてしまいます。その様な場合は分位数を用います。分位数はデータを中央値で2分し、分けられたデータに対してさらに中央値で2分します。なので四分位数はデータを4個に分割し、十分位数ではデータを10個に分割します。

例えば以下のような分布のデータの十分位数を求めると下の表の様になります。

image.png

image.png

この値をグラフに示すと以下の図の様になり、データの数量が均等になる様に幅が求められていることがわかります。

image.png

実装したプログラムを以下に示します。

分位数でグループ化する場合(グラフ)

quantile.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

##乱数固定
np.random.seed(100)

data_array = []
for i in range(1, 1000):
  s = np.random.randint(0, i * 10, 10)
  data_array.extend(s)
data_array.extend(np.zeros(2000))
data = pd.DataFrame({'Listen Count': data_array})

deciles = data['Listen Count'].quantile([.1, .2, .3, .4, .5, .6, .7, .8, .9])

print(deciles)

plt.vlines(deciles, 0, 5500, "blue", linestyles='dashed') 

image.png

分位数でグループ化する場合

quantile.py
import numpy as np

large_counts = []
for i in range(1, 100, 10):
  tmp = np.random.randint(0, i * 1000, 5)
  large_counts.extend(tmp)
np.array(large_counts)

# 四分位数に変換
print(pd.qcut(large_counts, 4, labels=False))

image.png

最後に

YouTubeで機械学習を中心に技術書のレビューや解説動画を上げていこうと思っています。またIT系に行くなら知っておいた方がいい企業の紹介もやっています。YoutubeとQiita更新のモチベーションに繋がるため、いいね、チャンネル登録、高評価をよろしくお願い致します。

YouTube: https://www.youtube.com/channel/UCywlrxt0nEdJGYtDBPW-peg
Twitter: https://twitter.com/tatelabo

8
11
0

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
8
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?