分散式機器學習小註解

先前學過的 Tensorflow model training, 久而久之也還給老師了. 今天趁颱風假學習分散式的機器學習, 順便把基本功也補一些回來!

需要分散式學習的原因就是 AI (ML) model 太大了, 因此有各式各樣的方法把工作分散給不同的 CPU, GPU, TPU (後續用 NPU 涵蓋之). 分散的方法包括把 training data 分散給大量 NPU, 或是把 model 的不同層拆給不同的 NPU 做. 後者比較沒有參數及時互通的問題就略過不談.

Data 分散出去給不同的 NPU 學習, 最明顯的問題就是大家拿到的 data 不同, 算出來的 gradient 理論上也不同, 那要麼收斂到同一版呢? 解決這個問題的架構 (architecture) 有兩個大方向, 分別為 synchronous 和 Asynchronous 兩種.

Synchronous 架構下, 每個 NPU 都要等其它 NPU 做完一個段落. 然後大家同步一下參數. 同步的方式可能只是將大家得到的數取個平均. 假設原本一個 update grdient 的段落是一個 batch. 現在有 N 個NPU 均分 data, 所以每個 NPU 只要做一個 mini-batch.

mini-batch = batch * strategy.num_replicas_in_sync (e.g. 1/N)

在一台機器有多個 NPU 的時候, 我們稱這個策略為 mirrorstrategy. 因為每個 NPU 做的事情都一樣, 像是照鏡子. 假如我有多台機器, 每一台機器 (worker) 都執行 mirrorstrategy, 此時稱為 multi-worker mirror strategy. 實際上的精神都是一樣的. 就是三個動作:

  1. 初始化:所有 worker 從相同的初始模型參數開始。
  2. 同步:取一個段落, 每個 worker 把自己的 grafient 傳出去. 每個 worker 看到其他所有 worker 的資料後, 做個計算 (像是取平均). 因為只要有一個 worker 沒更新, 大家都缺一筆資料, 所以不需要中控也可以自動進行.
  3. 參數更新:每個 worker 使用同步的梯度, 以 optimizer 更新其模型參數, 確保所有工作者在每一步都有相同的模型參數。

至於 asynchronous architecture 就沒有互等的機制, 參數 (weight, bias) 會放在一個以上的 parameter server (PS). 大家都去跟它要參數就對了. 等到 worker 算出自己的 gradient, 就把它傳給 PS, PS 負責用大家的 gradient 更新出新的參數給下一個 worker 抓取. 講義原文如下:

Each worker independently fetches the latest parameters from the parameter servers and computes gradients based on a subset of training samples. It then sends the gradients back to the parameter server, which then updates its copy of the parameters with those gradients.

由 Asynchronous 的架構會有大量的資料要傳遞 (weight, bias), 所以適合用在參數大多是 0 的 sparse model. 而參數大多不是 0 的 dense model (如 BERT, GPT) 就更適合 synchronous architecture. 言下之意是傳的時候多少會做壓縮吧!

MirroredStrategy 的 sample code 如下, 藍色字是和普通 training 不一樣的地方. 特別留意是 model 這行退縮到 with strategy.scope(): 的下一層.

import tensorflow as tf
import tensorflow_datasets as tfds

# Load the dataset

datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets['train'], datasets['test']

# Define the distribution strategy
strategy = tf.distribute.MirroredStrategy()
print('Number of devices: {}'.format(strategy.num_replicas_in_sync))

# Set up the input pipeline
BUFFER_SIZE = 10000
BATCH_SIZE_PER_REPLICA = 64
BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync

def scale(image, label):
    image = tf.cast(image, tf.float32)
    image /= 255
    return image, label

train_dataset = mnist_train.map(scale).cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
test_dataset = mnist_test.map(scale).batch(BATCH_SIZE)

# Build and compile the model within the strategy scope
with strategy.scope():
    model = tf.keras.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(10)
    ])

    model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  optimizer=tf.keras.optimizers.Adam(),
                  metrics=['accuracy'])

# Train the model
model.fit(train_dataset, epochs=10, validation_data=test_dataset)

用 Multi-LLM 解釋投資風險

Coursera 有一門新的課 [1], 由該公司老闆 Andrew 介紹 CrewAI 來講課. 主要是講多個 LLM 怎麼應用. 課程不長, 有 Lab, 沒證書. 看在老闆推薦的份上, 我也來蹭一下.

用最簡單的話來講, 它的技術就是叫每個 Agent 執行一個 task. 雖然大家平平都是 LLM, 但是指定了不同的角色, 每個 agent 就會各自專注在它的 task 上, 達到互相幫忙的結果. 當然每個 agent 的排列方式 (hierachy) 會影響他們共事的結果.

可不可 search 網路? 需不需要 human input, 可不可以非同步? 這些在 CrewAI 這家公司的 library 中都可以設定. 每個 agent 透過 memory 互相溝通, 因此即使不指定誰 (agent) 要傳訊息給誰 (other agents), 資料也可以共用.

有個 Lab 很好玩, 就是建立一個 crew 去分析買股票的風險. 它的架構是 Crew 叫 agent 做 task. Task 就只是明訂工作內容 (description) 和預期成果 (expect output), 然後註明給哪個 agent. Agent 要指定 role, goal, backstroy (工作指導), 標記可以用那些 tools? 標記可不可以餵資料給別人 (delegation), log 要多詳細 (verbose).

from crewai import Crew, Process
from langchain_openai import ChatOpenAI

# Define the crew with agents and tasks
financial_trading_crew = Crew(
    agents=[data_analyst_agent, 
            trading_strategy_agent, 
            execution_agent, 
            risk_management_agent],
    
    tasks=[data_analysis_task, 
           strategy_development_task, 
           execution_planning_task, 
           risk_assessment_task],
    
    manager_llm=ChatOpenAI(model="gpt-3.5-turbo", 
                           temperature=0.7),
    process=Process.hierarchical,
    verbose=True
)

Crew kickoff 之後, agent 就會去做事. 至於要做什麼? 寫在 input string 裡, 相當於一個 prompt. 舉例指定用 1000 元去買 Nvidia, 風險承受度中等, 應該如何操作? 在課程的例子中, 因為指定 process 是 hierachy. 所以叫第一個 agent 去做 data analysis, 它有 search 網路的 tool, 因此就會各個網站 search Nvidia 的新聞. 總結出 10 條. 交給下一棒 Trade agent.

Trade agent 的工作是要分析標的物的統計值, 它也有網路工具. 所以它也去找了一堆網站. 總結出 Nvidia 的評價.

Based on the information gathered from various analyst forecasts and recommendations, the average 12-month price target for NVDA is $130.68, with the highest target being $200.00 and the lowest at $90.00. The consensus rating for NVDA is “Strong Buy," supported by 38 buy ratings and 3 hold ratings. The stock has a current price of $135.58. The analysis suggests that there is a potential -3.61% downside from the current price based on the average price target. The historical performance of NVDA shows consistent outperformance relative to the industry.

接一下到了 execution agent. 它有甚麼大膽的創見嗎? 沒有. 即使它收到這麼明顯地看多訊息: Considering the historical performance and analyst forecasts, developing a trading strategy that aligns with the bullish sentiment towards NVDA could be a profitable approach, especially for day trading preferences.

它還是說我要上網查看看, 然後歸納出 5 點結論:

Execution Plan for NVDA:
1. Utilize historical performance data to identify key trends and patterns in NVDA’s stock price movements.
2. Implement a strategy that leverages the ‘Strong Buy’ recommendation and average 12-month price target of $130.68.
3. Monitor market trends and movements closely to capitalize on potential trading opportunities presented by NVDA’s growth potential.
4. Develop a risk management strategy that aligns with the user-defined risk tolerance (Medium) and trading preferences (Day Trading).
5. Regularly review and adjust the execution plan based on new market data and insights to optimize trading outcomes for NVDA.

接著回到 Crew. 它根據風險承受度為 Medium 這個條件, 再上網去跑一輪. 對每個網站的內容做一個小結論. 最後叫 risk management agent 彙總, 結果就是給安全牌 (因為風險承受度不高).

Overall, the risk analysis for NVDA’s trading strategies should focus on understanding the potential risks associated with each strategy, assessing the firm’s risk tolerance, and implementing appropriate safeguards to manage and mitigate risks effectively.

我認為畢竟 Crew 收到的指令就是風險承受度中等而已. 已經預設立場, 不用問 AI 也知道結果. 當我把風險承受度改為 Ultra High 重跑一次. 這次它的結論就變狠了! 建議了一些選擇權策略: Straddle Strategy、Iron Condor Strategy 、Long Call Butterfly Spread Strategy、LEAPS Contracts Strategy 等等.

這告訴我們兩件事.:

  1. CrewAI 使用 multi LLM 的功效很強大. 大家做完自己的事就交給同事 (co-worker), 各司其職. 可以用同一個 LLM 做出一群同事開會的效果!
  2. 你跟 AI 講我風險承受度低, AI 就叫你保守. 你說你不怕死, AI 就叫你玩選擇權. 這些不用問 AI, 應該是問施主你自己就好了.

[REF]

  1. https://www.coursera.org/learn/multi-ai-agent-systems-with-crewai/home/welcome

程式語言雜記

最近幾天在天竺國出差, 剛好有機會面試印度人. 我問到: 既然您的專長是 Android, 為何語言的專長是 C 和 C++, 沒有 Java 呢? 印度人說, 因為他做 Android 時已經升管理職, 所以沒有 coding Java 的機會.

話說一隻手指指向別人, 就有四隻指頭指向自己. 當初 Sun Micron 找工研院電通所合作發展 Java 下線時, 我也去受訓拿到一張 Java 講師證. 但後來沒機會用上, 日久愈來愈生疏, 最後也覺得還是藏拙比較不尷尬. 哈!

至於 C++, 我剛好有個網路課程只剩幾個小時沒上完. 正好就今天處理了. 畢竟從天竺轉機回台灣這兩天, 加起來睡不到十小時, 累到幾乎無法思考大事. 這麼難用的時間, 碰上簡單的課程和超簡單的最後一個作業, 真是天作之合. (Adjacency List 那個作業就難多了, 題意說明落落長, class 定義在哪裡要自己找出來).

這門課雖然用到一些 C++, 重點還是講資料結構. 例如: Dijkstra’s algorithm wasn’t able to find the shortest path if edge has negative weight. 翻譯成白話是: 假如我們的工作流程中有人扯後腿, 怎麼優化都會鬼打牆. 基本上這堂課還不錯.

當初會上 Coursera 是為了學 AI. 為了發揮最大投資效益, 我買了一年Plus 會員吃到飽來學習 Tensorflow, LLM, 和其他 AI 的訓練課程. 基本上能選的課, 我聽得差不多了, 甚至還產生了心得. 像是同樣的生成式 AI 課程, Google 版重視 AI 倫理, Amazon 版重視 AWS 生態系實作, IBM 版重視如何用在 project 管理, DeepLearning AI 重視知識完整性等等.

其中上過最硬的課算是 Scrimba 的 Learn Embeddings and Vector Databases (RAG 相關). 因為我 Java script 確實有點生鏽了, 跟不太上講師 trace code. 基本上, 各門各派用的語言都不同, 加強程式語言能力才能了解實作細節, 體會複雜度, 甚至是交程式作業 (現在電腦改程式作業好簡單). 這些能力不是 AI 可以替我們感同身受的, 也是最不會被 AI 取代的 – 至少我這麼認為.

Give Myself a Pat on the Back

以前連假的時候, 我都會趁機讀完一兩本書. 不過這次我用它來完成我網課的最後一哩路. 這是一個 Coursera 的 AI TensorFlow Developer 學程, 裡面包括 4 個子課程.

Introduction to TensorFlow for Artificial Intelligence, Machine Learning, and Deep Learning
Convolutional Neural Networks in TensorFlow

Natural Language Processing in TensorFlow

Sequences, Time Series and Prediction

這個課程大概需要兩個月, 本來我想我好歹也算有個一知半解吧! 打算在免費試用七天的時間就把課程走完, 不過它還是有點難度, 所以我破功了. 只好為它花了註冊費. 接著我以生日前通過為目標, 失敗! 改為 2024/3/31 前通過, 又失敗! 總算在清明連假最後一天通過最後一個 Lab 了! 花了快一個月之久.

model = tf.keras.models.Sequential([ 
    tf.keras.layers.Conv1D(64, input_shape = [64, 1], kernel_size = 3, padding = 'causal', activation = "relu"),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32,return_sequences = True)),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
    tf.keras.layers.Dense(32, activation = "relu"),
    tf.keras.layers.Dense(16, activation = "relu"),
    tf.keras.layers.Dense(1),
    tf.keras.layers.Lambda(lambda x: x* 25)
]) 
model.compile(loss= tf.keras.losses.Huber(),
optimizer=tf.keras.optimizers.SGD(momentum = 0.9, learning_rate = 5e-4),
metrics=["mae"])

最後一堂課的結語是 give yourself a pat on the back. 所以我就拿它來當標題. 接下來找下一個可以學的東西.

生成式 AI 大材小用記

原本聽說三星的 S24 應該有很厲害的 AI, 結果玩了一天看不出任何不同的地方?? 假如我沒有買到假貨的話, 應該就是我不會用!!

上網找了一篇比較新的評測, 終於知道有哪些功能可以用了. 但所有特異功能幾乎都是預設關閉. 難怪我覺得跟掛掉的 S20 用起來幾乎沒差別.

在即時翻譯的部分, 要進到設定 –> 進階功能 –> 進階智慧工具, 然後把電話、三星鍵盤、翻譯助理一一打開. 翻譯還要下載語言包, 小包的越南文、泰文需要 300 MB 上下, 大包的中英日韓接近 450MB. 這些都要個別下載. 測試起來雖然有時會認錯, 不過我覺得還堪用, 這樣就不用買科大訊飛翻譯機了.

至於那個圈圖搜尋, 首先 APP 要相容. 初步試過 Chrome, Disney+ 不行, Netflix 可以操作但會隱藏掉 video, 只留 OSD. 而 Facebook 和 YouTube 可以. 另外, 不是想畫圈就畫圈, 我試了一下要先按 Android 底部的那個圓圈圈 home icon, 接下來才能圈或是框要搜尋的對象. 初步測試效果沒有很好. 不過以圖找圖大概就是那種程度.

在照片的部分, 生成式照片要先在照片編輯時, 選編輯 (一隻筆的 icon), 再按花花的藍底三星 icon, 才會進入生成功能頁面.

用手寫筆歪七扭八地把水管框住, 它就會自己貼到物件的輪廓上.

被框住的物件可以移動或是消除. 我選消除. 水管就拿掉了. 當然會有一點痕跡在. 被蓋掉的英文字也還拚不出來, 但以後進版應該有機會.

另外一個樣本是今年的尾牙, 當我們吃到甜湯的時候, 桌上已經一堆雜物了. 畢竟沒發垃圾桶, 座位又擠, 總不能塞到隔壁同仁那邊. 所以拍起來是這樣.

靠著 AI 生成技術, 衛生紙拿走了. 灑出來的湯汁也清掉了, 質感好了很多! 唉, 我真是讓它完全大材小用啊.