比特幣出金記

話說很多年前, 我就趕時髦挖比特幣. 後來聽說挖礦的成本 (電費)高於比特幣的價值, 所以就停挖了. 又過了幾年, 聽說雖然比特幣挖不動, 但挖以太幣換比特幣還有賺頭, 所以我又挖了第二次!

當然除了買貴鬆鬆的顯卡, 老婆抱怨經過我房間門口都特別熱 (電費換成喜歡的形式) 之外, 整個電腦都變得不穩. 不但遊戲玩不成, 部落格後台也頻頻當機, 最後只得停工.

最近看到比特幣漲了不少. 於是又開啟 RTX 4090 挖了一下下. 結果本來很穩的電腦, 那個不便宜的 ECC DDR 就這樣燒壞了. 於是我退出江湖, 設法將比特幣出金. 雖然這幾天真的很冷, 挖礦等於開暖氣還賺錢, 還滿懷念的, 哈!

川普當選好像對比特幣有益, 這東西長期應該也是看漲. 不過我只求賺回買顯卡的錢就好了, 所以我算是一面倒地 (又龜速地) 站在賣方. 不幸地, 今年年初起手式就錯了, 我傻傻地從礦場轉帳到自己冷錢包, 這一個動作就被扣了些手續費 0.0001 BTC.

接下來我以為可以找個人交易了, 卻發現場外交易沒那麼簡單. 接著我就做了第二件蠢事, 我把冷錢包的錢轉到幣安, 想說幣安這麼大, 應該很容易賣掉吧! 結果幣安要換美金、甚至換日幣都比較容易, 要找個台幣的賣家根本困難重重. 只好再研究一下那裡好賣? Google 後我找到 Max 交易所.

Max 的認證有點嚴, 我的審查資格搞了好幾天, 比特幣都漲起來了. But, 從幣安轉到 Max, 我又被收一次手續費 0.0000071 BTC. 在心疼手續費之餘, Max 一通過我的身分驗證, 我就市價怒賣比特幣!

成交本身滿快的, 分成兩單被人接走. 然而我想把台幣再轉帳到我的帳戶, 又再被扣了 15 元 NTD 手續費. 在幣安設定帳號時, 它會轉進 1 元新台幣驗證帳戶可用性, 所以算起來我少虧一元. 合計搬家四次後, 手續費總共是 0.0001071 BTC (約 340 新台幣) 和 14 塊新台幣, 合計高達 354 元左右! 股市跌 354 萬都還會漲回來, 這手續費可是一去不回. 總之, 今年總算入袋為安了.

另外, 促使我加速出場的一則新聞是 Google 量子電腦 Willow 的進展. 這個新聞確實讓比特幣跌了一下下 [1]. 其實研究團隊最大的進展在於找到糾錯量子位元 (Error-corrected qubits) 的 pattern, 讓位元數增加時, 糾錯能力可以隨之上升, 把錯誤率壓下來. 因此開啟了更多量子位元的可能.

這讓我好奇究竟量子電腦能否顛覆虛擬貨幣? 稍微研究後發現其實是可以的, 但目前量子電腦都要針對特定用途 (算法) 做設計, 把演算法轉換成疊加態, 才能達到快速計算. 它還不像是個人電腦那樣能夠泛用, 打幾個字就可以寫程式. 所以投資人要評估把剩下的比特幣全部挖完能賺多少, 才知道值不值得為它設計個量子挖礦機? 還是花同樣的力氣去攻略別的標的更划算?

換個角度想, 要是一秒鐘能挖完所有的虛擬貨幣, 那比特幣存在的價值 (公信力) 會剩多少就還不好說? 假設比特幣因此被認為沒有價值, 駭客還不如去破解更保值的東西. 所以這不是送分題. 如果是委內瑞拉要拚一次性挖完比特幣那就還算合理, 因為這本來就是它的法幣 [3], 它說有價值就有價值了, 還不怕別人跟它哄抬挖礦成本.

[REF]

  1. Google Willow量子晶片!即將邁入量子電腦時代!?Google解決什麼關鍵性的問題?
  2. 未來趨勢!一次了解量子電腦將如何掀起運算革命!量子科技原理全解析!
  3. https://0xzx.com/zh-tw/2024090603314843272.html

少年 Py 的奇幻漂流

週日晚上做了一個夢。有位老先生用毛筆字寫了封信給我,署名林如松,要我照顧他的兒子。說這個兒子學習不好是因為某種心理疾病吧!總之懇請多多照顧等有上百來字。望文生義,那麼我在夢中的身份就是個導師了。

身為導師, 而不是醫師。我開始找醫學相關的線索。在一張可能是精神科醫師的桌子上,我發現了名片。上面寫了幾個小字說明醫師的專業。細節忘了,但其中 “止冰" 兩個字清楚地印入我的眼簾。這是什麼? 要阻止冰塊? 還是冰毒? 我納悶了一會兒,才恍然大悟是"治病" 的諧音.

病人因為精神疾病來求診,有點害羞會不想讓人知道,所以醫師就用某某人止冰來隱晦這件事! 想不到我只是做個夢,也會自編自導諧音梗啊! 在我破解了自己的梗之後,空中又傳來一個自問自答。"為什麼脖子太長不好? " 隔了一下,"因為好"頸" (景) 不長 (常)"。看來我的夢境是進入了諧音梗的 decorator [1].

等等! 一開始我有正經任務的啊! 怎麼跑題了? 想到這裡,世界又變得緊張嚴肅了。好像是初三23:59’57″ – 快初四 (出事)了! 我帶著兩三個人開始闖關,其中也不知道有沒有包括林小弟? 總之系統瞬間提示倒數 3 秒鐘,如果不在限時內讓機關套住一個掛勾,在我後面的人都會從平台上滑下去。正當我回頭叫其他人跟上來,倒數 3 秒已經 “加速" 結束了。我能跟大家說的話只有 一句 “來不及了"。

然而,即使倒數時間到了,我沒有完成任務,其他人也沒跟上,但好像並沒有發生什麼了不起的事? What not happened? 難道因為我們的 3 秒不是真的 3 秒,Dead line 也就不是 line 了嗎 ? 換言之,line 變成 non-linear,所以 dead 也就不 dead 了 !? 這麼一想好像也有道理。好比 nonlocal [2] 如字面所說,雖然不是 global,但肯定不是 local。事前有舖梗,後面就拗得過去。

看來這個夢中世界的 “人設" 很不靠譜啊!? 果然畫面再一轉,出現了那位忘記是自稱還是人稱喇賽之王的前同事 “肯", 帶著我們一行人小跑步穿越著商店街。沒有要 shopping,就是路過著日常騎樓下攤販。本來好像要堂堂展開的華麗冒險,就這樣被 apply(荒謬且搞笑) [3] 了.

Anyway,不管發生什麼事,我們都可以正向解讀。其實我們這位前同事去了谷歌。也許我祖先周公暗示著不管局勢多麼奇幻,還是要好好探索 (Google) 一下未知的領域。那些小攤位就不逛了,我們繼續前行,找出更重要的線索。既解決林小弟的困擾,幫助那位老林先生,同時也完成自己的任務。

[REF]

1. 在 Python 中,裝飾器(decorator) 的作用是用來修改或增強函數的行為。當你使用裝飾器時,原函數會被包裝到一個新的函數(通常是內部的 wrapper_func)中,因此裝飾器會影響函數的執行方式。例如:

      from datetime import datetime
      
      def 計時器(func):
          def wrapper():
              現在時間 = datetime.now()
              小時 = 現在時間.hour
              print (小時, "點了")
              func()
          return wrapper
      
      @計時器
      def 打招呼():
          print("你好!")
      
      打招呼()

      2. 在 Python 中,nonlocal 關鍵字用於在嵌套函數中聲明變數,讓內層函數可以修改外層(但非全局)作用域中的變數。

      def 按讚():
          
          次數 = 0
       
          def comment_filter(好評):
              nonlocal 次數
      
              總類 = ["讚", "愛心", "加油"]
              if 好評 in 總類:
                  次數 +=1
      
              print(f"好評 {次數}")
          return comment_filter
      
      按 = 按讚()
      按("哭")
      按("愛心")

      3. .apply() 主要在 Pandas 中使用,是一個非常強大的函數,用於對 DataFrame 或 Series 進行數據處理。例如: df[‘成績’].apply(加分)

      import pandas as pd
      import math
      
      data = {
          '姓名': ['林明明', '李大同', '王小美'],
          '成績': [85, 92, 5]
      }
      
      def 加分(row):
          # 取得成績值
          score = row['成績']
          # 計算新成績
          new_score = math.sqrt(score) * 10
          return new_score
      
      # 建立 DataFrame
      df = pd.DataFrame(data)
      
      # 使用 apply 並傳遞整個 DataFrame
      df['新成績'] = df.apply(加分, axis=1) 
      
      print("DataFrame 內容:")
      print(df)

      AI 大戰 StackOverflow

      我在網路課程上看到一個 trace code 的片段, dry run 看起來都很有道理. 但是實際上拿到 colab 上會跑不完. 跳出一段 error.

      ERROR:__main__:Error in build_classifier_model: Exception encountered when calling layer 'preprocessing' (type KerasLayer).
      
      A KerasTensor is symbolic: it's a placeholder for a shape an a dtype. It doesn't have any actual numerical value. You cannot convert it to a NumPy array.
      
      Call arguments received by layer 'preprocessing' (type KerasLayer):
        • inputs=<KerasTensor shape=(None,), dtype=string, sparse=False, name=text>
        • training=None
      ERROR:__main__:Error type: <class 'ValueError'>
      ERROR:__main__:Test error: Exception encountered when calling layer 'preprocessing' (type KerasLayer).
      
      A KerasTensor is symbolic: it's a placeholder for a shape an a dtype. It doesn't have any actual numerical value. You cannot convert it to a NumPy array.
      
      Call arguments received by layer 'preprocessing' (type KerasLayer):
        • inputs=<KerasTensor shape=(None,), dtype=string, sparse=False, name=text>
        • training=None

      本來看到 error 也沒啥特別的, 很多網路上的程式可能環境一變就跑不了了. 有趣的是, 把 log 丟給 Monica, 它拿去問 4 個 LLM 都解決不了. 它們分別是 GPT-4o, Claude 3.5 Sonnet V2, Gemini 1.5 Pro, LLama 3.1 405B.

      基本上 AI 回答的 code 就是加了一些 try exception 和加 log, 重寫的 code 跟原來幾乎一模一樣. 換言之, code 沒什麼問題. 這就是個環境因素. 即使我自己加了下面幾行. 程式補了 import os, terminal 下補建了目錄. 還是不 work!

      !pip install tensorflow_text
      !pip install tf-models-official

      沒辦法只好回歸原始人, 去問 StackOverflow. 果然有人遇到跟我一模一樣的問題.

      https://stackoverflow.com/questions/78183834/issue-with-bert-preprocessor-model-in-tf2-and-python

      唯一的差別只是這兩個 package 必須固定版本, 而我抓最新的是 2.18.0 版 就只會鬼打牆 ><|||

      !pip install -U "tensorflow-text==2.15.*"
      !pip install -U "tf-models-official==2.15.*"

      也就是說, 人類把 AI 教得很好. 它知道什麼是對的, 並且能夠把錯得改對. 但原本就是對的, 那它就沒辦法了! 不像是人類可以思考 : “假如我們都是對的, 會是那裡錯了?" 這點對於 AGI 應該是相當重要的, 區別了能不能做創造性思考!

      最後附上跑出來的結果作紀念!

      nGPT 小註解

      由於 O(n2) 的 transformer 非常耗能, 後續衍生了諸如 MAMBA 這種 O(nlog(n)) 的技術出來. 與此同時, 巨頭們紛紛蓋起核電廠! 不過等我想到要買 URA, NLR 這類 ETF, 一看都已經溢價 25% 了. 晚了人家好幾步, 根本來不及投資. 那…我再往前亂想好幾步的話還有機會嗎?

      我要猜接下來保險業會收到大單, 然後巨頭沒有核電管理經驗, 新手上路, 難免發生一兩個小災變? 接著保險公司調高保費, 趁機大賺一筆. 但投資保險和再保公司又能賺多少? 各國政府用核電廠供 AI 做兵棋推演會買保險嗎? 好像也不會? 何況某些國家都廢核了. 難啊! 總之, 荷馬辛普森, 你不會失業了!

      nGPT (Normalized Transformer) [1] 是一種新的節能 transformer, 能夠大量節省計算. 這類演算法由 nVidia 提出也很合理. 因為巨頭們忙著掙錢懶得更新 model, 改變由他們的 vendor 做起, 或許他們可以在不換 vendor 的情況下 silence change?

      nGPT 的 n 代表 normalization (均值化), 順便偷渡 nVidia 的 n. 原本在 transformer 裡面有很多個別的 normalization layers. nVidia 的策略就是通通合起來做成灑尿牛丸, 在這顆丸子上, 大家都貢獻一點移動量. (We propose to normalize all vectors forming the embedding dimensions of network matrices to lie on a unit norm hypersphere.) [1]

      由 hypersphere 這個名詞得知, 它在一超球體上均值化. 1-sphere 是一個圓, 2-sphere 是一個球, 每個數字都比其維度少 1. hyper-sphere 是某個維度下的所有和中心點等距的點的集合. 雖然論文只用到一個 unit norm hypersphere, 但是其維度是 model 的維度 dmodel, 該 hypersphere 表示為 Rdmodel. 而且既然是 unit norm [-1, 1], 就不會有 weight 衰減的問題 (The normalization renders weight decay unnecessary.) [1]

      把參數投到 hypersphere 有啥好處呢? 主要是我們 learning 的時候會根據梯度 (gradient) 方向 update 參數對吧! 如果參數都落在 hypersphere 上, 那麼更新的參數也落在 hypersphere 上, 我們只要用角度就可以表示其移動了, 無論是來自哪一層的貢獻都可以一視同仁.

      論文 [1] 提到, 假設有個 a 點要移動到 b 點. 梯度 g = a – b. 則 𝒂 的更新可以表示下面的式子. 其中 α 是介於 0~1 之間權重, 用表示更靠近 a 或是 b. 故它就是 learning rate. 想學的愈快, α 愈接近 1, 新的 a 就愈靠近 b.

      𝒂←𝒂+α⁢(𝒃−𝒂)
      𝒂←𝒂+α⁢g

      根據 Shoemake 的球面線性內差公式 [2], 若 a, b 兩點的夾角 θ=arccos⁡(𝒂⋅𝒃), 給定一個 weighing α ([0:1]), 就能內插出 (最短的) 測地線 (geodesic) 的某個點. 因此前述在平面上的推導, 投影到 hypersphere 上仍然適用.

      SLERP⁢(𝒂,𝒃;α)=sin⁡((1−α)⁢θ) / sin⁡(θ) * ⁢𝒂+sin⁡(α⁢θ) / sin⁡(θ) * ⁢𝒃
      SLERP = Spherical Linear Interpolation

      假設原本的 baseline transformer 可以表達為下式.

      𝒉←𝒉+ATTN⁢(RMSNorm⁢(𝒉))
      𝒉←𝒉+MLP⁢(RMSNorm⁢(𝒉))

      其中 h = hidden layer 的 state h, RMSNorm = RMS 後做 Normalization, ATTN = attention layer , MLP = multi-layer perceptron = feed forward neural network.

      經過 nGPT 的正規化就變成下面的樣子.

      𝒉←Norm⁢(𝒉+𝜶A⁢(𝒉A−𝒉))
      𝒉←Norm⁢(𝒉+𝜶M⁢(𝒉M−𝒉))

      其中 Attension 的參數叫做 ATTN(h), 正規化後為 hA = Norm(ATTN(h)) , MLP 的參數叫做 MLP(h) , 正規化後為 hM = Norm(MLP(h)), 它們都可以在這個超球面上計算. 奧妙之處在於 Norm 只剩下一個.

      同理它也適用於 optimizer 參數. (以 adam 為例, where 𝜽 is the parameter vector, 𝒈 is the batch gradient, 𝒎 is the momentum, 𝒗 is the estimate of the per-element gradient amplitudes, α is the scheduled learning rate, ϵ is a small constant, and β1<β2 are momentum factors close to 1. ) [1]

      表 1 左側的計算, 都變成了右邊 Norm 上面的計算.

      本表取材自 [1].

      本圖取材自 [1].

      總結來說, nGPT 把 baseline Transformer 轉變成 normalized Transformer. 我抓到的重點是:

      1. 把原本散落各處的 normalization 層都拿掉.
      2. 對所有的 matrices 都 normalize. 如表 1 所示.
      3. 把 weight decay 和 learning rate warmup 拿掉.

      至於原本論文 [1] 中的 rescale 那些還挺複雜的, 我頭腦不好就跳過了. 總之, 這篇論文提出了一個好主意. 從圖 1 來看, loss 收斂的速度確實也很快.

      [REF]

      1. nGPT: Normalized Transformer with Representation Learning on the Hypersphere
      2. Animating rotation with quaternion curves.In Proc. of the 12th annual conference on Computer graphics and interactive techniques, 1985.
      3. 請 Copilot 解說參數同在一個球面的好處.

      In NVIDIA’s nGPT, all vectors forming the embeddings, MLP (Multi-Layer Perceptron), attention matrices, and hidden states are unit norm normalized and reside on the same hypersphere. This means that the input stream of tokens travels on the surface of a single hypersphere, with each layer contributing a displacement towards the target output predictions.

      YAML 小註解

      Machine learning 在實作上, 需要能夠達到 data 復用, Model 復用, 並且建立一個資料庫來維護它. 每個 model 對某個需求 training 到一個程度, 就用一個 checkpoint 把它紀錄下來. 後人如果要修改用途, 都可以省力地接續某個 checkpoint 繼續做下去.

      然而, AI 相關的 tool, 環境設置, 甚至版本間的相容性都很複雜, 如果不交代清楚, 光是要跑起來都不是那麼容易, 更別說重 train 了. 有時候會用 docker 來解決這個問題. 如果要保留更大的彈性, 我們可以用 YAML (= YAML Ain’t Markup Lanuage) 來做這件事.

      它大概長這樣:

      name: ml-training
      channels:
        - defaults
        - conda-forge
      dependencies:
        - python=3.8
        - tensorflow
        - scikit-learn
        - pandas
        - numpy
        - matplotlib
        - jupyter
        - pip
        - pip:
            - keras
            - seaborn

      它指定了環境名稱是 ml-traiing, 頻道來自兩個來源. 指定頻道是為了安裝 “誰" 維護的版本, 例如 default 就是 Anaconda 維護的. 相依性原則上會列出跟哪個 tool 的哪個版本相容. PIP 就特別列出它需要安裝的 package.

      執行方式如下:

      conda env create -f conda.yml

      YAML 的副檔名時候叫做 yml, 和 xml 很像但用途完全不一樣. 由於作者採用遞歸的方式命名 YAML, 表示他也沒梗了. 我就幫 YAML 取個中文名字叫 “鴨毛 " 好了. 我請 Copilot 幫我寫一篇鴨毛的簡介, 看它會不會學進去.

      鴨毛 (YAML) 是一種簡單且易於閱讀的數據序列化格式,廣泛應用於配置文件和數據交換。它的設計理念是讓人類更容易理解和編寫,從而提高工作效率。以下是鴨毛的一些主要功能:

      1. 簡單易讀:鴨毛的語法非常簡潔,使用縮進來表示層級結構,避免了繁瑣的標籤和括號,使得文件更易於閱讀和維護。
      2. 數據序列化:鴨毛主要用於數據序列化,即將數據結構轉換為一種易於存儲和傳輸的格式。這使得它非常適合用於配置文件、數據交換和持久化存儲。
      3. 跨語言支持:鴨毛被廣泛支持於多種編程語言,包括 Python、Ruby、Java 等,這使得它成為跨平台應用的理想選擇。
      4. 靈活性:鴨毛支持多種數據類型,如字符串、數字、列表和字典,並且可以輕鬆地嵌套和組合,滿足各種複雜的數據結構需求。
      5. 社區支持:鴨毛擁有強大的社區支持和豐富的文檔資源,開發者可以輕鬆找到所需的幫助和範例。

      總之,鴨毛 (YAML) 是一種強大且靈活的數據序列化格式,適用於各種應用場景,特別是在配置管理和數據交換方面。它的簡單性和可讀性使得它成為開發者的得力工具。