跳到主要內容

NLP Day 30 進階 RAG:GraphRAG 與結構化知識

NLP Day 30 進階 RAG:GraphRAG 與結構化知識

執行需求:Colab T4 可跑。今天是 RAG 章節的最後一篇基礎建設,從 Day 25 的架構總覽一路走到這裡,我們已經會用向量檢索把相關段落撈回來、會做查詢改寫、會重排序、也會用引用與忠實度評估 RAG 的品質。但純粹以「段落嵌入 + 相似度比對」為核心的 RAG,遇到一個明顯的罩門:跨段落的整體性問題。像是「這份報告主要在討論哪幾個主題」、「A 公司跟 B 公司在這份新聞裡出現過哪些合作」,這類需要橫向彙整好幾段文字才能回答的題目,向量檢索往往只能撈到看起來最像問題的某一兩段,生成端只能憑印象亂湊。GraphRAG 嘗試用一張「知識圖」補上這個缺口。

引言

過去五天,我們把 RAG 的每個環節都拆開看過了:文件切分、嵌入、檢索、查詢改寫、重排序、評估。每一個改良都有效,但都沒有解決「整體性問題」這個本質困難。一份十頁的合規報告,向量檢索會撿到三段說明某個條款細節的段落,卻沒辦法告訴你「這份報告的主題有 A、B、C 三塊,它們之間的關係是什麼」。這不是召回數量或排序演算法的問題,而是資訊的「結構」沒有被保留。

GraphRAG 的核心想法,是先把文本拆解成一張「實體—關係」圖,再對圖做不同範圍的查詢。微軟研究院在 2024 年中把這個做法整理成論文 From Local to Global: A Graph RAG Approach to Query-Focused Summarization(arXiv:2404.16130)並開源同名函式庫,把流程拆成兩階段:先用 LLM 從文本抽出實體與關係建成圖,再用 LLM 對圖上偵測到的社群各自生成摘要,最後以「本地實體檢索」與「全域社群摘要」兩條路線回答問題。對企業知識庫來說,這個做法有兩個明顯的好處:一是能直接看到「這份報告提到了哪些人、事、時」,二是回答整體性問題時不再只能從單一段落硬湊。

今天這一篇會先用一個最精簡的版本展示 GraphRAG 的概念:用 spaCy 抽實體、用 networkx 建圖、用社群偵測找主題,再用一段問答示範「跨段落彙整」的效果與正經比較。為了讓程式能在 Colab T4 上一鍵執行,我們刻意避開需要付費 API 的環節;如果你想在正式環境用 LLM 做摘要與關係抽取,文末會提供整合 OpenAI 與 Ollama 的延伸閱讀。

為什麼純向量 RAG 會卡在整體性問題

向量檢索的強項是「找到跟問題最像的段落」,弱項是「讀懂段落之間的關係」。舉一個企業知識庫常見的例子:一份供應商管理辦法,裡面提到 A 供應商在某年因品質異常被停權、B 供應商因交期延遲被罰款、C 供應商是新加入的合作廠商。如果使用者問「這份辦法今年處罰過哪些供應商」,向量檢索可能撈到「A 供應商停權」那一段,卻撈不到「B 供應商罰款」那段,因為「處罰」這個詞在第二段被換成了「裁罰」、「違約金」,兩段文字的相似度被詞彙差異拉低。生成模型就只能根據單一段落回答,看起來自信卻不完整。

GraphRAG 的解法是先把文本結構化:每一段文字先經過「實體抽取」轉成「A 公司—因—品質異常—被—停權」這種三段式陳述,再把同一個實體在不同段落出現的關係串起來。A 跟 B 就會在同一張圖的不同邊上出現,搜尋時只要在圖上找到「A 供應商」這個節點、沿著「被處罰」這類關係走,就能一次把今年所有處罰事件拉齊。對整體性問題而言,這種圖形檢索明顯比純相似度比對更貼近人類整理資料的方式。

知識圖譜基礎:用 spaCy 抽實體

知識圖譜的基本單位是「節點」與「邊」。節點代表一個實體(例如一個公司、一個產品、一個條款),邊代表兩個實體之間的關係(例如「供應」、「處罰」、「引用」)。要把文本轉成圖,需要先做命名實體辨識(NER)找出節點,再用句子分析找出邊。spaCy 在 2025 年 3 月的版本(3.7 與 3.8 世代)內建了多種語言的 NER 模型,中文模型 zh_core_web_sm 與 trf 變體可以直接拿來用,CPU 上每秒可處理數百個 token,足以應付中型企業知識庫。

import spacy

nlp = spacy.load("zh_core_web_sm")
text = "碩網資訊於 2024 年向 A 供應商採購伺服器,因品質異常於同年停權。"
doc = nlp(text)
for ent in doc.ents:
    print(f"實體:{ent.text}({ent.label_})")
# 輸出(實際結果會略有不同):
# 實體:碩網資訊(ORG)
# 實體:2024 年(DATE)
# 實體:A 供應商(ORG)

這段程式把一段中文文字丟給 spaCy 的中文模型,印出模型認出的實體。輸出會包含人名(PERSON)、組織(ORG)、時間(DATE)、地點(GPE)等類別。中文 NER 模型的精確度不如英文,但對常見的組織與時間詞彙仍有一定水準。實務上企業文件常見的「合約編號」、「產品代號」這類自訂實體,可以用 spaCy 的 `EntityRuler` 自行擴充,今天的範例為了簡化,先用模型內建類別。

有了實體,我們還需要關係。spaCy 3.x 沒有內建關係抽取器,但可以借用「兩個實體在同一句話中共同出現」這個簡單假設來建立候選邊。更精緻的做法是用 LLM 抽關係或用規則模板比對句型,但今天的精簡版本只用共同出現,因為這對小型文件集已經能畫出有用的圖。

把段落建成圖:用 networkx

Python 生態系最成熟的圖函式庫是 networkx。我們把每一段文字視為一個節點,把同一段內共同出現的實體配對視為一條邊,加上共現次數當權重,方便後續做社群偵測時有依據。為了不讓圖過於雜亂,我們只保留權重超過門檻的邊,這是業界常用的降噪手段。

import networkx as nx
from itertools import combinations

paragraphs = [
    "碩網資訊於 2024 年向 A 供應商採購伺服器,因品質異常於同年停權。",
    "B 供應商因交期延遲被裁罰違約金,C 供應商為新加入合作廠商。",
    "A 供應商另於 2023 年因文件缺失被記點,累計滿三點停權。",
]

G = nx.Graph()
for idx, para in enumerate(paragraphs):
    doc = nlp(para)
    entities = [ent.text for ent in doc.ents if ent.label_ in {"ORG", "PERSON"}]
    G.add_node(f"p{idx}", kind="paragraph", text=para)
    for entity in set(entities):
        G.add_node(entity, kind="entity")
        G.add_edge(f"p{idx}", entity, kind="mentions")
    for a, b in combinations(set(entities), 2):
        if G.has_edge(a, b):
            G[a][b]["weight"] += 1
        else:
            G.add_edge(a, b, kind="cooccur", weight=1)

print(f"節點數:{G.number_of_nodes()},邊數:{G.number_of_edges()}")
# 輸出:節點數:8,邊數:10(實際數字會略有不同)

這段程式把三段文字建成一張小型圖:六個實體節點加兩個段落節點,再加上段落與實體的「提及」邊、實體之間的「共現」邊。輸出節點數與邊數會因為 spaCy 的實體辨識結果而略有不同;真實的企業知識庫通常會用幾百到幾千段文字建圖,圖的規模會比這裡大上兩個量級,但建立過程完全一樣。

社群偵測:找出文件主題

有了圖之後,下一步是把「同一主題」聚集在一起,這個動作在圖論裡叫「社群偵測」(community detection)。networkx 內建了幾種演算法,比較常用的是 label propagation 與 greedy modularity。社群偵測的直覺是「邊比較密的子圖內部成員之間關係強,應該被視為同一主題」,這正好對應企業文件中「一個章節討論一個主題」的概念。我們用 greedy_modularity_communities 把圖切開,計算每個社群的代表詞,當作這個社群的主題摘要。

from networkx.algorithms.community import greedy_modularity_communities

communities = list(greedy_modularity_communities(G))
for i, comm in enumerate(communities):
    members = [n for n in comm if G.nodes[n].get("kind") == "entity"]
    print(f"社群 {i}:{members}")
# 輸出(實際結果會略有不同):
# 社群 0:['A 供應商', 'B 供應商', 'C 供應商', '碩網資訊']
# 社群 1:['A 供應商']

輸出顯示我們的圖被切成兩個社群:一個包含四個供應商與公司,另一個只剩單一節點。雖然這個小型範例的社群結構不算豐富,但已經能看出 GraphRAG 的價值:當問題問「所有供應商」時,可以直接從社群 0 取出所有相關節點,不需要逐一比對段落相似度。這就是 GraphRAG 比純向量 RAG 更擅長整體性問題的根本原因。

兩階段問答:本地檢索與全域檢索

原始 GraphRAG 論文把問答流程分成兩條路線:本地(local)檢索負責處理「某某做了什麼」這類聚焦在少數實體的問題;全域(global)檢索負責處理「整份文件的主題是什麼」這類需要橫向彙整的問題。兩條路線在論文中都是用 LLM 對圖上的節點與社群摘要做查詢;為了讓程式能在沒有 API key 的環境下也能展示流程,我們把 LLM 換成「依圖結構挑選代表性段落」的啟發式方法,效果雖然不及真正的 LLM 摘要,但足以示範架構。

def local_search(graph, query_entity, top_k=3):
    """以一個實體為中心,從圖上擷取相鄰段落與共現實體。"""
    if query_entity not in graph:
        return []
    neighbors = list(graph.neighbors(query_entity))
    para_neighbors = [n for n in neighbors if graph.nodes[n].get("kind") == "paragraph"]
    return [graph.nodes[p]["text"] for p in para_neighbors[:top_k]]

def global_search(graph, communities, top_k=2):
    """以一個社群為範圍,擷取社群內所有段落當作全域摘要。"""
    results = []
    for comm in communities[:top_k]:
        para_nodes = [n for n in comm if graph.nodes[n].get("kind") == "paragraph"]
        text = " ".join(graph.nodes[p]["text"] for p in para_nodes)
        results.append(text)
    return results

print("=== 本地檢索:A 供應商 ===")
for line in local_search(G, "A 供應商"):
    print(line)

print("=== 全域檢索:社群 0 ===")
for line in global_search(G, communities):
    print(line[:80], "...")

這段程式定義了兩個函式:`local_search` 以一個實體為起點,從圖上擷取相鄰段落;`global_search` 以一個社群為範圍,把社群內所有段落接起來當作整體摘要。輸出會把 A 供應商相關段落與整個供應商社群涵蓋的段落分開印出。實務上的 GraphRAG 會把這兩段文字丟給 LLM 生成答案,但我們這裡只示範「結構上能怎麼做」,把 LLM 留給明天與之後的延伸。

完整實作:小型 GraphRAG 管線

把 spaCy、networkx、社群偵測與兩階段檢索串起來,就是一個最精簡的 GraphRAG 管線。下面的程式可以整段貼進 Colab 執行,CPU 即可運行(Colab 預設環境已包含 spaCy、networkx;如未安裝則需先 `pip install spacy networkx` 並下載中文模型)。

import spacy
import networkx as nx
from itertools import combinations
from networkx.algorithms.community import greedy_modularity_communities

# 1. 載入中文模型;第一次執行會自動下載 ~50MB
nlp = spacy.load("zh_core_web_sm")

# 2. 文件集;為了讓示例可離線運作,這裡直接寫死。
documents = [
    "碩網資訊於 2024 年向 A 供應商採購伺服器,因品質異常於同年停權。",
    "B 供應商因交期延遲被裁罰違約金新台幣 50 萬元,C 供應商為新加入合作廠商。",
    "A 供應商另於 2023 年因文件缺失被記點,累計滿三點停權。",
    "碩網資訊啟動供應商分級制度,預計 2025 年導入 AI 自動稽核。",
]

# 3. 建圖:以段落為節點、實體為節點,邊代表共同出現。
G = nx.Graph()
for idx, doc_text in enumerate(documents):
    doc = nlp(doc_text)
    entities = [ent.text for ent in doc.ents if ent.label_ in {"ORG", "PERSON", "GPE"}]
    G.add_node(f"p{idx}", kind="paragraph", text=doc_text)
    for entity in set(entities):
        G.add_node(entity, kind="entity")
        G.add_edge(f"p{idx}", entity, kind="mentions")
    for a, b in combinations(set(entities), 2):
        if G.has_edge(a, b):
            G[a][b]["weight"] += 1
        else:
            G.add_edge(a, b, kind="cooccur", weight=1)

# 4. 社群偵測並輸出每個社群的代表實體
communities = list(greedy_modularity_communities(G))
for i, comm in enumerate(communities):
    members = [n for n in comm if G.nodes[n].get("kind") == "entity"]
    print(f"社群 {i} 代表實體:{members}")
# 輸出(實際結果會略有不同):
# 社群 0 代表實體:['A 供應商', 'B 供應商', 'C 供應商', '碩網資訊']
# 社群 1 代表實體:[]

這段完整實作把所有片段接起來,輸出圖上偵測到的社群與每個社群的代表實體。在 Colab 上執行時,第一次會自動下載 `zh_core_web_sm`,後續執行會從快取讀取,整個流程大約 10 秒內完成。實務上你會把 `documents` 換成真實的文件集,例如從法務部門抓出的幾十份供應商合規紀錄,再把 `local_search`、`global_search` 的輸出接上 LLM,就能搭建完整的 GraphRAG 應用。

GraphRAG 與向量 RAG 的互補

GraphRAG 並不是要取代向量 RAG,而是要互補。向量 RAG 對「找出最像問題的那段」這種本地化查詢表現優異;GraphRAG 對「整份文件在講什麼主題」、「某個實體在文件裡被怎麼描述」這種全域性查詢更有優勢。實務上常見的折衷做法是:先用 GraphRAG 建立文件集的整體骨架(主題、社群、關鍵實體),再用向量 RAG 在骨架的指引下做精細檢索。微軟的開源函式庫就把這兩個階段串起來,提供 `global_search` 與 `local_search` 兩個 API,讓開發者根據問題類型選用合適的路線。

如果你的文件集不大(數百份以內),用 spaCy + networkx 的精簡版本就足以應付;如果文件集規模到上萬份,就會需要 LLM 來做更精準的關係抽取與摘要,或考慮改用圖形資料庫(Neo4j 與其老版本、TigerGraph)來處理更大規模的圖。今天的範例停在小型精簡版本,正是為了讓讀者在沒有 API key 的情況下也能把概念跑通;後續若要擴充,文末的延伸資源會給出指引。

import json

# 把小型 GraphRAG 圖存成 JSON,方便之後載入或跨程式分享
def graph_to_json(graph):
    data = {
        "nodes": [{"id": n, **graph.nodes[n]} for n in graph.nodes],
        "edges": [{"source": u, "target": v, **graph.edges[u, v]} for u, v in graph.edges],
    }
    return json.dumps(data, ensure_ascii=False, indent=2)

def json_to_graph(payload):
    data = json.loads(payload)
    g = nx.Graph()
    for node in data["nodes"]:
        g.add_node(node["id"], **{k: v for k, v in node.items() if k != "id"})
    for edge in data["edges"]:
        g.add_edge(edge["source"], edge["target"], **{k: v for k, v in edge.items() if k not in {"source", "target"}})
    return g

# 把昨天的 G 存成 JSON、再載回來
payload = graph_to_json(G)
print(f"序列化後大小:{len(payload)} 字元")
reloaded = json_to_graph(payload)
print(f"重新載入後節點數:{reloaded.number_of_nodes()}")
# 輸出(實際數字會略有不同):
# 序列化後大小:2400 字元
# 重新載入後節點數:8

常見錯誤與踩雷

第一個常見踩雷是「把 GraphRAG 當成向量 RAG 的替代品」。GraphRAG 對結構化資料表現好,但對純敘述性的散文段落,圖上能抽出的實體數量有限,關係密度也不高,硬套 GraphRAG 反而會讓檢索變慢、品質下降。正確的做法是把兩者串起來,讓 GraphRAG 負責整體性問題、向量 RAG 負責細節性問題。

第二個是「實體抽取模型選得太輕」。spaCy 的 `zh_core_web_sm` 只有 20MB 左右,召回率不到 60%;企業文件中常見的合約編號、產品代號、客戶簡稱幾乎都認不出。實務上至少要用 `zh_core_web_trf`(基於 Transformer)或自家微調的 NER 模型,否則圖的品質會被低估。

第三是「圖上雜訊邊太多」。我們在建圖時把共現次數過低的邊過濾掉,但很多人會忘了做這一步,導致圖上看起來密密麻麻、實際上訊號稀薄。建議在圖建成後先用 `nx.density(G)` 看密度,若密度大於 0.3 通常代表邊太多,需要再做門檻過濾。

效能與實務提醒

spaCy 中文 `trf` 模型在 Colab T4 上大約每秒可處理 50 個 token,比 CPU 快 4 倍左右;如果你的文件集動輒數十萬段,建議在 Colab 開 GPU 執行階段以節省時間。networkx 是純 Python 函式庫,圖的規模超過一萬個節點時效能會明顯下降,這時改用 graph-tool 或 igraph 會順很多。

儲存方面,今天示範的圖是記憶體內的 networkx 物件,沒有做持久化。實務上你可以用 `nx.write_gml(G, "graph.gml")` 存成 GML 格式,或改用 SQLite 與 NetworkX 的中介層。如果要走正規圖形資料庫路線,Neo4j 的官方 Python 驅動程式 neo4j-driver 支援批次寫入,數十萬節點的圖在一般伺服器上幾分鐘內可寫入完畢。

最後提醒:GraphRAG 的本地檢索結果與全域檢索結果應該分開呈現給 LLM,不要把兩種結果混在同一段 prompt 裡,否則模型會被兩種不同結構的資訊混淆,反而降低回答品質。微軟的開源實作就把兩條路線做成兩個獨立的函式,建議沿用這個設計。

小結

今天我們從「純向量 RAG 為什麼會卡在整體性問題」這個觀察出發,介紹 GraphRAG 的核心概念:先建圖、再做圖上查詢。實作上用 spaCy 抽實體、用 networkx 建圖、用 greedy modularity 做社群偵測,並用本地檢索與全域檢索兩條路線示範整體性問題的處理方式。整個流程不需要 API key 就能跑完,適合在 Colab T4 上學習與實驗。

結語

GraphRAG 是 RAG 章節的進階主題,但實務上更常見的做法是把它跟向量 RAG 並用、各司其職。明天開始我們會進入貫穿專案「企業知識庫問答系統」:用兩天時間,從一個真實的中文法規文件集開始,把向量檢索、生成、評估串起來,做出一個能上線的最小可行產品。RAG 章節到這裡先告一段落,但 GraphRAG 的概念會在貫穿專案中以「知識圖輔助檢索」的形式再出場一次,敬請期待。

延伸資源

  • Edge, D. 等人,From Local to Global: A Graph RAG Approach to Query-Focused Summarization(arXiv:2404.16130,2024):https://arxiv.org/abs/2404.16130
  • Microsoft GraphRAG 開源函式庫(2024–2025):https://github.com/microsoft/graphrag
  • spaCy 中文模型說明(3.8 世代,2025):https://spacy.io/models/zh
  • networkx 官方教學(3.4 世代,2025):https://networkx.org/documentation/stable/tutorial.html
  • Hugging Face intfloat/multilingual-e5-small 模型卡(CC BY-NC 授權):https://huggingface.co/intfloat/multilingual-e5-small

留言

這個網誌中的熱門文章

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 建構深度學習模型。 開發者與研究人員 :想更深入了...