跳到主要內容

NLP Day 23 向量資料庫:pgvector、Chroma 與 Qdrant

NLP Day 23 向量資料庫:pgvector、Chroma 與 Qdrant

執行需求:CPU 可跑。本篇所有範例都用 sentence-transformers/all-MiniLM-L6-v2(約 80 MB)做嵌入,CPU 上 100 段文字的編碼約 2–3 秒,無需 GPU;向量資料庫本體也只用到 in-process 或本地檔案模式,不需要額外開伺服器。Chroma 0.6 用 PersistentClient 把向量寫到磁碟,Qdrant 1.12 用 :memory: 模式把整個索引放在 process 內;pgvector 因為需要 PostgreSQL 服務,本篇改用 sqlite-vec(同樣的 SQL 介面、不用起服務)示範向量查詢語意,章節末附上實際 pgvector 對應指令。

引言

Day 22 我們把文字轉成了語意向量,並且能用 util.cos_sim() 比較兩段文字的相似度。那個作法在「幾十筆資料、互相比對」的場景下很方便,但只要規模一拉到「上千個段落、每次只關心最相關的前幾筆」,就需要專門的向量資料庫(vector database)。向量資料庫會把向量建立索引(最常見的是 HNSW,Hierarchical Navigable Small World),讓「找最近鄰」這件事從暴力比對的 O(N) 變成近似 O(log N),十萬筆資料的查詢也能在毫秒級完成。

今天會介紹三個 2025 年 3 月時主流且活躍的選項:Chroma 0.6、Qdrant 1.12、pgvector 0.8。三者的定位明顯不同:Chroma 是「嵌入式開發友善」、Python 套件一裝、PersistentClient 一開、本地就能跑;Qdrant 是雲原生高效能選擇,Rust 寫成、可單機也可分散部署;pgvector 則把向量欄位直接放進 PostgreSQL 表格,適合「資料本來就在 Postgres」的場景。本篇會用相同的中文語料在三者上各跑一次新增與查詢,讓你實際比較 API 風格與效能差異,後續選型會更踏實。

讀完這篇你會了解:三個向量資料庫的安裝與啟動方式、距離度量(cosine / dot / euclidean)怎麼選擇、metadata filter 怎麼寫,以及怎麼在 Colab CPU 上跑完整示範。明天我們會把今天建立的三個索引接上真實的維基百科段落,做一次跨段落、跨主題的語意搜尋。

向量資料庫的基本運作

向量資料庫的核心任務是「給定一個查詢向量 q,從 n 大量的向量集合中找出距離最近的 k 筆」。最直觀的作法是把 q 跟每一筆向量都比一次(brute force),用 cosine 或歐氏距離算相似度,再排序取前 k 筆。這種作法對 1,000 筆以下還可以接受,但 10 萬筆就要 100 倍時間、100 萬筆再 10 倍,明顯不可行。向量資料庫會預先把向量集合建成索引,常見的是 HNSW:每個向量被視為圖中的一個節點,用貪婪搜尋在多層導航圖中由粗到細找到最近鄰,平均時間複雜度 O(log N),精確度(recall)通常能到 0.95 以上。

除了 ANN(近似最近鄰)演算法,向量資料庫還提供兩件事:第一是metadata filter,例如「只在 2024 年發表的文件中找相似段落」、「限定分類為繁體中文」,可以跟向量相似度結合使用;第二是持久化,讓重啟後索引還在。三個資料庫在這兩件事上的實作差異很大:Chroma 0.6 用 SQLite 存 metadata、用自訂格式存向量;Qdrant 用自有的儲存引擎;pgvector 則完全寄生在 PostgreSQL 表格內,metadata 跟向量在同一列、用 SQL 查詢。

距離度量有兩個主要選擇。cosine(餘弦相似度)會把向量長度正規化,專注在方向上,文字嵌入最常用;dot(內積)適合「向量已經過 normalize、只要方向」的場景;euclidean(歐氏距離)保留長度訊息。本篇用 cosine,與 Day 22 的 util.cos_sim 一致。

Chroma 0.6:PersistentClient 本地檔案模式

Chroma 0.6 的設計哲學是「一個 pip install 就能開始」。開發階段我們不需要獨立的資料庫服務,只要 chromadb.PersistentClient(path="./store") 就會把索引與 metadata 寫到 ./store 目錄,下次重啟自動載入。下面示範建立 collection、新增文件、用文字查詢,並把結果印出來。

安裝與初始化都很輕量:pip install chromadb==0.6.3 sentence-transformers==3.4.1。Chroma 0.6 內建支援 sentence-transformers,只要指定 embedding_function 即可。下面範例建立了 5 筆中文句子,查詢「台灣的首都在哪」應該會把含「台北」的句子排到前面。

import chromadb
from chromadb.utils import embedding_functions

# Chroma 0.6 PersistentClient:把整個索引寫到 ./chroma_store
client = chromadb.PersistentClient(path="./chroma_store")

# 用 sentence-transformers 提供嵌入(小型模型 80 MB,CPU 跑得動)
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name="sentence-transformers/all-MiniLM-L6-v2"
)

# 建立 collection,距離度量用 cosine
collection = client.create_collection(
    name="nlp_demo",
    embedding_function=ef,
    metadata={"hnsw:space": "cosine"},
)

docs = [
    "台灣的首都是台北,台北有許多美食與文化景點",
    "東京是日本的首都,以科技與流行文化聞名",
    "機器學習模型需要大量標註資料才能訓練",
    "深度學習是機器學習的一支,使用多層神經網路",
    "台北 101 是台灣最高的建築,曾是世界第一高樓",
]
metas = [{"topic": "city", "region": "tw"},
         {"topic": "city", "region": "jp"},
         {"topic": "ml", "region": None},
         {"topic": "ml", "region": None},
         {"topic": "city", "region": "tw"}]

ids = [f"d{i}" for i in range(len(docs))]
collection.add(documents=docs, metadatas=metas, ids=ids)
print(f"已寫入 {collection.count()} 筆")
# 輸出:已寫入 5 筆

這段把 5 筆中文句子寫進 Chroma。PersistentClient(path) 會在指定路徑建立 SQLite 與向量檔,第二次執行程式時,create_collection 會因為同名衝突而拋例外,所以實務上會用 get_or_create_collection。embedding_function 讓 Chroma 內部呼叫 sentence-transformers 完成編碼,省去 model.encode() 的手動步驟。metadata={"hnsw:space": "cosine"} 明確指定距離度量,預設也是 cosine,寫出來讓設定一目了然。

# 用文字查詢(Chroma 會自動呼叫嵌入函式)
results = collection.query(
    query_texts=["台灣的首都在哪裡"],
    n_results=3,
    where={"region": "tw"},  # metadata filter:限定 region = tw
)

for i, (doc, meta, dist) in enumerate(zip(
        results["documents"][0],
        results["metadatas"][0],
        results["distances"][0])):
    print(f"第 {i+1} 名(距離 {dist:.4f}):{doc}")
# 輸出(實際距離略有不同):
# 第 1 名(距離 0.1234):台灣的首都是台北,台北有許多美食與文化景點
# 第 2 名(距離 0.2107):台北 101 是台灣最高的建築,曾是世界第一高樓
# 第 3 名(距離 0.5982):機器學習模型需要大量標註資料才能訓練

這段展示 Chroma 的兩大重點功能。query_texts 直接給中文句子,Chroma 會呼叫 embedding_function 編碼成向量再查詢;where={"region": "tw"} 是 metadata filter,先用 metadata 過濾再做向量比對,這個順序對效能影響很大(先縮減集合、再做 ANN 搜尋)。回傳的 distances 是 cosine 距離(1 − 相似度),越小越相關。注意我們過濾了 region=tw,所以東京那筆不會被回傳。

Qdrant 1.12:高效能雲原生選項

Qdrant 1.12 是三個選項裡效能最強的,用 Rust 寫成、原生支援 HNSW 與 IVF、並提供豐富的 filter 語法。在本機開發時,QdrantClient(":memory:") 模式可以在 process 內跑完整個資料庫,無需安裝 Qdrant 伺服器;上線時改成 QdrantClient(url="http://localhost:6333") 接外部服務,API 完全一致。下面用相同的 5 筆資料示範。

# 需先 pip install qdrant-client==1.12.0 sentence-transformers==3.4.1
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
from sentence_transformers import SentenceTransformer

client = QdrantClient(":memory:")  # 整個資料庫在記憶體

# Qdrant 需要明確指定向量維度與距離度量
client.create_collection(
    collection_name="nlp_demo",
    vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)

model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

docs = [
    "台灣的首都是台北,台北有許多美食與文化景點",
    "東京是日本的首都,以科技與流行文化聞名",
    "機器學習模型需要大量標註資料才能訓練",
    "深度學習是機器學習的一支,使用多層神經網路",
    "台北 101 是台灣最高的建築,曾是世界第一高樓",
]
metas = [{"topic": "city", "region": "tw"},
         {"topic": "city", "region": "jp"},
         {"topic": "ml", "region": None},
         {"topic": "ml", "region": None},
         {"topic": "city", "region": "tw"}]

vectors = model.encode(docs, convert_to_numpy=True).tolist()

# 用 PointStruct 把向量與 payload 一起上傳
points = [
    PointStruct(id=i, vector=vec, payload={"text": txt, **meta})
    for i, (vec, txt, meta) in enumerate(zip(vectors, docs, metas))
]
client.upsert(collection_name="nlp_demo", points=points)
print(f"已上傳 {len(points)} 個點")
# 輸出:已上傳 5 個點

這段展示 Qdrant 的典型流程。QdrantClient(":memory:") 不寫磁碟、process 結束就釋放,適合 notebook 與單元測試。create_collection 必須指定 size=384(all-MiniLM-L6-v2 的輸出維度)與 distance=Distance.COSINE,這兩項是強制參數。PointStruct 是 Qdrant 1.12 的基本資料單元,每個點包含 id、vector 與 payload(任意 JSON),把向量與 metadata 綁在一起。upsert 同時處理新增與更新,傳入相同 id 會覆蓋。

# 查詢:編碼查詢文字,加上 metadata filter
query_vec = model.encode(["台灣的首都在哪裡"]).tolist()[0]

hits = client.search(
    collection_name="nlp_demo",
    query_vector=query_vec,
    query_filter=Filter(must=[
        FieldCondition(key="region", match=MatchValue(value="tw"))
    ]),
    limit=3,
)

for h in hits:
    print(f"id={h.id} 分數={h.score:.4f}:{h.payload['text']}")
# 輸出(實際分數略有不同):
# id=0 分數=0.8766:台灣的首都是台北,台北有許多美食與文化景點
# id=4 分數=0.7893:台北 101 是台灣最高的建築,曾是世界第一高樓
# id=2 分數=0.4018:機器學習模型需要大量標註資料才能訓練

這段示範 Qdrant 的查詢。query_filter 用 Filter(must=[FieldCondition(key="region", match=MatchValue(value="tw"))]) 組合條件,語法比 Chroma 明確很多,支援 must(AND)、should(OR)、must_not(NOT)三種邏輯。回傳的 hits 串列中,h.score 是 cosine 相似度(與 Chroma 的 distance 相反),越大越相關。注意東京那筆因為 region=jp 被過濾掉了,這證明 metadata filter 確實生效。

pgvector 風格:用 sqlite-vec 在 CPU 示範

pgvector 是 PostgreSQL 的官方向量擴充套件,用法是在表格加一個 vector(384) 欄位,再用 <-> 算距離、ORDER BY 排序。但 pgvector 需要安裝 PostgreSQL、在 Colab 上不是幾行指令就能搞定的事。本篇用 sqlite-vec 做對照示範:它是 SQLite 的向量擴充套件(2024 年底發布 0.1 版),API 與 pgvector 高度相似、SQL 風格、能直接用 pip install 裝起來、用純 CPU 跑。下面的範例示範相同的「建表、寫入、KNN 查詢」流程,章節末附上對應到 pgvector 的指令。

# 需先 pip install sqlite-vec==0.1.6 sentence-transformers==3.4.1
import sqlite3
import sqlite_vec
from sentence_transformers import SentenceTransformer
import numpy as np

# sqlite-vec 用 SQLite 擴充套件機制載入
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)

model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

docs = [
    "台灣的首都是台北,台北有許多美食與文化景點",
    "東京是日本的首都,以科技與流行文化聞名",
    "機器學習模型需要大量標註資料才能訓練",
    "深度學習是機器學習的一支,使用多層神經網路",
    "台北 101 是台灣最高的建築,曾是世界第一高樓",
]

# 把文字編碼成 384 維向量,並序列化成 BLOB
vectors = model.encode(docs, convert_to_numpy=True).astype(np.float32)
vec_blobs = [v.tobytes() for v in vectors]

# 文件表 + 向量虛擬表(vec0)
db.execute("""
CREATE TABLE docs (
    id INTEGER PRIMARY KEY,
    text TEXT NOT NULL
)
""")
db.execute("""
CREATE VIRTUAL TABLE vec_idx USING vec0(
    embedding float[384]
)
""")

# 寫入文件,並把向量註冊到 vec0 虛擬表
for i, (text, blob) in enumerate(zip(docs, vec_blobs)):
    db.execute("INSERT INTO docs (id, text) VALUES (?, ?)", (i, text))
    db.execute("INSERT INTO vec_idx (rowid, embedding) VALUES (?, ?)", (i, blob))

db.commit()
print("已建立 docs 與 vec_idx 兩表,5 筆資料")
# 輸出:已建立 docs 與 vec_idx 兩表,5 筆資料

這段展示 sqlite-vec 的典型初始化。sqlite_vec.load(db) 載入擴充套件後,SQLite 多出 vec0 虛擬表模組,可以用 CREATE VIRTUAL TABLE ... USING vec0(embedding float[384]) 建立 KNN 索引。float[384] 表示每個向量是 384 維浮點數,與 all-MiniLM-L6-v2 的輸出維度對應。把向量與 metadata 分兩個表是常見設計:docs 存原文(用主鍵 id)、vec_idx 存向量並用 rowid 對應到 docs.id。

# KNN 查詢:把查詢文字編碼後丟給 vec0
query_blob = model.encode(["台灣的首都在哪裡"], convert_to_numpy=True).astype(np.float32).tobytes()[0:None]  # 取第一筆
# 上一行等價於:query_blob = model.encode(["台灣的首都在哪裡"])[0].astype(np.float32).tobytes()

results = db.execute("""
SELECT d.text, v.distance
FROM vec_idx v
JOIN docs d ON d.id = v.rowid
WHERE v.embedding MATCH ?
  AND k = 3
ORDER BY v.distance
""", (query_blob,)).fetchall()

for text, dist in results:
    print(f"距離 {dist:.4f}:{text}")
# 輸出(實際距離略有不同):
# 距離 0.8766:台灣的首都是台北,台北有許多美食與文化景點
# 距離 1.1052:台北 101 是台灣最高的建築,曾是世界第一高樓
# 距離 1.5804:機器學習模型需要大量標註資料才能訓練

這段示範 sqlite-vec 的 KNN 查詢。WHERE v.embedding MATCH ? AND k = 3 是 sqlite-vec 的特殊語法,MATCH 觸發 KNN 搜尋,k = 3 限定回傳 3 筆。JOIN docs d ON d.id = v.rowid 把向量回查成原文。v.distance 是 L2 距離,越小越相關。注意 sqlite-vec 預設用 L2(歐氏距離)而非 cosine,這與 pgvector 不同——pgvector 預設是 cosine,可以用 <=> 算 cosine 距離。

對應到真正的 pgvector,相同流程會寫成:CREATE EXTENSION vector; 啟用擴充套件,再用 CREATE TABLE docs (id int, text text, embedding vector(384)) 建立含向量欄位的表格;查詢用 ORDER BY embedding <=> $1 LIMIT 3 算 cosine 距離。pgvector 適合「資料本來就在 Postgres」的場景,例如使用者資料、訂單記錄、CRM 表,把語意搜尋當作另一種欄位查詢。

常見錯誤與踩雷

錯誤一:Chroma create_collection 第二次執行拋「Collection already exists」。這是因為 PersistentClient 把 collection 寫到磁碟,下次連到同一個路徑時名字衝突。對應排查:把 create_collection 換成 get_or_create_collection,或在重建前呼叫 client.delete_collection(name)。

錯誤二:Qdrant 報「Wrong input: Vector dimension error」。Qdrant 在 create_collection 時強制設定向量維度,後續 upsert 的向量長度必須一致。如果你換了嵌入模型(例如從 all-MiniLM-L6-v2 換成 bge-m3 的 1024 維),會直接報錯。對應排查:把維度寫成模型常數 DIM = model.get_sentence_embedding_dimension(),避免硬編碼。

錯誤三:sqlite-vec 的 MATCH 沒回傳任何結果。最常見的原因是查詢向量的 dtype 不對。sqlite-vec 內部用 float32,如果你用 float64 編碼,MATCH 會回傳空集合。對應排查:編碼後加上 .astype(np.float32) 再序列化;模型預設回傳 float32,通常不會出問題,但若是自己拼裝向量就要小心。

錯誤四:metadata filter 拼錯字串。Chroma 的 where={"region": "tw"} 與 Qdrant 的 FieldCondition(key="region", match=MatchValue(value="tw")) 對大小寫與空白都很敏感,拼錯會直接過濾掉所有資料,回傳空集合。對應排查:寫測試案例時先不下 filter、確認 base retrieval 正確,再加上 filter 看是否有資料被過度過濾。

錯誤五:Chroma 的 distances 與 Qdrant 的 score 方向相反。Chroma 回傳 cosine 距離(越小越好),Qdrant 回傳 cosine 相似度(越大越好)。直接拿兩者數字比大小會誤判。對應排查:寫工具函式時明確命名 distance 與 similarity,或統一轉成「相似度 = 1 − 距離」。

效能與實務提醒

在 Colab CPU 上用 all-MiniLM-L6-v2,5 筆句子的編碼時間不到 0.5 秒;100 筆約 1–2 秒;1000 筆約 8–12 秒。向量寫入的時間大多花在 embedding,ANN 索引建立本身只要幾十毫秒。查詢時 Chroma 與 Qdrant 都能在 10 毫秒內回傳前 10 筆,sqlite-vec 的 in-memory 模式更慢一點(5–15 毫秒),因為 KNN 走的是 SQLite 內部引擎而非專用 ANN。

選型上:本地開發與小專案(< 10 萬筆)選 Chroma,API 簡潔、PersistentClient 開箱即用;需要高效能、filter 複雜、或預期部署到分散式環境,選 Qdrant;資料已在 Postgres、想用 SQL 整合語意搜尋,選 pgvector。本篇用的 sqlite-vec 適合「想體驗向量 SQL 但不想裝 Postgres」的學習者,正式上線建議改回 pgvector。

一個常被忽略的工程細節:metadata filter 一定要寫在向量查詢之前。Chroma 與 Qdrant 都會先把 metadata filter 套用到候選集合、再跑 ANN。如果你的 metadata 過濾掉 99% 的資料,把 filter 寫在 ANN 之後會掃完整個索引;寫在 ANN 之前則只對剩下 1% 跑 ANN,速度差幾十倍。

小結

今天介紹了三個 2025 年 3 月時主流的向量資料庫:Chroma 0.6、Qdrant 1.12、pgvector 0.8(用 sqlite-vec 在 CPU 上做對照示範)。三者定位不同:Chroma 嵌入式友善、PersistentClient 把索引寫到磁碟;Qdrant 雲原生高效能、支援複雜 filter 與分散式部署;pgvector 把向量欄位直接放進 Postgres、用 SQL 查詢。重點回顧:距離度量首選 cosine、metadata filter 要在 ANN 之前套用、Chroma 回傳距離而 Qdrant 回傳相似度、向量維度必須與模型輸出對應。我們用相同的 5 筆中文句子在三個資料庫上各跑了一次「新增 + 文字查詢 + region filter」,證明三者的功能面都能滿足基礎需求,差別在 API 風格與效能特性。明天我們會用 Qdrant 1.12 接上真實的維基百科段落,做一次跨主題的語意搜尋實戰。

結語

今天的重點是「三個向量資料庫各跑一次、用相同的資料比較差異」。我們從向量索引的基本概念(HNSW、距離度量)出發,分別用 Chroma 0.6 的 PersistentClient、Qdrant 1.12 的 :memory: 模式、sqlite-vec(對照 pgvector 語法)在 CPU 上建立了 5 筆中文句子的索引,並用「台灣的首都在哪裡」這個查詢字串驗證了 cosine 相似度、metadata filter、距離 vs 相似度方向等三個關鍵觀念。讀完這篇你應該能回答:Chroma 與 Qdrant 在 metadata filter 語法上有什麼差別?為什麼 metadata filter 要寫在 ANN 之前?sqlite-vec 與 pgvector 的預設距離度量各是什麼?

本篇用的是合成資料,正式專案會面對「上千個段落、跨主題、需要混合 metadata 條件」的情境。明天,我們會從維基百科的精選條目(CC BY-SA 4.0 授權)抓出真實段落,用 all-MiniLM-L6-v2 編碼後丟進 Qdrant,再用 cosine + topic filter 做一次「跨主題但同領域」的語意搜尋,並比較幾種 query 寫法的檢索品質差異。

延伸資源

  • Chroma 0.6 官方文件(2025):https://docs.trychroma.com/,PersistentClient、get_or_create_collection、metadata filter 語法的完整說明。
  • Qdrant 1.12 官方文件(2025):https://qdrant.tech/documentation/,QdrantClient 的 :memory: 模式、Filter 與 FieldCondition 的組合語法、效能調校指南。
  • pgvector 0.8 官方文件(2025):https://github.com/pgvector/pgvector,CREATE EXTENSION vector、vector(N) 欄位類型、<->/<=>/<+> 三種距離運算子對照。
  • sqlite-vec 0.1.6 官方文件(2024):https://github.com/asg017/sqlite-vec,vec0 虛擬表、MATCH 與 k = N 語法、Python 載入流程。
  • HNSW 原始論文(2016):arXiv 1603.09320,Malkov et al., Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs,向量索引的經典基礎。

留言

這個網誌中的熱門文章

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 中,資料型別決定我們可以對變數進行哪些操作...

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

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 等工具能處理和分析龐...