日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python从数组中随机选择一些元素_numpy.random随机选择数组元素如何更高效

發布時間:2024/3/12 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python从数组中随机选择一些元素_numpy.random随机选择数组元素如何更高效 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在看代碼庫rlkit時,發現一句有意思的代碼和注釋(如下所示),大意是從列表中隨機選擇一個元素時使用np.random.randint比np.random.choice更加高效,相關的解釋是np.random.choice會進行一些不必要的復制操作,使得效率相較于randint低一些。

possible_future_obs_idxs = self._idx_to_future_obs_idx[i]

# This is generally faster than random.choice.

# Makes you wonder what random.choice is doing

num_options = len(possible_future_obs_idxs)

next_obs_i = int(np.random.randint(0, num_options))

future_obs_idxs.append(possible_future_obs_idxs[next_obs_i])

我做了相關的實驗進行對比,發現使用np.random.random的實現比np.random.randint更快,并且是否使用參數size=1對結果的影響也很大,文末進行了總結。

1. random, randint, choice

生成長度為1e6的隨機array,從中隨機選擇1個數和1000個數,比較兩種情況下運行速度,測試代碼如下:

import numpy as np

import time

N = 1000000

array = np.random.random(N)

def random(N=N): # 使用random隨機選擇1個數

return array[int(np.random.random() * N)]

def random_size1(N=N):# 使用random(size=1)隨機選擇1個數

return array[int(np.random.random(size=1) * N)]

def random_size_n(n, N=N): # 使用random隨機選擇n個數

return array[(np.random.random(n) * N).astype(np.int)]

def randint(N=N):# 使用randint隨機選擇1個數

return array[np.random.randint(N)]

def randint_size1(N=N): # 使用randint(size=1)隨機選擇1個數

return array[np.random.randint(N, size=1)]

def randint_size_n(n, N=N): # 使用randint隨機選擇n個數

return array[np.random.randint(N,size=n)]

def choice(array=array): # 使用choice隨機選擇1個數

return np.random.choice(array)

def choice_size1(array=array): # 使用choice(size=1)隨機選擇1個數

return np.random.choice(array, size=1)

def choice_size_n(n, array=array): # 使用choice隨機選擇n個數

return np.random.choice(array, size=n)

test_funs = [random, random_size1, randint, randint_size1, choice, choice_size1]

test_randn_funs = [random_size_n, randint_size_n, choice_size_n]

def test_main(mode, times=1000000):

test_fun = test_funs[mode]

start = time.time()

for _ in range(times):

test_fun()

end = time.time()

print('test {} {} times using time {} s'.format(test_fun, times, end - start))

def test_randn_main(mode,n=1000, times=1000000):

test_fun = test_randn_funs[mode]

start = time.time()

for _ in range(times):

test_fun(n)

end = time.time()

print('test {} {} times using time {} s'.format(test_fun, times, end - start))

if __name__ == "__main__":

for i in range(6):

test_main(i)

for i in range(3):

test_randn_main(i)

進行1e6次的實驗結果(單位:s):

更直觀的使用ipython的%timeit的結果:

import numpy as np

N = 1000

%timeit int(np.random.random() * N)

446 ns ± 3.21 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.randint(N)

908 ns ± 4.11 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.randint(N, size=1)

1.29 μs ± 5.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

以上實驗結果在不同環境中跑會有些許誤差,但是應該能得到以下結論:隨機選擇一個數時,random最快,速度是randint的2倍;

隨機選擇一個數時,不指定size=1的參數更快,以random為例,速度差異能到5倍左右;

隨機選擇n個數時,指定size=n,randint最快。

以下是我的猜測和解釋,如有問題歡迎指出:choice會有內存申請和復制array的操作,通常是最慢的;

指定size會有內存申請的操作,并且會轉化為ndarray類型,因此產生一個隨機數時不指定size=1更快;

random的輸出是python的float類型,指定size后是ndarray類型,乘以N時,float類型和N都直接進行python的float類型運算,而ndarray乘以N多進行了數據轉化和傳遞操作(轉化為numpy的類型并傳入底層進行運算,可以參考這個問題https://www.zhihu.com/question/24789359/answer/55643155),randint內部實現其實是一樣的,但是乘以N的操作本身是在numpy的類型中進行的,減少了兩次數據轉化和傳遞,速度更快。

>>> x=np.random.random()

>>> type(x)

>>> y=np.random.random(size=1)

>>> type(y)

為了讓大家體會到數據格式轉化的耗時,補充一個實驗,注意上面是np.random.random()乘以的是python的常數,均為python內置數據類型的運算,而如果乘以的是numpy數據類型,結果可能不一樣:

import numpy as np

N = 1000

L = np.random.randint(1, N, size=N)

%timeit [np.random.randint(x) for x in L]

1.12 ms ± 87.9 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit [int(np.random.random() * x) for x in L]

2.68 ms ± 92.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

## 可以看到這里使用np.random.random 反而比randint慢了,這是因為x其實是numpy.int64的格式

# np.random.random()是python數據類型,又涉及到numpy的數據格式轉換和數據傳遞。

>>>type(L[0])

numpy.int64

>>>type(np.random.random())

float

# 而當我們將x轉換為int型后,再次得到了我們之前的結論

%timeit [int(np.random.random() * int(x)) for x in L]

638 μs ± 12.8 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

因為涉及到數據格式轉化和向底層代碼的數據傳遞,簡單的python內置運算可能比numpy更快,當運算較多時,numpy并行的優勢才能顯示出來。

2. 案例優化

我們以rlkit的這段代碼為例進行優化,該段代碼的目的是從不等長的列表組里對每個列表隨機選擇1個數據。這個案例特殊的地方在于列表組里有N個不等長的子列表,還要考慮循環處理子列表的時間,使用numpy并行進行向量對應位相乘速度更快,選擇random_idx的過程能夠加速80倍左右。

import numpy as np

N = 1000

L = np.random.randint(1, N, size=N) # 子列表的長度

%timeit random_idx = (np.random.random(N) * L).astype(np.int)

13 μs ± 419 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit random_idx = [np.random.randint(x) for x in array_len]

1e+03 μs ± 22.1 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

3. Take Awaynumpy的運算會涉及到數據格式轉化和向底層代碼的數據傳遞,當運算比較少時python內置運算可能比numpy更快,所以要注意運算量的類型,numpy的優勢在于大規模的并行計算;

隨機選擇一個數時,盡量避免設置size=1,不設置size的運行速度從快到慢為:random > randint > choice;

隨機選擇n個數時,由于randint(size=n)內置了random(size=n) * N的操作,比外部實現的random(size=n) * N少了兩次數據轉化而更快,速度從快到慢為:randint > random > choice。

總結

以上是生活随笔為你收集整理的python从数组中随机选择一些元素_numpy.random随机选择数组元素如何更高效的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。