はじめに
機械学習や統計学で登場する各種の確率分布について、「計算式の導出・計算のスクラッチ実装・計算過程や結果の可視化」などの「数式・プログラム・図」を用いた解説により、様々な角度から理解を目指すシリーズです。
この記事では、ガウス分布のグラフ作成についてPythonを使って確認します。
【前の内容】
【他の内容】
【今回の内容】
1次元ガウス分布の作図
1次元ガウス分布(Gaussian distribution・正規分布・Normal distribution)のグラフを作成します。この記事では、PythonのMatplotlibライブラリを利用して作図します。
ガウス分布については「1次元ガウス分布の定義式 - からっぽのしょこ」、確率密度計算については「【Python】1次元ガウス分布の計算 - からっぽのしょこ」、Rを利用する場合は「【R】1次元ガウス分布の作図 - からっぽのしょこ」を参照してください。
利用するライブラリを読み込みます。
# ライブラリを読込 import numpy as np from scipy.stats import norm import matplotlib.pyplot as plt
グラフの作成
まずは、1次元ガウス分布のグラフを作成します。
パラメータの設定
ガウス分布のパラメータ を指定します。
# 平均パラメータを指定 mu = 0.0 print(mu) # 標準偏差パラメータを指定 sigma = 1.0 print(sigma)
0.0
1.0
平均(実数) 、標準偏差(正の値)
を指定します。
確率変数 の作図範囲を設定します。
# x軸の範囲を設定 #x_min = -5.0 #x_max = 5.0 k = 4.0 u = 5.0 x_size = sigma # 基準値を指定 x_size *= k # 定数倍 x_min = mu - x_size x_max = mu + x_size x_min = np.floor(x_min /u)*u # u単位で切り下げ x_max = np.ceil(x_max /u)*u # u単位で切り上げ print(x_min, x_max) # x軸の値を作成 x_vec = np.linspace(start=x_min, stop=x_max, num=1001) print(x_vec[:5])
-5.0 5.0
[-5. -4.99 -4.98 -4.97 -4.96]
範囲を指定して、確率変数がとり得る値(実数) の数値ベクトルを作成します。
この例では、指定したパラメータ mu, sigma を使って、平均を中心に標準偏差の倍数 の範囲を設定しています。
続いて、設定した値に従う確率密度を計算して、グラフを作成していきます。
確率分布の計算
の値ごとにガウス分布に従う確率密度
を計算します。
# 確率密度を計算 dens_vec = norm.pdf(x=x_vec, loc=mu, scale=sigma) print(dens_vec[:5])
[1.48671951e-06 1.56286711e-06 1.64275059e-06 1.72654452e-06
1.81443119e-06]
1次元ガウス分布の確率密度は、sp.stats.norm.pdf() で計算できます。確率変数の引数 x に (の配列)、平均の引数
loc に 、標準偏差の引数
scale に を指定します。
確率分布の作図
パラメータラベルを作成します。装飾用の処理です。
# ラベル用の文字列を作成 param_lbl = f'$\\mu = {mu}, \\sigma = {sigma}$' print(param_lbl)
[tex: \mu = 0.0, \sigma = 1.0$
ギリシャ文字などの記号を使った数式を表示する場合は、LaTeXの記法(LaTeXコマンド)を使います。数式に変換する範囲(コマンドの文字列)を $ で挟んで、'$コマンド$' の形式で文字列を指定します。ただし、メタ文字(改行文字 \n など)として認識されないために、バックスラッシュを追加(2つ \\ に)する必要がある場合があります。
オブジェクト(プログラム上の変数)の値を使う場合は、f文字列(や format() )を使います。変数名を波括弧 {} で挟んで、f'{変数名}' の形式で文字列を指定します。(丸め込みなど)数値の文字列を調整する場合は、format() の記法で指定します。
ガウス分布のグラフを作成します。
# ガウス分布を作図 plt.figure(figsize=(9, 6), dpi=100, facecolor='white') plt.plot( x_vec, dens_vec, color='#00A968', linewidth=1.0 ) # 折れ線 plt.xlabel('$x$') # x軸ラベル plt.ylabel('density') # y軸ラベル plt.title(param_lbl, loc='left') # タイトル plt.suptitle('Gaussian distribution', fontsize=20) # 図タイトル plt.grid() # グリッド線 plt.show()

折れ線グラフは、plt.plot() で描画できます。第1引数に変数、第2引数に確率密度を指定します。
以上で、基本的な作図処理を確認しました。
複数グラフの作成
次は、複数のパラメータの1次元ガウス分布を並べて描画します。
パラメータの設定
複数個のパラメータ を設定します。
# 平均パラメータを指定 mu_vals = np.array([-5.0, 0.0, 7.4]) print(mu_vals) # 標準偏差パラメータを指定 sigma_vals = np.array([2.4, 1.0, 0.5]) print(sigma_vals)
[-5. 0. 7.4]
[2.4 1. 0.5]
平均 、標準偏差
をそれぞれ数値ベクトルで指定します。
確率分布の作図
1つの領域に複数の分布を重ねて表示する図と、複数の領域に分割してそれぞれの分布を表示する図の2パターンを作成します。
重ねて描画
こちらのの図は、mu_vals と sigma_vals が同じパラメータ数である必要があります。
確率変数 の作図範囲を設定します。
# x軸の範囲を設定 #x_min = -15.0 #x_max = 10.0 k = 4.0 u = 5.0 x_size_vals = sigma_vals.copy() # 基準値を指定 x_size_vals *= k # 定数倍 x_min = np.min(mu_vals - x_size_vals) x_max = np.max(mu_vals + x_size_vals) x_min = np.floor(x_min /u)*u # u単位で切り下げ x_max = np.ceil(x_max /u)*u # u単位で切り上げ print(x_min, x_max) # x軸の値を作成 x_vec = np.linspace(start=x_min, stop=x_max, num=1001) print(x_vec[:5])
-15.0 10.0
[-15. -14.975 -14.95 -14.925 -14.9 ]
「グラフの作成」のときと同様に処理します。
この例では、指定したパラメータ mu_vals, sigma_vals を使って、平均を中心に標準偏差の倍数 の最小値から最大値の範囲を設定しています。
と
の組み合わせごとに確率密度を計算します。
# パラメータ数を設定 param_num = len(mu_vals) print(param_num) # パラメータごとに確率密度を計算:(事前計算の場合) dens_lt = [ norm.pdf(x=x_vec, loc=mu_vals[i], scale=sigma_vals[i]) for i in range(param_num) ] print(np.array(dens_lt).shape) print(dens_lt[0][:5])
3
(3, 1001)
[2.82345875e-05 2.94854304e-05 3.07883470e-05 3.21453493e-05
3.35585202e-05]
計算や作図の処理用に、指定したパラメータ数 param_num を作成しておきます。
パラメータ( mu_vals, sigma_vals の要素)ごとに、sp.stats.norm.pdf() で1次元ガウス分布の確率密度を計算して、リストに格納します。リスト内包表記により、パラメータ のペアと変数
の全ての組み合わせに対して計算できます。
パラメータごとのガウス分布を重ねて描画します。
# パラメータごとにガウス分布を作図 plt.figure(figsize=(9, 6), dpi=100, facecolor='white') for i in range(param_num): # 値を取得 mu = mu_vals[i] # 平均 sigma = sigma_vals[i] # 標準偏差 dens_vec = dens_lt[i] # 確率密度:(事前計算の場合) # 確率密度を計算:(逐次計算の場合) #dens_vec = norm.pdf(x=x_vec, loc=mu, scale=sigma) # パラメータラベルを作成 param_lbl = f'$\\mu = {mu}, \\sigma = {sigma}$' plt.plot( x_vec, dens_vec, linewidth=1.0, label=param_lbl ) # 折れ線 plt.xlabel('$x$') plt.ylabel('density') plt.suptitle('Gaussian distribution', fontsize=20) # 図タイトル plt.legend(title='parameter') # 凡例 plt.grid() # グリッド線 plt.show()

for 文でパラメータごとに、「グラフの作成」のときと同様にグラフを描画します。
分割して描画
こちらの図は、mu_vals と sigma_vals が異なるパラメータ数でも処理できます。
確率変数 の作図範囲を設定します。
# x軸の範囲を設定 k = 2.0 u = 5.0 x_size = np.max(sigma_vals) x_size *= k # 定数倍 x_min = np.min(mu_vals) - x_size x_max = np.max(mu_vals) + x_size x_min = np.floor(x_min /u)*u # u単位で切り下げ x_max = np.ceil(x_max /u)*u # u単位で切り上げ #x_min = -10.0 #x_max = 15.0 print(x_min, x_max) # x軸の値を作成 x_vec = np.linspace(start=x_min, stop=x_max, num=1001) print(x_vec[:5])
-10.0 15.0
[-10. -9.975 -9.95 -9.925 -9.9 ]
「グラフの作成」のときと同様に処理します。
この例では、指定したパラメータ mu_vals, sigma_vals を使って、平均を中心に標準偏差の倍数 の最小値から最大値の範囲を設定しています。
と
の組み合わせごとに確率密度を計算します。
# パラメータ数(サブプロット数)を設定 row_num = len(mu_vals) col_num = len(sigma_vals) # パラメータの組み合わせごとに確率密度を計算:(事前計算の場合) #dens_lt = [ # [norm.pdf(x=x_vec, loc=mu, scale=sigma) for sigma in sigma_vals] for mu in mu_vals #] dens_lt = [ [norm.pdf(x=x_vec, loc=mu_vals[i], scale=sigma_vals[j]) for j in range(col_num)] for i in range(row_num) ] print(np.array(dens_lt).shape) print(dens_lt[0][0][:5])
(3, 3, 1001)
[0.01897665 0.01939192 0.01981412 0.02024332 0.02067958]
この例では、mu_vals の要素数を行数 row_num、sigma_vals の要素数を列数 col_num として、パラメータ数を作成しておきます。
2つのリスト内包表記により、2つのパラメータ の全ての組み合わせと、さらに変数
との全ての組み合わせに対して、確率密度を計算できます。
パラメータの組み合わせごとに描画領域を分割して分布を描画します。
# 確率密度軸の範囲を設定 #dens_max = 1.0 u = 0.5 dens_max = np.max(dens_lt) dens_max = np.ceil(dens_max /u)*u # u単位で切り上げ # パラメータの組み合わせごとにガウス分布を作図 fig, axes = plt.subplots( nrows=row_num, ncols=col_num, constrained_layout=True, figsize=(12, 8), dpi=100, facecolor='white' ) fig.suptitle('Gaussian distribution', fontsize=20) for i in range(row_num): for j in range(col_num): # サブプロットを取得 ax = axes[i, j] # 値を取得 mu = mu_vals[i] # 平均 sigma = sigma_vals[j] # 標準偏差 dens_vec = dens_lt[i][j] # 確率密度:(逐次計算の場合) # 確率密度を計算:(逐次計算の場合) #dens_vec = norm.pdf(x=x_vec, loc=mu, scale=sigma) # パラメータラベルを作成 param_lbl = f'$\\mu = {mu}, \\sigma = {sigma}$' ax.plot( x_vec, dens_vec, linewidth=1.0 ) # 確率密度 ax.set_title(param_lbl, loc='left') ax.grid() ax.set_ylim(ymin=0.0, ymax=dens_max) # 確率密度軸の描画範囲 fig.supxlabel('$x$') fig.supylabel('density') plt.show()

plt.subplots() で描画領域を分割してグラフを描画できます。nrows 引数に縦方向の数、ncols 引数に横方向の数を指定します。
この例では、 の変化を縦方向、
の変化を横方向に並べています。
以上で、複数の確率分布の作図処理を確認しました。
この記事では、1次元のガウス分布のグラフを作成しました。次の記事では、パラメータと分布の関係を可視化します。
参考文献
おわりに
グラフを描いて満足するつもりだったのだけど、もう少し踏み込みたくなってしまったので、確率論の本をいくつか借りてきて読み始めた。
- 2025.01.06:加筆修正しました。その際に、この記事から「分布の計算」「パラメータの可視化」「乱数の生成」をそれぞれ独立の記事として分割しました。
Python版の「パラメータの可視化」については、作図コードの解説を止めたこともありR版と内容は重複するので、Zennの方に投稿しています。
修正版の更新日に公開された、私立恵比寿中学のライブ映像をどうぞ♪
これまでは記事の投稿日と記念日などが被ったときに(実のところは記念日に投稿日を合わせることが多いのですが)関連するMVなどを貼ってたのですが、近頃は色んなグループがライブ映像を公開することが多くなったようなので、記事の末尾にとりあえず置いておくことにしました。
このブログは技術ブログに偽装したオタクブログなので、記事を読んだならぜひ聴いてください♬
それやこれやが私のブログ運営のモチベーションにも繋がりますので🌸
【次の内容】