仙豆のレシピ

ちょっとしたことでも書いていく姿勢で

numpy覚書

大したことしてないけど忘れたとき用に書いておく。

命名が微妙なのはまあ文脈によって変えるという感じで)

one_hot

def one_hot(v):
    return np.eye(v.shape[1], dtype=int)[np.argmax(v, axis=1)]

n個のd次元ベクトルに対し、それぞれのベクトルで最大の要素を1他を0にしたベクトルを返す。具体的には以下。

>>> v
array([[0.1, 0.2, 0.7],
       [0.5, 0.3, 0.2],
       [0.3, 0.3, 0.4]])
>>> one_hot(v)
array([[0, 0, 1],
       [1, 0, 0],
       [0, 0, 1]])

仕組みはnp.eye()n \times n単位行列を生成、np.argmax()vの各ベクトルの最大値のインデックスを並べたn次元ベクトルを生成しそれを添え字とする。

count_class

def count_class(v):
    return np.sum(one_hot(v), axis=0)

n個のd次元ベクトルに対し、各インデックスごとにそのインデックスが最大値をとるベクトルの個数を現した配列を返す。

>>> v
array([[0.1, 0.2, 0.7],
       [0.5, 0.3, 0.2],
       [0.3, 0.3, 0.4]])
>>> count_class(v)
array([1, 0, 2])

one_hot()してaxis=0で足すだけ。

select_classes

def select_classes(v, cls):
    return v[np.isin(np.argmax(v, axis=1), cls)]

n個のd次元ベクトルに対し、最大値のインデックスが指定したいずれかの値とマッチしているベクトルのみを返す。

>>> v
array([[0.1, 0.2, 0.7],
       [0.5, 0.3, 0.2],
       [0.3, 0.3, 0.4]])
>>> select_classes(v, [0, 1])
array([[0.5, 0.3, 0.2]])
>>> select_classes(v, [1, 2])
array([[0.1, 0.2, 0.7],
       [0.3, 0.3, 0.4]])

np.isin()vの最大値のインデックスがclsに含まれているか否かの真偽値ベクトルを生成し添え字に利用。

ちなみにnp.isin()はnumpyのversion 1.13.0 から入ったらしく、これが無いときは以下のようにしてた。

def select_classes(v, cls):
    ind = np.zeros(v.shape[0], dtype=bool)
    v_cls = np.argmax(v, axis=1)
    for c in cls:
        ind |= (v_cls == c)
    return v[ind]

おまけ

pythonインタラクティブシェル便利だけど、毎回import numpyするのめんどうなので以下のようにしておくとコマンドラインnumpyと打てばnumpyをインポートした状態でインタラクティブシェルを始められる。

$ echo "import numpy as np" > ${HOME}/.startup_numpy.py
$ alias numpy="PYTHONSTARTUP=${HOME}/.startup_numpy.py python"