urscos Tech - Jkeeper
type: channel
link: https://novel.urscos.com/author/1/
description: Jkeeper
items: Unity 全螢幕解析度問題排解合集：獨占模式 vs 無邊框模式常見 Bug 與解法
items: Steam 雲端存檔完全指南：查看、強制同步與徹底刪除教學
items: OSM 的隱藏陷阱：λ 指數修正 2 —— 建照數據校準與方法論局限
items: 三門問題的資訊熵解法：用 Shannon 熵計算 Monty Hall 換門的資訊增益，兼談與 Everett 多世界的類比
items: LLM 記憶壓縮實戰：滑動視窗 vs 摘要記憶，用答對率與 Token 成本量化取捨
items: LLM 為什麼沒有記憶？Stateless 原理與 Prompt 層記憶模擬實戰（含 Token 成長曲線）
items: Prompt Engineering 實戰：Zero-shot vs Few-shot vs CoT 的 Token 成本與情感分析對比
items: OSM 的隱藏陷阱 - 以 λ 指數修正志願者貢獻偏差
items: CodeGraph 實戰心得：用「地圖導航＋精確搜索」提升 Claude Code 程式碼理解效率
items: 從 Shannon 熵到 Everett 資訊：互資訊非負性證明全解析

Unity 全螢幕解析度問題排解合集：獨占模式 vs 無邊框模式常見 Bug 與解法
type: item
date: 2026-07-23T10:28:00+00:00
description: 目前常規的PC游戲顯示模式有幾種模式如下， 一、視窗模式（FullScreenMode.Windowed） 二、獨占模式（FullScreenMode.ExclusiveFullScreen） FPS游戲多數使用獨占模式，也是最早的全屏幕模式，性能較好，但使用 Alt+Tab時切換會出現閃頻 三、無邊框模式 （FullScreenMode.FullScreenWindow） 目前游戲多數使用這個模式，開啓後切換不會出現閃屏 問題1、切換解析度時屏幕出現黑屏無訊號 Exclusive Fullscreen 必須使用顯示卡的「原生支援模式」(Display Modes)，Windows 桌面「縮放 / 插值後」能顯示許多非原生模式，但 Unity 的 Exclusive Fullscreen 只能切換到顯示卡真正支援的模式，不能靠 OS 自動補正。 如果顯示卡沒有 真正的 1280×800 模式： Windows 桌面會用 GPU scaling → 顯示正常 Unity Exclusive Fullscreen 嘗試切換 → 找不到完全匹配的 mode → 會改用 fallback（通常 1280×720 或 native resolution） 結果畫面偏移、拉伸或出現 左側黑屏 所以： 你以為進入了 1280×800，但實際上顯卡沒有成功切換到這個 mode。 問題2、兩個屏幕，一個 1080p，一個2k，切換2k解析度時出現錯誤，游戲無法調整到對應的2k解析度 目前沒有處理這個問題。 問題3、無邊框模式切換獨占模式無效 在主要解析度，譬如設備解析度為 1920 X 1080，情況下從無邊框模式切換到獨占模式，雖然切換成功，但實際上卻是無邊框模式，這是 windows 全螢幕最佳化處理的結果，unity無法干涉。 原因是 Windows 10/11 強制 Fullscreen Optimizations（全螢幕最佳化），導致獨占模式被轉成 Borderless Fullscreen Windows 會把要求 Exclusive Fullscreen 的遊戲「包裝成」 ➡ Borderless Fullscreen + 可變刷新率 + 全螢幕優化圖層 這樣能快速切換視窗、疊加 UI（Xbox Bar）、降低 alt-tab 黑屏，但缺點就是： 看起來像無邊框， 還是會回報給 Unity 「正在使用 Exclusive Fullscreen」， 顯示卡 API 也會回報獨佔模式成功，所以 Unity 的 log 會印出 ExclusiveFullScreen，但你看到的是 Borderless 外觀。 需要處理【關閉全螢幕最佳化】 有兩種做法： 方法一、設定 exe 檔案，關閉全螢幕最佳化。 方法二、游戲啓動后新增注冊表關閉最佳化，如下： public static void SetDisableFullscreenOptimization() { string exePath = string.Empty; // 獲取當前執行檔路徑 (包含執行檔名稱) Debug.Log("System.AppDomain.CurrentDomain.BaseDirectory: " + AppDomain.CurrentDomain.BaseDirectory); // 獲取執行檔所在目錄的路徑 Debug.Log("Application.streamingAssetsPath: " + Application.streamingAssetsPath); // 獲取可讀寫的持久化資料夾路徑 Debug.Log("Application.persistentDataPath: " + Application.persistentDataPath); try { string baseDirectory = AppDomain.CurrentDomain.BaseDirectory; string exeName = Application.productName + ".exe"; exePath = Path.Combine(baseDirectory, exeName); } catch (System.Exception e) { Debug.LogError($"使用 BaseDirectory 獲取執行檔路徑時發生錯誤: {e.Message}"); return; } if (string.IsNullOrEmpty(exePath)) { Debug.LogError("無法推導執行檔路徑，操作取消。"); return; } // 檢查檔案是否存在（額外的安全檢查） if (!File.Exists(exePath)) { …

Steam 雲端存檔完全指南：查看、強制同步與徹底刪除教學
type: item
date: 2026-07-22T08:00:00+00:00
description: 查看雲端存檔 輸入網址 https://store.steampowered.com/account/remotestorage 然後滾動到想查看的游戲，點擊顯示檔案 可以看到目前游戲下的所有雲端存檔 强制同步雲端存檔做法 使用 WIN+R 輸入指令開啓 steam 主控臺 steam://open/console 在主控臺輸入指令 cloud_sync_up 4778780 這代表强制同步雲端存檔 刪除所有雲端存檔方式 開啓 steam client 確認所有同步都跑完的情況下，進入主控台 這時候進入游戲安裝目錄還能看到 remotecache.vdf 是含有所有檔案的版本 C:\Program Files (x86)\Steam\userdata\31135361\4770000\remotecache.vdf 然後進入存檔路徑 C:\Users\joker0000\AppData\LocalLow\U**\ 將遠端存檔目錄全刪掉 確保刪除后，回到主控臺輸入同步指令 cloud_sync_up 4778780 這時候再回到雲端就會發現檔案都刪除了 https://store.steampowered.com/account/remotestorageapp/?appid=4770000

OSM 的隱藏陷阱：λ 指數修正 2 —— 建照數據校準與方法論局限
type: item
date: 2026-07-18T16:54:00+00:00
description: 延續上一篇的話題，關於 λ 的修正計算，如何更準確的預估或是計算出 λ 呢？ 理論上 λ 應由「外部基準」決定，以下是三條可行的校準路徑： PATH 1：對照官方建照數據 最直接的方法——以政府公布的「年度核發建照數」作為 ground truth，反推 λ： λ* = log(N_t/N_0 / G_real) / log(C_t/C_0) 其中 G_real 為官方建照累計增長率。台中建管處（CPA）有公開資料，可據此反算出城市特定的 λ 值。 PATH 2：跨城市穩定性檢驗 若同一個 λ 值應用於台北、高雄、台中均能與官方數據對齊，則可視其為 OSM 系統性偏差的穩健估計，與個別城市無關。 PATH 3：保守採用 λ = 0.5 在缺乏 ground truth 校準的情況下，以 0.5 作為「未知條件下假設各佔一半」的保守選擇。報告中務必附上靈敏度分析表，讓讀者知悉結論在 λ ∈ [0.25, 0.75] 範圍內的穩健性。 批次修正多項指標 以下一鍵完成所有指標的偏差修正： # osm/bias_correction.py:146-179 def run_bias_correction(osm_metrics, target_cols=None, base_year=BASE_YEAR, lambda_=DEFAULT_LAMBDA): if target_cols is None: target_cols = ["building_count", "amenity_count", "shop_count", "poi_diversity"] community_proxy = compute_total_elements(osm_metrics) yearly_means = osm_metrics.groupby("year")[target_cols].mean() all_results = [] for col in target_cols: series = yearly_means[col].dropna() df = bias_correction_index(series, community_proxy, base_year, lambda_) df.insert(0, "indicator", col) all_results.append(df) return pd.concat(all_results, ignore_index=True) 輸出兩份結果檔： output/osm_bias_corrected.csv——各指標各年的原始與修正後增長指數 output/osm_bias_sensitivity.csv——λ 靈敏度分析結果 修正前後各 OSM 指標的 8 年總增長率對比（λ = 0.5）： 指標 原始增長 修正後增長 差距幅度 building_count +393% +140% 巨大 amenity_count +44% −30% 中等 shop_count +61% −22% 中等 poi_diversity +37% −33% 中等 為何 amenity / shop / poi_diversity 修正後呈現負增長？ 這個結果頗具啟示性——它說明：設施、商店、POI 多樣性的增長速度，低於社群整體活躍度的增長速度。以白話解讀： 社群志願者在 8 年間新增了 4.23 倍的「總元素」 其中建築物增長最為顯著（4.93 倍），佔新增貢獻的絕大部分 設施、商店類元素雖有增長，但比例上未能跟上社群整體活躍度的提升 修正後的負值意味著：這些指標的「真實增長」可能接近零，幾乎全數源於社群回填效應。 這一發現本身即具有獨立的研究價值——它告訴規劃者一個有悖直覺的事實：從 OSM 觀察到的「商店設施大量增加」，很可能並非真實現象。 八、方法論的局限 誠實面對這套修正方法的潛在問題： 1. 假設「真實建設增長」與「社群活躍度」相互獨立 此假設未必成立。當城市快速擴張時，社群往往也更有動力更新 OSM（例如建商人員主動補登自家樓盤）。兩者之間實際存在正相關。 即便如此，修正的方向仍是正確的——只是修正幅度可能略有過度。 2. C_t 以「總元素數」代理過於粗略 更精細的做法：以 OSM changeset 數量、活躍編輯者數，或某類「不會新增的歷史地物」（如山脈、河川的 way）作為更純粹的社群活躍度代理。但 changeset 資料須從 OSM Planet 下載，工程量較大。 3. λ 不宜跨指標共用 修正建築物所用的 λ，未必適用於設施類指標。理論上每個指標都應有其專屬 λ，但此舉會使校準工作量大幅增加。 4. 全域 λ 假設的侷限 目前 λ 假設在整座城市中均一。實際上市中心與郊區的…

三門問題的資訊熵解法：用 Shannon 熵計算 Monty Hall 換門的資訊增益，兼談與 Everett 多世界的類比
type: item
date: 2026-07-16T16:00:00+00:00
description: 三門問題的資訊熵解釋 核心思路 三門問題（Monty Hall）的關鍵在於：主持人的動作不是隨機的，而是攜帶訊息的。用資訊熵來看，整個過程是一次「熵減少」的過程──你獲得了訊息，不確定性就下降了。 初始熵 三扇門，獎品等機率藏在其中一扇後面： $$ H_0 = -\sum_{i=1}^{3} \frac{1}{3}\log_2\frac{1}{3} = \log_2 3 \approx 1.58 \ bits $$ 當主持人揭示門後的熵 重點在於主持人知道獎品在哪，且他的選擇受約束（不能開你選的門，不能開有獎品的門）。所以他打開的門本身包含了訊息。 若你原選的門（假設 A）剛好是獎品門（機率 1/3），主持人在 B、C 中隨機開一扇，各 1/2。 若獎品在 B（機率 1/3），主持人被迫開 C。 若獎品在 C（機率 1/3），主持人被迫開 B。 主持人開門這個"訊號"傳遞了條件機率資訊。用貝葉斯更新後： $$ P(\text{獎品在B} \mid \text{主持人開C}) = \frac{2}{3}, \quad P(\text{獎品在A} \mid \text{主持人開C}) = \frac{1}{3} $$ 不確定性從 3 選 1（$\log_2 3 bits$）坍縮到 2 選 1、但機率不均（2/3 vs 1/3）： $$ H_1 = -\frac{1}{3}\log_2\frac{1}{3} - \frac{2}{3}\log_2\frac{2}{3} \approx 0.918 \ bits $$ 熵減少量： $H_0 - H_1 \approx 1.58 - 0.918 = 0.667 bits$ ——這正是主持人（那一步互動作的資訊）。 回到問題核心，為什麼"換門"是理性的 在資訊理論視角下，主持人開門不是噪聲，是一次非對稱的信息注入：他必須遵守規則（不能打開獎品門、不能開你選的門），這個約束讓他的"選擇"本身洩露了獎品位置的線索。換門利用了這個訊息，不換則等於把這份訊息白白丟棄，等價於仍停留在原始的 $\frac{1}{3}$ 機率上。 然而與 Everett 多世界進行類比對照時 這個類比有意思但要小心區分層次： 三門問題是經典貝葉斯推斷——熵的下降來自"觀測者獲得了新資訊"，本體上獎品位置從一開始就是確定的，只是你不知道。 Everett 的多世界詮釋中，量子態的"熵"（如馮諾依曼熵）在退相干後增加，是因為系統與環境糾纏，不同分支彼此退相干、變得"經典化"。這裡沒有一個先驗確定的結果被"揭示"——按 MWI，所有分支都實際發生了，你只是發現自己處於某一支。 一個常見的對比點是：三門問題的熵下降屬於認知熵（Shannon 熵，反映主觀資訊狀態的更新）；而量子退相干中的熵增屬於糾纏熵/馮諾依曼熵（von Neumann 熵），反映的是分支之間關聯性的物理增長，兩者數學形式相似但物理內涵不同——這也是很多人在類比量子貝葉斯分支時容易混淆的地方分支時容易混淆的地方。

LLM 記憶壓縮實戰：滑動視窗 vs 摘要記憶，用答對率與 Token 成本量化取捨
type: item
date: 2026-07-13T16:00:00+00:00
description: 本章節要實作滑動視窗與摘要壓縮兩種記憶，並用事實問答量化「省 token vs 記得住」的取捨 一、滑動視窗記憶 實作只保留最近 N 輪的 SlidingWindowMemory，並驗證在 Context Window 中「忘掉久遠的事」 """SlidingWindowMemory：只保留最近 N 輪對話（FIFO）（W2）。""" class SlidingWindowMemory: def __init__(self, system=None, max_turns=3): """max_turns：保留最近幾輪（1 輪 = 1 user + 1 assistant）。""" self.system = system self.max_turns = max_turns self._messages = [] # 內部保留完整歷史（除錯用） def add_user(self, text): self._messages.append({"role": "user", "content": text}) def add_assistant(self, text): self._messages.append({"role": "assistant", "content": text}) def build_messages(self): """只回傳最近 max_turns 輪 = 最多 2*max_turns 則訊息。""" window = self._messages[-2 * self.max_turns:] # 確保以 user 開頭（避免 assistant 開頭導致 API 報錯） while window and window[0]["role"] != "user": window = window[1:] return window def __len__(self): return len(self._messages) 接著寫一個測試用例 import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from memory.llm import chat from memory.window import SlidingWindowMemory SYSTEM = "你是助理，用繁體中文簡短回答。" mem = SlidingWindowMemory(system=SYSTEM, max_turns=2) # 只記最近 2 輪 script = [ "我對甲殼類過敏，請記住。", # 埋在最早——會被滑出去 "我最喜歡的顏色是藍色。", "幫我推薦一部電影。", "再推薦一首歌。", "我對什麼過敏？", # 回頭考：早已滑出視窗 ] for user in script: mem.add_user(user) reply, _ = chat(mem.build_messages(), system=SYSTEM) mem.add_assistant(reply) print(f"你 > {user}\nAI > {reply}\n (視窗內 {len(mem.build_messages())} 則)\n") 執行測試 python demos/w2_window_probe.py 你 > 我對甲殼類過敏，請記住。 AI > 好的，我會記住您對甲殼類過敏。 (視窗內 2 則) 你 > 我最喜歡的顏色是藍色。 AI > 知道了，您最喜歡的顏色是藍色。 (視窗內 4 則) 你 > 幫我推薦一部電影。 AI > 如果您喜歡藍色，或許您會喜歡《藍色是最溫暖的顏色》（Blue Is the Warmest Color），這是一部法國電影，講述了一段深刻的愛情故事。 (視窗內 4 則) 你 > 再推薦一首歌。 AI > 推薦您聽周杰倫的《青花瓷》，這是一首融入中國傳統元素的現代流行音樂，歌詞優美，旋律動聽。 (視窗內 4 則) 你 > 我對什麼過敏？ AI > 要確定您對什麼過敏，需要進行具體的過敏原檢測。這通過皮膚點刺試驗、血液中的IgE測試或其他相關的過敏檢查來進行。如果您有過敏症狀，建議咨詢醫生或過敏科專家並進行專業檢測。 (視窗內 4 則) 可以觀察得到最早的對話内容已經不見了 二、摘要壓縮記憶 實作由滑窗 + 滾動摘要，當—舊對話滑出視窗時，則并入一段由 LLM 維護的摘要。 在下面新增滑動窗口功能 """SummaryMemory：近期用滑動視窗保留原文，滑出的舊對話併入滾動摘要。""" from memory.llm import chat SUMMARIZE_SYSTE…

LLM 為什麼沒有記憶？Stateless 原理與 Prompt 層記憶模擬實戰（含 Token 成長曲線）
type: item
date: 2026-07-12T16:00:00+00:00
description: 一、大模型沒有記憶 由於 LLM 本質上是無狀態的（Stateless）。每一次 API 呼叫都是獨立的、全新的計算過程，模型內部不會保留任何「記住上一句話」的狀態。因此，兩次呼叫彼此獨立，第二次完全不知道第一次發生過的事情。於是乎就有了以下的做法。 Prompt 層模擬記憶 把「歷史聊天記錄」+「當前新問題」打包拼接，作為一個完整的 Prompt 一次性傳給模型，讓它在 單次推理中 看到全部上下文。 我們會把對話歷史塞進 context 中，如下： messages = [ {"role": "user", "content": "我叫小明"}, {"role": "assistant", "content": "你好小明！很高興認識你。"}, {"role": "user", "content": "我叫什麼名字？"}, ] 這裏面的role代表如下： role 作用 典型內容 system 設定助理的身份、規則、語氣（Anthropic 放在獨立的 system 參數） 「你是一位耐心的數學家教」 user 使用者說的話 「幫我解這題」 assistant 模型過去的回覆（由你把它加回歷史） 「好的，第一步…」 兩種計費 token 類型 說明 相對成本 input_tokens 輸入進去的（包含全部對話歷史） 便宜 output_tokens 模型生成輸出的 貴（通常 4~5×） 問題：每一輪你都把 全部歷史 當作 input 重新送一次。第 10 輪的 input 包含了前 9 輪的所有內容。 累計 input token ≈ 每輪歷史長度的總和 ≈ 1 + 2 + 3 + … + n ≈ O(n²) Anthropic 定價（每 MTok = 100 萬 token） 模型 Input Output claude-opus-4-8 $15 $75 claude-sonnet-5 $3 $15 claude-haiku-4-5 $0.80 $4 Context Window 上限 每個模型有 上下文視窗（context window） 上限——單次呼叫能吃下的最大 token 數（input + output 合計）。將所有對話記錄都塞進去 context，歷史記錄一多就會超出限額。 模型世代 典型視窗 早期 GPT-3.5 4K / 16K GPT-4 8K / 32K / 128K Claude 3/4 200K 前沿長上下文 1M 撰寫一個簡單的 anthropic API 呼叫 import anthropic client = anthropic.Anthropic() # 讀取環境變數 ANTHROPIC_API_KEY resp = client.messages.create( model="claude-haiku-4-5", max_tokens=512, system="你是一位友善的助理，用繁體中文回答。", messages=[ {"role": "user", "content": "你好"}, ], ) print(resp.content[0].text) # 模型的文字回覆 print(resp.usage.input_tokens, resp.usage.output_tokens) # token 用量 幾個重點 system 是獨立參數，不放在 messages 裡（這是 Anthropic 與 OpenAI 的差異）。 messages 必須 user / assistant 交替，且以 user 開頭、user 結尾（送出時最後一則是使用者的新問題）。 回覆是 content 陣列：純文字對話取 resp.content[0].text。 resp.usage 直接告訴你這次用了多少 token——這是 Lab 3 畫曲線的資料來源，不需自己估算。 如果想知道精確 token 數量，可用： count = client.messages.count_tokens( model="claude-haiku-4-5", system="你是一位友善的助理。", messages=messages, ) print(count.input_tokens) 下面是全量拼接對話流程，並添加用於管理對話的 BufferMemory class BufferMemory: def __init__(self, system=None): self.system = system self._messages = [] # [{"role": ..., "content": ...}, ...] def add_user(self, text): self._messages.append…

Prompt Engineering 實戰：Zero-shot vs Few-shot vs CoT 的 Token 成本與情感分析對比
type: item
date: 2026-07-11T16:05:00+00:00
description: 「將原始模型輸出轉化為結構化、可靠、可預測的行為」。 這是 prompt engineering 的工程定義。其中三個層次： 策略：zero-shot / few-shot / Chain-of-Thought — 用什麼方式引導模型推理 約束：JSON mode、schema、格式規範 — 讓輸出可被程式接住 曡代：用標註資料集量化準確率，像調程式一樣調 prompt Context Engineering（上下文工程）：重點不是單句 prompt，而是 「在有限 context window 裡，放對的範例、對的格式說明、對的歷史」。 一、三種 prompt 策略並排比較 這邊設計腳本對同一句話組出三種 prompt，逐一送模型，並示範各策略的輸出怎麼解析： def chat(messages, temperature=0.0): """呼叫真實 LLM 取得文字回覆；無任何憑證則回傳 None，由呼叫端決定是否走 offline。""" kimi = _kimi_cfg() try: if kimi: from openai import OpenAI # Kimi 為 OpenAI 相容 API cli = OpenAI(api_key=kimi["api_key"], base_url=kimi["base_url"], timeout=120) r = cli.chat.completions.create(model=kimi["model"], messages=messages, temperature=temperature) return r.choices[0].message.content if os.environ.get("ANTHROPIC_API_KEY"): import anthropic cli = anthropic.Anthropic() sys_txt = "\n".join(m["content"] for m in messages if m["role"] == "system") usr = [m for m in messages if m["role"] != "system"] r = cli.messages.create(model="claude-opus-4-8", max_tokens=1024, system=sys_txt or None, messages=usr, temperature=temperature) return r.content[0].text if os.environ.get("OPENAI_API_KEY"): from openai import OpenAI cli = OpenAI() r = cli.chat.completions.create(model="gpt-4o", messages=messages, temperature=temperature) return r.choices[0].message.content except Exception as e: print(f"⚠ 線上呼叫失敗，改用 offline mock：{e}", file=sys.stderr) return None return None def build_prompt(task, strategy): """回傳 (messages, 說明) — 示範三種主流策略如何組 prompt。""" system = "你是情感分類器。只輸出標籤本身，不要解釋。" if strategy == "zero-shot": user = f"判斷情感（正面/負面/中性）：\n{task}" elif strategy == "few-shot": ex = "\n".join(f"文本：{t}\n標籤：{l}" for t, l in FEWSHOT) user = f"依照範例判斷情感（正面/負面/中性）：\n\n{ex}\n\n文本：{task}\n標籤：" elif strategy == "cot": user = (f"判斷以下文本的情感（正面/負面/中性）。\n" f"先用一句話分析語氣與關鍵詞，最後一行只寫『標籤：X』。\n\n文本：{task}") else: raise ValueError(strategy) return [{"role": "system", "content": system}, {"role": "user", "content": user}], strategy 執行策略看效果 python prompt_lab.py strategies --task "這家餐廳雷到爆，再也不…

OSM 的隱藏陷阱 - 以 λ 指數修正志願者貢獻偏差
type: item
date: 2026-07-11T13:20:00+00:00
description: 本篇要講述的是台中 OSM 建築數量 2018→2025 增長 392%，但其中有多少是真實建設、多少是社群回填？本篇提出一個可量化、可控制修正強度的 λ 偏差修正指數。 關於 OSM 其中的 392% 增長，有多少是真的？ 先來檢視台中市 OSM 數據 8 年的原始增長： 年份 OSM 建築物總數 設施 商店 休閒 2018 16,926 1,015 408 30 2019 12,771 1,207 466 32 2020 16,117 1,520 541 39 2021 18,500 1,599 534 47 2022 24,973 1,640 590 49 2023 41,055 1,762 647 57 2024 47,584 1,874 690 59 2025 50,208 1,921 705 61 採樣點 500m 範圍內的「平均建築數量」更為顯著——從 2018 年的 27.6 棟，增至 2025 年的 136 棟，+392.1%。 然而其中一個問題隨之而來： 台中市真的在 8 年內新建了比原有存量多 4 倍的建築嗎？ 答案顯然是否定的。即便是開發最密集的城市，10 年內新建建築數量也不會超過存量的 1 倍。這 392% 中，相當大一部分其實是「OSM 社群志願者持續將既有建築數位化補登」，也就是「歷史回填」（backfilling）效應。 量化「回填效應」：社群貢獻量代理變數 若某城市/地區 2018 年 OSM 共有 1 萬個元素（建築 + 設施 + 商店 + 休閒），2025 年增至 5 萬，則社群整體活躍度約提升 5 倍。建築數的增長，有相當一部分是被這個系統性的「社群更積極補登」推高的。 我們在這邊定義「社群貢獻量代理」C_t： C_t = building_count_t + amenity_count_t + shop_count_t + leisure_count_t 將所有有測量目標的標籤加總，作為志願者整體投入程度的代理變數。 # osm/bias_correction.py:37-54 def compute_total_elements(osm_metrics: pd.DataFrame) -> pd.Series: """ 計算每年 OSM 快照的「總元素數」（社群貢獻量代理）。 """ count_cols = [c for c in ["building_count", "amenity_count", "shop_count", "leisure_count"] if c in osm_metrics.columns] osm_metrics = osm_metrics.copy() osm_metrics["total_elements"] = osm_metrics[count_cols].sum(axis=1) return osm_metrics.groupby("year")["total_elements"].mean() 台中 8 年的 C_t（每採樣點 500m 範圍內均值）： 年份 C_t（總元素均值） 2018 34.6 2021 57.1 2025 146.4 C_2025 / C_2018 ≈ 4.23，社群貢獻量翻了逾四倍。 核心假設：社群貢獻量增長與真實建設增長是兩個獨立過程。OSM 元素總數的增長是兩者的疊加，而研究者真正關心的是後者。 修正公式 定義第 t 年的「校正後增長指數」： G_t_corr = (N_t / N_0) × (C_0 / C_t)^λ 各符號意義： 符號 意義 N_t / N_0 原始增長率（基準年 N_0 = 2018） (C_0 / C_t) 社群貢獻量的衰減倒數（C 愈大，此因子愈小） λ ∈ [0, 1] 修正強度，由分析者根據研究假設設定 三種直覺解讀： λ = 0：完全不修正 → G_corr = N_t / N_0，還原為原始指數 λ = 1：完全比例修正 → 假設所有 OSM 元素增長均來自社群活躍度提升 λ = 0.5：中度修正，假設增長中一半來自真實建設、一半來自社群回填 # osm/bias_correction.py:80-97 v0 = series[base_year] c0 = community_proxy[base_year] for year in sorted(series.index): v_t = series[year] c_t = community_proxy.get(year, c0) raw_growth = v_t / v0 if v0 > 0 else np.nan # 社群貢獻量修正因子 = (C_t0 / C_t)^λ if c0 > 0 and c_t > 0: c…

CodeGraph 實戰心得：用「地圖導航＋精確搜索」提升 Claude Code 程式碼理解效率
type: item
date: 2026-07-08T06:52:00+00:00
description: 以下將 codegraph 納入實際項目運作查看使用效益 $ (py3.10) D:\OlgCase\RS\HXXR_3>codegraph init ┌ Initializing CodeGraph │ ◆ Initialized in D:\OlgCase\RS\HXXR_3 | | * Scanning files - 2,371 found | * Parsing code - done | * Resolving refs - done │ ◆ Indexed 2,371 files │ ● 69,568 nodes, 192,594 edges in 53.1s │ └ Done $ (py3.10) D:\OlgCase\RS\HXXR_3>codegraph status CodeGraph Status Project: D:\OlgCase\RS\HXXR_3 Index Statistics: Files: 2,371 Nodes: 69,568 Edges: 192,594 DB Size: 147.56 MB Backend: node:sqlite - built-in (full WAL) Journal: wal Nodes by Kind: method 25,000 field 16,000 import 8,000 enum_member 3,000 property 3,737 class 3,500 constant 2,515 file 2,365 namespace 1,581 struct 527 enum 421 variable 276 function 253 interface 207 Files by Language: csharp 2,285 python 42 xml 14 javascript 12 php 10 yaml 6 c 1 objc 1 [OK] Index is up to date 進入項目后提出需求給 cc cc先是透過llm分析出 keyword，然後查詢 codegraph 可用工具，再將關鍵詞輸入給codegraph "query": "UIAIDebugMenu AIDebugMenu aiwnd close hide AICondBlock refresh ai decision" 對話内容如下： 後續都是 Grep、Read ，如圖： codegraph 的實際使用流程并不是全面替代 grep、read，而是將項目 code roadmap 查找出來 先用 codegraph 做「地圖導航」 用戶提出需求 ↓ mcp__codegraph__codegraph_explore ← 只用一次 ↓ 目的：快速了解整個專案結構 "讓我先知道這個 codebase 長什麼樣" codegraph 的作用是給 Claude 一個高層次的程式碼地圖，知道哪些檔案、哪些 class、哪些 function 存在。 再來用 Grep + Read 做「精確搜索」 已知地圖後 ↓ Grep × 8 ← 搜尋具體關鍵字（如 "aiwnd", "CloseUI", 事件名稱） Read × 4 ← 讀取找到的具體檔案內容 後面因爲 Claude 已經知道方向了，就不需要再用 codegraph，改用更精準、更輕量的工具。 本質差異 工具 用途 比喻 codegraph 理解整體結構、依賴關係 看地圖 Grep 搜尋特定字串/pattern 用關鍵字查字典 Read 讀取完整檔案內容 打開具體頁面閱讀 沒有全部使用 codegraph 的原因大概也是如下： codegraph 執行成本 每次呼叫需要分析程式碼結構，在 CPU、IO 上比 grep 慢且耗資源。 必要性 第一次 codegraph 已給出足夠的「索引」，後續只需要針對性搜尋。 Claude 的工具選擇策略 不確定結構 → codegraph（掃描全局） 已知方向 → grep（精確定位） 找到目標 → read（深入閱讀） 如下是 Claude 的工作流程： codegraph（1次）→ 建立認知地圖 ↓ grep（8次）→ 精確定位關鍵程式碼 ↓ read（4次）→ 深入理解細節

從 Shannon 熵到 Everett 資訊：互資訊非負性證明全解析
type: item
date: 2026-07-06T21:23:00+00:00
description: Shannon 熵（標準定義） $$ H(X) \;=\; -\sum_i P_i \log P_i \;\ge\; 0 $$ $H$ 代表的是 Entropy 不確定性 / 亂度；分布越平均，$H$ 越大（越不確定）；分布越尖（越確定），$H$ 越小。 均勻分布（n 個等機率）達最大 $H = \log n$；確定事件 $H = 0$。 在上述説到分布越平均，熵越大越不確定，大概可以思考為篩子6個面每一個面的概率都為 $\frac{1}{6}$，這代表相對的不確定性，因爲你無法明確的説出接下來會篩中1或3， $熵 \approx 0$：但如果颱風來了，那麽大概率你會說今天會下雨，這就是確定性高 $熵 \gt 0$：篩子6面 Everett 的「資訊」 Everett 不用 $H$，他定義資訊（information）為： $$ I_X \;=\; \sum_i P_i \log P_i \;=\; -\,H(X) $$ ⚠️ 注意正負號：Everett 的 $I_X$ 就是 負熵（negative entropy）。 Shannon $H$ Everett $I$ 公式 $-\sum P\log P$ $+\sum P\log P$ 意義 不確定性 「銳利度 / 已知程度」 分布變尖時 變小 變大 確定事件 $0$（最小） $0$（最大，因 $P\log P\to0$） 原本的shannon熵在不確定性大時 H 值增加，而確定的時候 H 值為 0 另外一個解釋方式則是 Everett 想要的「觀測之後會增加」的量。理由是觀測讓分布變尖 → 不確定性 $H$ 下降 → 「資訊」$I$ 上升。用 $I$ 講「觀測獲得資訊」在符號上更順。 §4 互資訊 = 關聯（全章的主角） 兩個變數綁多緊？Everett 定義 X 與 Y 的關聯（correlation）： $$ \{X,Y\} \;=\; \sum_{i,j} P(x_i,y_j)\,\log\frac{P(x_i,y_j)}{P(x_i)\,P(y_j)} $$ 這正是現代資訊論的互資訊（mutual information） $I(X;Y)$。逐項拆解： 若 X、Y 獨立：$P(x,y)=P(x)P(y)$ → 每項 $\log 1 = 0$ → $\{X,Y\}=0$。沒關聯。 若 X、Y 有關聯：聯合機率偏離「獨立預測」→ $\{X,Y\}>0$。 證明「互資訊 I(X;Y) 一定 ≥ 0」 看這張圖:藍色曲線是 y = log t(自然對數,凹函數),橘色直線是 y = t − 1(在 t=1 處的切線)。因為 log 是凹函數,它的切線永遠在它自己上方——這條直線只在切點 t=1 碰到曲線,其他地方都比曲線高。這就是整段推導唯一用到的「物理直覺」。 1. 互資訊的定義 $I(X;Y) = \sum p(x,y) \log\frac{p(x,y)}{p(x)p(y)}$ 令 $p = p(x,y)(真實聯合分布)$、$q = p(x)p(y)$(假裝獨立時「應該」長怎樣)。於是 $I(X;Y) = \sum p \log\frac{p}{q}$ 這就是 p 對 q 的 KL 散度。 2. 套用圖上的不等式 圖上畫的是 log t ≤ t − 1。現在把 t 換成 q/p(注意,是反過來的比值): $log\frac{q}{p} \le \frac{q}{p} - 1$ 3. 兩邊同乘 p,再對所有 (x,y) 求和 因為 p ≥ 0,不等式方向不變: $p\log\frac{q}{p} \le q - p$ 對所有 (x,y) 加總: $\sum p\log\frac{q}{p} \le \sum q - \sum p$ 4. 右邊為什麼是 0 $\sum q(x,y) = \sum p(x)p(y) = \left(\sum p(x)\right)\left(\sum p(y)\right) = 1\times 1 = 1$ $\sum p(x,y) = 1 \quad \text{(本來就是一個機率分布)}$ 所以右邊 = 1 − 1 = 0。 5. 左邊等於什麼 $\sum p\log\frac{q}{p} = -\sum p\log\frac{p}{q} = -I(X;Y)$ 6. 合起來 $-I(X;Y) \le 0 \;\Longrightarrow\; I(X;Y) \ge 0$ 而且,因為 log t = t − 1 唯一在 t = 1 成立(就是圖上那個相切點),所以 I(X;Y) = 0 的充要條件是「對所有 (x,y) 都有 q/p = 1」,也就是 p(x,y) = p(x)p(y) 處處成立——也就是 X、Y 獨立。 所以整個證明的邏輯鏈是…