標籤:

如何用python numpy產生一個正態分布隨機數的向量或者矩陣?

現在用了兩個循環,每個數都這麼寫,現在太慢了,如何能直接產生向量或者矩陣呢

def mc_return(npaths,ndays):

mmreturn=DataFrame(np.zeros([npaths,ndays]))

for i in range(npaths):

for j in range(ndays):

print np.exp(stats.norm.ppf(np.random.rand(),loc=0.07 / 250, scale=0.2 / np.sqrt(250)))-1

mmreturn.iloc[i,j]=np.exp(stats.norm.ppf(np.random.rand(),loc=0.07 / 250, scale=0.2 / np.sqrt(250)))-1

return mmreturn


一般的正態分布可以通過標準正態分布配合數學期望向量和協方差矩陣得到。如下代碼,可以得到滿足一維和二維正態分布的樣本。希望有用,如有錯誤,歡迎指正!

# coding=utf-8

import numpy as np
from numpy.linalg import cholesky
import matplotlib.pyplot as plt

sampleNo = 1000;
# 一維正態分布
# 下面三種方式是等效的
mu = 3
sigma = 0.1
np.random.seed(0)
s = np.random.normal(mu, sigma, sampleNo )
plt.subplot(141)
plt.hist(s, 30, normed=True)

np.random.seed(0)
s = sigma * np.random.randn(sampleNo ) + mu
plt.subplot(142)
plt.hist(s, 30, normed=True)

np.random.seed(0)
s = sigma * np.random.standard_normal(sampleNo ) + mu
plt.subplot(143)
plt.hist(s, 30, normed=True)

# 二維正態分布
mu = np.array([[1, 5]])
Sigma = np.array([[1, 0.5], [1.5, 3]])
R = cholesky(Sigma)
s = np.dot(np.random.randn(sampleNo, 2), R) + mu
plt.subplot(144)
# 注意繪製的是散點圖,而不是直方圖
plt.plot(s[:,0],s[:,1],"+")
plt.show()


numpy.random.normal(size=100)
numpy.random.normal(size=(10, 10))


import numpy as np
from numpy.linalg import cholesky
import matplotlib.pyplot as plt

sampleNo = 1000
mu = np.array([[1, 5]])
Sigma = np.array([[10, 5], [5, 5]])
R = cholesky(Sigma).T
va,vc = np.linalg.eig(Sigma); R2 = (np.diag(va)**0.5)@vc.T

s1 = np.random.randn(sampleNo, 2) @ R + mu #法1
s2 = np.random.randn(sampleNo, 2) @ R2 + mu #法2
s3 = np.random.multivariate_normal(mu[0],Sigma,sampleNo) #法3

plt.plot(*s1.T,".",label = "s1")
plt.plot(*s2.T,".",label = "s2")
plt.plot(*s3.T,".",label = "s3")
plt.axis("scaled")
plt.legend()

討論下多維情況。

法3 為庫函數。

法1,根據 採石工 答案,使用cholesky分解。然而我們產生的隨機向量X是行向量,右乘的變換陣R需要對cholesky分解結果轉置,即若有X" = XR,則 Sigma = R.T @ R,原答案有誤。

法2,借Sigma的酉相似對角化求R2,幾何意義明顯,更直觀。va,vc = np.linalg.eig(Sigma); R2 = (np.diag(va)**0.5)@vc.T。R2變換相當於先沿坐標軸伸縮後旋轉翻轉,va是伸縮比,酉陣vc是由斜轉正的右乘旋轉矩陣,其列向量為主軸方向(指上圖橢圓最長軸和最短軸)。


numpy.random.multivariate_normal


如果是標準正態分布,np.random.randn(n, m)


推薦閱讀:

python numpy的樣本標準差怎麼寫?
python下numpy不成功,請問有沒有簡單的安裝方法?
Numpy中arr[:]和arr[...],arr[:,i,j] 與arr[:][i][j]的區別?

TAG:Python | numpy |