【NumPy入門】np.vectorizeでPython関数を簡単にユニバーサル関数化!

こんにちは!インストラクターのフクロウです!NumPyにはホントにたくさんの関数があります。これを全部使いこなすのは少し難しいですし、NumPyの機能だけでは実装できない処理もあるはずです。

そんなときに役に立つのがnp.vectorize関数。Pythonの関数を簡単にNumPyの関数にしてくれます!この記事で使い方を学んで使ってみてください!

np.vectorizeの使い方

np.vectorizeの基本的な使い方

np.vectorizeは、Pythonの関数を配列に適用できるように変換する関数です。NumPyにおいて、配列のすべての要素に一括で処理を適用できる関数のことをユニバーサル関数といいます。

np.vectorizeでユニバーサル関数にできる関数は、スカラー値や文字列が引数になっているものです。では、Pythonで実装したsigmoid関数を、np.vectorizeでユニバーサル関数化してみましょう。

import numpy as np
import math

# ①ターゲットのPython関数
def py_sigmoid(x):
    return 1/ (1+math.exp(-x))

# ②forループでユニバーサル関数っぽくしたもの
def vpy_sigmoid(X):
    result = np.zeros_like(X)
    for i in range(len(X)):
        result[i] = py_sigmoid(X[i])
    return result

# ③np.vectorizeでユニバーサル関数を作ったもの
vsigmoid = np.vectorize(py_sigmoid)

# ④NumPy関数で作ったユニバーサル関数
def np_sigmoid(x):
    return 1/ (1+np.exp(-x))

①はスカラーを受け取って、スカラーを返す関数です。

>>> X = np.linspace(-10,10, 10)

>>> py_sigmoid(X)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-a145f0f92b5a> in <module>()
----> 1 py_sigmoid(X)

<ipython-input-2-bcf4ceeeadd2> in py_sigmoid(x)
      1 def py_sigmoid(x):
----> 2     return 1/ (1+math.exp(-x))
      3 
      4 def vpy_sigmoid(X):
      5     result = np.zeros_like(X)

TypeError: only size-1 arrays can be converted to Python scalars

この関数を配列のすべての要素に適用するには、普通に考えるとfor文を使うことになります。それが②ですが、np.vectorizeを使うと一行で再現することができます。

では、これらの関数がちゃんと動作するか見てみましょう。

>>> vpy_sigmoid(X)

array([4.53978687e-05, 4.18766684e-04, 3.85103236e-03, 3.44451957e-02,
       2.47663801e-01, 7.52336199e-01, 9.65554804e-01, 9.96148968e-01,
       9.99581233e-01, 9.99954602e-01])

>>> vsigmoid(X)

array([4.53978687e-05, 4.18766684e-04, 3.85103236e-03, 3.44451957e-02,
       2.47663801e-01, 7.52336199e-01, 9.65554804e-01, 9.96148968e-01,
       9.99581233e-01, 9.99954602e-01])

>>> np_sigmoid(X)

array([4.53978687e-05, 4.18766684e-04, 3.85103236e-03, 3.44451957e-02,
       2.47663801e-01, 7.52336199e-01, 9.65554804e-01, 9.96148968e-01,
       9.99581233e-01, 9.99954602e-01])

どの書き方の関数でも、同様にすべての要素にsigmoid関数の計算ができていることがわかりますね。今回はsigmoidなのでNumPyの機能だけでキレイに書き下せますが、難しい場合には非常に便利ですね。

何よりfor文を書かずにNumPyっぽくプログラムがかけるのがいいですね!

np.vectorizeの速度比較

さて、Pythonの関数を気軽にユニバーサル関数にできるnp.vectorizeですが、実行速度はどうでしょうか。ipythonやjupyterなどの環境で、プログラムの実行時間を測る%timeit機能を使って測ってみましょう!

sample = np.linspace(-100,100, 1000)

%timeit vpy_sigmoid(sample)
%timeit vsigmoid(sample)
%timeit np_sigmoid(sample)
[Output]
357 µs ± 2.84 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
244 µs ± 2.73 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
15.3 µs ± 170 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

for文で書いたvpy_sigmoidよりは、<np.vectorizeで書いたvsigmoidの方が速いですね!でも実は、すべてNumPy関数で書いたものは桁違いの速さ(15.3 µs )です。

NumPyでかける関数はできるだけNumPyで書いてしまって、速度があまり必要でない関数やNumPyで書くのが難しい関数はnp.vectorizeで書くと良さそうです。

まとめ

この記事では、Python関数を簡単にNumPyのユニバーサル関数にする機能、np.vectorize関数を紹介しました。NumPyの関数は独特なので、最初から使いこなすのは難しいかもしれません。

そんなとき、np.vectorize関数を使うことで、手軽に欲しい機能が実装できます!簡単なので是非試して見てくださいね!

LINEで送る
Pocket

ITエンジニアへ転職したい方におすすめ

自分を評価してくれる企業に転職して年収を上げたい! 自分のスキルにあった独自案件を知りたい!
エンジニアは今もっとも注目されている職業の1つ。エンジニアになって年収を増やしたい方や、あなたのスキルに見合った企業へ転職したいエンジニアの方も多いですよね。

しかし、大手の転職媒体は扱う求人数が多くても、誰もが登録しているので競争率もかなり高くなっています。そのため、あなたの条件に見合った企業を見つけても転職するためには、相応の努力とスキルが必要となります。

こういった媒体では、未経験からエンジニアを目指す方やエンジニア歴2〜3年で転職を考えている方にとって、最適な転職環境とはいえません。

そこでオススメしたいのが、未経験者や若手エンジニア向けの独自案件を多く掲載している「侍ワークス」です。

侍ワークスは、独自案件を多く掲載しているだけでなく、

・応募から就業まで一貫したサポート

・就業後もアフターフォロー

といった経験の浅い方や初めてエンジニアを目指す方にも安心のフォロー体制が整っています。もちろん登録は完全無料!しかも案件を見るだけなら登録も不要です。

まずは、お気軽にどんな求人があるか見てみてください。あなたにピッタリの企業がきっと見つかりますよ! 侍ワークスの求人情報を見る

書いた人

フクロウ

フクロウ

第一言語はPythonです。
皆さんRustやりましょう。