【C#】正規分布に従う乱数の取得

.NETでは乱数のクラスにRamdomクラスがあります、どれも一様に分布する乱数しか取得できません。

 

例えば、NextDoubleメソッドを用いると、0以上、1.0未満の一様に分布した乱数を取得する事ができます。

var rnd = new Random(); 

for (int i = 0; i < 1000; i++) 
{ 
	Console.WriteLine(rnd.NextDouble().ToString()); 
}

上記プログラムで出力した値をExcelでヒストグラムにしてみると、0~1.0の一様??な乱数が取得させていることが分かります。

 

 

正規分布に従う乱数を取得するには、今回はボックス=ミュラー法という手法で乱数をしてみます。

XとYがお互いに独立で、0~1の範囲で一様に分布する乱数のとき

 

$${ Z }_{ 1 }=\sqrt { -2\log { X } } cos(2\pi Y)\\ { Z }_{ 2 }=\sqrt { -2\log { X } } sin(2\pi Y)$$

 

のZ1、Z2はそれぞれ標準偏差1.0、平均値0.0の正規分布に従う乱数となります。

(参考)ボックス=ミュラー法 Wikipedia

https://ja.m.wikipedia.org/wiki/%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%EF%BC%9D%E3%83%9F%E3%83%A5%E3%83%A9%E3%83%BC%E6%B3%95

 

これをC#のプログラムにしてみると

var rnd = new Random(); 

double X, Y; 
double Z1, Z2; 

for (int i = 0; i < 1000; i++) 
{ 
	X = rnd.NextDouble(); 
	Y = rnd.NextDouble(); 
	
	Z1 = Math.Sqrt(-2.0 * Math.Log(X)) * Math.Cos(2.0 * Math.PI * Y); 
	Z2 = Math.Sqrt(-2.0 * Math.Log(X)) * Math.Sin(2.0 * Math.PI * Y); 

	Console.WriteLine(Z1.ToString()); 
	Console.WriteLine(Z2.ToString()); 
}

という感じ。

コンソールに吐き出された値をExcelでヒストグラムにしてみると

 

となり、確かに正規分布に従った感じの分布となりました。
標準偏差1.0、平均値0.0ではなく、標準偏差sigma、平均値ave のときの乱数が欲しい場合は

Z1 = sigma * Math.Sqrt(-2.0 * Math.Log(X)) * Math.Cos(2.0 * Math.PI * Y) + ave;
Z2 = sigma * Math.Sqrt(-2.0 * Math.Log(X)) * Math.Sin(2.0 * Math.PI * Y) + ave;

となります。

 

← C#へ戻る

シグモイド関数の微分の計算方法

シグモイド関数を微分するには合成関数の微分を用いて行います。

 

まず、シグモイド関数

$$f(x)=\frac { 1 }{ 1+{ e }^{ -x } } $$

において

$$u=g(x)=1+{ e }^{ -x }$$

と置くと、

$$y=f(u)=\frac { 1 }{ u } ={ u }^{ -1 }$$

より、合成関数の微分を使って

$$f'(x)=\frac { dy }{ dx } =\frac { dy }{ du } \frac { du }{ dx } \\ =-{ u }^{ -2 }(-{ e }^{ -x })\\ =\frac { { e }^{ -x } }{ { u }^{ 2 } } \\ =\frac { { e }^{ -x } }{ (1+{ e }^{ -x }) ^{ 2 }}$$

となりますが、この先がちょとトリッキーな式の変形を行い、

$$=\frac { { e }^{ -x } }{ 1+{ e }^{ -x } } \frac { 1 }{ 1+{ e }^{ -x } } \\ =(\frac { { 1+e }^{ -x } }{ 1+{ e }^{ -x } } -\frac { 1 }{ 1+{ e }^{ -x } } )\frac { 1 }{ 1+{ e }^{ -x } } \\ =(1-\frac { 1 }{ 1+{ e }^{ -x } } )\frac { 1 }{ 1+{ e }^{ -x } }$$

となります。

ここで

$$f(x)=\frac { 1 }{ 1+{ e }^{ -x } } $$

であるから、

$$f’(x)=(1-f(x))f(x)$$

となるのが、シグモイド関数の微分となります。

 

例によってPythonのmatplotlibを使ってグラフを書いてみると、

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.linspace(-10, 10)

#シグモイド関数
y = sigmoid(x)
plt.plot(x, y)

#シグモイド関数の微分
dy = (1 - sigmoid(x)) * sigmoid(x)
plt.plot(x, dy)

plt.show()

 

途中の計算は、自分一人では解けないな。。きっと。

シグモイド関数

ニューラルネットワークに出てくる、活性化関数の一つであるシグモイド関数

$$h(x)=\frac { 1 }{ 1+{ e }^{ -x } }$$

 

この関数の特徴は x = 0, y = 0.5 の点を通り、yの値は0~1の範囲に制限され、xが小さくなるとyは0に漸近し、xが大きくなると1に漸近します。

 

これをPythonのmatplotlibを使ってグラフを書いてみると、こんな感じ

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.linspace(-10, 10)
y = sigmoid(x)

plt.plot(x, y)
plt.show() 

 

シグモイド関数を初めて見たのは画像処理でエッジ検出に使う例だったのですが、

「シグモイド関数 エッジ」

と検索したら、トップに出てくるページの記事は、知っている人のだった。

https://www.fast-corp.co.jp/upload/thesis/0013/2.pdf

合成関数の微分

Deep Learningをお勉強していたら、合成関数の微分が出てきたのですが、もう30年ぶりぐらいに見たので、その復習です。

\(y=f(u), u=g(x)\)としたとき、\(y=f(g(x))\)を合成関数とよび、この合成関数を\(x\)に関して微分すると、

 

$$\frac{ dy }{ dx } =\frac { dy }{ du } \frac { du }{ dx } \\ \quad =\frac { d }{ du } f(u)\frac { d }{ dx } g(x)$$

 

となります。

合成関数を教わったときは、合成関数の微分は「外側の微分x内側の微分」って覚えてたような。。

 

試しに\(y=sin({ x }^{ 2 })\)の微分は\(u={ x }^{ 2 }\)と置くと

 

$$\frac { dy }{ dx } =\frac { d }{ du } f(u)\frac { d }{ dx } g(x)\\ \quad =cos(u)\times 2x\\ \quad =cos({ x }^{ 2 })\times 2x$$

 

これをPythonのmatplotlibを使ってグラフにしてみると

 

となり、青の線の微分(傾き)がオレンジ色の線なので、合ってそう。