Numpy入門教程:07. 隨機抽樣

背景

什麼是 NumPy 呢?

NumPy 這個詞來源於兩個單詞 – NumericalPython。其是一個功能強大的 Python 庫,可以幫助程序員輕鬆地進行數值計算,通常應用於以下場景:

  • 執行各種數學任務,如:數值積分、微分、內插、外推等。因此,當涉及到數學任務時,它形成了一種基於 Python 的 MATLAB 的快速替代。
  • 計算機中的圖像表示爲多維數字數組。NumPy 提供了一些優秀的庫函數來快速處理圖像。例如,鏡像圖像、按特定角度旋轉圖像等。
  • 在編寫機器學習算法時,需要對矩陣進行各種數值計算。如:矩陣乘法、求逆、換位、加法等。NumPy 數組用於存儲訓練數據和機器學習模型的參數。

隨機抽樣

numpy.random 模塊對 Python 內置的 random 進行了補充,增加了一些用於高效生成多種概率分佈的樣本值的函數,如正態分佈、泊松分佈等。

  • numpy.random.seed(seed=None) Seed the generator.

seed()用於指定隨機數生成時所用算法開始的整數值,如果使用相同的seed()值,則每次生成的隨機數都相同,如果不設置這個值,則系統根據時間來自己選擇這個值,此時每次生成的隨機數因時間差異而不同。

在對數據進行預處理時,經常加入新的操作或改變處理策略,此時如果伴隨着隨機操作,最好還是指定唯一的隨機種子,避免由於隨機的差異對結果產生影響。


離散型隨機變量

二項分佈

  • numpy.random.binomial(n, p, size=None) Draw samples from a binomial distribution.

表示對一個二項分佈進行採樣,size表示採樣的次數,n表示做了n重伯努利試驗,p表示成功的概率,函數的返回值表示n中成功的次數。

【例】野外正在進行9(n=9)口石油勘探井的發掘工作,每一口井能夠開發出油的概率是0.1(p=0.1)。請問,最終所有的勘探井都勘探失敗的概率?

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

np.random.seed(20200605)
n = 9
p = 0.1
size = 50000
x = np.random.binomial(n, p, size)
print(np.sum(x == 0) / size)  # 0.3897

plt.hist(x)
plt.show()

s = stats.binom.pmf(range(10), n, p)
print(np.around(s, 3))
# [0.387 0.387 0.172 0.045 0.007 0.001 0.    0.    0.    0.   ]

【例】模擬投硬幣,投2次,請問兩次都爲正面的概率?

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

np.random.seed(20200605)
n = 2
p = 0.5
size = 50000
x = np.random.binomial(n, p, size)
print(np.sum(x == 0) / size)  # 0.25154
print(np.sum(x == 1) / size)  # 0.49874
print(np.sum(x == 2) / size)  # 0.24972

plt.hist(x, density=True)
plt.show()

s = stats.binom.pmf(range(n + 1), n, p)
print(np.around(s, 3))
# [0.25 0.5  0.25]

泊松分佈

  • numpy.random.poisson(lam=1.0, size=None) Draw samples from a Poisson distribution.

表示對一個泊松分佈進行採樣,size表示採樣的次數,lam表示一個單位內發生事件的平均值,函數的返回值表示一個單位內事件發生的次數。

【例】假定某航空公司預定票處平均每小時接到42次訂票電話,那麼10分鐘內恰好接到6次電話的概率是多少?

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

np.random.seed(20200605)
lam = 42 / 6
size = 50000
x = np.random.poisson(lam, size)
print(np.sum(x == 6) / size)  # 0.14988

plt.hist(x)
plt.show()

x = stats.poisson.pmf(6, lam)
print(x)  # 0.14900277967433773

超幾何分佈

  • numpy.random.hypergeometric(ngood, nbad, nsample, size=None) Draw samples from a Hypergeometric distribution.

表示對一個超幾何分佈進行採樣,size表示採樣的次數,ngood表示總體中具有成功標誌的元素個數,nbad表示總體中不具有成功標誌的元素個數,ngood+nbad表示總體樣本容量,nsample表示抽取元素的次數(小於或等於總體樣本容量),函數的返回值表示抽取nsample個元素中具有成功標識的元素個數。

【例】一共20只動物裏有7只是狗,抽取12只有3只狗的概率(無放回抽樣)。

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

np.random.seed(20200605)
size = 500000
x = np.random.hypergeometric(ngood=7, nbad=13, nsample=12, size=size)
print(np.sum(x == 3) / size)  # 0.198664

plt.hist(x, bins=8)
plt.show()

"""
M 爲總體容量
n 爲總體中具有成功標誌的元素的個數
N,k 表示抽取N個元素有k個是成功元素
"""
x = range(8)
s = stats.hypergeom.pmf(k=x, M=20, n=7, N=12)
print(np.round(s, 3))
# [0.    0.004 0.048 0.199 0.358 0.286 0.095 0.01 ]


連續型隨機變量

均勻分佈

  • numpy.random.uniform(low=0.0, high=1.0, size=None) Draw samples from a uniform distribution.

Samples are uniformly distributed over the half-open interval [low, high) (includes low, but excludes high). In other words, any value within the given interval is equally likely to be drawn by uniform.

【例】在low到high範圍內,創建大小爲size的均勻分佈的隨機數。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

np.random.seed(20200614)
a = 0
b = 100
size = 50000
x = np.random.uniform(a, b, size=size)
print(np.all(x >= 0))  # True
print(np.all(x < 100))  # True
y = (np.sum(x < 50) - np.sum(x < 10)) / size
print(y)  # 0.40144

plt.hist(x, bins=20)
plt.show()

a = stats.uniform.cdf(10, 0, 100)
b = stats.uniform.cdf(50, 0, 100)
print(b - a)  # 0.4

作爲uniform()的特列,可以得到[0,1)之間的均勻分佈的隨機數。

  • numpy.random.rand(d0, d1, ..., dn) Random values in a given shape.

Create an array of the given shape and populate it with random samples from a uniform distribution over [0, 1).

【例】根據指定大小產生[0,1)之間均勻分佈的隨機數。

import numpy as np

np.random.seed(20200614)
print(np.random.rand())
# 0.7594819171852776

print(np.random.rand(5))
# [0.75165827 0.16552651 0.0538581  0.46671446 0.89076925]

print(np.random.rand(4, 3))
# [[0.10073292 0.14624784 0.40273923]
#  [0.21844459 0.22226682 0.37246217]
#  [0.50334257 0.01714939 0.47780388]
#  [0.08755349 0.86500477 0.70566398]]

np.random.seed(20200614)
print(np.random.uniform())  # 0.7594819171852776
print(np.random.uniform(size=5))
# [0.75165827 0.16552651 0.0538581  0.46671446 0.89076925]

print(np.random.uniform(size=(4, 3)))
# [[0.10073292 0.14624784 0.40273923]
#  [0.21844459 0.22226682 0.37246217]
#  [0.50334257 0.01714939 0.47780388]
#  [0.08755349 0.86500477 0.70566398]]

作爲uniform的另一特例,可以得到[low,high)之間均勻分佈的隨機整數。

  • numpy.random.randint(low, high=None, size=None, dtype='l') Return random integers from low (inclusive) to high (exclusive).

Return random integers from the “discrete uniform” distribution of the specified dtype in the “half-open” interval [low, high). If high is None (the default), then results are from [0, low).

【例】若high不爲None時,取[low,high)之間隨機整數,否則取值[0,low)之間隨機整數。

import numpy as np

np.random.seed(20200614)
x = np.random.randint(2, size=10)
print(x)
# [0 0 0 1 0 1 0 0 0 0]

x = np.random.randint(1, size=10)
print(x)
# [0 0 0 0 0 0 0 0 0 0]

x = np.random.randint(5, size=(2, 4))
print(x)
# [[3 3 0 1]
#  [1 1 0 1]]

x = np.random.randint(1, 10, [3, 4])
print(x)
# [[2 1 7 7]
#  [7 2 4 6]
#  [8 7 2 8]]

正態分佈

  • numpy.random.randn(d0, d1, ..., dn) Return a sample (or samples) from the “standard normal” distribution.

【例】根據指定大小產生滿足標準正態分佈的數組(均值爲0,標準差爲1)。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

np.random.seed(20200614)
size = 50000
x = np.random.randn(size)
y1 = (np.sum(x < 1) - np.sum(x < -1)) / size
y2 = (np.sum(x < 2) - np.sum(x < -2)) / size
y3 = (np.sum(x < 3) - np.sum(x < -3)) / size
print(y1)  # 0.68596
print(y2)  # 0.95456
print(y3)  # 0.99744

plt.hist(x, bins=20)
plt.show()

y1 = stats.norm.cdf(1) - stats.norm.cdf(-1)
y2 = stats.norm.cdf(2) - stats.norm.cdf(-2)
y3 = stats.norm.cdf(3) - stats.norm.cdf(-3)
print(y1)  # 0.6826894921370859
print(y2)  # 0.9544997361036416
print(y3)  # 0.9973002039367398

還可以指定分佈以及所需參數來進行隨機,例如高斯分佈中的mu和sigma。

  • numpy.random.normal(loc=0.0, scale=1.0, size=None) Draw random samples from a normal (Gaussian) distribution.

normal()爲創建均值爲 loc(mu),標準差爲 scale(sigma),大小爲 size 的數組。

sigma * np.random.randn(...) + mu

【例】

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(20200614)
x = 0.5 * np.random.randn(2, 4) + 5
print(x)
# [[5.39654234 5.4088702  5.49104652 4.95817289]
#  [4.31977933 4.76502391 4.70720327 4.36239023]]

np.random.seed(20200614)
mu = 5
sigma = 0.5
x = np.random.normal(mu, sigma, (2, 4))
print(x)
# [[5.39654234 5.4088702  5.49104652 4.95817289]
#  [4.31977933 4.76502391 4.70720327 4.36239023]]

size = 50000
x = np.random.normal(mu, sigma, size)

print(np.mean(x))  # 4.996403463175092
print(np.std(x, ddof=1))  # 0.4986846716715106

plt.hist(x, bins=20)
plt.show()

指數分佈

  • numpy.random.exponential(scale=1.0, size=None) Draw samples from an exponential distribution.

【例】scale = 1/lambda

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

np.random.seed(20200614)
lam = 7
size = 50000
x = np.random.exponential(1 / lam, size)
y1 = (np.sum(x < 1 / 7)) / size
y2 = (np.sum(x < 2 / 7)) / size
y3 = (np.sum(x < 3 / 7)) / size
print(y1)  # 0.63218
print(y2)  # 0.86518
print(y3)  # 0.95056

plt.hist(x, bins=20)
plt.show()

y1 = stats.expon.cdf(1 / 7, scale=1 / lam)
y2 = stats.expon.cdf(2 / 7, scale=1 / lam)
y3 = stats.expon.cdf(3 / 7, scale=1 / lam)
print(y1)  # 0.6321205588285577
print(y2)  # 0.8646647167633873
print(y3)  # 0.950212931632136


其它隨機函數

  • numpy.random.choice(a, size=None, replace=True, p=None) Generates a random sample from a given 1-D array.

從序列中獲取元素,若a爲整數,元素取值從np.range(a)中隨機獲取;若a爲數組,取值從a數組元素中隨機獲取。該函數還可以控制生成數組中的元素是否重複replace,以及選取元素的概率p

【例】

import numpy as np

np.random.seed(20200614)
x = np.random.choice(10, 3)
print(x)  # [2 0 1]

x = np.random.choice(10, 3, p=[0.05, 0, 0.05, 0.9, 0, 0, 0, 0, 0, 0])
print(x)  # [3 2 3]

x = np.random.choice(10, 3, replace=False, p=[0.05, 0, 0.05, 0.9, 0, 0, 0, 0, 0, 0])
print(x)  # [3 0 2]

aa_milne_arr = ['pooh', 'rabbit', 'piglet', 'Christopher']
x = np.random.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3])
print(x) # ['pooh' 'rabbit' 'pooh' 'pooh' 'pooh']

np.random.seed(20200614)
x = np.random.randint(0, 10, 3)
print(x)  # [2 0 1]

數據一般都是按照採集順序排列的,但是在機器學習中很多算法都要求數據之間相互獨立,所以需要先對數據集進行洗牌操作。

  • numpy.random.shuffle(x) Modify a sequence in-place by shuffling its contents.

This function only shuffles the array along the first axis of a
multi-dimensional array. The order of sub-arrays is changed but
their contents remains the same.

x進行重排序,如果x爲多維數組,只沿第 0 軸洗牌,改變原來的數組,輸出爲None。

【例】洗牌,改變自身內容,打亂順序。

import numpy as np

np.random.seed(20200614)
x = np.arange(10)
np.random.shuffle(x)
print(x)
# [6 8 7 5 3 9 1 4 0 2]

print(np.random.shuffle([1, 4, 9, 12, 15]))
# None

x = np.arange(20).reshape((5, 4))
print(x)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]
#  [16 17 18 19]]

np.random.shuffle(x)
print(x)
# [[ 4  5  6  7]
#  [ 0  1  2  3]
#  [ 8  9 10 11]
#  [16 17 18 19]
#  [12 13 14 15]]
  • numpy.random.permutation(x) Randomly permute a sequence, or return a permuted range.

If x is a multi-dimensional array, it is only shuffled along its first index.

permutation()函數的作用與shuffle()函數相同,可以打亂第0軸的數據,但是它不會改變原來的數組。

【例】

import numpy as np

np.random.seed(20200614)
x = np.arange(10)
y = np.random.permutation(x)
print(y)
# [6 8 7 5 3 9 1 4 0 2]

print(np.random.permutation([1, 4, 9, 12, 15]))
# [ 4  1  9 15 12]

x = np.arange(20).reshape((5, 4))
print(x)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]
#  [16 17 18 19]]

y = np.random.permutation(x)
print(y)
# [[ 8  9 10 11]
#  [ 0  1  2  3]
#  [12 13 14 15]
#  [16 17 18 19]
#  [ 4  5  6  7]]

參考文獻

  • https://www.jianshu.com/p/63434ad5ea64

當前活動


我是 終身學習者“老馬”,一個長期踐行“結伴式學習”理念的 中年大叔

我崇尚分享,渴望成長,於2010年創立了“LSGO軟件技術團隊”,並加入了國內著名的開源組織“Datawhale”,也是“Dre@mtech”、“智能機器人研究中心”和“大數據與哲學社會科學實驗室”的一員。

願我們一起學習,一起進步,相互陪伴,共同成長。

後臺回覆「搜搜搜」,隨機獲取電子資源!
歡迎關注,請掃描二維碼:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章