---
title: "驗收測試驅動開發與 AI 訓練相似之處"
date: 2024-03-06T00:00:00+08:00
publishDate: 2024-03-06T18:06:58+08:00
lastmod: 2024-03-06T22:48:14+08:00
tags: ["AI","測試","ATDD"]
toc: true
permalink: "https://blog.aotoki.me/posts/2024/03/06/the-atdd-and-ai-training-is-similar/"
language: "zh-tw"
---


最近完成公司的 AI 培訓後，開始思考我們說的模型（Model）跟軟體開發中的領域模型（Domain Model）是否有關聯，如果仔細思考，似乎在抽象層面上是類似的。

<!--more-->

## 模型{#model}

領域模型通常指的是封裝商業邏輯（Business Logic）的部分，而且跟特定領域有很深入的關聯。軟體開發中我們去設計一個領域模型，也是為了讓我們可以處理特定類型的邏輯。

舉例來說，假設有一個以關鍵字判斷惡意網址的系統，我們可能會預期輸入（Input）是網址，輸出（Output）則是一個評分，中間的判斷可能是一些正規表達式（Regexp）和預先設計好的關鍵字名單。

```go
type URL string
type Score float

type AntiScam interface {
  Execute(input URL) Score
}
```

如果改成用機器學習來處理這件事情，我們從人工篩選關鍵字，轉換到讓機器自己學習哪些關鍵字是有惡意的，進而判斷某個網址是否帶有惡意，那麼輸入跟輸出的介面（Interface），跟原本我們設計的領域模型實際上是相同的。

從抽象的角度去看，模型的建構差異只在於是否人工還是自動（或半自動）的建立。

## 訓練{#training}

在機器學習中，要對模型進行訓練才能夠處理特定的任務。以監督式學習（Supervised Learning）的方式進行時，會需要提供 Ground Truth 來對資料標注，讓機器可以理解到怎樣是正確，或者預期看到的結果。

例如，我們可以提供一些訓練資料

| url | score |
| ---- | ---- |
| https://i-am-scam.com | 10 |
| https://i-am-safe.com | 100 |
| https://hi-scame.com | 5 |

訓練時，根據我們對網址的編碼（Encode）和分數的關聯（如：`scam` ~= `10`）得到一個模型，並且透過訓練資料的一部分當作測試，後續反覆調整參數（Hyper Parameter）後得到一個最佳的參數用於模型。

> 關於模型的訓練，網路上有許多文章能更詳細的說明，這邊只簡單介紹概念。

對應到驗收測試驅動開發（ATDD，Acceptance test-driven development）的情境，我們也是在做相同的事情，有測試資料以及訓練過程（反覆修正程式）的情境，概念上可能是非常接近的。

首先，由團隊先撰寫測試（訓練資料）

```gherkin
Feature: Anti Scam Checker
  Scenario: give a scam url and return lower score
    Given a url as input "https://i-am-scam.com"
    When I run the anti-scam checker
    Then the score is 10
```

接下來進行實作，跟模型訓練相同的情境，我們會從失敗（成果不理想）開始出發，嘗試改進這個模型

```go
type KeywordBasedAntiScam struct {
}

func (m *KeywordBasedAntiScam) Execute(input URL) Score {
  return Score(100)
}
```

隨著實作更加完善，我們的模型就能得到更好的分數

```go
func (m *KeywordBasedAntiScam) Execute(input URL) Score {
  score := Score(100)
  // ...
  for _, keyword := range m.Keywords {
    hasScamKeyword := strings.Contains(input, keyword)
    if hasScamKeyword {
      score -= m.Weights[keyword]
    }
  }

  return score
}
```

最後就能夠得到一個通過測試的領域模型，雖然跟機器學習相比測試資料的規模、複雜度都不同，但是在改善正確性這件事情上本質還是一樣的，也許可以認為是當下提升對特定領域理解的最佳實踐。

## 雜訊{#noise}

最近在讀的[雜訊：人類判斷的缺陷](https://www.kobo.com/tw/zh/ebook/XQg6AKFEOjKU8fvxMFktcA)一書中，提到許多依靠經驗、直覺、偏見（Bais）判斷的情況，讓許多法律判斷、行情預測等結果有許多差異。

而透過機器學習產生的模型進行判斷，通常雜訊（Noise）的情況會減少許多，在各種參數的權重（Weights）配比上也能找到更適合的分配方式，讓每一次的評估結果都接近一致。

之所以能做到這點，從監督式學習的訓練過程中可以發現，我們會以訓練資料的一部分來驗證輸出，同時不斷的調整到大多數情境都符合這個輸出結果，中間對於不同資訊的參考、排除就是一種消除雜訊的方式。

如果應用在軟體開發上，我們撰寫驗收測試也是為了避免開發團隊跟產品負責人（Product Owner）的認知有差異，假設單純依靠開發團隊想像，這些假想就變成一種雜訊存在於開發過程中，那麼最終的成果就會變得不可預測，或者偏離目標。

如果想要明確的對結果做評估，使用舉例的方式效果會更好，如同訓練資料中提供輸入、輸出是什麼，訓練過程則要想辦法讓輸入跟輸出接近測試的內容。

從這點來看，機器學習跟軟體開發剛好在不同的情境對不同需求的模型建構，是能夠相輔相成的。

