どうもこんにちは。
コンです。
数あるNumpyライブラリの関数の一つである
numpy.fromfunction
画像処理で使われる、ガウシアンフィルタであったり
配列の処理に非常に役に立つ関数ですので、この関数の使い方を具体例をだしながら
解説したいと思います。
基本
まずはNumpyの公式ページに紹介されているのがこんな感じです。
○numpy.fromfunction(function(必須), shape(必須), *, dtype=<class ‘float’>, like=None, **kwargs)
○retrun : from functionany : any
これをちょっとずつ解説させていただくと
○function:関数、なんでもよい。公式はlambda(無名関数)を使ってますが定義した関数でも大丈夫です
○shape:outputの行列の形、functionによるんですけど、例えば(2, 2)にするとoutputがarray([[0, 0], [1, 1]])
もしくは array([[0, 1], [0, 1]])
になるらしい。
○dtypeとlike:オプション
○**kwargs : **アスタリスクを2つで可変長の辞書型、とりあえず色々変数いれるよ〜って意味です。
でこんな感じの例なんですが、よくわからなかったので色々試してみてました。
まずは lambdaについて
lambdaは無名関数と呼ばれるもので、その名前の通り名前のない関数です。
以下のような形式で記述します。
lambda 引数 : 返り値
例えば次のように使用することができます。
lambda_fn = lambda n: n * 3
print(lambda_fn(4))
###12と出力されます
実際のlambdaコードを動かす部分はこちらのページでも紹介しているので、是非読んでみてください。
shapeってなんだ?
公式を読んでいてわからなかったのが、shapeについてでした。
これは、基本1次元なら[0, 1, 2, 3, …], 2次元なら([[0, 0], [1, 1]])
が 出力されるそうです。
1次元
data = np.fromfunction(lambda x:x, (10, ), dtype=float)
print(data)
#[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]と出力される
def f(x):
return x*2
data2 = np.fromfunction(f, (10, ), dtype=float)
print(z data2)
#data2, [ 0. 2. 4. 6. 8. 10. 12. 14. 16. 18.]と出力される
なんとなくshapeの形にfor文で1づつ増えていき、関数によって返り値が変化する
といった結果になりました。
2次元
次に2次元について書いていきます。
こちらは計算とかlambdaとかを含むとややこしいので、基本的に
入力変数をそのまま出力する関数を使い、np.fromfunctionがどんな計算をするのか
みていきましょう。
def g(x, y):
return x
data3 = np.fromfunction(g, (5, 5), dtype=float)
print('data3', data3, len(data3))
'''
[0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1.]
[2. 2. 2. 2. 2.]
[3. 3. 3. 3. 3.]
[4. 4. 4. 4. 4.]], 5 と表示される
'''
def j(x, y):
return x, y
data4 = np.fromfunction(j, (5, 5), dtype=float)
print('data4', data4, len(data4))
'''
(array([[0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2.],
[3., 3., 3., 3., 3.],
[4., 4., 4., 4., 4.]]), array([[0., 1., 2., 3., 4.],
[0., 1., 2., 3., 4.],
[0., 1., 2., 3., 4.],
[0., 1., 2., 3., 4.],
[0., 1., 2., 3., 4.]])) 2と表示される
'''
def k(x, y):
return x+y, x-y
data5 = np.fromfunction(k, (5, 5), dtype=float)
print('data5', data5, len(data5))
'''
array([[0., 1., 2., 3., 4.],
[1., 2., 3., 4., 5.],
[2., 3., 4., 5., 6.],
[3., 4., 5., 6., 7.],
[4., 5., 6., 7., 8.]]), array([[ 0., -1., -2., -3., -4.],
[ 1., 0., -1., -2., -3.],
[ 2., 1., 0., -1., -2.],
[ 3., 2., 1., 0., -1.],
[ 4., 3., 2., 1., 0.]])) 2と表示される
'''
1つめの(5×5)配列は行が増えるごとに1づつ増えていき、2つ目の(5×5)配列は列が増えるごとに数字が増えていきます。
関数を足し算、引き算に変更した時の結果もよくわかると思います。
この結果を知っていると、公式ページが出している以下の例も
わかりやすいですよね。
1つ目が上のコードのdata3、4つ目がdata5の最初の配列のreturnを示しています。
3次元
3次元も、これまたややこしいので3×3の配列で
入力の値をそのまま出力してみます。
これまた難しいとはおもいますが
1つ目の(3×3)配列は奥行き方向が増えるごとに(3×3)行列の全ての要素1ずつ増えていき、あとは2次元どうように2つ目・3つ目の配列は行・列が増えるごとに数字が増えていきます。
こう書いてみると、かなり分かりやすくなったと思います。
おわりに
ここまで読んでいただき、誠にありがとうございます。
Pythonを7年もやっているのに、知らないことだらけなんだなと最近は実感するばかりです。
他にもこんな面白い関数あるよ。
なんてのがあったら是非教えてください。