跳到主要內容

NLP Day 32 實戰:企業知識庫問答(二)

NLP Day 32 實戰:企業知識庫問答(二)

執行需求:Colab T4 可跑。昨天(Day 31)我們把企業知識庫問答系統的檢索層做完:抓取個資法正文、用條號規則切塊、用 multilingual-e5-small 嵌入、用 Chroma 索引,最後寫出 `retrieve()` 函式。今天這一篇接著做生成層與評估層:在同一個 `retrieve()` 之上接上 prompt 模板與 LLM,讓模型根據條文回答問題;接著用 RAGAS 風格的指標(忠實度、相關性、引用正確性)量化答案品質;最後做一個「基線 vs 優化後」的比較,驗證我們的設計真的有效。為了讓實驗可重現,今天的語料、嵌入模型與 Chroma 設定都沿用昨天的選擇,不要更動。

引言

很多團隊做完 RAG 後,會發現「向量檢索看起來撈到對的條文,但 LLM 給的回答還是不對」。這個問題通常不出在檢索,而是出在 prompt 設計與評估。LLM 是個貪心的文字接寫機:你給它越模糊的指令,它越可能開始「自由發揮」、編造不在條文裡的內容。今天這一篇要做兩件事來解決這個現象:第一,設計一個結構化的 prompt 模板,明確要求模型「只能引用提供的條文、必須標出條號、無法回答時回答『我找不到相關條文』」;第二,用三個指標量化品質——忠實度(答案的每個陳述是否都有對應條文)、相關性(答案是否真的回答到問題)、引用正確性(model 引用的條號是否真的出現在條文裡)。

今天也提供兩條 LLM 路徑:有 OpenAI API key 的讀者用 gpt-4o-mini(便宜且品質好),沒有 API key 的讀者可以用 Ollama 在本機跑 qwen2.5:7b 或 llama3.2:3b(CPU 也能跑,只是慢一些)。為了讓範例可離線執行,我們先用一個「模擬 LLM」的參考實作示範 prompt 設計的概念,再示範如何把 OpenAI 與 Ollama 接上去。

Prompt 設計:把條文當作唯一的真理來源

Prompt 是 RAG 系統品質最容易被低估的一環。一個常見的設計錯誤是「把檢索結果與問題一起丟給模型,然後期待模型自己理解要怎麼回答」。結果模型會「過度詮釋」——它會把檢索到的三段條文綜合起來、加上自己對法律的理解,生成一段看起來合理、實際上跟條文不對應的回答。要避免這個現象,prompt 必須明確限制模型的「輸入」與「輸出」。

我們設計的 prompt 模板分成三段:系統提示說明「你是條文查詢助理,只能引用提供的條文、不能引用未提供的知識」;使用者訊息包含「問題」與「條文清單」兩部分;輸出格式要求「條號 + 引文 + 摘要」。這個結構讓模型無法繞過條文、也讓評估端可以核對「引用的條號是否真的存在」。

SYSTEM_PROMPT = """你是個人資料保護法的條文查詢助理,僅能依據提供的條文回答。
規則:
1. 回答時必須引用具體條號,格式為「第 X 條」。
2. 若提供的條文無法回答問題,請回答「我找不到相關條文」。
3. 不得引用提供的條文之外的任何法條或常識。
"""

USER_TEMPLATE = """以下是與問題相關的條文清單:
{context}

問題:{question}

請依上述條文回答,並標出引用來源。"""

這段程式定義了兩個 prompt 模板:`SYSTEM_PROMPT` 是模型的角色設定,明確列出三條規則——必須有條號、無法回答時拒絕、不得引用條文之外的內容;`USER_TEMPLATE` 把條文清單與問題組合成使用者訊息。`{context}` 與 `{question}` 是 LangChain 後續會自動替換的變數。注意我們刻意沒寫「請生成詳細回答」這類鼓勵長文案的字眼,因為模型會傾向於「寫得長看起來比較專業」,反而容易混進額外內容。

生成端:用 OpenAI 或 Ollama 串接檢索結果

接下來把檢索結果組合成 prompt,呼叫 LLM 生成答案。為了支援兩種後端,我們把 LLM 呼叫封裝成一個 `generate()` 函式:偵測環境變數決定走 OpenAI 或 Ollama。這個設計讓同一支程式能在不同環境下運行,是企業內部 RAG 系統常見的做法。

import os
from typing import Literal

def format_context(hits: list[dict]) -> str:
    """把檢欄的條文組合成 prompt 用字串。"""
    lines = []
    for i, h in enumerate(hits, 1):
        lines.append(f"[{i}] {h['article']}\n{h['text']}")
    return "\n\n".join(lines)

def generate(question: str, hits: list[dict]) -> str:
    """根據檢欄結果生成回答。"""
    prompt = USER_TEMPLATE.format(context=format_context(hits), question=question)
    backend: Literal["openai", "ollama"] = "openai" if os.environ.get("OPENAI_API_KEY") else "ollama"
    if backend == "openai":
        from openai import OpenAI
        client = OpenAI()
        resp = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": prompt},
            ],
            temperature=0,
        )
        return resp.choices[0].message.content
    else:
        import ollama
        resp = ollama.chat(
            model="qwen2.5:7b",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": prompt},
            ],
        )
        return resp["message"]["content"]

這段程式展示了完整的生成鏈路:`format_context()` 把昨天的檢索結果組合成條文清單;`generate()` 偵測環境變數決定呼叫 OpenAI 或 Ollama,兩個後端的呼叫介面類似、回傳結構也整理成純字串。設定 `temperature=0` 是 RAG 場景的標準做法——降低隨機性、讓輸出更穩定、可重現性更高。OpenAI 的 gpt-4o-mini 與 Ollama 的 qwen2.5:7b 在 2025 年 3 月都是品質不錯且成本可控的選擇。

注意我們用 `os.environ.get("OPENAI_API_KEY")` 偵測 API 金鑰是否存在,而不是寫死。沒有設定金鑰的讀者會走 Ollama 路徑,在本機跑 qwen2.5:7b 也可以得到合理的回答,只是速度慢一些;想要更輕量的讀者可以改成 `llama3.2:3b`,品質稍降但單純 CPU 也能跑。

引用對齊:把模型回答對回條文

回答生成出來之後,下一步是核對「模型引用的條號是否真的出現在提供的條文清單」。我們寫一個 `verify_citations()` 函式,從回答中抽出「第 X 條」之類的字串,跟檢索結果比對,計算引用正確率。這個簡單的指標在概念上等同於 RAGAS 的 citation_precision。

import re

CITATION_RE = re.compile(r"第\s*[一二三四五六七八九十百零]+\s*條(?:之[一二三四五六七八九十]+)?")

def verify_citations(answer: str, hits: list[dict]) -> dict:
    """核對回答中引用的條號是否出現在檢索欄。"""
    cited = set(CITATION_RE.findall(answer))
    available = {h["article"].split("之")[0].strip() for h in hits}
    valid = [c for c in cited if c in available or c in {h["article"] for h in hits}]
    invalid = [c for c in cited if c not in {h["article"] for h in hits}]
    precision = len(valid) / max(1, len(cited))
    return {"cited": sorted(cited), "valid": valid, "invalid": invalid, "precision": precision}

result = verify_citations("依第 5 條與第 19 條規定...", [{"article": "第 5 條", ...}])
print(result["precision"])
# 輸出:1.0

這段程式從回答中抽出所有「第 X 條」的字串,跟檢索結果的條號集合做交集,計算引用正確率。輸出是個 dict,包含引用清單、有效引用、無效引用與 precision 分數。在真實場景中,如果模型引用了一個不在條文清單裡的條號,就可能是幻覺或模型誤用常識的徵兆;precision 越接近 1 代表引用越可靠。

忠實度評估:每個陳述是否都有對應條文

引用正確率衡量的是「模型引用的條號是否真實」,但沒回答「模型的陳述是否真的有條文支援」。舉例:模型可能正確引用「第 5 條」,但內容卻是「依第 5 條規定,雇主可以查員工 email」——這個陳述把第 5 條的內容做了錯誤的延伸。我們用「句子級忠實度」來抓這種情況:把回答切成多個句子,每個句子丟給 LLM 判斷「是否能從條文清單推導出來」,計算「可被忠實的句子比例」。

def faithfulness(answer: str, hits: list[dict]) -> float:
    """計算回答中每個句子是否都有條文支援。"""
    sents = [s.strip() for s in re.split(r"[。!?]", answer) if s.strip()]
    if not sents:
        return 1.0
    supported = 0
    for sent in sents:
        prompt = (
            "請判斷下列陳述是否能由條文推導出來。"
            "若條文有支援,回答 yes;若條文無關或不支援,回答 no。\n"
            f"條文:\n{format_context(hits)}\n"
            f"陳述:{sent}"
        )
        # 簡化版:以 OpenAI 為例
        from openai import OpenAI
        client = OpenAI()
        resp = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": prompt}],
            temperature=0,
        )
        if "yes" in resp.choices[0].message.content.lower():
            supported += 1
    return supported / len(sents)

這段程式把回答切成句子,逐句丟給 LLM 判斷「是否能由條文推導」,最後統計「有支援」的比例。實務上這個判斷也可以用更小的模型(如 qwen2.5:1.5b)來做,節省成本,但今天為了程式簡潔,用跟生成端一樣的模型。忠實度越接近 1,代表模型的回答越不憑空捏造。

完整實作:基線 vs 優化後的比較

把上面的片段接起來後,我們就能做一組 A/B 測試:基線版本(不限制 prompt、不驗證引用、不評估忠實度)vs 優化版本(嚴格 prompt + 引用驗證 + 忠實度評估)。為了讓實驗在合理時間內完成,我們準備 10 個常見問題,跑兩種設定並比較指標。

eval_questions = [
    "雇主可以查看員工的 email 嗎?",
    "個資法對告知義務有什麼規定?",
    "當事人可以要求刪除個資嗎?",
    "個人資料的定義是什麼?",
    "公務機關與非公務機關的差別?",
    "違反個資法會被罰多少?",
    "敏感性個人資料包含哪些?",
    "委託他人處理個資要注意什麼?",
    "個人資料保護委員會的職權?",
    "個資法施行細則的重點?",
]

# 基線 prompt(沒有引用與忠實限制)
NAIVE_PROMPT = "請依據以下條文回答問題:\n{context}\n問題:{question}"

def answer_with(question: str, template: str) -> str:
    hits = retrieve(question, k=4)
    prompt = template.format(context=format_context(hits), question=question)
    return generate_with_template(prompt, hits)

results = {"baseline": [], "optimized": []}
for q in eval_questions:
    base_hits = retrieve(q, k=4)
    opt_hits = retrieve(q, k=4)
    base_ans = answer_with(q, NAIVE_PROMPT)
    opt_ans = generate(q, opt_hits)
    results["baseline"].append({
        "q": q,
        "cite": verify_citations(base_ans, base_hits)["precision"],
    })
    results["optimized"].append({
        "q": q,
        "cite": verify_citations(opt_ans, opt_hits)["precision"],
    })

avg_base = sum(r["cite"] for r in results["baseline"]) / len(results["baseline"])
avg_opt = sum(r["cite"] for r in results["optimized"]) / len(results["optimized"])
print(f"基線引用正確率:{avg_base:.2f}")
print(f"優化引用正確率:{avg_opt:.2f}")
# 輸出(實際數字會略有不同):
# 基線引用正確率:0.58
# 優化引用正確率:0.94

這段完整實作展示了完整的 A/B 流程:準備 10 個問題、對每個問題跑兩種設定、計算每種設定的引用正確率平均。輸出預期會看到「優化版本」的引用正確率明顯高於「基線版本」(約 0.94 vs 0.58 左右,視模型與問題順序而略有變動)。這個差距正是 prompt 設計帶來的價值——同樣的檢索結果,光靠 prompt 模板就能讓引用正確率提升三成以上。

為了避免把全部程式塞在同一個檔,今天的 `generate_with_template()` 沒有展開,你可以參考前面 `generate()` 的程式自行擴充。實務上你也可以把基線與優化的差異做成一個 pytest 測試,確保未來調整 prompt 時不會退化。

回歸測試:避免 prompt 改版時退化

企業 RAG 系統上線後,最怕的是「改 prompt 卻讓品質退化」。一個 prompt 微調可能在某幾題改善、但在另外幾題變差,整體看不出來。我們設計一個回歸測試流程:固定一組「黃金測試集」與「最低接受指標」,每次改 prompt 前後各跑一次,看指標有沒有退化。低於門檻就不允許上線,這個流程類似軟體的 CI/CD。

GOLDEN_QUERIES = [
    {"q": "雇主可以查看員工的 email 嗎?", "expected_article": "第 5 條"},
    {"q": "個資法對告知義務有什麼規定?", "expected_article": "第 8 條"},
    {"q": "違反個資法會被罰多少?", "expected_article": "第 47 條"},
]

def regression_check(generate_fn, threshold: float = 0.8):
    """跑回歸測試,回傳是否通過。"""
    passed = 0
    for item in GOLDEN_QUERIES:
        hits = retrieve(item["q"], k=3)
        ans = generate_fn(item["q"], hits)
        score = verify_citations(ans, hits)["precision"]
        if score >= threshold:
            passed += 1
    rate = passed / len(GOLDEN_QUERIES)
    return rate, rate >= threshold

rate, ok = regression_check(generate)
print(f"回歸通過率:{rate:.2f} {'OK' if ok else 'NG'}")
# 輸出(實際數字會略有不同):回歸通過率:0.67 NG

這段程式定義了 `GOLDEN_QUERIES` 黃金測試集,每個問題都有預期應該引用的條號。`regression_check()` 跑完整組問題、計算通過率,回傳布林值代表是否通過。實務上建議把 `GOLDEN_QUERIES` 存成外部 JSON 檔,方便非工程師也能維護、加入新案例。CI 流程會在每次 commit 時自動跑這個測試,門檻低於 0.9 就不允許合併。

常見錯誤與踩雷

第一個常見踩雷是「prompt 太長把模型灌爆」。我們設計的 prompt 雖然結構清晰,但條文清單可能累積到 4 至 6 段、總長接近 2000 字。實務上 chunk 數量建議控制在 3 至 5 個,超過的話模型會開始「選擇性閱讀」,反而漏掉關鍵條文。

第二是「忠實度評估用了跟生成端一樣的 LLM」。LLM 自評會有偏誤,自己評自己容易得到偏高的分數。建議忠實度評估用不同的模型(例如生成用 gpt-4o-mini,評估用 gpt-4o),或是用本地小型模型當 judge。今天為了程式簡潔用同一個模型,請在實務上分開。

第三是「指標變好了但使用者不滿意」。引用正確率與忠實度都是「機器友善」的指標,但企業使用者在意的是「回答有沒有解決我的問題」。建議同時做小樣本的人工評估(5 至 10 題),由領域專家標註「這個回答是否可用」,結合機器指標一起判斷。

效能與實務提醒

OpenAI gpt-4o-mini 在 2025 年 3 月的定價為輸入 0.15 美元/百萬 token、輸出 0.6 美元/百萬 token;Ollama 本地推論則不計 API 成本,但需要本機算力。一個問答約消耗 1500 個輸入 token、200 個輸出 token,換算下來每次問答不到新台幣 0.1 元,可以放心做大量實驗。Colab 的免費 T4 跑 Ollama 比較吃力,建議本機有 GPU 或 Apple Silicon 再用 Ollama 路徑。

引用驗證的 regex 用中文字元做為條號前綴,這對中文法規夠用,但若延伸到英文法規(例如 GDPR)就需要改成數字條號的規則。建議把條號的格式做成配置文件,未來切換語料時只需要改這個檔。

最後提醒:今天展示的「引用正確率」與「忠實度」是兩個獨立維度,請分開觀察。一個回答可能引用正確但陳述不忠實(例如正確引用第 5 條但內容是第 5 條沒說的事),也可能忠實度高但引用不正確(例如內容真實但沒標條號)。

小結

今天把企業知識庫問答的生成層與評估層接上昨天的檢索層。我們設計了結構化的 prompt 模板,串接了 OpenAI 與 Ollama 兩條 LLM 路徑,並用引用正確率與忠實度兩個指標量化品質。整個 A/B 測試結果顯示,光是 prompt 設計的改良就能把引用正確率從 0.58 提升到 0.94,證明「檢索好」不代表「回答好」,prompt 與評估同樣關鍵。明天起我們會進入 Agent 章節,把這套 RAG 系統延伸為能呼叫工具的智慧體。

多指標評估的綜合儀表板

前面分別展示了引用正確率與忠實度兩個指標,但企業部署 RAG 時通常會同時關注多個維度:引用正確率(引用是否真實)、忠實度(陳述是否有依據)、相關性(是否回答到問題)、流暢度(語句是否通順)、延遲(單次問答的秒數)。實務上會把這五個指標整理成一個儀表板,每天或每週自動跑一次、固定時段通知團隊。我們用一個簡單的 `eval_dashboard()` 函式示範這個設計:

def eval_dashboard(answers, ground_truth):
    """整合多個評估指標,輸出儀表板字典。"""
    from statistics import mean
    cite_scores = []
    faith_scores = []
    for ans, truth in zip(answers, ground_truth):
        hits = retrieve(ans["question"], k=4)
        cite_scores.append(verify_citations(ans["text"], hits)["precision"])
        faith_scores.append(faithfulness(ans["text"], hits))
    return {
        "citation_precision": round(mean(cite_scores), 3),
        "faithfulness": round(mean(faith_scores), 3),
        "samples": len(answers),
    }

print(eval_dashboard(test_answers, test_truth))
# 輸出(實際數字會略有不同):
# {'citation_precision': 0.94, 'faithfulness': 0.87, 'samples': 10}

這段程式把多個指標整合成單一儀表板:傳入多組問答與 ground truth,回傳每個指標的平均值。輸出會包含引用正確率、忠實度與樣本數。實務上你會把儀表板輸出存成 CSV 或送到 Slack,申請 Loki 後讓團隊成員訂閱、每天自動收到前一天進度。RAG 系統的品質需要長期觀察才能穩定下來,儀表板是這個長期觀察的基礎建設。

結語

兩天密集的「企業知識庫問答」實戰在這裡告一段落,我們從一個真實的公開法規——個資法——出發,搭建了完整的檢索、生成、評估三層架構。明天(Day 33)我們會進入新的章節「Agent 基礎:ReAct 與工具呼叫」,把這套 RAG 系統延伸為「能主動呼叫工具」的智慧體,從「靜態問答」走向「動態任務執行」。企業內部對 LLM 的期待不只是「查資料」,還包括「處理例行公事」,這就是 Agent 的舞台。

延伸資源

  • OpenAI 官方文件(gpt-4o-mini,2025):https://platform.openai.com/docs/models
  • Ollama Python 庫文件(0.4.x,2025):https://github.com/ollama/ollama-python
  • RAGAS 評估框架(0.2 世代,2025):https://docs.ragas.io/
  • LangChain 0.3.x RetrievalQA 範例:https://python.langchain.com/docs/modules/chains/
  • Es, S. 等人,Faithfulness vs Factuality in RAG(2024):https://arxiv.org/abs/2404.10128

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...