模型層 開放閱讀

Shuffling

Data Shuffling

概念 ID
data-shuffling
更新時間
2026-05-29
來源數量
待補

Shuffling(Data Shuffling)

3 秒看懂

資料洗牌:在模型訓練的每個 Epoch 開始前(或資料讀取過程中),隨機打亂訓練樣本的呈現順序,防止模型從資料排列順序中”偷學”虛假規律,是幾乎所有監督/自監督訓練流水線的標準操作。

一句話定性:Shuffling ≠ 加新資料,而是讓同一批資料以不同順序被看到——這是正則化的最低成本手段之一。

3 分鐘產業解釋

為什麼產業研究需要重視一個”看起來這麼簡單”的操作?

  1. 訓練質量的地基:不 Shuffle 的後果不是”稍微差一點”,而是模型可能根本無法收斂到合理解。它直接決定下游訓練的有效性。

  2. 分散式訓練的吞吐瓶頸之一:在萬卡叢集訓練大型模型時,如何在數百個 Worker 之間高效完成全域性 Shuffle,直接影響 GPU 利用率。資料載入和 Shuffle 策略選擇不當,會導致 GPU 空等(Stall),浪費算力。

  3. 資料工程的核心環節:當前大型模型訓練的資料集規模達到數萬億 Token(數 TB~數十 TB),Shuffle 的工程實現本身就是一個分散式系統問題——涉及磁碟 I/O、記憶體緩衝、跨節點通訊的綜合權衡。

  4. 與資料合規的交叉點:Shuffle 後的訓練資料難以追溯特定樣本在哪個 Step 被消費,這在一定程度上影響”被遺忘權”(Right to Be Forgotten)的技術實現,是 AI 合規的潛在討論點。

產業定位:Shuffling 處於 AI 訓練資料管線(Data Pipeline)的核心層,上承資料儲存與預處理,下接 DataLoader 與訓練迴圈。它不是一個獨立產品,而是所有訓練架構的內建基礎設施。

15 分鐘專家深入

1. Shuffle 的本質:打破樣本間的時間相關性

機器學習的 SGD 系列最佳化器假設每個 Mini-Batch 是從資料分佈中獨立同分布(i.i.d.)取樣的。如果資料按固定順序排列(例如分類資料集中所有貓→所有狗→所有鳥),則連續多個 Batch 會高度同質,導致:

  • 梯度方向偏差:連續 Batch 的梯度高度相關,引數更新方向偏離全域性最優。
  • Batch Normalization 統計量偏移:BN 層的均值/方差估計嚴重偏離全域性統計量。
  • 過擬合局部模式:模型可能”記住”的是”第 N 個 Batch 大機率是貓”這種序號訊號。

Shuffle 的作用是近似恢復 i.i.d. 條件

2. Shuffle 的層次架構

在實際工程中,Shuffle 不是單一操作,而是分層的:

┌──────────────────────────────────────────────┐
│            Global Shuffle (跨節點)             │
│  ┌────────────────────────────────────────┐  │
│  │     Shuffle Buffer (流式 Shuffle)       │  │
│  │  ┌──────────────────────────────────┐  │  │
│  │  │  Per-Worker Shuffle (本地隨機)    │  │  │
│  │  │  ┌────────────────────────────┐  │  │  │
│  │  │  │  Shuffle Seed 管理 (可復現) │  │  │  │
│  │  │  └────────────────────────────┘  │  │  │
│  │  └──────────────────────────────────┘  │  │
│  └────────────────────────────────────────┘  │
└──────────────────────────────────────────────┘
層次作用域典型實現資源開銷
Epoch-level Global Shuffle全資料集打亂先 Shuffle 索引,再按索引分片需要全域性索引載入到記憶體
Shuffle Buffer Shuffle流式近似打亂從資料流中抽取樣本填滿 Buffer,隨機彈出記憶體 = Buffer × 樣本大小
Per-Worker Shuffle單節點/單卡本地每個 DataLoader Worker 獨立 Shuffle極低
跨節點 Shuffle(Distributed Shuffle)多機多卡全域性All-to-All 通訊或共享 Shuffle 索引通訊開銷為主要成本

3. Shuffle Buffer:記憶體與隨機性的權衡

當資料集大到無法全部載入進記憶體時(如 TB 級),需要流式 Shuffle

輸入流: [a, b, c, d, e, f, g, h, ...]  (按檔案/分片順序)

Buffer 容量 = 4

Step 1: 填充 → Buffer = [a, b, c, d]
Step 2: 隨機選中 b 彈出 → 輸出 b, 讀入 e → Buffer = [a, e, c, d]
Step 3: 隨機選中 d 彈出 → 輸出 d, 讀入 f → Buffer = [a, e, c, f]
...
  • Buffer 越大:隨機性越接近全域性 Shuffle,但記憶體佔用越高。
  • Buffer 越小:隨機性越弱,資料仍保留較強的區域性相關性。
  • 正確實踐:Shuffle Buffer 的合適大小主要取決於資料集總大小和可用記憶體。若記憶體允許,Buffer 容量應儘量設為整個資料集的大小,以實現完全隨機;對於無法全量載入的超大數據集,通常設定為一個足夠大的固定樣本數(如 10,000 或 100,000),以提供充分的隨機性,與 Batch Size 的數量級無直接關聯。

4. 分散式訓練中的 Shuffle 策略

在大規模分散式訓練中,資料通常先被分片(Shard)再分配給各 Worker。兩種主流策略:

策略 A:先 Shuffle 再分片(Pre-Partition Shuffle)

全資料集索引 → Shuffle → 均分給 N 個 Worker
  • ✅ 每個 Worker 拿到的資料是全域性隨機的
  • ❌ 需要一個全域性 Shuffle 的協調點,或共享索引檔案

策略 B:先分片再 Shuffle(Post-Partition / Local Shuffle)

全資料集索引 → 均分給 N 個 Worker → 各 Worker 本地 Shuffle
  • ✅ 無需跨節點通訊,完全並行
  • ❌ 每個 Worker 只在自己的分片內隨機,全域性隨機性較弱
  • ⚠️ 如果資料本身已按類別排列且分片是順序切的,可能每個 Worker 拿到高度同質的資料

工程實踐(多數架構的預設做法):採用策略 A 的變體——在每個 Epoch 開始前,所有 Worker 使用相同的全域性隨機種子,各自獨立生成相同的全域性 Shuffle 索引排列(如 PyTorch 的 DistributedSampler 所為),然後每個 Worker 根據自己的 rank 取負責的索引切片。這樣既保證全域性隨機性,又完全避免了索引的廣播通訊。

5. Shuffle 與 DataLoader 的工程實現

架構Shuffle 相關介面關鍵引數
PyTorchtorch.utils.data.DataLoader(shuffle=True)shuffle, sampler, generator, worker_init_fn
TensorFlowtf.data.Dataset.shuffle(buffer_size)buffer_size, seed, reshuffle_each_iteration
JAX/Flax手動管理或通過 Grain/tfds視具體資料管線而定
HuggingFaceTrainer(train_dataset, ...)內部呼叫 PyTorch/TF 的 DataLoader

PyTorch 中的一個重要細節

  • shuffle=True 配合 DistributedSampler 時,DistributedSampler 會先做全域性 Shuffle 再分配索引,此時 DataLoadershuffle 引數應設為 False(避免重複 Shuffle)。
  • num_workers > 0 時,每個 Worker 程序擁有獨立的資料副本和隨機狀態。

6. Seed 管理與可復現性

Shuffle 的隨機性由隨機種子(Seed)控制。關鍵實踐:

  • 全域性種子 → 各 Worker 子種子worker_seed = global_seed + worker_id + epoch
  • Epoch 間是否 Reshuffle
    • PyTorch DistributedSampler 預設每個 Epoch 重新 Shuffle(通過 set_epoch(epoch) 控制)
    • TensorFlow tf.data.Dataset.shufflereshuffle_each_iteration 引數控制
  • 可復現性需求與 Shuffle 的張力:完全可復現要求固定 Seed,但這意味著”隨機”只發生一次——實踐中通常接受”同一 Seed + 同一硬體 = 同一結果”的弱可復現。

7. Shuffle 不足 / 過度的影響

現象可能原因後果
訓練 Loss 震盪大、收斂慢Shuffle 不充分,Batch 內樣本同質梯度方差偏高
驗證集表現遠好於訓練集(反常)訓練資料可能洩漏了順序資訊到驗證集需排查資料劃分
GPU 利用率低(Data Stall)Shuffle Buffer 太大導致 I/O 瓶頸GPU 空等 CPU/磁碟
OOM(記憶體溢位)Shuffle Buffer 佔用過多記憶體訓練崩潰
不同 Epoch 結果完全一致未 Reshuffle 或 Seed 固定模型看到的資料順序永遠相同

技術原理(最深)

機制詳解:Shuffle 如何影響 SGD 的收斂性

數學直覺(定性,非嚴格證明):

設總訓練集為 \mathcal{D} = \{x_1, x_2, ..., x_N\},在 Epoch $t$ 中,如果按固定順序切分為 Mini-Batch \{B_1, B_2, ..., B_K\},則相鄰 Batch 的梯度 g_k = \nabla L(B_k)g_{k+1} = \nabla L(B_{k+1}) 之間存在正相關:

\text{Cov}(g_k, g_{k+1}) > 0 \quad \text{(非 Shuffle 情形)}

這種正相關意味著 SGD 的引數軌跡會產生系統性偏差(Systematic Bias),而非單純圍繞最優解做無偏隨機遊走。

Shuffle 通過打亂樣本順序,使相鄰 Batch 之間的相關性接近零:

\text{Cov}(g_k, g_{k+1}) \approx 0 \quad \text{(充分 Shuffle 情形)}

理論結論(來自最佳化理論文獻的定性共識):

  • Without Replacement SGD(不放回取樣 + 充分 Shuffle):相比 With Replacement SGD,在凸問題上具有同等或更優的收斂速率常數(方差更小)。
  • 每個 Epoch 的 Shuffle 保證了不放回取樣下各 Epoch 間的資料多樣性。

分散式場景下的 Shuffle 通訊拓撲

場景: 4 Worker, 資料集 12 個樣本, 每 Epoch 每 Worker 消費 3 個

策略 A - 全域性 Shuffle + 分配 (主流架構做法):
  每個 Worker 使用相同隨機種子, 獨立生成相同的全排列 π = [7,2,11,5,1,9,3,8,10,6,12,4]

  ├─ Worker 0 取 π[0:3]  = [7, 2, 11]
  ├─ Worker 1 取 π[3:6]  = [5, 1, 9]
  ├─ Worker 2 取 π[6:9]  = [3, 8, 10]
  └─ Worker 3 取 π[9:12] = [6, 12, 4]

通訊量: 0 (各Worker獨立計算, 無需廣播)

關鍵觀察:該方式利用相同種子在各自程序內確定性地生成相同的全域性排列,從而直接消除 Shuffle 階段的任何跨節點通訊。真正的資料傳輸僅發生在各 Worker 根據索引從儲存讀取樣本時。

Shuffle Buffer 的記憶體消耗估算

Buffer 記憶體 = buffer_size × per_sample_size

示例 (ImageNet 級別):
  buffer_size = 10,000
  per_sample_size ≈ 200KB (解碼後 JPEG)
  總記憶體 ≈ 2 GB

示例 (LLM Token 級別):
  buffer_size = 1,000,000 tokens
  每 token = 2~4 bytes (int16/int32)
  總記憶體 ≈ 2~4 MB  (Token 級別非常輕量)

Token 級別的 Shuffle 在 LLM 訓練中幾乎不是記憶體瓶頸;真正的挑戰在於文件級別的 Shuffle(保持文件完整性 vs 跨文件隨機性)。

LLM 訓練中的特殊 Shuffle 問題

在大規模 LLM 預訓練中,Shuffle 面臨獨特挑戰:

  1. 文件級 vs Token 級 Shuffle

    • Token 級 Shuffle:打亂所有 Token 的順序 → 破壞文件語義結構 ❌
    • Document-level Shuffle:按文件打亂順序,文件內部 Token 保持不變 → 保留語義 ✅
    • 實踐:主流做法是先做 Document Shuffle,再做 Packing(將多個文件拼接到固定長度序列中)
  2. Packing 對 Shuffle 的影響

    • Packing 後的序列包含多個文件的片段
    • 如果 Packing 方式固定,則同一文件的 Token 始終與同一批鄰居拼接
    • 可通過在每個 Epoch 重新隨機 Packing 來增加多樣性
  3. 資料混合比例(Data Mix)與 Shuffle 的互動

    • 不同來源的資料(程式碼、網頁、書籍等)按比例混合後 Shuffle
    • Shuffle 的粒度(按樣本/按文件/按來源塊)直接影響模型對不同來源的學習效果

技術演進史

時期階段Shuffle 方式驅動因素
1980s-1990s早期神經網路記憶體中全量 Shuffle資料集小,全在記憶體
2000sSVM/傳統ML時代訓練集通常不 Shuffle(隨機性由演算法本身保證)核方法不依賴 SGD 順序
2012-2015深度學習爆發 (AlexNet→VGG)每 Epoch 全量 Shuffle,資料集在單機記憶體可容納ImageNet ~128K 樣本,JPEG 約 150GB
2015-2017大規模 CVShuffle Buffer 出現(tf.data 等),流式讀取資料集增長,單機記憶體不足
2017-2019分散式訓練普及DistributedSampler + 全域性 ShufflePyTorch/TensorFlow 分散式訓練成熟
2020-2022LLM 預訓練 (GPT-3 級)Document-level Shuffle + Packing資料規模達數 TB,需保持文件完整性
2023-2025萬億引數模型訓練多源資料混合後 Document Shuffle,預計算並快取 Shuffle Index訓練資料成為瓶頸,資料質量 > 資料順序

技術路線對比

維度全量 Shuffle(In-Memory)Shuffle Buffer(Streaming)全域性 Index Shuffle + 分片讀取無 Shuffle(固定順序)
隨機性質量★★★★★ 理想★★★☆☆ 取決於 Buffer 大小★★★★★ 近似理想★☆☆☆☆ 無
記憶體開銷O(N) 樣本全在記憶體O(B) Buffer 大小O(N) 索引(整數)O(1)
I/O 模式隨機讀取半順序讀取可預讀最佳化純順序讀取
GPU 利用率中~高高(但訓練效果差)
分散式友好需廣播大量索引每 Worker 獨立無需廣播索引 ✅無需協調
適用場景小資料集超大數據集、單機流式大規模分散式訓練除錯/基準測試
典型使用者影像分類、小NLP早期 TF PipelineMegatron-LM、LLaMA 訓練消融實驗對照

上下游

上游(資料供給)                    下游(訓練消費)
┌───────────────┐               ┌───────────────────┐
│ 原始資料儲存   │               │  訓練迴圈 (Loop)   │
│ (S3/GCS/HDFS) │               │                   │
└───────┬───────┘               │  ┌─Forward Pass   │
        │                       │  ├─Backward Pass  │
        ▼                       │  └─Optimizer Step │
┌───────────────┐               └────────▲──────────┘
│ 資料預處理     │                        │
│ Tokenization  │               ┌────────┴──────────┐
│ 解碼/Resize   │               │  DataLoader       │
│ Packing       │               │  Batch Collation  │
└───────┬───────┘               └────────▲──────────┘
        │                                │
        ▼                                │
┌───────────────────┐                    │
│ ★ SHUFFLE ★       │────────────────────┘
│ (本文主題)         │
│ 索引生成/Buffer   │
│ 分片分配          │
└───────────────────┘

上游依賴

  • 資料儲存系統(決定了順序讀取 vs 隨機讀取的效能特徵)
  • 資料格式(TFRecord/WebDataset/MemoryMap 影響 Shuffle 的工程實現)
  • 預處理管線(Tokenization、Packing 是否在 Shuffle 之前/之後影響語義完整性)

下游影響

  • DataLoader 的 Batch 拼接(Collation)效率
  • 訓練迴圈中 data_time 指標(GPU 等待資料的時間)
  • 模型收斂速度和最終精度

關鍵指標

指標含義觀測方式
GPU Idle Ratio (%)GPU 等待資料的時間佔比Profiler (Nsys/TensorBoard)
Data Load Time / Step Time資料載入佔每步總時間的比例訓練架構日誌
Buffer Hit RateShuffle Buffer 中已滿時的命中分佈均勻度自定義監控
Shuffle Entropy輸出序列相對於理想隨機排列的熵理論度量,工程中少用
Epoch Interleaving不同 Epoch 間同一 Batch 組成的重疊率低重疊 = 好 Shuffle
Per-Source Mix Variance多源混合後每個 Batch 內各來源比例的方差LLM 多源訓練關鍵指標

供需與市場資料

⚠️ Shuffling 不是獨立產品,不產生直接市場規模。 以下為定性關聯分析。

算力市場的隱性影響

  • 資料管線(含 Shuffle)效率低下導致的 GPU 空等,業界估算可浪費 5%~30% 的 GPU 時間 [供應鏈經驗估算,無單一權威來源]。
  • 以一塊 H100 的雲端租賃價格估算(約 $2~3/小時 [各雲端廠商公開定價]),一個萬卡叢集每天因資料管線低效損失可達 數萬至數十萬美元

最佳化趨勢

  • 預計算 Shuffle Index:在訓練開始前完成全資料集的 Shuffle Index 生成並持久化,避免訓練中即時計算開銷。
  • WebDataset / Mosaic StreamingDataset:將資料打包為大 Shard 檔案,配合記憶體對映實現高效 Shuffle,減少小檔案 I/O。
  • 硬體加速資料管線:NVIDIA DALI 等庫在 GPU 上完成資料預處理和部分 Shuffle 邏輯,減少 CPU-GPU 資料搬運。

代表公司與資本對映

公司/組織與 Shuffle 的關聯資本對映
NVIDIADALI 資料管線庫,GPU 加速 Shuffle 和預處理NVDA(直接受益於訓練效率需求)
PyTorch (Meta)DataLoader + DistributedSampler,工業標準實現META(開源基礎設施投入)
Google (TensorFlow/JAX)tf.data.shuffle、Grain 資料管線GOOGL
HuggingFaceDatasets 庫內建 Shuffle 和 Streaming 模式私有 → 潛在 IPO 標的
MosaicML (Databricks)StreamingDataset,專為大規模訓練最佳化的 Shuffle 方案DBKS(Databricks 收購 MosaicML)
Determined AI (HPE)訓練平台中資料管線排程最佳化HPE
各種 MLOps 平台資料版本管理中的 Shuffle Seed 管理

投資邏輯對映:Shuffle 本身不直接對應標的,但資料管線效率 → GPU 利用率 → 單位訓練成本的傳導鏈條,使得資料管線最佳化成為 AI Infra 投資的隱性加分項。


投資邏輯

核心關聯

  1. 資料管線最佳化 = 隱性降本:GPU 計算是最大成本項。如果 Shuffle 和資料載入能將 GPU 利用率從 70% 提升到 90%,相當於同等硬體下獲得 ~29% 的額外有效算力。這直接轉化為訓練成本的降低。

  2. 資料規模持續膨脹的受益者:隨著訓練資料從 TB 級向數十 TB 級演進,簡單粗暴的全量 Shuffle 越來越不現實,高效 Shuffle 方案(Streaming、預計算索引、WebDataset 格式等)的需求持續增長。

  3. 多源資料混合訓練的趨勢:GPT-4 級模型的訓練涉及數十種來源的資料(程式碼、網頁、書籍、對話等),各來源的混合比例和 Shuffle 粒度直接影響模型能力。這催生了對資料編排(Data Orchestration)工具的需求。

風險提示

  • Shuffle 最佳化本身技術壁壘不高,不太可能成為獨立商業模式。
  • 主要價值體現為訓練架構和資料管線平台的一個 feature,而非獨立產品。
  • 當前主流架構的 Shuffle 實現已經”夠用”,邊際改進空間有限。

常見誤讀糾偏

❌ 誤讀 1:“Shuffle 是可選的最佳化手段,不做也不影響訓練”

糾偏:Shuffle 不是錦上添花,而是幾乎不可或缺的基礎操作。在資料本身有序的情況下(這很常見,因為資料通常按來源、時間或類別儲存),不 Shuffle 可以導致:

  • 模型在訓練早期只學到部分類別,後期才接觸到其餘類別。
  • Batch Normalization 統計量嚴重偏移。
  • 最終模型精度可能下降數個百分點甚至更多(取決於資料排序程度)。

唯一的例外是某些特殊訓練範式(如課程學習 Curriculum Learning,有意按難度排序資料),但即便如此通常也只是”受控的部分 Shuffle”,而非完全不 Shuffle。

❌ 誤讀 2:“Shuffle Buffer 越大越好,設定成資料集大小就是完美 Shuffle”

糾偏:理論上 Buffer = 資料集大小 等價於全量 Shuffle,但這意味著:

  • 全部資料要先載入到記憶體/Buffer 中,對 TB 級資料集不可行。
  • Buffer 過大會導致首次輸出延遲極高(需要先填滿 Buffer)。
  • 實際上 Buffer 大到一定程度後,對模型精度的邊際改善急劇遞減。存在明顯的”收益遞減拐點”——通常 Buffer 大小達到 Batch Size 的數十倍後,額外增大的收益已經很小。

❌ 誤讀 3:“分散式訓練中每個 Worker 本地 Shuffle 就足夠了”

糾偏:本地 Shuffle 只在自己的資料分片內隨機化。如果資料分片本身不是全域性隨機的(例如,資料集前 1/4 是圖片、中間 1/4 是文本),則每個 Worker 只看到單一模態的資料,等價於沒有 Shuffle。必須先做全域性索引 Shuffle 再分片,或至少保證各分片的資料分佈與全集一致。

❌ 誤讀 4:“Shuffle 對 LLM 預訓練不重要,因為序列很長且資料來源多樣”

糾偏:雖然 LLM 預訓練的資料來自多種來源且序列很長,但:

  • 文件級別的 Shuffle 仍然至關重要:如果同一個來源的文件連續出現數百個 Step,模型對不同來源的學習是不均勻的。
  • 資料混合比例和 Shuffle 粒度的互動:如果不 Shuffle,則每個 Epoch 中各來源被消費的順序固定,可能導致訓練後期梯度主要來自某一種來源,造成能力偏斜。
  • 已有多項實證研究表明 [定性引用:業界公開討論],資料 Shuffle 策略對 LLM 的最終能力有可測量的影響。

學習路徑

入門(1-2 小時)

  1. PyTorch 官方文件:torch.utils.data.DataLoadershufflesampler 引數說明
  2. 動手實驗:用 MNIST/CIFAR-10,分別對比 shuffle=Trueshuffle=False 的訓練曲線差異

進階(3-5 小時)

  1. 閱讀 PyTorch DistributedSampler 原始碼(約 100 行),理解全域性 Shuffle + 分片的實現
  2. 閱讀 TensorFlow tf.data.Dataset.shufflebuffer_sizereshuffle_each_iteration 機制
  3. 實驗:手動實現一個 Shuffle Buffer(Python 列表 + random.choice),體會 Buffer 大小對隨機性的影響

專家級(持續)

  1. 閱讀 MosaicML StreamingDataset 的設計文件,理解 TB 級資料集的 Shuffle 工程方案
  2. 研究 Megatron-LM / DeepSpeed 的資料載入管線原始碼,看大規模分散式訓練中 Shuffle 的實際實現
  3. 關鍵文獻:Recht & Ré (2012) “Toward a Noncommutative Algebra of…” 關於 Without Replacement SGD 的理論分析;Bengio et al. (2009) 關於 Curriculum Learning 的經典工作

一句話總結

Shuffling 是訓練資料管線中最基礎卻最容易被忽視的環節——它不增加任何新資訊,僅通過改變資訊的呈現順序來顯著改善模型學習效果;在萬卡訓練時代,高效 Shuffle 的工程實現本身已成為資料基礎設施的核心元件。


延伸閱讀與來源

來源說明
PyTorch DataLoader 文件shuffle 引數、DistributedSampler 用法
TensorFlow tf.data 指南Dataset.shuffle 的 Buffer 機制
MosaicML StreamingDataset (GitHub)大規模訓練的 Shuffle 方案設計
Megatron-LM 原始碼 (NVIDIA GitHub)megatron/data/ 目錄下的資料載入與 Shuffle 實現
NVIDIA DALI 文件GPU 加速資料管線
Recht & Ré (2012), “Parallel Stochastic Gradient Algorithms…”SGD 與資料排列的理論分析
Bengio et al. (2009), “Curriculum Learning”有意識地不完全 Shuffle(反面參考)
各雲端廠商 H100/A100 例項定價頁面GPU 時間成本參考

*本文技術事實基

source: 公開揭露與公開資料整理 本頁僅用於產業鏈學習、資訊檢索和研究輔助;不構成投資建議,不預測漲跌,不提供買賣、部位或目標價建議。
完整概念頁 複盤 13 節結構 公司投研頁 沿產業鏈找到受益公司 投資課 把概念轉成可跟蹤模型