shikoan’s memo

プログラミング初心者のチラ裏

ぷろぐらみんぐ帳

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として指定した場合と同等ですよと。なるほど、これでスッキリした。