numpy.bincountのweightの意味
100 Numpy Exercisesの56問目で解いていたときにふと湧いた疑問。こんな問題。
56.How to accumulate elements of a vector (X) to an array (F) based on an index list (I)? (★★★)
# Author: Alan G Isaac X = [1,2,3,4,5,6] I = [1,3,9,3,4,1] F = np.bincount(I,X) print(F)
解説
第2引数を指定しない場合はわかりやすい。0以上の整数が登場した回数を表す。
>>> import numpy as np >>> x = np.random.randint(0,10,10) >>> x array([8, 5, 0, 4, 1, 2, 7, 0, 3, 1]) >>> np.bincount(x) array([2, 2, 1, 1, 1, 1, 0, 1, 1], dtype=int64)
結果は、0が登場した回数、1が登場した回数……と続く。とてもわかりやすい(randintが整数の乱数発生関数なので、結果は実行するたびに変わるのに注意)。
第2引数はweight(重み付け)の引数である。これが何について重み付けしているのかわからずにハマった。weightのベクトルを用意する。
>>> w = np.linspace(0.1,1,10) >>> w array([ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]) >>> np.bincount(x,w) array([ 1.1, 1.5, 0.6, 0.9, 0.4, 0.2, 0. , 0.7, 0.1])
0は0.1で重み付け、1は0.2で重み付けしているのかなと思ったらそうではない。なんだろう?と数十分試していてようやくわかった。このweightは登場する値に対する重み付けではなく、サンプルに対する重み付けなのだ。
この場合、
- xの1番目の8のサンプルは0.1としてカウントする
- xの2番目の5のサンプルは0.2としてカウントする
- : : :
- xの10番目の1のサンプルは1としてカウントする
これをやっていたのだ。確かにこれで計算すると辻褄が合う。
リファレンスをよく見ると載っていた。
weights is specified the input array is weighted by it, i.e. if a value n is found at position i, out[n] += weight[i] instead of out[n] += 1.
numpy.bincount — NumPy v1.14 Manual
つまりデフォルトでは重み付けのパラメーターを全て1として指定した場合と同等ですよと。なるほど、これでスッキリした。