はじめに
PythonのMatplotlibライブラリを使ってグラフを動かそうシリーズです。
この記事では、1次元のランダムウォークのアニメーションを作成します。
【他の内容】
【目次】
1次元ランダムウォークの作図
1方向(上下)に移動するランダムウォーク(random walk)のアニメーションを作成します。
利用するライブラリを読み込みます。
# 利用するモジュール import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation import numpy as np
1サンプル
まずは、1つのサンプルを描画します。
試行回数を指定して、移動量をランダムに生成します。
# 試行回数を指定 max_iter = 100 # 乱数を生成 random_vec = np.random.choice([-1, 1], size=max_iter, replace=True) # 移動量 print(random_vec[:5]) print(random_vec.shape)
[-1 -1 1 1 -1]
(100,)
試行ごとに -1
または 1
をランダムに(等確率で)割り当てます。1
は正の方向、-1
は負の方向の移動に対応します。
移動量に応じた座標を計算します。
# 試行ごとに集計 x_vec = np.cumsum( np.hstack([0, random_vec]) # 初期値を追加 ) print(x_vec[:5]) print(x_vec.shape)
[ 0 -1 -2 -1 0]
(101,)
初期値(スタート地点・0回目の結果)を 0
として追加して、各試行までの和(累積和)を np.cumsum()
で計算します。
点の推移のグラフを作成します。
# 余白サイズを指定 margin_rate = 0.1 # グラフサイズを設定 axis_size = np.abs(x_vec).max() axis_size = np.ceil(axis_size * (1+margin_rate)) # 余白を追加 # 1Dランダムウォークを作図 fig, ax = plt.subplots(figsize=(3, 6), dpi=250, facecolor='white') ax.axhline(y=0, color='red', linestyle='dashed') # 初期値 ax.plot(np.repeat(0, repeats=max_iter+1), x_vec) # 軌跡 ax.scatter(x=0, y=x_vec[max_iter], s=100, zorder=100) # 最終地点 ax.set_xticks(ticks=[0], labels=['']) ax.set_xlabel('') ax.set_ylabel('x') ax.set_title('iteration: {}, $x = {}$'.format(max_iter, x_vec[max_iter]), loc='left') fig.suptitle('Random Walk', fontsize=20) ax.set_ylim(ymin=-axis_size, ymax=axis_size) ax.grid() plt.show()
点の推移のアニメーションを作成します。
# 余白サイズを指定 margin_rate = 0.1 # グラフサイズを設定 axis_size = np.abs(x_vec).max() axis_size = np.ceil(axis_size * (1+margin_rate)) # 余白を追加 # グラフオブジェクトを初期化 fig, ax = plt.subplots(figsize=(3, 6), facecolor='white') fig.suptitle('Random Walk', fontsize=20) # 作図処理を定義 def update(i): # 前フレームのグラフを初期化 plt.cla() # 1Dランダムウォークを作図 ax.axhline(y=0, color='red', linestyle='dashed') # 初期値 ax.plot(np.repeat(0, repeats=i+1), x_vec[:i+1]) # 軌跡 ax.scatter(x=0, y=x_vec[i], s=100, zorder=100) # 現在地点 ax.set_xticks(ticks=[0], labels=['']) ax.set_xlabel('') ax.set_ylabel('x') ax.set_title('iteration: {}, $x = {}$'.format(i, x_vec[i]), loc='left') ax.set_ylim(ymin=-axis_size, ymax=axis_size) ax.grid() # 動画を作成 ani = FuncAnimation(fig=fig, func=update, frames=max_iter+1, interval=100) # 動画を書出 ani.save(filename='1d_x_1.gif', dpi=250)
初期値(期待値)を破線で示します。
試行回数軸を追加したグラフを作成します。
# 余白サイズを指定 margin_rate = 0.1 # グラフサイズを設定 axis_size = np.abs(x_vec).max() axis_size = np.ceil(axis_size * (1+margin_rate)) # 余白を追加 # 1Dランダムウォークを作図 fig, ax = plt.subplots(figsize=(8, 6), dpi=250, facecolor='white') ax.axhline(y=0, color='red', linestyle='dashed', zorder=0) # 初期値 ax.plot(np.arange(max_iter+1), x_vec) # 軌跡 ax.scatter(x=max_iter, y=x_vec[max_iter], s=100, zorder=100) # 最終地点 ax.set_xlabel('iteration') ax.set_ylabel('x') ax.set_title('iteration: {}, $x = {}$'.format(max_iter, x_vec[max_iter]), loc='left') fig.suptitle('Random Walk', fontsize=20) ax.set_ylim(ymin=-axis_size, ymax=axis_size) ax.grid() plt.show()
試行回数軸を追加した点の推移のアニメーションを作成します。
# 余白サイズを指定 margin_rate = 0.1 # グラフサイズを設定 axis_size = np.abs(x_vec).max() axis_size = np.ceil(axis_size * (1+margin_rate)) # 余白を追加 # グラフオブジェクトを初期化 fig, ax = plt.subplots(figsize=(8, 6), facecolor='white') fig.suptitle('Random Walk', fontsize=20) # 作図処理を定義 def update(i): # 前フレームのグラフを初期化 plt.cla() # 1Dランダムウォークを作図 ax.axhline(y=0, color='red', linestyle='dashed', zorder=0) # 初期値 ax.plot(np.arange(i+1), x_vec[:i+1]) # 軌跡 ax.scatter(x=i, y=x_vec[i], s=100, zorder=100) # 現在地点 ax.set_xlabel('iteration') ax.set_ylabel('x') ax.set_title('iteration: {}, $x = {}$'.format(i, x_vec[i]), loc='left') ax.set_xlim(xmin=-max_iter*margin_rate, xmax=max_iter*(1+margin_rate)) ax.set_ylim(ymin=-axis_size, ymax=axis_size) ax.grid() # 動画を作成 ani = FuncAnimation(fig=fig, func=update, frames=max_iter+1, interval=100) # 動画を書出 ani.save(filename='1d_ix_1.gif', dpi=250)
試行回数(時間)の変化を横軸で表します。
複数サンプル
続いて、複数のサンプルを並べて描画します。
作図コードについては「RandomWalk_1d.py at anemptyarchive/matplotlib · GitHub」を参照してください。
・サンプル軸あり
等確率で移動する場合、初期値が期待値になりますが分散を持ち(散らばり)ます。
・試行回数(時間)軸あり
回数が増えると分散が大きくなるのを確認できます。
この記事では、1次元の(上下に移動する)ランダムウォークを扱いました。次の記事では、2次元の(上下左右に移動する)場合を扱います。
おわりに
Rで作った2次元までのランダムウォークをリメイクしたところ、3次元版を作りたくなったのでPythonで1次元からやっていきます。
2024年2月22日は、モーニング娘。'24の横山玲奈さんの23歳のお誕生日です。
いつも楽しそうにしている姿が素敵です。
【次の内容】