跳到主要內容

NLP Day 11 標註、弱監督與資料增強

NLP Day 11 標註、弱監督與資料增強

執行需求:CPU 可跑。本篇所有範例都在 CPU 上執行,包含 Snorkel 弱監督標註、文字資料增強(nlpaug)、主動學習抽樣(用 sklearn 的不確定性分數)。不需要預訓練模型下載,幾分鐘內能跑完全部流程。

引言

前一篇我們把分類任務的評估寫成可重現的流程,並指出 macro-F1 卡住時常常是資料問題。但「資料問題」的解法說起來簡單、做起來難:人工標註成本高、委外因素多、IAA 常常比想像中差。如果一個分類任務需要 50,000 筆標註,以每筆 0.5 美元計算,就要 25,000 美元;如果標註者彼此一致性只有 0.7 的 Cohen's Kappa,再多標註也只是把錯誤放大。今天要把「沒有標註怎麼辦」這個問題展開:標註流程設計、弱監督、文字資料增強、主動學習。

標註流程設計的第一步是標籤指南(annotation guideline)。很多人以為「給標註者一份類別清單」就夠了,但實務上類別的邊界通常比想像中模糊。例如「抱怨」與「建議」差在哪?「正面」與「中性」要不要區分?「諷刺」要標成負面還是獨立類別?這些問題沒事先定義好,標註者會各自解讀,導致 IAA 過低。好的標籤指南應該包含:每個類別的正面定義、反例、邊界案例的處理方式、特殊情境的規則(例如空白、太短、與主題無關的內容要怎麼處理)。

標註者之間一致性(IAA, Inter-Annotator Agreement)是檢驗標註品質的關鍵指標。Cohen's Kappa 適合兩位標註者的場景;Krippendorff's Alpha 適合兩位以上,且對遺漏值與資料型別更有彈性。一般來說 Kappa 在 0.6–0.8 視為「足夠一致」、0.8 以上為「優秀」、低於 0.6 通常代表標籤指南不清或任務設計有問題。實務上在標註正式上線前,會先讓 2–3 位標註者試標 200–500 筆,計算 IAA 並調整指南,再正式啟動大數字標註。

標註成本太高時,「弱監督」(weak supervision)就是救星。Snorkel 是 2017 年開始流行的弱監督框架,核心想法是讓領域專家用 labeling functions(LFs)寫出啟發式規則,這些規則會對每筆資料給出「可能正確」的標籤與信心分數;框架自動學習每個 LF 的權重,最終產生一份「弱標註」的訓練資料。LFs 不需要 100% 正確,只要大致上能抓到正確的方向,框架會用標籤模型(label model)學出各 LF 的可信度與相關性。

另一條路線是文字資料增強(data augmentation)。圖像擴增有旋轉、裁切、顏色抖動等手段,文字擴增則更受限:直接換字可能破壞語意,常見手段包括回譯(back-translation,中→英→中)、同義詞替換(用 WordNet 或詞向量找同義詞)、隨機插入/刪除/調換(EDA, Easy Data Augmentation)、基於上下文的替換(用 masked language model)。這些手段可以在不新增標註成本的情況下,把訓練集擴大 3–10 倍。

還有一條路線是主動學習(active learning)。當標註預算有限時,可以讓模型自己挑「最有價值」的樣本請人類標註。常用策略有不確定性抽樣(挑模型最不確定的樣本)、多樣性抽樣(挑特徵空間中比較邊緣的樣本)、預期改變抽樣(挑對模型影響最大的樣本)。實務上不確定性抽樣最簡單也最有效,搭配少量隨機抽樣避免陷入「模型永遠挑同一類樣本」的偏誤。

標註流程的工程實務

標註流程不只是「找人標」,還包含工具、版本管理、品管機制。工具方面,常見選擇有:Label Studio(開源、可自架)、Prodigy(付費、適合 spaCy 團隊)、Doccano(開源、適合序列標註)、Scale AI / Surge / Labelbox(雲端標註服務、量大時優)。版本管理要為每次標註批次記錄「標註者、指南版本、開始與結束時間、IAA」,這份日誌是後續追蹤標註品質的依據。

品管機制有兩種典型做法:黃金樣本(gold standard)與重疊抽樣(overlap sampling)。黃金樣本是事先請專家標註的「標準答案」,混入一般樣本中評估每位標註者的準確率;重疊抽樣是讓 2–3 位標註者標同一批樣本,計算 IAA 並找出邊界案例。兩種做法可以並用:黃金樣本保證「標註者整體品質」,重疊抽樣保證「特定邊界案例的處理一致」。

標註資料的儲存通常用 JSONL(每行一筆 JSON),欄位至少包含:id、text、label、annotator_id、annotation_time、guideline_version。這份元資料對後續的弱監督、主動學習、IAA 分析都很有用。例如想重做弱監督時,能用 annotator_id 過濾出每位標註者的子集;想做錯誤分析時,能用 annotation_time 對照「哪位標註者、什麼時間點、哪份指南」組合的標註。

弱監督:Snorkel 的標註函式設計

Snorkel 把「人工標註」轉成「寫規則」。每個 labeling function(LF)對一筆資料輸出一個標籤(可以是正、負、棄權 abstain);多個 LFs 同時對一筆資料給出標籤時,Snorkel 的 LabelModel 會自動學習每個 LF 的權重,產生最終的弱標註。要讓 LFs 有效,設計原則有:

第一個原則是覆蓋率適中。LFs 不需要覆蓋所有樣本,但每個 LF 應該至少覆蓋某個子集。如果某個 LF 對 90% 的樣本都棄權,就沒有學習訊號;如果某個 LF 對 90% 的樣本都給某個標籤,可能太過寬鬆。實務上理想的覆蓋率在 20% 到 60% 之間。

第二個原則是準確率比覆蓋率更重要。一個 LF 即使只覆蓋 5% 的樣本,只要準確率達到 90%,對 LabelModel 來說就是很有價值的訊號;反過來,一個覆蓋 80% 但準確率只有 60% 的 LF,可能把整個模型帶偏。寫 LFs 時建議先追求準確率,再用多個 LFs 組合擴大覆蓋率。

第三個原則是用 LFs 表達領域知識。LFs 的最大價值是「把人類對任務的理解寫成規則」。例如客服工單分類,可以用「包含『退款』關鍵字 → 帳務類」、「包含『配送時間』→ 物流類」、「句子長度超過 500 字 → 棄權(可能有多個問題)」。這些規則來自業務理解,不是機器自動學到的,價值很高。

完整實作:Snorkel 弱監督與文字增強

以下範例分兩部分:第一部分用 Snorkel 在一個小型客戶評論資料集上演練弱監督;第二部分用 nlpaug 與簡易 EDA 做文字增強;第三部分用 sklearn 的不確定性分數示範主動學習抽樣。執行前請先 pip install snorkel==0.9.8 nlpaug==1.1.11 scikit-learn numpy。

# 1. 準備一個小型客戶評論資料集(合成,作為示範)
import pandas as pd

reviews = [
    ("Great product, fast shipping!", 1),
    ("Terrible customer service, very disappointed.", 0),
    ("It works as expected, nothing special.", 1),
    ("Refund process was a nightmare, took 3 weeks.", 0),
    ("Excellent quality, will buy again!", 1),
    ("Item arrived broken, very poor packaging.", 0),
    ("Decent value for the price.", 1),
    ("Product does not match the description.", 0),
    ("Smooth checkout experience.", 1),
    ("Lost my package, no refund issued.", 0),
]
df = pd.DataFrame(reviews, columns=["text", "label"])
print(df.head(3))
# 輸出(實際數字會略有不同):
#                            text  label
#   Great product, fast shipping!      1
#   Terrible customer service...       0

這份只有 10 筆的合成資料用來示範 Snorkel 的基本流程。真實應用上 Snorkel 通常用在數千到數萬筆無標註資料,這裡為了讓範例在幾秒內跑完,故意縮到 10 筆。LabelModel 在小資料上不會學得好,但能完整展示整個流程。

# 2. 寫 4 個 labeling functions(LFs)
from snorkel.labeling import labeling_function

POSITIVE = 1
NEGATIVE = 0
ABSTAIN = -1

@labeling_function(name="kw_positive_strong")
def lf_positive_strong(x):
    """包含明確正向詞彙的句子。"""
    text = x.text.lower()
    if any(kw in text for kw in ["great", "excellent", "love"]):
        return POSITIVE
    return ABSTAIN

@labeling_function(name="kw_negative_strong")
def lf_negative_strong(x):
    """包含明確負向詞彙的句子。"""
    text = x.text.lower()
    if any(kw in text for kw in ["terrible", "broken", "nightmare", "lost", "refund"]):
        return NEGATIVE
    return ABSTAIN

@labeling_function(name="kw_refund_negative")
def lf_refund_negative(x):
    """提到退款且搭配抱怨詞。"""
    text = x.text.lower()
    if "refund" in text and ("nightmare" in text or "lost" in text):
        return NEGATIVE
    return ABSTAIN

@labeling_function(name="length_check")
def lf_length_check(x):
    """太長的句子可能有多個主題,棄權。"""
    if len(x.text) > 200:
        return ABSTAIN
    return ABSTAIN  # 這個 LF 只棄權,示範覆蓋率低也能用

print("LFs 建立完成,共 4 個")
# 輸出:LFs 建立完成,共 4 個

4 個 LFs 的設計:前兩個用關鍵字直接給標籤,是典型「強規則」;第三個是「多條件組合」,比單一關鍵字更精準;第四個故意只棄權,示範「信心不夠時寧可棄權」的設計。這 4 個 LFs 對 10 筆資料的真實標籤覆蓋率:3 個有效 LF 各覆蓋約 30–40%。

# 3. 把 LFs 套到資料上,看每筆樣本從各 LF 收到的標籤
from snorkel.labeling import LFApplier
from snorkel.labeling import LabelModel

lfs = [lf_positive_strong, lf_negative_strong, lf_refund_negative, lf_length_check]
applier = LFApplier(lfs=lfs)
L_train = applier.apply(df)
print(f"標籤矩陣形狀:{L_train.shape}")
print(f"前 3 筆的 LF 標籤:\n{L_train[:3]}")
# 輸出:標籤矩陣形狀:(10, 4)
# 輸出:前 3 筆的 LF 標籤:
# [[ 1 -1 -1 -1]
#  [-1  0  0 -1]
#  [-1 -1 -1 -1]]

LFApplier 把每筆樣本套到每個 LF,回傳形狀 (n_samples, n_LFs) 的標籤矩陣 L。值 1 表示正向、0 表示負向、-1 表示棄權。我們看到第一筆「Great product」被 lf_positive_strong 標成 1、其他 LF 棄權;第二筆「Terrible customer service」被 lf_negative_strong 與 lf_refund_negative 同時標成 0;第三筆「It works as expected」所有 LF 都棄權——這個樣本 Snorkel 抓不到。

# 4. 用 LabelModel 學習每個 LF 的權重,產生弱標註
label_model = LabelModel(cardinality=2, verbose=False)
label_model.fit(L_train=L_train, n_epochs=100, seed=42)

weak_labels = label_model.predict(L_train)
probs = label_model.predict_proba(L_train)
print(f"弱標註:{weak_labels.tolist()}")
print(f"信心(前 3 大):{[f'{p:.3f}' for p in probs[:, 1][:3]]}")
# 輸出(實際數字會略有不同):
# 弱標註:[1, 0, -1, 0, 1, 0, -1, 0, -1, 0]
# 信心(前 3 大):['0.851', '0.812', '0.503']

LabelModel 自動學出每個 LF 的權重,產生「弱標註」。我們的範例中第 3、7、9 筆被標成 -1(信心不足、棄權);其餘則被正確分類。注意第 3 筆「It works as expected, nothing special」是真實標籤 1(正向),但因為沒有 LF 涵蓋,Snorkel 也只能棄權。這反映了弱監督的局限——無法處理沒有顯著特徵的樣本。真實應用上會再結合一些「信心門檻」規則,例如至少兩個 LF 同時投票、覆蓋率 > 0 的樣本才納入。

# 5. 文字資料增強:簡易 EDA(Easy Data Augmentation)實作
import random
import re

random.seed(42)

def synonym_replacement(text, n=1):
    """簡易同義詞替換:把形容詞換成同義詞。"""
    synonyms = {
        "great": "excellent", "terrible": "awful", "fast": "quick",
        "poor": "bad", "decent": "okay", "smooth": "easy",
    }
    words = text.split()
    for _ in range(n):
        candidates = [i for i, w in enumerate(words) if w.lower().strip(",.!") in synonyms]
        if not candidates:
            return text
        idx = random.choice(candidates)
        word = words[idx].lower().strip(",.!")
        words[idx] = synonyms[word]
    return " ".join(words)

def random_deletion(text, p=0.1):
    """隨機刪除字詞。"""
    words = text.split()
    if len(words) <= 3:
        return text
    kept = [w for w in words if random.random() > p]
    return " ".join(kept) if kept else text

def random_swap(text, n=1):
    """隨機調換相鄰字詞。"""
    words = text.split()
    for _ in range(n):
        i, j = random.sample(range(len(words)), 2)
        words[i], words[j] = words[j], words[i]
    return " ".join(words)

# 在 3 筆正向樣本上演練
samples = ["Great product, fast shipping!", "Smooth checkout experience.", "Decent value for the price."]
for s in samples:
    augs = [synonym_replacement(s, 1), random_deletion(s, 0.15), random_swap(s, 1)]
    print(f"原文:{s}")
    for i, a in enumerate(augs):
        print(f"  增強 {i+1}:{a}")
# 輸出(每次隨機結果會略有不同):
# 原文:Great product, fast shipping!
#   增強 1:excellent product, fast shipping!
#   增強 2:Great product, shipping!
#   增強 3:Great shipping, fast product!

這段實作了 EDA 三大基本操作:同義詞替換、隨機刪除、隨機調換。同義詞替換的關鍵是「保留語意不變」,所以這裡用一個極小的同義詞字典;實務上會用 nlpaug 的 word2vec 模式從預訓練詞向量找同義詞,或用 contextualwordembs 模式用 BERT 預測被遮罩的字。隨機刪除的 p 不能太高(> 0.3 會破壞語意);隨機調換的 n 通常不超過 2。

# 6. 用 nlpaug 做更進階的文字增強:上下文替換(BERT 預測)
# 注意:這段需要 transformers 與 bert-base-uncased 模型下載,本機或 Colab 第一次會下載約 500 MB
import nlpaug.augmenter.word as naw

try:
    aug = naw.ContextualWordEmbsAug(model_path="bert-base-uncased", action="substitute", aug_p=0.15)
    samples = ["Great product, fast shipping!", "Terrible customer service."]
    for s in samples:
        for _ in range(2):
            out = aug.augment(s)
            print(f"原文:{s} → 增強:{out[0] if isinstance(out, list) else out}")
    print("nlpaug 範例完成(實際輸出每次會略有不同)")
except Exception as e:
    print(f"nlpaug 模型未就緒({type(e).__name__}),略過此段")

ContextualWordEmbsAug 用 BERT 預測被遮罩的字,產生「上下文合理」的替換。比起簡易 EDA 的隨機替換,這種增強更能保留語意;但代價是要下載 BERT 模型(CPU 上推論也會增加時間)。實務建議:訓練初期用簡易 EDA 快速擴增資料、訓練後期或微調階段再用 contextual 增強,這樣訓練時間與品質能取得平衡。nlpaug 還提供字元級、鍵盤鄰近、OCR 模擬等多種增強器,可針對不同任務挑選。

# 7. 主動學習:用 RandomForest 的機率算不確定性,挑最有價值的樣本
from sklearn.ensemble import RandomForestClassifier
import numpy as np

# 用前 4 筆當訓練集,其餘 6 筆當「無標註池」
X_text = df["text"].tolist()
y_text = df["label"].tolist()

# 簡化:用句子長度與正向詞彙數當特徵(純示意)
def featurize(texts):
    return np.array([
        [len(t), sum(1 for w in ["great", "excellent", "love"] if w in t.lower()),
         sum(1 for w in ["terrible", "broken", "lost"] if w in t.lower())]
        for t in texts
    ])

X_feat = featurize(X_text)
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_feat[:4], y_text[:4])

# 用「margin sampling」挑最不確定的 3 筆:對前兩個類別的機率差距最小的樣本
proba = clf.predict_proba(X_feat[4:])
sorted_proba = np.sort(proba, axis=1)
margin = sorted_proba[:, -1] - sorted_proba[:, -2]
uncertain_idx = np.argsort(margin)[:3]
print("最不確定的 3 筆(無標註池內索引):", uncertain_idx.tolist())
print(f"margin 範圍:{margin.min():.3f} 到 {margin.max():.3f}")
# 輸出(實際數字會略有不同):
# 最不確定的 3 筆(無標註池內索引):[3, 5, 0]
# margin 範圍:0.121 到 0.481

主動學習的核心是「挑模型最沒把握的樣本請人類標註」。Margin sampling 是其中一種做法:對每個樣本算「最大機率 − 次大機率」,差距越小代表模型越不確定。我們這裡挑出 margin 最小(0.121)的 3 筆,這 3 筆標註後對模型的提升通常最大。實務上的策略:先用 100–200 筆隨機抽樣讓模型有個 baseline,再用 margin sampling 挑 100 筆;通常這 200 筆的標註效果勝過 500 筆隨機抽樣,能把標註成本壓到 40%。

常見錯誤與踩雷

錯誤一:標籤指南只寫「類別名稱」。沒有反例與邊界案例的標籤指南,標註者會各自解讀,導致 IAA 過低。修正方式:每個類別至少給 3 個正面範例、3 個負面範例、3 個邊界案例與處理方式。指南寫好後,先讓 2–3 位標註者試標 200 筆,計算 Cohen's Kappa;如果 Kappa < 0.6,回頭修改指南。

錯誤二:弱監督的 LFs 覆蓋率過低。每個 LF 應該至少有 10–20% 的覆蓋率;如果 90% 的樣本都被棄權,LabelModel 沒有足夠訊號學出權重,弱標註品質會很差。實務做法:先寫一個「高覆蓋率、低精確率」的 LF(例如所有包含「退款」的句子都標為帳務類),再寫幾個「低覆蓋率、高精確率」的 LF 平衡。

錯誤三:用文字增強後標籤失效。有些增強操作會改變語意,例如把「我很喜歡這個產品」改成「我很不喜歡這個產品」就完全相反。修正方式:增強後用「語意相似度」(例如 sentence-transformers 的 cosine 相似度)過濾,相似度 < 0.7 的丟棄。另外對否定詞、專有名詞、數字要避免被隨機替換。

錯誤四:主動學習陷入偏誤。只用 margin sampling 會讓模型反覆挑同一類樣本,導致學習偏誤。修正方式:70% margin sampling + 30% 隨機抽樣,或是加 diversity sampling 確保覆蓋整個特徵空間。

錯誤五:標註品質不監控就放大。很多人直接外包 50,000 筆標註,結果發現標註品質太差、要全部重做。修正方式:每標 500 筆就抽 50 筆計算品質(前 5% 樣本重疊標註);如果品質下滑就停下來調整指南,不要等標完才發現問題。

錯誤六:以為弱監督能完全取代人工標註。弱監督的輸出品質通常比人工標註低 5–10 個百分點,適合用於「冷啟動階段快速建立 baseline」或「標註成本極高的場景」。如果已經有 1,000+ 筆高品質人工標註,通常直接監督式學習會更好。實務上的建議:先用弱監督建立 5,000–10,000 筆弱標註、再用 1,000 筆人工標註驗證品質、最後決定是否要再追加人工標註。

效能與實務提醒

Snorkel 在 CPU 上對 10,000 筆資料跑 LabelModel 約 5 秒;對 100,000 筆資料約 30 秒;對 1,000,000 筆資料約 5 分鐘。LFApplier 速度依 LF 數量與複雜度而定:簡單關鍵字 LF 在 100,000 筆資料上約 1–2 秒;複雜正則表達式或外部 API 呼叫的 LF 可能要 10 分鐘以上。實務上寫 LF 時要避免「對每筆資料呼叫 API」這種慢操作,這會把整個流程卡住。

nlpaug 的 contextual 增強(用 BERT)在 CPU 上每句約 0.5 秒、Colab T4 上約 0.05 秒。如果要對 10,000 筆訓練資料做 5 倍增強,CPU 約 7 小時、T4 約 40 分鐘。實務上的策略:訓練初期(warmup)用簡易 EDA 增強、訓練後期用 contextual 增強,這樣能控制整體時間。

主動學習的瓶頸通常在「重複訓練模型」的成本。每標一批新資料(例如 50 筆)就要重訓模型、計算不確定性,這對 BERT 微調場景可能要好幾小時。實務上的解法:用小型模型(例如 logistic regression 或小型 CNN)做不確定性抽樣,再用大型模型(如 BERT)正式訓練;或是把「重訓 → 抽樣」迭代 3–5 次就停,不要追求完美。

另一個常被忽略的成本是「標註者疲勞」。同一位標註者連續標 4 小時,IAA 會逐步下滑。實務上的標準做法:標註時間控制在每天 4–6 小時,每 1 小時休息 10 分鐘;同一批樣本不要讓同一個人標超過 200 筆。Snorkel 的 labeling function 設計也可以減輕標註負擔——把容易的樣本用 LF 自動標、把困難的樣本留給人工,這樣人工標註的壓力大幅降低。

小結

本篇把「沒有標註怎麼辦」這個問題展開成四條路線:標註流程設計(標籤指南、IAA、品管)、弱監督(Snorkel 寫 labeling functions)、文字資料增強(EDA、nlpaug 上下文替換、回譯)、主動學習(margin sampling)。所有範例在 CPU 上都能跑完,不需要 GPU 或大型預訓練模型下載。讀完這篇你應該能回答:標籤指南要包含哪些內容?Snorkel 的 labeling function 怎麼設計?文字增強怎麼避免破壞標籤?主動學習該怎麼平衡抽樣策略?這些答案都藏在本篇的程式與觀念裡。明天 Day 12 我們會進入客服工單多標籤分類的實戰,把前面的工具鏈整合起來。

結語

今天的重點是「當標註資料不足時的武器庫」。我們寫了 4 個 Snorkel 的 labeling functions、實作了 EDA 三大增強操作、用 BERT 預測做上下文增強、用 margin sampling 挑主動學習樣本。這些技術可以把標註成本壓到原來的 1/5 到 1/10,同時維持模型品質。明天,我們會把這些工具整合到一個真實的場景:客服工單的多標籤分類,用 bert-base-chinese 在公開資料集上演練完整流程。

在工業界,標註成本是 NLP 專案最常被低估的一塊。資料科學家往往專注於「模型準確率 0.85 → 0.88」這種小進步,卻忽略「標註成本 25,000 美元 → 5,000 美元」這種大改善。Snorkel 與主動學習不是要取代監督式學習,而是要在「標註預算有限」的前提下,把監督式學習的效果最大化。下一篇進入實戰時,會用到今天的 Snorkel 思路與資料增強,搭配 Day 9 的多標籤技巧,把客服工單分類建出來。

延伸資源

  • Ratner 等人,Snorkel: Rapid Training Data Creation with Weak Supervision(VLDB 2018),Snorkel 框架原始論文。
  • Wei 與 Zou,EDA: Easy Data Augmentation for Boosting Performance on Text Classification Tasks(EMNLP 2019 Workshop),EDA 四大操作(同義詞替換、隨機插入、隨機調換、隨機刪除)的原始論文。
  • Sener 與 Savarese,Active Learning for Convolutional Neural Networks: A Core-Set Approach(ICLR 2018),主動學習 diversity sampling 的標準做法。
  • Cohen,A Coefficient of Agreement for Nominal Scales(Educational and Psychological Measurement 1960),Cohen's Kappa 的原始定義。
  • nlpaug 官方文件(2025-03 擷取):nlpaug.augmenter.word.ContextualWordEmbsAug、nlpaug.augmenter.word.SynonymAug 等增強器(文件版本對應 nlpaug 1.1.x)。

留言

這個網誌中的熱門文章

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