見出し画像

NumPy公式チュートリアルを効率的に学習する方法

今回はNumPy公式チュートリアルを効率的に学習する方法をノートしたいと思います。

公式チュートリアルの重要性

まず、今回のNumPyに限らず新しいライブラリやフレームワークを学習する際にはその公式HPにあるチュートリアルで学習することをおすすめします。理由は、公式チュートリアルはその作者によって書かれたものなので重要なことが全て書いてあります。また使い方の説明が断片的ではなく体系的に書かれているので理解しやすいです。

急いでいるプロジェクトなどでは公式チュートリアルを全部読むの面倒くさいなと思うことが多々ありましたが、プロジェクトの初期の段階で公式チュートリアルを読んでいることによって結果的にプロジェクトが早く終ることが多かったです。

特に、公式チュートリアルの目次が頭の片隅にあるか or ないによって、なにか問題が発生した場合の解決のスピードが違ってきます。問題の解決手段をネットで時間をかけてあれこれ調べたけれど、結局それは公式のチュートリアルに書いてあったということが多々ありました。まさに急がば回れです。

NumPy公式チュートリアル

NumPyの公式チュートリアルは以下のURLにあります。
@naoya_tさんがブログで、NumPyチュートリアルの日本語訳を公開しているのでそちらのリンクも記載します。

効率的に理解するには早く作る(早く間違う)ことが重要

そして、時間をかけて公式チュートリアルを読み終わった後、なるほど、このライブラリ・フレームワークは確かに便利そうだな、使い方や便利な機能も一通り知ったことだし、あとは使うだけ。と思っていざ何かを作ろうとなると思うのですが、その時になって初めて自分がいかに分かったつもりであったかに気付かされることがよくあります。

つまり、知っているということと作れること(使えること)には大きな違いがあります。知っているだけではそのライブラリについて理解したとは言えず、作ること(使えること)が出来て初めて本当に理解したと言えると思います。そして、チュートリアルで紹介されている全ての機能を一通り使ったコードを実際に書いてみることで、自分がどの部分を理解できてないかに早く気付くことができます。これは言い換えると、効率的に理解するには早く作ってみる(早く間違いに気付く)ことが大事だと言えると思います。これはまさにFail Fast(フェイルファスト)の精神です。

Unittestのフレームワークを利用して最小のコードを書く

それでは話を一般論からNumPyに戻しますが、NumPyの公式チュートリアルに紹介されている全ての機能を一通り使ったPythonコードを書く手段として私がオススメするのは、Unittestのフレームワークを利用する方法です。

例えば、NumPyの公式チュートリアルにndarrayオブジェクトが持つ属性について以下のように3つ説明があった場合。

ndarray.ndim
配列の軸数(次元)
ndarray.shape
配列の寸法。これは各次元の配列長を表す整数から成るタプル。n行m列の行列の場合、shapeは(n,m)となる。故に、shapeタプルの長さはランク、すなわち次元数 ndim である。
ndarray.size
配列に含まれる要素の総数。これはshapeの要素すべての積に等しい。

以下のように1次元のベクトルと2次元の行列を作成し、それぞれの属性をassertEqualでチェックするUnitテストを3つ書きます。assertEqualの左側の引数には実際の値、右側の引数にはこうなるはずだとの予想する値をハードコードします。

import unittest
import numpy as np

class TestArrayBasic(unittest.TestCase):

    def test_ndim(self):
        vector = np.array([0, 0, 0])
        metrix = np.array([[0, 0, 0], [0, 0, 0]])
        self.assertEqual(vector.ndim, 1)
        self.assertEqual(metrix.ndim, 2)

    def test_shape(self):
        vector = np.array([0, 0, 0])
        metrix = np.array([[0, 0, 0], [0, 0, 0]])
        self.assertEqual(vector.shape, (3,))
        self.assertEqual(metrix.shape, (2, 3))

    def test_size(self):
        vector = np.array([0, 0, 0])
        metrix = np.array([[0, 0, 0], [0, 0, 0]])
        self.assertEqual(vector.size, 3)
        self.assertEqual(metrix.size, 6)

if __name__ == '__main__':
    unittest.main()

このUnitテストコードをPyCharm上で実行すると以下のような結果になります。チュートリアルの内容を正しく理解できていて、assertEqualの予想値が的中していればUnitテストはオールグリーンになります。

NumPy配列の検証にはassert_array_equal()を使う

NumPy配列(ndarray)を使ってテストコードを書く際に1つ注意する点があります。それは、2つのNumpy配列(ndarray)を比較して検証するにはunittestフレームワークのassert_equal()ではなく、numpy.testing.assert_array_equal()を使う必要があります。

例えば、単位行列を生成するeye()をテストしたい場合は、
以下のようなテストコードになります。

import unittest
import numpy as np
from numpy.testing import assert_array_equal

class TestArrayEye(unittest.TestCase):

    def test_eye_NxN(self):
        metrix = np.eye(3)
        assert_array_equal(metrix, np.array([[1, 0, 0],
                                             [0, 1, 0],
                                             [0, 0, 1]]))

    def test_eye_NxM(self):
        metrix = np.eye(2, 3)
        assert_array_equal(metrix, np.array([[1, 0, 0],
                                             [0, 1, 0]]))

    def test_eye_k0(self):
        metrix = np.eye(3, k=0)
        assert_array_equal(metrix, np.array([[1, 0, 0],
                                             [0, 1, 0],
                                             [0, 0, 1]]))

    def test_eye_k1(self):
        metrix = np.eye(3, k=1)
        assert_array_equal(metrix, np.array([[0, 1, 0],
                                             [0, 0, 1],
                                             [0, 0, 0]]))

    def test_eye_k1m(self):
        metrix = np.eye(3, k=-1)
        assert_array_equal(metrix, np.array([[0, 0, 0],
                                             [1, 0, 0],
                                             [0, 1, 0]]))

if __name__ == '__main__':
    unittest.main()

以下はブロードキャストの仕組みを確認するテストコードです。

import unittest
import numpy as np
from numpy.testing import assert_array_equal

class TestArrayBroadcast(unittest.TestCase):

    def test_plus(self):
        vector = np.arange(6).reshape(2, 3)
        assert_array_equal(vector, np.array([[0, 1, 2], [3, 4, 5]]))
        assert_array_equal(vector + 1, np.array([[1, 2, 3], [4, 5, 6]]))

    def test_minus(self):
        vector = np.arange(6).reshape(2, 3)
        assert_array_equal(vector, np.array([[0, 1, 2], [3, 4, 5]]))
        assert_array_equal(vector - 1, np.array([[-1, 0, 1], [2, 3, 4]]))

    def test_multi(self):
        vector = np.arange(6).reshape(2, 3)
        assert_array_equal(vector, np.array([[0, 1, 2], [3, 4, 5]]))
        assert_array_equal(vector * 2, np.array([[0, 2, 4], [6, 8, 10]]))

    def test_square(self):
        vector = np.arange(6).reshape(2, 3)
        assert_array_equal(vector, np.array([[0, 1, 2], [3, 4, 5]]))
        assert_array_equal(vector ** 2, np.array([[0, 1, 4], [9, 16, 25]]))

if __name__ == '__main__':
    unittest.main()

このような感じでNumPy公式チュートリアルの各トピック毎に1つのテストケースのクラスを作成して、確認したい機能毎にテストメソッドを追加していきます。

以上がNumPy公式チュートリアルを効率的に学習する方法になります。この方法は今回のNumPyに限らず、他の新しいライブラリやフレームワークを学習するときにも有効です。NumPy力のアップにぜひこの方法を試してみるのはいかがでしょうか。

Unitテストを実行する場合のIDEはPyCharmがオススメ

PyCharmの場合、右クリックで簡単にUnitテストコードを実行することができます。関数単位やファイル単位やモジュール単位でのテスト実行が可能なのでとても便利です。

補足:Unitテストの本来の目的

ここではUnittestのフレームワークを新しいライブラリを効率的に理解するための遊び場(Playground)として利用していますが、Unitテストの本来の目的は自分の書いたコードやロジックをテストするためのもので、今回は特殊な使い方であることをご留意下さい。


最後まで読んで頂きありがとうございます。もしこのノートを気に入ってくれたなら下記のボタンよりフォロー&ブックマーク宜しくお願いします。

【参考文献】
NumPy - Quickstart tutorial https://docs.scipy.org/doc/numpy/user/quickstart.html.
@naoya_t - 私訳「暫定的 NumPy チュートリアル」(日本語訳)http://naoyat.hatenablog.jp/entry/2011/12/29/021414.
Python - 26.4. unittest — ユニットテストフレームワーク https://docs.python.jp/3/library/unittest.html.



この記事が気に入ったらサポートをしてみませんか?