Numpy Tutorial:Ufuncs, Random numbers

前回のNumpy tutorialの続きをこのサイトを参考にしながらやる。今回はUniversal functions (Ufuncs)についてのチュートリアルをやる。

スポンサーリンク

Universal functions (Ufuncs)

ufuncsはスカラーと配列の両方に機能する関数として知られている。配列では、ufuncはelement-wise(要素毎)形式で関数を適用する。ufuncの使用はベクトル化には必須で、通常、各要素に対して(explicit loop)明示的なループを用いるより演算的に遥かに高速だ。

import os
import sys
import glob
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
%precision 4
plt.style.use('ggplot')
xs = np.linspace(0, 2*np.pi, 100)
ys = np.sin(xs) # np.sin is a universal function
plt.rcParams['figure.figsize'] = 12, 8
plt.rcParams["font.size"] = "17"
plt.plot(xs, ys);

演算子もデフォルトでelementwise(要素ごとに)演算を行う。

# operators also perform elementwise operations by default

xs = np.arange(10)
print (xs)
print (-xs)
print (xs+xs)
print (xs*xs)
print (xs**3)
print (xs < 5)
[0 1 2 3 4 5 6 7 8 9]
[ 0 -1 -2 -3 -4 -5 -6 -7 -8 -9]
[ 0  2  4  6  8 10 12 14 16 18]
[ 0  1  4  9 16 25 36 49 64 81]
[  0   1   8  27  64 125 216 343 512 729]
[ True  True  True  True  True False False False False False]

Generalized ufucns

universal function(万能関数)は、スカラーに対してvectorized looping(ベクトル化ループ)を行う。generalized ufucn(汎用ufunc)は、ベクトルや配列に対してループを実行する。現在、numpyはたった一つの汎用ufuncしか提供してないが、それらは、今後カバーするトピックである、numbaのJITコンパイルに対して重要な役割を演じている。

from numpy.core.umath_tests import matrix_multiply

print (matrix_multiply.signature)
(m,n),(n,p)->(m,p)
us = np.random.random((5, 2, 3)) # 5 2x3 matrics
vs = np.random.random((5, 3, 4)) # 5 3x4 matrices
# perform matrix multiplication for each of the 5 sets of matrices
ws = matrix_multiply(us, vs)
print (ws.shape)
print (ws)
(5, 2, 4)
[[[0.4652 0.7768 0.2822 0.8682]
  [0.6196 0.9977 0.3662 0.913 ]]

 [[0.5601 1.1896 1.2667 1.5861]
  [0.2192 0.4064 0.7416 0.6606]]

 [[1.9953 0.9855 0.9405 0.7292]
  [1.8009 0.9847 0.7144 0.897 ]]

 [[1.3074 1.3115 1.5631 1.4331]
  [0.711  0.8359 1.0549 0.9593]]

 [[0.5399 0.4656 0.8044 0.4517]
  [0.9644 0.6275 0.5986 0.2654]]]

Random numbers

広く利用されている(疑似)乱数用の2つのモジュールが存在する。ある分布から乱数を生成するだけならnumpy.randomモジュールを使うのが最も簡単だ。分位点やPDFのような分布に関するより多くの情報が必要な場合、scipy.statsモジュールが使える。

import numpy.random as npr
npr.seed(123) # fix seed for reproducible results

サイコロを100回振るのを10回トライする。

# 10 trials of rolling a fair 6-sided 100 times
roll = 1.0/6
x = npr.multinomial(100, [roll]*6, 10)
x
array([[18, 14, 14, 18, 20, 16],
       [16, 25, 16, 14, 14, 15],
       [15, 19, 16, 12, 18, 20],
       [19, 13, 14, 18, 18, 18],
       [18, 20, 17, 16, 16, 13],
       [15, 16, 15, 16, 20, 18],
       [12, 17, 17, 18, 17, 19],
       [15, 16, 22, 21, 13, 13],
       [18, 12, 16, 17, 22, 15],
       [14, 17, 25, 15, 15, 14]])
# uniformly distributed numbers in 2D
x = npr.uniform(-1, 1, (100, 2))
plt.rcParams['figure.figsize'] = 12, 8
plt.rcParams["font.size"] = "17"
plt.scatter(x[:,0], x[:,1], s=50)
plt.axis([-1.05, 1.05, -1.05, 1.05]);

ベクトルをランダムにシャッフルする。

# ranodmly shuffling a vector
x = np.arange(10)
npr.shuffle(x)
x
array([3, 4, 9, 2, 1, 6, 0, 7, 8, 5])

ランダム並び替え

# radnom permutations
npr.permutation(10)
array([6, 9, 1, 7, 0, 3, 8, 4, 5, 2])

置換無しランダムセレクション

# radnom selection without replacement
x = np.arange(10,20)
npr.choice(x, 10, replace=False)
array([11, 14, 15, 18, 13, 19, 16, 17, 12, 10])

置換有りランダムセレクション

# radnom selection with replacement
npr.choice(x, (5, 10), replace=True) # this is default
array([[11, 15, 13, 18, 19, 10, 18, 19, 17, 12],
       [14, 10, 18, 13, 12, 13, 16, 12, 18, 15],
       [14, 14, 10, 10, 13, 18, 15, 14, 11, 14],
       [12, 11, 14, 11, 18, 11, 11, 17, 12, 18],
       [19, 18, 13, 13, 14, 13, 13, 16, 11, 16]])
# toy example - estimating pi inefficiently
n = 1000000
x = npr.uniform(-1,1,(n,2))
4.0*np.sum(x[:,0]**2 + x[:,1]**2 < 1)/n
3.145668