Files
pop-fem-audit/docs/methodology.md
T
2026-08-17 22:38:41 +08:00

239 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 方法細節
(全文方法節底稿。演算法在執行前寫定;任何修訂記入
`decision-log.md`。定義檔全文見 `prompts/`,執行紀錄見
`runs/`。)
## 自然編碼管線總覽
四個步驟:步驟 1 自由標註(兩次執行進池)→ 步驟 2 詞彙表
建構(詞向量分群,確定性)→ 步驟 3 全量編碼(三次執行+
多數決)→ 步驟 4 語意編碼群(三次執行+多數決)。歌詞只
出現在步驟 1 與步驟 3;步驟 2 與步驟 4 完全不接觸歌詞,
步驟 2 亦不呼叫 LLM。設計原則見 `research-plan.md`;本檔
記載可重現的演算法細節。
編號的所指為**研究程序的工序**,不是定義檔:步驟 1、
步驟 3 與步驟 4 有定義檔(`prompts/`),步驟 2 沒有——
它是單一確定性計算,由 `cluster-keywords` 一個子命令
完成。有無定義檔的區別即「該步是否為 LLM 判斷」,由
`prompts/` 是否存在同號檔案直接可見。
## 步驟 2 詞彙表建構——詞向量分群
詞彙表由確定性程序產生,不經 LLM。完整分割(每個關鍵字
恰屬一組、不遺漏、不新增)由演算法結構保證,無須事後
驗證。
### 進池
兩次標註執行的全部關鍵字取聯集、逐字串精確去重、字典序
排列。失敗與拒答的記錄跳過(其歌曲不貢獻關鍵字);解析
時偵測重複鍵,違規即失敗。
### 分群
- **嵌入**`sentence-transformers/all-mpnet-base-v2`
(釘定 revision),關鍵字的連字號先還原為空格再編碼,
輸出 768 維向量並 L2 正規化。
- **分群**:階層式聚合分群(Ward linkage),k=100。
向量既已正規化,歐氏距離與餘弦相似度單調對應;三種
linkage 實測比較,Ward 於各個 k 的組內一致性均最高
average 與 complete 皆產生吞噬半數語料的巨大異質
組)。
- **組數的取捨**:k 太小則壓縮比過高,樹上層被迫併入
不相干的詞,組雖大而無主題(k=30 最大組 491 詞、
組內一致性 0.41,成員橫跨籃球、海灘、外星人綁架);
k 太大則人工難以通覽。定於 100,理由是實測顯示雜物櫃
組於此始裂解為有主題的組,且編碼實測未見碼數過多的
副作用——全量三次執行下 101 個碼全數用到;模型另行
造出的碼共 13 筆,佔 44,149 筆標籤指派的 0.03%。
- **組名**:取 medoid——與該組中心(成員向量均值後
正規化)餘弦相似度最高的成員詞。組名因此必為模型
自己產出過的關鍵字,非任何人事後撰寫。已知限制:
組越大越異質時,medoid 只是折衷詞,可能代表不了組內
內容(實測 `mutual-individuality` 組內一致 0.70 而
編碼從未使用);此類碼於結果中呈現為零使用,據實
報告,不事後改名。
- **取捨紀錄**:曾以 LLM 單發收斂(mergecap 兩步)
實作本步,四種模型六次執行全部無法維持完整分割,
已棄用(詳見 `decision-log.md` 2026-08-05;棄用的
定義檔止於 git 歷史,見 `git log -- prompts/`)。
- **產物**:五份,前綴分別標示來源與結果。
`source-keywords.txt`(進池後的關鍵字,一行一個)
記錄進來的是什麼;`result-keywords.txt`(組名,一行
一個)與 `groups.csv`(欄位 Group、Keyword,一列一個
成員)記錄算出來的分割;`keywords-to-merge.json`
`{"keywords": [...]}`)是實際交給模型的碼,即組名
加上先驗主題詞——五份中只有這一份含研究者的介入。
`meta.json` 記錄執行本身:進池的兩份執行歸檔與其有效
筆數、嵌入模型與釘定 revision、分群參數與組數、外加
的先驗詞、關鍵字總數,以及產生數字的套件版本。凡命令
列上的選擇與環境事實皆在此,不記時間戳與輸入雜湊
——前者使同環境重跑逐位元組可再生,後者只會重述 git
已保證的事。
- **可重現性**:同一輸入、同一釘定模型、同一參數逐次
重現。不同 CPU/BLAS 實作的浮點尾數差異可能使邊界
詞的歸屬翻動,屬已揭露的限制;論文所用碼表逐字
commit,引用單位為該份定案檔案。
### women-power 的注入
定案詞彙表為 100 個分群組名再加上 `women-power` 一詞,
共 101 個碼。`women-power` 是研究者任意決定的先驗主題(即本
論文的主題本身),不由資料產生,屬揭露的儀器介入。該詞
於執行時以 `--extra-keyword` 明示加入,不寫死在程式裏
——研究者的介入因此每次都出現在重現命令上,而非無聲
發生;分群結果的兩份產物不含它,只有交給模型的碼表含
它。
注入而非另設篩選軌的理由:讓研究者的主題詞與模型自己
收斂出的類別(分群已自行長出 `female-empowerment` 等組)
在同一份提示詞、同一個判斷體制下受檢,避免單目標提問
把該主題的顯著性人為抬高。兩者的落點差異本身即可報告
的結果。
## 步驟 3 編碼的三次執行與多數決
- **三次執行**:同一份定義檔、同一份輸入檔,獨立執行
三次,三份歸檔並列(`runs/03-code/run1``run2`
`run3`),彼此無先後主從之別。
- **多數決**:一首歌的一個標籤,三次執行中至少兩次標出
即收入定案編碼。三票不平手,裁決規則因此無例外條款,
計票由確定性子命令完成(見交接契約)。
- **第三票取全量**:只對前兩次分歧的標籤補問第三票,
計票結果相同;仍採全量執行——全部歌曲、全部關鍵字
——使三票在同一條件下取得。
- **對邊緣標籤的作用**:兩次執行只分得出「兩次皆標」與
「僅一次標」;三次執行還分得出 3-0 與 2-1,故「定案
編碼中有多少比例僅以一票之差成立」成為可報告的量。
至於判定本身,兩次執行相左的標籤在何種協定下都由第三
個判斷定奪,票數不使不確定性消失:某標籤於單次執行被
標出的傾向若恰為一半,任何票數皆為擲幣。三票之效在
傾向偏離一半處——多數決將判定推向該傾向本身(單次
0.7 者為 0.780.9 者為 0.97),程序重跑的一致性因而
高於單次執行,唯獨恰半處無從改善。
## 步驟 4 語意編碼群
- **對象**:將 101 個編碼依語意劃入研究者命名的四個編碼
群——女性力量(women-power group)、反女性力量/厭女
misogyny group)、陽剛男性氣質(masculine group)、
脆弱(vulnerable group)。群只有名字,沒有定義;歸屬
由 LLM 依編碼名的字面語意判斷。
- **任務**:每筆輸入為一個群名加 101 個編碼的字母序
清單,輸出為入選編碼的單層 JSON 陣列;定義檔
`prompts/04-group.md` 只定格式,不含任何群的語意定義。
- **模型**`claude-fable-5`(步驟 1、3 為
`claude-sonnet-4-6`)。該模型不受理 `temperature`
`thinking` 參數,兩者均不送出;取樣變異由多數決吸收。
模型裁定的理由與對照實驗見決策日誌。
- **三次執行**:同一份定義檔、同一份輸入檔,獨立執行
三次,歸檔並列(`runs/04-group/run1``run2``run3`)。
- **多數決**:一個(群,編碼)配對,三次執行中至少兩次
入選即屬該群;不在 101 碼詞彙表內的輸出項無效,每筆
丟棄印於標準錯誤。計票由確定性子命令 `tally-groups`
完成:`tally-groups <執行歸檔 1> <執行歸檔 2> <執行歸檔
3> <合法碼清單> <輸出 CSV>`,合法碼清單之產法同步驟 3。
定案分群寫入 `results/groups.csv`,欄位 `Group`
`Keyword``Votes`,列序先依群名、再依編碼,一律以
Unicode 碼位比較,換行為 CRLF。
- **工作儲存**`build-db --groups <定案分群 CSV>` 將定案
分群逐欄照存入 `groups` 資料表(群、編碼、票數),供
群層次查詢。
## 女性力量候選集
候選集為兩類歌曲的合集:定案編碼含 `women-power` 者,
以及定案編碼含研究者指認之女性力量概念域分群組者。
指認於詞彙表定案後、黃金標準編碼開始前完成,指認清單
與理由記入決策日誌。
## 軌跡對映(診斷用)
沿收斂軌跡的機械對映:原始關鍵字 →(兩份標註執行歸檔的
`output.jsonl`)歌曲、原始關鍵字 →(分群)組,純程式查表,
決定性。以其結果與步驟 3 直接編碼的差異率作為「收斂軌跡
扭曲」的診斷量,不作主結果。
## 全管線的交接契約
每一步的輸出如何變成下一步的輸入,皆為確定性程序,規則
明定如下:
- **歌詞輸入檔(步驟 1**`export-llm-input` 自工作
儲存產出,每筆 `{"id": "song-<ID>", "content": <歌詞>}`
依歌曲 ID 升序。步驟 3 的輸入由同一子命令、同一工作
儲存產出(見下),兩步的語料同一性由此成立;各步
輸入檔的 SHA-256 記入該步 meta。
- **步驟 1 → 2**`cluster-keywords` 讀兩份執行歸檔的
`output.jsonl`(一律以換行字元 `\n` 切行——歌詞含
U+0085 等控制字元時,`str.splitlines()` 類的通用切行
會截斷 JSON 字串,實測踩中),進池後直接分群,一次
產出上列五份檔案。
- **步驟 2 → 3 輸入檔**`export-llm-input --extras
<定案碼表>` 自工作儲存產出步驟 3 的輸入,每筆
`{"id": "song-<ID>", "content": <字串>}``content` 為
固定鍵序序列化的 `{"lyrics": …, "keywords": [...]}`
依歌曲 ID 升序。碼表以參數傳入而非填進定義檔——定義
檔只規定任務形狀,換詞彙表、換演算法都不必改它。
- **步驟 3 定案**`tally-codings <執行歸檔 1> <執行歸檔
2> <執行歸檔 3> <輸出 CSV> --corrections <更正表>
--valid-keywords <合法碼清單>` 讀三份執行歸檔的
`output.jsonl`,依序套用更正表、驗證所有標籤皆在合法碼
清單之內、計票。
- **更正表**`data/manual/coding-corrections.csv`,研究者
逐列校定的人工著作,欄位 `Song ID`、`Run`、`Type`、
`To Be Replaced`、`Correct Term`。`Type` 為 `keyword`
或 `evidence`,分別更正標籤與引述;`Correct Term` 為
替代字串,或 `**REMOVE**` 表示刪去該筆標籤指派(`keyword`
或該句引述(`evidence`)。一筆 `evidence` 更正套用於該
首歌該次執行的所有出現處。兩個文字欄以歌詞慣例「 / 」
表示換行(與載入後的執行紀錄同一表示法,逐字比對、不再
轉換),故一列一行,純文字工具可逐列處理。表中任一列若
在資料中找不到對應者,即中止;校定的判準記於
`decision-log.md`。
- **合法碼清單**:純文字、一行一個碼,自詞彙表產出:
`{ cat runs/02-cluster/result-keywords.txt; echo
women-power; } | sort`。
- **定案表**`results/codings.csv`,欄位 `Song`、
`Artist Credit`、`Keyword`、`Quote`,一列一個標籤。歌名
與演出者名銜逐首查工作儲存取得,故本子命令須在
`build-db` 之後執行。`Quote` 為該標籤在計票中各份執行
所引的歌詞行:各份的引述串接後逐字去重,按 Unicode
碼位排序,以單一 `|` 相接(三份執行彼此無先後主從之
別,引述之序取決於引述本身);引述內的換行於執行紀錄
載入時一次換成歌詞慣例「 / 」,此後更正表、定案表與
工作儲存全鏈路同一表示法,不再還原。「 / 」的無歧義性
是語料事實而非結構保證:全 883 首歌詞經窮舉查核不含
「 / 」;換語料須重查。列序依印出的前三欄依序排:
歌名、演出者名銜、
標籤,一律以 Unicode 碼位比較,換行為 CRLF(同專案
其他 CSV)。
- **序列化通則**:所有中間檔為 UTF-8,欄序、鍵序與元素
序皆依上列規則明定,無時間戳、無隨機成分;JSON 解析
一律偵測重複鍵,違規即失敗。人讀為主的產物採純文字或
CSVCSV 依 RFC 4180,標題列字首大寫),機器交接檔採
JSON。給定相同的 LLM 執行輸出,全部交接產物逐位元組
可再生。
## 執行與稽核
- LLM 步驟以 `run-llm <定義檔> <輸入檔> <歸檔目錄>`
執行;一步的 N 次執行=重現命令清單上的 N 行命令,
各自歸檔(`runs/<步驟>/run1`、`run2`,三票制步驟另有
`run3`)。
- 確定性步驟(進池、分群、計票、對映)為子命令,其
輸入輸出檔同隨 `runs/` 歸檔;因無執行變異,歸檔目錄
下不分 `run<N>` 層。
- Batch API 的每筆請求自含全部脈絡且互不可見(平台
契約),歌與歌之間的獨立性由此成立;各次執行的獨立
性由「一次呼叫、一個批次、一份歸檔」的執行結構自明。
- 每次 `run-llm` 執行的 token 用量與費用記入
`run-costs.md`,被取代的執行一併保留供總支出核算。
## 映射分析方法
(依 2026-07-30 決策,於看到結果前寫定;待黃金標準
編碼展開前補入。)