概要
自然言語処理などでは、文や文書を分散表現に変換する際、文字列のリストに単語ベクトルを適用して変換する必要がある。
これをできるだけ速く行いたいので、速度比較して見た。
方法はこのページを参考にした
- 2019/07更新: 配列の要素数が少なすぎて、呼び出しのオーバヘットが大きくなっているのではないかと言うご指摘を踏まえて更新しました。
問題設定・評価
jupyterの %%timeit
で評価をおこなった
擬似問題として以下を用意し、足し合わせが最も速くなるものを比較した
配列が長い時
a = ['a', 'b', 'c'] * 100
b = {'a': np.arange(100), 'b': np.ones(100), 'c': np.zeros(100)}
配列が短い時
a = ['a', 'b', 'c']
b = {'a': np.arange(100), 'b': np.ones(100), 'c': np.zeros(100)}
各種実行方法
for文
%%timeit
c = np.zeros(100)
for x in a:
c += b[x]
内包表記
%%timeit
np.add.reduce(np.array([b[x] for x in a]))
map
%%timeit
np.add.reduce(np.array(list(map(lambda x: b[x], a))))
np.frompyfunc
def d(x):
return b[x]
f = np.frompyfunc(d, 1, 1)
%%timeit
np.sum(f(a))
結果
配列が長い時
内包表記が一番早くなった。
- for文:
453 µs ± 45.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
- 内包表記:
175 µs ± 185 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
- map:
189 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
- np.frompyfunc:
310 µs ± 316 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
配列が短い時
何と、普通にfor文が速いという結果になった。
- for文:
6.57 µs ± 61.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
- 内包表記:
9.41 µs ± 112 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
- map:
10 µs ± 224 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
- np.frompyfunc:
18 µs ± 1.08 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)