【numpy】meshgrid メモ

f([a,b])という関数があったとするとf([[a,b], [c,d]])というのは[f([a,b]), f([c,d])]と同じ結果を出力するのはnumpyやmatplotlibの常套らしい.

>>> import numpy as np
>>> x = np.array([1,2,3])# l * m
>>> y = np.array([10,11])# n * k
>>> xx, yy = np.meshgrid(x,y)
>>> xx
array([[1, 2, 3],
       [1, 2, 3]])
>>> yy
array([[10, 10, 10],
       [11, 11, 11]])

xx, yy = np.meshgrid(x,y)ではlen(y)*len(x)の行列を2つ作る.
2次元配列に拡張すると

>>> x = np.array([[10,11],[3,4],[5,6]])#3*2
>>> y = np.array([[1,2,3,4],[5,6,7,8]])#2*4
>>> xx, yy = np.meshgrid(x,y)
>>> xx
array([[10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6],
       [10, 11,  3,  4,  5,  6]])
>>> yy
array([[1, 1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4, 4],
       [5, 5, 5, 5, 5, 5],
       [6, 6, 6, 6, 6, 6],
       [7, 7, 7, 7, 7, 7],
       [8, 8, 8, 8, 8, 8]])

となり(len(y[0])*len(y[1])) * (len(x[0])*len(x[1]))となった.
xxとyyの各成分が重複なく全ての組み合わせとなるように対応している.
これは格子点を生成していると考えられる.
だから実際には上のような使い方は趣旨にあっていなくて, np.arange()などで生成した配列を引数にとるのが格子点を作る上で正しい使い方と言えるだろう.


自分がサンプルプログラムで見たのは

h = 0.02#格子点の間隔
xx, yy = np.meshgrid(np.arange(x.min()-1, x.max()+1, h), np.arange(y.min()-1, y.max()+1, h))#x,yはnp.array()
Z = clf.predict(np.c_[xx.ravel(),yy.ravel()]).reshape(xx.shape)
out = ax.contourf(xx,yy,Z,**params)

これでclassificationの識別領域を塗りつぶせる.

Z = clf.predict(np.c_[xx.ravel(),yy.ravel()]).reshape(xx.shape)

この処理を一つずつ追っていく.

>>> x = np.array([1,2,3,4])
>>> y = np.array([5,6,7,8])
>>> xx, yy = np.meshgrid(x,y)
>>> xx
array([[1, 2, 3, 4],[1, 2, 3, 4],[1, 2, 3, 4],[1, 2, 3, 4]])
>>> yy
array([[5, 5, 5, 5],[6, 6, 6, 6],[7, 7, 7, 7],[8, 8, 8, 8]])
# xx.ravel()で, 一行のベクトルに変形する.
>>> xx.ravel()
array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4])
>>> yy.ravel()
array([5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8])
# np.c_[]で第2軸方向に行列の連結を行う(xx,yyはnp.meshgrid()によって大きさが同じことが保証されている).
# これにより格子点を要素とした配列ができあがる.
>>> np.c_[xx.ravel(),yy.ravel()]
array([[1, 5],
       [2, 5],
       [3, 5],
       [4, 5],
       [1, 6],
       [2, 6],
       [3, 6],
       [4, 6],
       [1, 7],
       [2, 7],
       [3, 7],
       [4, 7],
       [1, 8],
       [2, 8],
       [3, 8],
       [4, 8]])
# 2次元空間上でこれらはテストデータの集合ともとれるので宣言した識別モデルclfのpredict()にかける
# 各格子点に対応したクラスのラベルが返ってくる
>>> clf.predict(np.c_[xx.ravel(),yy.ravel()])
np.array([0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,1])
# 最後にxxの形に整形する
>> clf.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx)#4*4行列
np.array([0,1,1,1],
         [0,0,1,1],
         [0,0,0,1],
         [0,0,0,1])
# これでxxとyyとZの各要素が対応し, 2次元グラフにおける点とクラスがわかる.
# plt.pcolormesh(xx,yy,Z,...)で領域を図示する

deepage.net
このブログの図が分かりやすい.



【参考】
https://deepage.net/features/numpy-meshgrid.html
http://kaisk.hatenadiary.com/entry/2014/11/05/041011
https://qiita.com/sotetsuk/items/d0e73afdcffdc8ac3e6b
https://qiita.com/ynakayama/items/3250452949102840e624