# 關於亂數種子 今天要說一點正經的事 (? 從小我就覺得亂數是開始寫程式中最酷的事, 這樣你可以寫個猜數字遊戲, 甚至任何遊戲, 開局不會都一個樣子。哦, 對不起, 要談正經的事... 正經的事是, 電腦的亂數其實是數學模擬出來的, 也就是是用算出來的。這需要一個引子, 我們叫亂數的種子 (random seed)。一般亂數種子都會用到時間去設, 因為這時時刻刻是不一樣的, 於是看起來真的是隨機的樣子。 但有時候你會希望亂數在每次執行時的結果是相同的。例如在機器學習裡訓練資料和測試資料隨機的分開, 例如你的模型初始值隨機的那個設定等等。這樣我們不會在一台電腦跑是這樣, 換一台跑是那樣。不會這次跑覺得好棒可以交作業了, 下次跑發現爆了。 Python 的 numpy 裡設 random seed 的方法是: ```python np.random.seed(0) ``` 裡面的 0 是設什麼數字都可以, 所以很多人覺得無所謂, 設 0 就好了。當然, 你愛設什麼數字就設什麼數字, 所以我們也可以設 ```python np.random.seed(9487) ``` 但是你可能會發現, 看人家寫程式的時候, 很多人會設 42 這個數字當 random seed! 可是 42 不是程式人最愛的 2 的某個次方啊, 這是怎麼來的呢? 原來這是致敬道格拉斯·亞當斯 (Douglas Adams)《銀河便車指南》(The Hitchhiker's Guide to the Galaxy)。雖然我們可能不太認識他, 但在歐美是紅透, 尤其《銀河便車指南》大概是人人, 至少宅男超熟悉的作品。不幸的是, 亞當斯還沒看到拍成電影的《銀河便車指南》就過逝了, 享年才 49 歲。後來出的這部 2005 的電影, 台灣翻為《星際大奇航》。 等等, 那 random seed 呢? 因為在《銀河便車指南》有一段, 人們想知道萬事萬物最高的答案是什麼, 去找超級電腦 Deep Thought (那時想這個名稱好厲害), Deep Thought 就說: > The answer to the ultimate question of life the universe and everything is... 42. 事實上你去 Google "the answer to the ultimate question of life the universe and everything is", Google 會開台計算機, 顯示這個問題的答案是: 42。 等一下, 今天不是說好要說正經的? 以下是正經的事。就在我們學會用 `np.random.seed` 去設亂數種子之際, [這篇文章](https://towardsdatascience.com/stop-using-numpy-random-seed-581a9972805f)居然教我們: > 「不要再用 np.random.seed 了!」 這是怎麼回事呢? 原因是小小的程式用 `np.random.seed` 沒什麼問題, 效果大概也和你想的一樣, 換一台機器也是一樣的結果。但是比較大的程式, 雜七雜八的套式引來引去, 你很難注意到中間可能也有在取亂數。於是最後這樣大亂鬥的結果, 你可能發現結果 (比方說一致性) 和你想的不一樣! 這該如何是好呢? 答案是用 numpy 新的 Random Generator 的概念, 簡單說就是每個任務指定自己的 random seed。做法是像這樣。 ```python rng = np.random.default_rng(42) ``` 然後呢就可以用這個 Random Generator 去生亂數, 不影響別人。比如說 ```python rng.random(5) rng.integers(1, 10) rng.standard_normal(5) ``` 等等。