Numpyの配列に対して「最も多く存在する値」を求める方法
Posted On 2018-11-22
アンサンブル学習などで、Numpyの配列のある軸に対して「最も多く存在する値」を求めたい、つまり「多数決」をしたいことがあります。その方法を見ていきます。
目次
最も大きい値がmax, 最も大きい値が存在するインデックスがargmax, では「最も多く存在する値」は?
配列のある軸に対して、「最も大きい値」「最も大きい値が存在するインデックス」を求めるのは簡単です。どちらもNumpyの関数であり、np.max, np.argmaxを使えばいいのです。
import numpy as np
np.random.seed(2)
X = np.random.randint(0, 3, size=(5, 3))
print(X)
# 列の中での最大値を求める
print(np.max(X, axis=-1))
# 列の中での、最大値が存在するインデックスを求める
print(np.argmax(X, axis=-1))
出力は以下のとおりです。
[[0 1 0]
[2 2 0]
[2 1 1]
[2 0 0]
[0 1 2]]
[1 2 2 2 2]
[1 0 0 0 2]
要するにmaxやargmaxと同じような感覚で使える、「最も存在する値」を求める関数がほしいのです。どうすればよいのでしょうか?
scipy.stats.modeを使う
「最も存在する値」とは統計学の用語では「最頻値」なので、これを返す関数を使えばいいのです。運良くnp.maxやnp.argmaxなどと同じように軸を指定できます。
scipy.stats.mode
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mode.html
ただし、注意点が1つだけ。数量が同一の値が複数存在したら、数字が小さいほうの値が返されます。例えば、「0, 1, 1, 2, 2」という値に対してmodeを使うと、返される値は「1」となります。
import numpy as np
import scipy.stats as stats
np.random.seed(2)
X = np.random.randint(0, 3, size=(5, 3))
print(X)
# 最頻値を求める(最頻値、その数 の順番)
print(stats.mode(X, axis=-1))
# 分割してもOK
mode_val, mode_num = stats.mode(X, axis=-1)
print(mode_val)
# インデックスでやってもOK
print(stats.mode(X, axis=-1)[0])
このようになります。返り値は2つあり、「最頻値」と「最頻値が存在する個数」になります。
[[0 1 0]
[2 2 0]
[2 1 1]
[2 0 0]
[0 1 2]]
ModeResult(mode=array([[0],
[2],
[1],
[0],
[0]]), count=array([[2],
[2],
[2],
[2],
[1]]))
[[0]
[2]
[1]
[0]
[0]]
[[0]
[2]
[1]
[0]
[0]]
以上です。これでNumpyでも多数決ができましたね。
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー