<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://rhincodone.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://rhincodone.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2025-08-05T03:56:08+00:00</updated><id>https://rhincodone.github.io/feed.xml</id><title type="html">blank</title><subtitle>A simple, whitespace theme for academics. Based on [*folio](https://github.com/bogoli/-folio) design. </subtitle><entry><title type="html">Structured Data Understanding — From LLMs to the Human Brain to a Biologically Inspired Implementation</title><link href="https://rhincodone.github.io/posts/2025-08-01-Structured/" rel="alternate" type="text/html" title="Structured Data Understanding — From LLMs to the Human Brain to a Biologically Inspired Implementation"/><published>2025-08-01T00:00:00+00:00</published><updated>2025-08-01T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/Structured</id><content type="html" xml:base="https://rhincodone.github.io/posts/2025-08-01-Structured/"><![CDATA[<h1 id="structured-data-understanding--from-llms-to-the-human-brain-to-a-biologically-inspired-implementation">Structured Data Understanding — From LLMs to the Human Brain to a Biologically Inspired Implementation</h1> <h2 id="1-problem-background">1. Problem Background</h2> <p>In risk-control scenarios, structured data (e.g. behavior sequences, social graphs, transaction tables) plays a core role in threat detection. While large language models (LLMs) excel at understanding text and images, they still face limitations in making sense of and reasoning over structured data:</p> <ul> <li><strong>Difficulty aligning structure with semantics</strong>: Graph or temporal structures are hard to map into the language-based semantic space</li> <li><strong>Input length and efficiency bottlenecks</strong>: Linearizing large-scale structured data easily exceeds the input limits of LLMs</li> <li><strong>Weak multi-step reasoning ability</strong>: Complex relationships in structured data are difficult for LLMs to handle using chain-of-thought</li> <li><strong>Immature fusion of heterogeneous sources</strong>: Combining graph, sequence, and tabular data into a unified representation remains an open challenge</li> </ul> <p>Models like GraphGPT, GraphRAG, and StructGPT have begun to explore how to integrate structural information with language, but most still focus on a single data type (either graphs or sequences), leaving multi-source fusion and reasoning mechanisms underdeveloped.</p> <hr/> <h2 id="2-limitations-of-llms-for-this-problem">2. Limitations of LLMs for This Problem</h2> <ul> <li><strong>Training data lacks structure-driven tasks</strong>: LLMs haven’t been pretrained on graph-specific or sequence-inductive tasks</li> <li><strong>Prompt + tool integration is limited</strong>: While RAG or tools like StructGPT can assist, they still depend on external structural models</li> <li><strong>No native structured reasoning</strong>: Chain-of-thought prompting is not well suited for deeply structured contexts; specialized structural reasoning strategies are needed</li> </ul> <p>This suggests exploring a <strong>biologically inspired architecture</strong> that mimics the brain’s ways of processing structured inputs to enhance LLM capabilities for complex reasoning.</p> <hr/> <h2 id="3-how-the-human-brain-tackles-it-four-structural-mechanisms">3. How the Human Brain Tackles It: Four Structural Mechanisms</h2> <h3 id="31-brain-richclub-network-long-range-hub-organization">3.1 Brain Rich‑Club Network (Long-range hub organization)</h3> <p>The brain features a network of “rich-club” nodes—highly interconnected hub regions that integrate information across functional zones and support high-level cognition.</p> <h3 id="32-structured-slots-sequence-memory--cognitive-map-integration">3.2 Structured Slots (Sequence Memory + Cognitive Map Integration)</h3> <p>Through prefrontal–hippocampal mechanisms, the brain unifies sequence memory (state-action transitions) and cognitive maps (graph structures). Whittington et al. (2025) propose the <strong>structured slots</strong> model to explain this integration.</p> <h3 id="33-episodic-buffer-working-memory-integration-mechanism">3.3 Episodic Buffer (Working Memory Integration Mechanism)</h3> <p>According to Baddeley’s working memory model, the brain uses an <strong>episodic buffer</strong> to fuse visual, language, and structural information into a coherent contextual representation.</p> <h3 id="34-predictive-coding-error-driven-learning-mechanism">3.4 Predictive Coding (Error-driven Learning Mechanism)</h3> <p>The brain employs top-down predictions and bottom-up error signals in a loop, iteratively updating its internal model, enabling stable structure perception and semantic fusion.</p> <hr/> <h2 id="4-biologically-inspired-modular-design-python--pytorch-implementation">4. Biologically Inspired Modular Design (Python / PyTorch Implementation)</h2> <h3 id="system-architecture-overview">System Architecture Overview</h3> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Graph Module (rich‑club graph)
↓
Slots Module (structured slots)
↓
Episodic Buffer (structure + semantic fusion)
↓
Predictive Coding Layer (prediction + SGD learning)

</code></pre></div></div> <p>Each module corresponds to one of the brain-inspired mechanisms and works together to facilitate structured data understanding and semantic integration.</p> <hr/> <h3 id="41-graph-module-rich-club-structure--gnn-implementation">4.1 Graph Module: rich-club structure + GNN implementation</h3> <ul> <li>Build a central dense subgraph (rich-club) plus two sparse subgraphs (each for a subtasks) and interconnect them</li> <li>Use NetworkX to generate the graph, and PyTorch Geometric’s <code class="language-plaintext highlighter-rouge">GCNConv</code> to extract node embeddings</li> <li>Aggregate embeddings of the central nodes to produce a rich-club representation</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">networkx</span> <span class="k">as</span> <span class="n">nx</span>
<span class="kn">import</span> <span class="n">random</span>
<span class="kn">import</span> <span class="n">torch</span>
<span class="kn">from</span> <span class="n">torch_geometric.utils</span> <span class="kn">import</span> <span class="n">from_networkx</span>
<span class="kn">from</span> <span class="n">torch_geometric.nn</span> <span class="kn">import</span> <span class="n">GCNConv</span>
<span class="bp">...</span>
</code></pre></div></div> <hr/> <h3 id="42-slots-module-structured-slots-implementation">4.2 Slots Module: Structured Slots Implementation</h3> <ul> <li>Use a set of trainable slots to simulate prefrontal activity slots</li> <li>Apply attention to read relevant slot states and write updates to them</li> <li>Train the module so it encodes both sequence memory and cognitive map representations</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">SlotsModule</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="n">weights</span> <span class="o">=</span> <span class="nf">softmax</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="n">slots</span><span class="p">)</span> <span class="o">@</span> <span class="n">key</span><span class="p">)</span>
        <span class="n">slot_read</span> <span class="o">=</span> <span class="n">weighted</span> <span class="nb">sum</span> <span class="n">over</span> <span class="n">slots</span>
        <span class="n">new_slot</span> <span class="o">=</span> <span class="n">slot_read</span> <span class="o">+</span> <span class="n">self</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">slot_read</span><span class="p">,</span> <span class="n">new_slot</span>
</code></pre></div></div> <hr/> <h3 id="43-episodic-buffer-multimodal-structure--semantic-fusion">4.3 Episodic Buffer: Multimodal Structure + Semantic Fusion</h3> <ul> <li>Concatenate the rich-club representation from GraphModule with the slot_read representation</li> <li>Use a linear projection layer to produce a fused contextual embedding</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">EpisodicBuffer</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">graph_repr</span><span class="p">,</span> <span class="n">slot_repr</span><span class="p">):</span>
        <span class="n">fused</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="nf">cat</span><span class="p">([</span><span class="n">graph_repr</span><span class="p">,</span> <span class="n">slot_repr</span><span class="p">],</span> <span class="n">dim</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">torch</span><span class="p">.</span><span class="nf">relu</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="nf">combine</span><span class="p">(</span><span class="n">fused</span><span class="p">))</span>
</code></pre></div></div> <hr/> <h3 id="44-predictive-coding-layer-error-driven-learning">4.4 Predictive Coding Layer: Error-driven learning</h3> <ul> <li>Build a layer <code class="language-plaintext highlighter-rouge">predict(state)</code> to predict the next state</li> <li>Compute error <code class="language-plaintext highlighter-rouge">state - pred</code> as the training loss</li> <li>Use SGD to update parameters and simulate predictive coding dynamics</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">PredCodeLayer</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
        <span class="n">pred</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">predict</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
        <span class="n">err</span> <span class="o">=</span> <span class="n">state</span><span class="p">.</span><span class="nf">detach</span><span class="p">()</span> <span class="o">-</span> <span class="n">pred</span>
        <span class="n">loss</span> <span class="o">=</span> <span class="n">err</span><span class="p">.</span><span class="nf">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">).</span><span class="nf">mean</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">pred</span><span class="p">,</span> <span class="n">loss</span><span class="p">,</span> <span class="n">err</span>
</code></pre></div></div> <hr/> <h2 id="5-integrated-example-pseudocode-structure">5. Integrated Example Pseudocode Structure</h2> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Inputs include: graph data, behavior sequence key, expected next slot state, etc.
</span>
<span class="n">h</span><span class="p">,</span> <span class="n">center_repr</span> <span class="o">=</span> <span class="nf">graph_module</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">slot_read</span><span class="p">,</span> <span class="n">new_slot</span><span class="p">,</span> <span class="n">att</span> <span class="o">=</span> <span class="nf">slots_module</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="n">buffer_state</span> <span class="o">=</span> <span class="nf">episodic_buffer</span><span class="p">(</span><span class="n">center_repr</span><span class="p">,</span> <span class="n">slot_read</span><span class="p">)</span>
<span class="n">pred</span><span class="p">,</span> <span class="n">loss_pc</span><span class="p">,</span> <span class="n">err</span> <span class="o">=</span> <span class="nf">predcode_layer</span><span class="p">(</span><span class="n">buffer_state</span><span class="p">)</span>
<span class="n">loss_slot</span> <span class="o">=</span> <span class="bp">...</span>
<span class="n">loss</span> <span class="o">=</span> <span class="n">loss_pc</span> <span class="o">+</span> <span class="n">loss_slot</span>
<span class="n">loss</span><span class="p">.</span><span class="nf">backward</span><span class="p">()</span>
<span class="n">optimizer</span><span class="p">.</span><span class="nf">step</span><span class="p">()</span>
</code></pre></div></div> <p>This design is intended to <strong>simulate rich-club architecture, structured slots, episodic buffer-based integration, and predictive-coding-based learning</strong>, all trained with SGD.</p> <hr/> <h2 id="6-future-outlook">6. Future Outlook</h2> <ul> <li>Starting from <strong>LLM limitations in structured data understanding</strong>, we draw inspiration from four brain mechanisms</li> <li>Each module is mapped to a neurally plausible function and implemented in PyTorch</li> <li>The integrated system uses predictive coding + SGD to simulate bio-inspired learning and semantic-structure fusion</li> <li>It can be extended to downstream risk-control tasks: graph-based account network reasoning, slot-based behavior sequence storage, buffer-level multimodal fusion, and predictive coding for structure-aware reasoning</li> <li>If this paradigm shows promising results on specific tasks, it may further motivate <strong>bio-inspired research directions</strong></li> </ul> <hr/>]]></content><author><name></name></author><category term="Brain_LLM_En"/><category term="metrics"/><summary type="html"><![CDATA[Structured Data Understanding — From LLMs to the Human Brain to a Biologically Inspired Implementation]]></summary></entry><entry><title type="html">结构化数据理解问题 — 从 LLM 到人脑，再到仿生实现</title><link href="https://rhincodone.github.io/posts/2025-08-01-%E7%BB%93%E6%9E%84%E5%8C%96%E6%95%B0%E6%8D%AE%E7%90%86%E8%A7%A3%E9%97%AE%E9%A2%98/" rel="alternate" type="text/html" title="结构化数据理解问题 — 从 LLM 到人脑，再到仿生实现"/><published>2025-08-01T00:00:00+00:00</published><updated>2025-08-01T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/%E7%BB%93%E6%9E%84%E5%8C%96%E6%95%B0%E6%8D%AE%E7%90%86%E8%A7%A3%E9%97%AE%E9%A2%98</id><content type="html" xml:base="https://rhincodone.github.io/posts/2025-08-01-%E7%BB%93%E6%9E%84%E5%8C%96%E6%95%B0%E6%8D%AE%E7%90%86%E8%A7%A3%E9%97%AE%E9%A2%98/"><![CDATA[<h1 id="结构化数据理解问题--从-llm-到人脑再到仿生实现">结构化数据理解问题 — 从 LLM 到人脑，再到仿生实现</h1> <h2 id="1-问题背景">1. 问题背景</h2> <p>风控场景中，结构化数据（如行为序列、社交图谱、交易表格）是风险检测的核心。当前大语言模型（LLM）对文本和图像理解能力强，但对结构化数据的理解与推理仍存在难点：</p> <ul> <li><strong>结构语义对齐困难</strong>：图结构或时序结构难以映射到语言语义空间</li> <li><strong>长输入与效率瓶颈</strong>：大规模结构数据直接线性化极易超出模型输入限制</li> <li><strong>推理能力弱</strong>：缺乏对多步链式推理中复杂结构关系的处理能力</li> <li><strong>异构数据融合不成熟</strong>：图 + 序列 + 表格等结构数据的联合理解仍是开放问题</li> </ul> <p>相关模型如 GraphGPT、GraphRAG、StructGPT 都开始探索结构与语言融合的方法，但仍主要聚焦单一数据类型（图或序列），对多源融合与推理机制仍不足。</p> <hr/> <h2 id="2-llm-面对该问题时的局限">2. LLM 面对该问题时的局限</h2> <ul> <li><strong>训练数据不包含结构化任务</strong>，LLM 本体未暴露图结构或序列归纳学习任务</li> <li><strong>prompt + 工具调用有限</strong>：虽然可用 RAG 或 struct‑GPT 结构接口辅助，但仍依赖外部结构模型</li> <li><strong>缺乏逐步推理机制</strong>：思维链设计不适合结构复杂场景，需要更多针对结构的推理策略</li> </ul> <p>因此，或许可以尝试引入<strong>一种仿脑式结构</strong>，模仿人脑处理结构化输入的机制，来尝试从仿生的角度提升模型对复杂结构推理的理解能力。</p> <hr/> <h2 id="3-人脑如何解决四种结构处理机制">3. 人脑如何解决：四种结构处理机制</h2> <h3 id="31-brain-richclub-网络大规模脑结构组织">3.1 Brain Rich‑Club 网络（大规模脑结构组织）</h3> <p>大脑中有“rich‑club”节点——即高度互联的枢纽子网，协调不同功能区间的信息整合与高级认知处理。</p> <h3 id="32-structured-slots序列记忆与认知地图融合">3.2 Structured Slots（序列记忆与认知地图融合）</h3> <p>通过前额叶-海马体机制，人脑可将序列记忆（状态‑动作转换）与认知地图（graph）统一表示。Whittington 等2025 年提出的<strong>structured slots</strong> 模型将这两类结构整合解释。</p> <h3 id="33-episodic-buffer工作记忆结构融合机制">3.3 Episodic Buffer（工作记忆结构融合机制）</h3> <p>Baddeley 的工作记忆模型指出，大脑通过 episodic buffer 将视觉、语言、结构信息融合在一起，构建统一的情境表示。</p> <h3 id="34-predictive-coding预测误差驱动学习机制">3.4 Predictive Coding（预测‑误差驱动学习机制）</h3> <p>大脑通过顶层预测、底层误差信号迭代更新内部模型，形成稳定的结构感知与语义融合机制。</p> <hr/> <h2 id="4-仿脑式模块设计思路python--pytorch-实现">4. 仿脑式模块设计思路（Python / PyTorch 实现）</h2> <h3 id="模块总体架构">模块总体架构</h3> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Graph Module（rich‑club 图）
↓
Slots Module（structured slots）
↓
Episodic Buffer（结构+语义融合）
↓
Predictive Coding Layer（预测编码 + SGD 学习）

</code></pre></div></div> <p>每个模块分别对应人脑的四种机制，通过融合实现结构理解与语义集成。</p> <hr/> <h3 id="41-graph-modulerichclub-架构--gnn-实现">4.1 Graph Module：rich‑club 架构 + GNN 实现</h3> <ul> <li>构建一个中心 dense 子图（rich-club）+ 两个 sparse 子图（处理不同子任务）+ 跨子图连接</li> <li>使用 NetworkX 构造图，并通过 PyTorch Geometric 的 <code class="language-plaintext highlighter-rouge">GCNConv</code> 提取节点 embedding</li> <li>聚合中心节点生成 rich‑club 表征</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">networkx</span> <span class="k">as</span> <span class="n">nx</span>
<span class="kn">import</span> <span class="n">random</span>
<span class="kn">import</span> <span class="n">torch</span>
<span class="kn">from</span> <span class="n">torch_geometric.utils</span> <span class="kn">import</span> <span class="n">from_networkx</span>
<span class="kn">from</span> <span class="n">torch_geometric.nn</span> <span class="kn">import</span> <span class="n">GCNConv</span>
<span class="bp">...</span>
</code></pre></div></div> <hr/> <h3 id="42-slots-modulestructured-slots-实现">4.2 Slots Module：Structured Slots 实现</h3> <ul> <li>使用一个可读写的 slot 集合模拟前额叶活动槽</li> <li>利用 attention 从 slots 中读取相关槽状态，并更新特定槽表示</li> <li>通过训练使 slot 模块能编码序列记忆与认知图状态</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">SlotsModule</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="n">weights</span> <span class="o">=</span> <span class="nf">softmax</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="n">slots</span><span class="p">)</span> <span class="o">@</span> <span class="n">key</span><span class="p">)</span>
        <span class="n">slot_read</span> <span class="o">=</span> <span class="n">weighted</span> <span class="nb">sum</span> <span class="n">of</span> <span class="n">slots</span>
        <span class="n">new_slot</span> <span class="o">=</span> <span class="n">slot_read</span> <span class="o">+</span> <span class="n">self</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">slot_read</span><span class="p">,</span> <span class="n">new_slot</span>
</code></pre></div></div> <hr/> <h3 id="43-episodic-buffer多模态结构与语义融合">4.3 Episodic Buffer：多模态结构与语义融合</h3> <ul> <li>将 GraphModule 中 rich-club 表征与 SlotsModule 返回的 slot 读取表示拼接</li> <li>用一个线性投影层构造统一上下文 embedding</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">EpisodicBuffer</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">graph_repr</span><span class="p">,</span> <span class="n">slot_repr</span><span class="p">):</span>
        <span class="n">fused</span> <span class="o">=</span> <span class="nf">concat</span><span class="p">(...)</span>
        <span class="k">return</span> <span class="nf">activation</span><span class="p">(</span><span class="nf">combine</span><span class="p">(</span><span class="n">fused</span><span class="p">))</span>
</code></pre></div></div> <hr/> <h3 id="44-predictive-coding-layer预测-误差驱动学习">4.4 Predictive Coding Layer：预测-误差驱动学习</h3> <ul> <li>构建一个预测层 <code class="language-plaintext highlighter-rouge">predict(state)</code>，预测下一时刻 state</li> <li>计算误差 <code class="language-plaintext highlighter-rouge">state - pred</code>，作为损失进行 SGD 更新</li> <li>结合 PyHGF 或使用原生 SGD 实现预测编码机制的结构化学习</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">PredCodeLayer</span><span class="p">(</span><span class="n">nn</span><span class="p">.</span><span class="n">Module</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(...):</span>
        <span class="bp">...</span>
    <span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
        <span class="n">pred</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">predict</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
        <span class="n">err</span> <span class="o">=</span> <span class="n">state</span><span class="p">.</span><span class="nf">detach</span><span class="p">()</span> <span class="o">-</span> <span class="n">pred</span>
        <span class="n">loss</span> <span class="o">=</span> <span class="n">err</span><span class="p">.</span><span class="nf">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">).</span><span class="nf">mean</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">pred</span><span class="p">,</span> <span class="n">loss</span><span class="p">,</span> <span class="n">err</span>
</code></pre></div></div> <hr/> <h2 id="5-模拟整合代码示例结构伪码">5. 模拟整合代码示例结构（伪码）</h2> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 输入包括：graph data、行为序列 key、预期下一个 slot state 等
</span>
<span class="n">h</span><span class="p">,</span> <span class="n">center_repr</span> <span class="o">=</span> <span class="nf">graph_module</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">slot_read</span><span class="p">,</span> <span class="n">new_slot</span><span class="p">,</span> <span class="n">att</span> <span class="o">=</span> <span class="nf">slots_module</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="n">buffer_state</span> <span class="o">=</span> <span class="nf">episodic_buffer</span><span class="p">(</span><span class="n">center_repr</span><span class="p">,</span> <span class="n">slot_read</span><span class="p">)</span>
<span class="n">pred</span><span class="p">,</span> <span class="n">loss_pc</span><span class="p">,</span> <span class="n">err</span> <span class="o">=</span> <span class="nf">predcode_layer</span><span class="p">(</span><span class="n">buffer_state</span><span class="p">)</span>
<span class="n">loss_slot</span> <span class="o">=</span> <span class="p">(...)</span>
<span class="n">loss</span> <span class="o">=</span> <span class="n">loss_pc</span> <span class="o">+</span> <span class="n">loss_slot</span>
<span class="n">loss</span><span class="p">.</span><span class="nf">backward</span><span class="p">()</span>
<span class="n">optimizer</span><span class="p">.</span><span class="nf">step</span><span class="p">()</span>
</code></pre></div></div> <p>这种设计尝试<strong>模拟人脑 rich‑club 架构、structured slots、episodic buffer 多模态融合、predictive coding-based 更新机制</strong>，并通过 SGD 更新整体系统。</p> <hr/> <h2 id="6-展望">6. 展望</h2> <ul> <li>从<strong>LLM 的结构理解弱点</strong>出发，我们借鉴人脑<strong>四大机制</strong>（rich‑club、slots、buffer、predictive coding）构建模块化系统；</li> <li>每个模块对应脑机制，并可替换成 PyTorch 代码；</li> <li>整体系统通过预测编码机制加 SGD 更新，模拟生物启发式学习与结构语义融合；</li> <li>可逐步扩展到风控任务：graph 表征推理账号网络、slots 存储行为序列、buffer 融合多源信息、predcode 提高结构推理能力。</li> <li>如果此模式在特定任务上具备一定的效果，或许可以尝试进一步开展仿生方面的研究。</li> </ul>]]></content><author><name></name></author><category term="Brain_LLM"/><category term="metrics"/><summary type="html"><![CDATA[本文主要介绍了LLM的结构化数据理解问题，并延伸思考至人脑仿生。]]></summary></entry><entry><title type="html">Hypothesis Interpretation of Differential Privacy</title><link href="https://rhincodone.github.io/posts/2025-01-08-Hypothesis-Interpretation-of-Differential-Privacy/" rel="alternate" type="text/html" title="Hypothesis Interpretation of Differential Privacy"/><published>2025-01-08T00:00:00+00:00</published><updated>2025-01-08T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/Hypothesis-Interpretation-of-Differential-Privacy</id><content type="html" xml:base="https://rhincodone.github.io/posts/2025-01-08-Hypothesis-Interpretation-of-Differential-Privacy/"><![CDATA[<h1 id="hypothesis-interpretation-of-differential-privacy">Hypothesis Interpretation of Differential Privacy</h1> <h2 id="content">Content</h2> <ul> <li><strong>Basic definition of differential privacy</strong></li> <li><strong>Hypothesis interpretation of differential privacy</strong></li> <li><strong>Membership inference attack (MIA) and hypothesis testing</strong></li> <li><strong>Auditing differential privacy with MIA</strong></li> <li><strong>Conclusion</strong></li> </ul> <hr/> <h2 id="basic-definition-of-differential-privacy">Basic definition of differential privacy</h2> <p>Let’s start with the basic definition of differential privacy. Specifically, we only focus on the widely adopted relaxed \((\epsilon,\delta)-\text{differential privacy}\).</p> <p><strong>Definition 1:</strong> \(M\) is \((\epsilon,\delta)-\text{differential privacy}\) if, for all neighboring data \(D_0\) and \(D_1\) that differ in at most one sample, and for all measurable sets \(\mathcal{O}\),</p> \[P(M(D_0)\in \mathcal{O}) \leq e^\epsilon P(M(D_1)\in \mathcal{O}) + \delta\] <p>and symmetrically,</p> \[P(M(D_1)\in \mathcal{O}) \leq e^\epsilon P(M(D_0)\in \mathcal{O}) + \delta\] <p>These symmetric conditions highlight that differential privacy mathematically defines the “indistinguishability” of the output of \(M(D_0)\) and \(M(D_1)\) on the measurable sets \(\mathcal{O}\) (output space).</p> <p>This “indistinguishability”, a binary classification problem, can be naturally described by hypothesis testing.</p> <hr/> <h2 id="hypothesis-interpretation-of-differential-privacy-1">Hypothesis interpretation of differential privacy</h2> <hr/> <p>Based on the “indistinguishablity” on the \(M(D_0)\) and \(M(D_1)\), we set up two hypothesis,</p> \[H_0: \text{M used } D_0 \tag{DP: Null hypothesis}\] \[H_1: \text{M used } D_1 \tag{DP: Alternative hypothesis}\] <p>Now let’s interpret what benefits we can get from it. We start with two errors in the basic hypothesis testing.</p> <h3 id="type-i-error-significants-level">Type I Error (significants level</h3> <p>This occurs when the null hypothesis (\(H_0\)) is <strong>rejected</strong> even though it is true, i.e., M is predicted did not use \(D_0\) when it actually did. The probability of this error is defined as:</p> \[\alpha = P_{\text{FA}}(D_0, D_1, M, S) \equiv P(M(D_0) \in S) \tag{1}\] <p>where \(S\) is the rejection region for \(H_0\).</p> <p>Type I error is also called “significance level.” It represents the maximum probability of making a Type I error that we are willing to tolerate in a test. When we say a test is conducted at the \(\alpha\) significance level, we mean:</p> \[P(\text{Reject } H_0|H_0 \text{ is true}) = \alpha\] <p>That is, if we repeated the same test many times under conditions where \(H_0\) is actually true, we’d expect to falsely reject \(H_0\) about \(\alpha \times 100\%\) of time. Thus, \(\alpha\) control how “strict” our test is in claiming a significant result</p> <h3 id="type-ii-error">Type II Error</h3> <p>This occurs when the null hypothesis (\(H_0\)) is <strong>not rejected</strong> even though it is false, i.e., M is predicted to use \(D_0\) when it actually did not. The probability of this error is defined as:</p> \[\beta = P_{\text{MD}}(D_0, D_1, M, S) \equiv P(M(D_1) \in \bar{S}),\ \tag{2}\] <p>where \(\bar{S}\) is the complement of the rejection region \(S\).</p> <p>Since \(\beta\) is the probability of mistakenly accepting the null hypothesis, \(1-\beta\) represents the correctly accepting the null hypothesis. In other words, if there really is a difference or effect to be found, a test with high power (\(1-\beta\)) is more likely to detect it. Thus, we also term \(1-\beta\) as the “power” of hypothesis testing.</p> <h3 id="differential-privacy-in-terms-of-hypothesis-testing">Differential Privacy in Terms of Hypothesis Testing</h3> <p>Here we turn to why we want to use a hypothesis to represent differential privacy. Actually, the hypothesis interpretation of differential privacy condition imposes constraints on the probabilities of <strong>false alarms</strong> (Type I errors) and <strong>missed detections</strong> (Type II errors). Let’s see how:</p> <p>For a mechanism \(M\) to satisfy \((\epsilon, \delta)\)-differential privacy, the following conditions must hold for all neighboring databases \(D_0\) and \(D_1\), and for all rejection regions \(S\):</p> <ol> <li> \[\alpha + e^\epsilon \beta \geq 1 - \delta \tag{3}\] </li> <li> \[e^\epsilon \alpha + \beta \geq 1 - \delta \tag{4}\] </li> <li> \[\alpha \leq e^\epsilon(1-\beta) + \delta \tag{5}\] </li> <li> \[1 -\beta \leq e^\epsilon \alpha + \delta \tag{6}\] </li> </ol> <p><strong>Proof:</strong></p> <p>Assuming \(M\) is \((\epsilon,\delta)-\text{differentially private}\) on neigboring datasets \(D_0\) and \(D_1\), and the complement sets \(\bar{S}\) of rejection region \(\), we have:</p> \[P(M(D_0)\in \bar{S}) \leq e^\epsilon P(M(D_1)\in \bar{S}) + \delta \tag{7}\] <p>and</p> \[P(M(D_1)\in \bar{S}) \leq e^\epsilon P(M(D_0)\in \bar{S}) + \delta \tag{8}\] <p>Combining equations 1, 2, 7, and 8, we can derive equations 3, and 4.</p> <p>Since \(\bar{S}\) is the complement set of rejection region \(S\), and \(\bar{S}\) is a measurable sets. \(S\) is also a measurable set. Thus equations 7, and 8 are also valid on \(S\):</p> \[P(M(D_0)\in S) \leq e^\epsilon P(M(D_1)\in S) + \delta \tag{9}\] <p>and</p> \[P(M(D_1)\in S) \leq e^\epsilon P(M(D_0)\in S) + \delta \tag{10}\] <p>Combining equations 1, 2, 9, and 10, we can derive equations 5, and 6.</p> <h3 id="privacy-region">Privacy Region</h3> <p>Now we can define a privacy region for \((\epsilon,\delta)-\text{differential privacy}\) as :</p> \[\mathcal{R}(\epsilon , \delta) \equiv \{(\alpha,\beta)|\alpha + e^\epsilon \beta \geq 1 - \delta, \text{ and }e^\epsilon \alpha + \beta \geq 1 - \delta,\text{ and }\alpha \leq e^\epsilon(1-\beta) + \delta,\text{ and } 1 -\beta \leq e^\epsilon \alpha + \delta\}\] <p>We can also define a privacy region for \((\epsilon,\delta)-\text{differentially private}\) mechanism \(M\) on neigboring datasets \(D_0\) and \(D_1\), and any rejection region \(S\subseteq \mathcal{O}\) as:</p> \[\mathcal{R}(M,D_0,D_1) \equiv \text{conv}(\{(\alpha,\beta)|\text{ for all }S\subseteq \mathcal{O}\})\] <p>Conv is the convex hull of a point set.</p> <hr/> <h2 id="membership-inference-attack-mia-and-hypothesis-testing">Membership inference attack (MIA) and hypothesis testing</h2> <hr/> <h3 id="what-are-membership-inference-attacks-mia">What are membership inference attacks (MIA)</h3> <p>Membership inference attacks aim to distinguish if a given data sample(s) is in the training set of a target model. It’s a typical binary distinguishing attack. MIA usually classifies a sample as “member” or “non-member” which represents whether the sample is training data or not. Typically, “Member” is a positive prediction, and “non-member” is a negative prediction.</p> <h3 id="differential-privacy-and-mia">Differential privacy and MIA</h3> <p>Since MIAs are distinguishing attacks, we can also use the hypothesis to perform the attacking target:</p> <p>Assuming mechanism \(M\) is a machine-learning model, victim sample is \(x\),</p> \[H_0: M\text{ is not trained on } x \tag{MIA: Null hypothesis}\] \[H_1: M \text{ is trained on } x \tag{MIA: Alternative hypothesis}\] <p>Assuming \(x\in D_1\) and \(x\notin D_0\), that is, \(D_0\) and \(D_1\) are neighboring datasets that differ only in \(x\). Then we compare the current hypothesizes in MIA with the hypothesizes in differential privacy (equation DP: Null hypothesis and DP: Alternative hypothesis), and we found that both the null hypothesizes represent the same thing - \(M\) is not trained on \(x\), and so do both alternative hypothesizes.</p> <h3 id="type-i-and-type-ii-errors-in-mia">Type I and Type II errors in MIA</h3> <p>Now we revisit the definitions of Type I and II errors and corresponding equations. We know that for the hypothesis-based membership inference attack:</p> \[\text{FPR} = \alpha = P_{\text{FA}}(D_0, D_1, M, S) \equiv P(M(D_0) \in S) \tag{11}\] \[\text{FNR} = \beta = P_{\text{MD}}(D_0, D_1, M, S) \equiv P(M(D_1) \in \bar{S}),\ \tag{12}\] <p>For simplicity we show the relationship between the confusion matrix and type I and II errors in the following table:</p> <table> <thead> <tr> <th style="text-align: left">Metric</th> <th style="text-align: center">Definition</th> <th style="text-align: right">Error Type</th> </tr> </thead> <tbody> <tr> <td style="text-align: left"><strong>True Positive Rate (TPR)</strong></td> <td style="text-align: center">\(\text{TPR} = 1 - \text{FNR}\)</td> <td style="text-align: right">Correct detection \(1-\beta\)</td> </tr> <tr> <td style="text-align: left"><strong>False Positive Rate (FPR)</strong></td> <td style="text-align: center">\(\text{FPR} = P(M(D_0) \in S)\)</td> <td style="text-align: right">Type I Error \(\alpha\)</td> </tr> <tr> <td style="text-align: left"><strong>False Negative Rate (FNR)</strong></td> <td style="text-align: center">\(\text{FNR} = P(M(D_1) \in \bar{S})\)</td> <td style="text-align: right">Type II Error \(\beta\)</td> </tr> <tr> <td style="text-align: left"><strong>True Negative Rate (TNR)</strong></td> <td style="text-align: center">\(\text{TNR} = 1 - \text{FPR}\)</td> <td style="text-align: right">Correct rejection \(1-\alpha\)</td> </tr> </tbody> </table> <h3 id="mia-audits-implementation-of-differential-privacy">MIA audits implementation of differential privacy</h3> <p>According to this table:</p> <ol> <li> \[\alpha + e^\epsilon \beta \geq 1 - \delta \iff \text{FPR}+e^\epsilon \text{FNR} \geq 1 - \delta \iff \frac{1-\text{FPR}-\delta}{1-\text{TPR}}\leq e^\epsilon \tag{13}\] </li> <li> \[e^\epsilon \alpha + \beta \geq 1 - \delta \iff e^\epsilon \text{FPR} + \text{FNR} \geq 1 - \delta \iff \frac{\text{TPR}-\delta}{\text{FPR}} \leq e^\epsilon \tag{14}\] </li> <li> \[\alpha \leq e^\epsilon(1-\beta) + \delta \iff \text{FPR} \leq e^\epsilon(1-\text{FNR}) + \delta \iff \frac{\text{FPR}-\delta}{\text{TPR}} \leq e^\epsilon \tag{15}\] </li> <li> \[1 -\beta \leq e^\epsilon \alpha + \delta \iff 1- \text{FNR} \leq e^\epsilon \text{FPR} +\delta \iff \frac{\text{TPR}-\delta}{\text{FPR}} \leq e^\epsilon \tag{16}\] </li> </ol> <p>We can find that equation 14 and 16 are equivalent. When we draw the privacy region, we can use equations 13, 15, and one from 14 and 16.</p> <p>With these three inequality, or namely the lower bound of $\epsilon$, we can audit the implementation of differential privacy. But why do we need to do auditing? In the recent couple of years, with the flourishing of machine learning, differential privacy has been incorporated into machine learning models to make a trained model differentially private. However, machine learning models are typically black-box, we don’t really know what happens inside when we train a model, let go of how epsilon changes through the entire training. To debug the potential implementation mistakes when training a differentially private model, we need to use some tool to audit the implementation.</p> <p>In the next section, I’ll introduce the basic concept of auditing differential privacy.</p> <hr/> <h2 id="auditing-differential-privacy-with-mia">Auditing differential privacy with MIA</h2> <hr/> <p>Basically, auditing differential privacy aims to use membership inference attacks to attack the target model and get the TPR, and FPR on each sample. Then we compute the lower bounds in equations 13, 15, and one of 14 and 16. If one of the lower bounds is not valid, then the implementation of differential privacy may have some bugs.</p> <p>As a simple example, you can try this <a href="https://huggingface.co/spaces/Rhincodon/privacy-region-example">app</a>.This app plots the privacy region of differential privacy on Type I &amp; Type II error rates (FPR and 1-TPR). You can try to understand the differential privacy by adjusting the \(\epsilon\) and \(\delta\) and inspecting the area of privacy region. Typically, smaller \(\epsilon\) will make a smaller privacy region and allow less combination of \((TPR,FPR)\). You can also try different points of \((TPR,FPR)\) and check if they lie in the privacy area. If a green dot shows, it indicates the \(TPR\) and \(FPR\) is valid for all equations 13 - 16. If it’s a red point, the \(TPR\) and \(FPR\) make at least one of equation 13-16 invalid.</p> <h3 id="problem-in-simple-auditing">Problem in simple auditing</h3> <p>A problem in the simplest method upon is that due to the empirical estimation of TPR, FPR are on a finite number of models, the uncertainty is inevitable if we don’t have statistical results or estimation of TPR and FPR.</p> <p>Imagine you’re conducting a <strong>privacy audit</strong> on a differentially private algorithm \(M\). The goal is to empirically estimate the privacy parameters \(\varepsilon\) and \(\delta\) by assessing an adversary’s ability to distinguish whether \(M\) was trained on dataset \(D_0\) or a neighboring dataset \(D_1\). Specifically, you aim to estimate:</p> <p><strong>Type I Error (\(\alpha\))</strong></p> <p><strong>Type II Error (\(\beta\))</strong></p> <p>To <strong>accurately bound</strong> \(\alpha\) and \(\beta\), ensuring the privacy guarantees (\(\varepsilon\), \(\delta\)) hold with high confidence. This requires not just single estimates of TPR and FPR but <strong>statistical bounds</strong> that account for uncertainty due to finite sample sizes.</p> <p>Let’s take a simple example:</p> <p>You got these two estimated TPR and FPR after running MIA on multiple DP models where \(\epsilon = 2.5\), \(\delta = 0.0001\):</p> <p><strong>\(\text{Estimated } FPR (\alpha) = 10\%\)</strong> <strong>\(\text{Estimated } TPR (1-\beta) = 90\%\)</strong></p> <p>Based on these single estimates, you might conclude that:</p> \[\frac{TPR-\delta}{FPR} \approx 9 &lt; e^\epsilon \approx 12.18\] <p>well, the implementation of differential privacy has no bugs.</p> <p>But we all know that the model training has uncertainty and finite hypothesis testing also has uncertainty. How confident can we say that the next estimation will not show the implementation has bugs?</p> <p>What we need is confidence. For example, with 95\% confidence, the estimated results will stay in the privacy region.</p> <p>In the next blog, I’ll introduce how to bound TPR and FPR with Clopper-pearson interval. This mathematical tool will give us a range of TPR and FPR with a specific confidence level. Through this bound, we can not only debug the implementation of differential privacy, we can also see how well the differential privacy is implemented.</p>]]></content><author><name></name></author><category term="Differential"/><category term="privacy"/><category term="DP-hp"/><summary type="html"><![CDATA[In this post, I'll generally introduce the hypothesis testing interpretation of differential privacy and why it's vital for private machine learning.]]></summary></entry><entry><title type="html">Fine-Tuning Vision Transformer (ViT) on Tiny ImageNet Dataset</title><link href="https://rhincodone.github.io/posts/2024-11-15-Fine_Tuning_ViT_Tiny_ImageNet/" rel="alternate" type="text/html" title="Fine-Tuning Vision Transformer (ViT) on Tiny ImageNet Dataset"/><published>2024-11-15T00:00:00+00:00</published><updated>2024-11-15T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/Fine_Tuning_ViT_Tiny_ImageNet</id><content type="html" xml:base="https://rhincodone.github.io/posts/2024-11-15-Fine_Tuning_ViT_Tiny_ImageNet/"><![CDATA[<h2 id="introduction">Introduction</h2> <p>This document provides a detailed overview of the strategy employed to fine-tune a Vision Transformer (ViT) on the Tiny ImageNet dataset, achieving a validation accuracy of <strong>90.5% within 10 epochs</strong>.</p> <h2 id="dataset-description">Dataset Description</h2> <ul> <li><strong>Dataset</strong>: Tiny ImageNet</li> <li><strong>Number of Classes</strong>: 200</li> <li><strong>Image Size</strong>: 64x64 resized to 384x384 for ViT</li> </ul> <h2 id="model-configuration">Model Configuration</h2> <ul> <li><strong>Model</strong>: ViT-Base with patch size 16 (<code class="language-plaintext highlighter-rouge">vit_base_patch16_384</code>)</li> <li><strong>Pretrained Weights</strong>: Used pretrained weights from ImageNet</li> <li><strong>Optimizer</strong>: SGD with momentum (0.9)</li> <li><strong>Learning Rate</strong>: 1e-4</li> <li><strong>Weight Decay</strong>: 0.01</li> <li><strong>Scheduler</strong>: Cosine Annealing Learning Rate</li> <li><strong>Loss Function</strong>: Soft Target Cross-Entropy (for Mixup/CutMix)</li> <li><strong>Augmentation</strong>: RandAugment, Random Erasing, Mixup, and CutMix</li> </ul> <h2 id="strategy">Strategy</h2> <h3 id="data-preprocessing">Data Preprocessing</h3> <ol> <li><strong>Image Resizing</strong>: <ul> <li>Images were resized to 384x384 to match the input dimensions required by the Vision Transformer (ViT) model. This ensures that the patching mechanism of the ViT (16x16 patches in this case) works seamlessly, dividing the images into the correct number of patches for transformer-based processing.</li> </ul> </li> <li><strong>Enhanced Data Augmentations</strong>: <ul> <li><strong>RandAugment</strong>: <ul> <li>Method: This augmentation policy applies a random combination of transformations such as rotation, brightness adjustment, and flipping, chosen from a predefined pool of operations.</li> <li>Implementation: Integrated using the <code class="language-plaintext highlighter-rouge">RandAugment</code> class from <code class="language-plaintext highlighter-rouge">torchvision.transforms</code>.</li> <li>Intuition: Augmentations simulate diverse scenarios in the dataset, enhancing model robustness to unseen variations in real-world applications.</li> </ul> </li> <li><strong>Random Erasing</strong>: <ul> <li>Method: Randomly erases parts of an image during training by replacing selected regions with random pixel values.</li> <li>Probability: Set to 0.25, meaning 25% of training images had a random region erased.</li> <li>Intuition: Prevents the model from over-relying on specific regions of an image, encouraging it to learn more generalized features.</li> </ul> </li> </ul> </li> </ol> <h3 id="training-enhancements">Training Enhancements</h3> <ol> <li><strong>Mixup and CutMix</strong>: <ul> <li><strong>Mixup</strong>: <ul> <li>Method: Mixup blends two training examples and their labels, creating a synthetic training sample:<br/> [ \tilde{x} = \lambda x_i + (1 - \lambda) x_j, \quad \tilde{y} = \lambda y_i + (1 - \lambda) y_j ]<br/> where ( \lambda ) is sampled from a Beta distribution.</li> <li>Implementation: Integrated using the <code class="language-plaintext highlighter-rouge">Mixup</code> utility from the <code class="language-plaintext highlighter-rouge">timm</code> library.</li> <li>Intuition: Mixup smoothens decision boundaries and reduces overfitting, as the model cannot rely on “hard” training labels.</li> </ul> </li> <li><strong>CutMix</strong>: <ul> <li>Method: Similar to Mixup, but instead of blending the entire images, rectangular patches of one image replace patches in another. Labels are proportionally adjusted.</li> <li>Implementation: Configured with probabilities for blending and patch placement using <code class="language-plaintext highlighter-rouge">timm.data.Mixup</code>.</li> <li>Intuition: Encourages spatially aware feature learning, improving robustness to occlusions or corruptions.</li> </ul> </li> </ul> </li> <li><strong>Stochastic Depth</strong>: <ul> <li>Method: During training, randomly drops a subset of transformer blocks in each forward pass, controlled by a drop probability.</li> <li>Implementation: Applied a drop probability of 0.1 to regularize deeper layers using <code class="language-plaintext highlighter-rouge">timm.layers.DropPath</code>.</li> <li>Intuition: Mimics an ensemble effect by allowing the model to explore multiple sub-networks, reducing overfitting and improving generalization.</li> </ul> </li> <li><strong>AMP (Automatic Mixed Precision)</strong>: <ul> <li>Method: Combines half-precision and full-precision computations dynamically during training.</li> <li>Implementation: Enabled with <code class="language-plaintext highlighter-rouge">torch.amp.GradScaler</code> and <code class="language-plaintext highlighter-rouge">torch.cuda.amp.autocast</code>.</li> <li>Intuition: Reduces GPU memory usage and accelerates training while maintaining model performance, especially useful for computationally intensive ViT models.</li> </ul> </li> </ol> <h3 id="training-loop">Training Loop</h3> <ul> <li><strong>Epochs</strong>: Trained for up to 50 epochs but utilized early stopping after achieving peak validation accuracy (90.5%) at 10 epochs.</li> <li><strong>Batch Size</strong>: Set to 128, optimized for GPU memory utilization.</li> <li><strong>Logging</strong>: Metrics, including training and validation loss and accuracy, were logged using TensorBoard. Logging frequency was every 100 batches to balance granularity and performance overhead.</li> </ul> <h3 id="validation">Validation</h3> <ul> <li>Standard Cross-Entropy loss was used during validation for hard-label accuracy computation. Unlike the training phase, which used soft-label losses (Mixup and CutMix), validation focused purely on the model’s ability to classify with confidence in real-world scenarios.</li> </ul> <hr/> <h3 id="layer-fine-tuning-strategy">Layer Fine-Tuning Strategy</h3> <p>The experiment tested two configurations for fine-tuning:</p> <ol> <li><strong>Fine-Tuning All Layers</strong>: <ul> <li>In this setting, all layers of the ViT model were unfrozen, allowing gradient updates to modify the pretrained weights.</li> <li><strong>Result</strong>: Achieved a validation accuracy of 90.5%, demonstrating the ability of the model to adapt its internal representations to the Tiny ImageNet dataset.</li> </ul> </li> <li><strong>Fine-Tuning the Last Fully Connected Layer Only</strong>: <ul> <li>In this setting, only the final classification head (Fully Connected Layer) was updated, while all transformer layers were frozen.</li> <li><strong>Result</strong>: Achieved a validation accuracy of 72.3%, indicating limited capacity to adapt the learned features to the new dataset.</li> </ul> </li> </ol> <p><strong>Analysis</strong>:</p> <ul> <li><strong>Why Fine-Tuning All Layers Performed Better</strong>: <ul> <li>The pretrained ViT model was trained on ImageNet, which shares some similarities with Tiny ImageNet but differs in scale and distribution.</li> <li>Fine-tuning all layers allowed the model to adjust its intermediate representations to the specific features and patterns of the Tiny ImageNet dataset, leading to significantly better performance.</li> </ul> </li> <li><strong>When to Fine-Tune Specific Layers</strong>: <ul> <li>Fine-tuning specific layers, such as only the classification head, may suffice for tasks with highly similar datasets (e.g., same domain). However, for diverse datasets, fine-tuning more or all layers is generally necessary.</li> </ul> </li> </ul> <hr/> <p><strong>Key Takeaway</strong>: Fine-tuning the entire network maximized the model’s adaptability to Tiny ImageNet, yielding superior performance. However, this comes at a higher computational cost compared to only tuning the last layer.</p> <h2 id="results">Results</h2> <ul> <li><strong>Validation Accuracy</strong>: 90.5% after 10 epochs</li> <li><strong>Training Time</strong>: Approximately 30 minutes per epoch on a single GPU</li> <li><strong>Best Model Saved</strong>: Model checkpoint saved at <code class="language-plaintext highlighter-rouge">./models/best_vit_tiny_imagenet.pth</code></li> </ul> <h2 id="key-insights">Key Insights</h2> <ol> <li><strong>Enhanced Augmentations</strong>: The combination of RandAugment, Mixup, and CutMix improved generalization.</li> <li><strong>Cosine Annealing</strong>: Helped achieve smooth convergence with the learning rate.</li> <li><strong>Pretrained Weights</strong>: Accelerated convergence and boosted performance significantly.</li> </ol> <hr/> <p><strong>Repository Setup</strong>: The code for this implementation, including the preprocessing and training pipeline, is structured for easy reproducibility. Ensure you have the following dependencies installed:</p> <ul> <li>PyTorch</li> <li>torchvision</li> <li>timm</li> <li>tqdm</li> </ul> <h2 id="code">Code</h2> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">```</span><span class="nl">python
</span>
<span class="kn">import</span> <span class="n">os</span>
<span class="kn">import</span> <span class="n">shutil</span>
<span class="kn">import</span> <span class="n">torch</span>
<span class="kn">import</span> <span class="n">torch.nn</span> <span class="k">as</span> <span class="n">nn</span>
<span class="kn">import</span> <span class="n">torch.optim</span> <span class="k">as</span> <span class="n">optim</span>
<span class="kn">from</span> <span class="n">torchvision</span> <span class="kn">import</span> <span class="n">datasets</span><span class="p">,</span> <span class="n">transforms</span>
<span class="kn">from</span> <span class="n">timm</span> <span class="kn">import</span> <span class="n">create_model</span>
<span class="kn">from</span> <span class="n">torch.optim.lr_scheduler</span> <span class="kn">import</span> <span class="n">CosineAnnealingLR</span>
<span class="kn">from</span> <span class="n">torch.utils.data</span> <span class="kn">import</span> <span class="n">DataLoader</span>
<span class="kn">from</span> <span class="n">torch.utils.tensorboard</span> <span class="kn">import</span> <span class="n">SummaryWriter</span>
<span class="kn">from</span> <span class="n">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>  <span class="c1"># For progress bar
</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="sh">'</span><span class="s">HF_HOME</span><span class="sh">'</span><span class="p">]</span> <span class="o">=</span> <span class="sh">'</span><span class="s">/tmp/ygu2/hf_cache_custom</span><span class="sh">'</span>
<span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="sh">'</span><span class="s">HUGGINGFACE_HUB_CACHE</span><span class="sh">'</span><span class="p">]</span> <span class="o">=</span> <span class="sh">'</span><span class="s">/tmp/ygu2/hf_cache_custom/hub</span><span class="sh">'</span>

<span class="c1"># Import Mixup and CutMix utilities from timm
</span><span class="kn">from</span> <span class="n">timm.data</span> <span class="kn">import</span> <span class="n">Mixup</span>
<span class="kn">from</span> <span class="n">timm.loss</span> <span class="kn">import</span> <span class="n">SoftTargetCrossEntropy</span>

<span class="c1"># Optional: Import RandAugment for enhanced data augmentation
</span><span class="kn">from</span> <span class="n">torchvision.transforms</span> <span class="kn">import</span> <span class="n">RandAugment</span>

<span class="c1"># Set CuDNN Benchmark for optimized performance
</span><span class="n">torch</span><span class="p">.</span><span class="n">backends</span><span class="p">.</span><span class="n">cudnn</span><span class="p">.</span><span class="n">benchmark</span> <span class="o">=</span> <span class="bp">True</span>

<span class="c1"># Paths and Constants
</span><span class="n">data_dir</span> <span class="o">=</span> <span class="sh">"</span><span class="s">./datasets/tiny-imagenet-200</span><span class="sh">"</span>
<span class="n">num_classes</span> <span class="o">=</span> <span class="mi">200</span>
<span class="n">batch_size</span> <span class="o">=</span> <span class="mi">128</span>  <span class="c1"># Adjust based on GPU memory
</span><span class="n">num_epochs</span> <span class="o">=</span> <span class="mi">50</span>  <span class="c1"># Increased number of epochs for better convergence
</span><span class="n">learning_rate</span> <span class="o">=</span> <span class="mf">1e-4</span>  <span class="c1"># Lowered learning rate for fine-tuning
</span><span class="n">weight_decay</span> <span class="o">=</span> <span class="mf">0.01</span>  <span class="c1"># Adjusted weight decay
</span><span class="n">image_size</span> <span class="o">=</span> <span class="mi">384</span>
<span class="n">log_interval</span> <span class="o">=</span> <span class="mi">100</span>  <span class="c1"># Log metrics every 100 batches
</span>
<span class="c1"># Reorganize validation data
</span><span class="n">val_dir</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="sh">'</span><span class="s">val</span><span class="sh">'</span><span class="p">)</span>
<span class="n">val_images_dir</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">val_dir</span><span class="p">,</span> <span class="sh">'</span><span class="s">images</span><span class="sh">'</span><span class="p">)</span>
<span class="n">val_annotations_file</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">val_dir</span><span class="p">,</span> <span class="sh">'</span><span class="s">val_annotations.txt</span><span class="sh">'</span><span class="p">)</span>

<span class="c1"># Create a mapping from image filenames to their labels
</span><span class="n">val_img_dict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="n">val_annotations_file</span><span class="p">,</span> <span class="sh">'</span><span class="s">r</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">.</span><span class="nf">readlines</span><span class="p">():</span>
        <span class="n">words</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="nf">strip</span><span class="p">().</span><span class="nf">split</span><span class="p">(</span><span class="sh">'</span><span class="se">\t</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">val_img_dict</span><span class="p">[</span><span class="n">words</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">words</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>

<span class="c1"># Create directories for each class if they don't exist
</span><span class="k">for</span> <span class="n">label</span> <span class="ow">in</span> <span class="nf">set</span><span class="p">(</span><span class="n">val_img_dict</span><span class="p">.</span><span class="nf">values</span><span class="p">()):</span>
    <span class="n">label_dir</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">val_images_dir</span><span class="p">,</span> <span class="n">label</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">exists</span><span class="p">(</span><span class="n">label_dir</span><span class="p">):</span>
        <span class="n">os</span><span class="p">.</span><span class="nf">makedirs</span><span class="p">(</span><span class="n">label_dir</span><span class="p">)</span>

<span class="c1"># Move images into the corresponding label directories
</span><span class="k">for</span> <span class="n">img_filename</span><span class="p">,</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">val_img_dict</span><span class="p">.</span><span class="nf">items</span><span class="p">():</span>
    <span class="n">src</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">val_images_dir</span><span class="p">,</span> <span class="n">img_filename</span><span class="p">)</span>
    <span class="n">dst</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">val_images_dir</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="n">img_filename</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">exists</span><span class="p">(</span><span class="n">src</span><span class="p">):</span>
        <span class="n">shutil</span><span class="p">.</span><span class="nf">move</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dst</span><span class="p">)</span>

<span class="c1"># Data Augmentation and Transformations
</span><span class="n">transform_train</span> <span class="o">=</span> <span class="n">transforms</span><span class="p">.</span><span class="n">Compose</span><span class="p">([</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">Resize</span><span class="p">((</span><span class="n">image_size</span><span class="p">,</span> <span class="n">image_size</span><span class="p">),</span> <span class="n">interpolation</span><span class="o">=</span><span class="n">transforms</span><span class="p">.</span><span class="n">InterpolationMode</span><span class="p">.</span><span class="n">BICUBIC</span><span class="p">),</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">RandomHorizontalFlip</span><span class="p">(),</span>
    <span class="nc">RandAugment</span><span class="p">(),</span>  <span class="c1"># Enhanced augmentation
</span>    <span class="n">transforms</span><span class="p">.</span><span class="nc">ToTensor</span><span class="p">(),</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">Normalize</span><span class="p">((</span><span class="mf">0.485</span><span class="p">,</span> <span class="mf">0.456</span><span class="p">,</span> <span class="mf">0.406</span><span class="p">),</span> <span class="p">(</span><span class="mf">0.229</span><span class="p">,</span> <span class="mf">0.224</span><span class="p">,</span> <span class="mf">0.225</span><span class="p">)),</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">RandomErasing</span><span class="p">(</span><span class="n">p</span><span class="o">=</span><span class="mf">0.25</span><span class="p">),</span>
<span class="p">])</span>

<span class="n">transform_test</span> <span class="o">=</span> <span class="n">transforms</span><span class="p">.</span><span class="n">Compose</span><span class="p">([</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">Resize</span><span class="p">((</span><span class="n">image_size</span><span class="p">,</span> <span class="n">image_size</span><span class="p">),</span> <span class="n">interpolation</span><span class="o">=</span><span class="n">transforms</span><span class="p">.</span><span class="n">InterpolationMode</span><span class="p">.</span><span class="n">BICUBIC</span><span class="p">),</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">ToTensor</span><span class="p">(),</span>
    <span class="n">transforms</span><span class="p">.</span><span class="nc">Normalize</span><span class="p">((</span><span class="mf">0.485</span><span class="p">,</span> <span class="mf">0.456</span><span class="p">,</span> <span class="mf">0.406</span><span class="p">),</span> <span class="p">(</span><span class="mf">0.229</span><span class="p">,</span> <span class="mf">0.224</span><span class="p">,</span> <span class="mf">0.225</span><span class="p">)),</span>
<span class="p">])</span>

<span class="c1"># Load Datasets
</span><span class="n">train_dataset</span> <span class="o">=</span> <span class="n">datasets</span><span class="p">.</span><span class="nc">ImageFolder</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">data_dir</span><span class="p">,</span> <span class="sh">'</span><span class="s">train</span><span class="sh">'</span><span class="p">),</span> <span class="n">transform</span><span class="o">=</span><span class="n">transform_train</span><span class="p">)</span>
<span class="n">train_loader</span> <span class="o">=</span> <span class="n">DataLoader</span><span class="p">(</span>
    <span class="n">train_dataset</span><span class="p">,</span>
    <span class="n">batch_size</span><span class="o">=</span><span class="n">batch_size</span><span class="p">,</span>
    <span class="n">shuffle</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
    <span class="n">num_workers</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>  <span class="c1"># Reduced from 8 to 2
</span>    <span class="n">pin_memory</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
    <span class="n">prefetch_factor</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span>
    <span class="n">persistent_workers</span><span class="o">=</span><span class="bp">True</span>
<span class="p">)</span>

<span class="n">val_dataset</span> <span class="o">=</span> <span class="n">datasets</span><span class="p">.</span><span class="nc">ImageFolder</span><span class="p">(</span><span class="n">val_images_dir</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">transform_test</span><span class="p">)</span>
<span class="n">val_loader</span> <span class="o">=</span> <span class="n">DataLoader</span><span class="p">(</span>
    <span class="n">val_dataset</span><span class="p">,</span>
    <span class="n">batch_size</span><span class="o">=</span><span class="n">batch_size</span><span class="p">,</span>
    <span class="n">shuffle</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
    <span class="n">num_workers</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>  <span class="c1"># Reduced from 8 to 2
</span>    <span class="n">pin_memory</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
    <span class="n">prefetch_factor</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span>
    <span class="n">persistent_workers</span><span class="o">=</span><span class="bp">True</span>
<span class="p">)</span>

<span class="c1"># Create Vision Transformer (ViT) Model
</span><span class="n">model</span> <span class="o">=</span> <span class="nf">create_model</span><span class="p">(</span><span class="sh">'</span><span class="s">vit_base_patch16_384</span><span class="sh">'</span><span class="p">,</span> <span class="n">pretrained</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">num_classes</span><span class="o">=</span><span class="n">num_classes</span><span class="p">)</span>

<span class="c1"># Apply Stochastic Depth
</span><span class="kn">from</span> <span class="n">timm.layers</span> <span class="kn">import</span> <span class="n">DropPath</span>  <span class="c1"># Updated import path
</span>
<span class="k">def</span> <span class="nf">apply_stochastic_depth</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">drop_prob</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="n">model</span><span class="p">.</span><span class="nf">modules</span><span class="p">():</span>
        <span class="k">if</span> <span class="nf">isinstance</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">DropPath</span><span class="p">):</span>
            <span class="n">module</span><span class="p">.</span><span class="n">drop_prob</span> <span class="o">=</span> <span class="n">drop_prob</span>

<span class="nf">apply_stochastic_depth</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">drop_prob</span><span class="o">=</span><span class="mf">0.1</span><span class="p">)</span>

<span class="c1"># Unfreeze the entire model for fine-tuning
</span><span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">model</span><span class="p">.</span><span class="nf">parameters</span><span class="p">():</span>
    <span class="n">param</span><span class="p">.</span><span class="n">requires_grad</span> <span class="o">=</span> <span class="bp">True</span>

<span class="c1"># Use DataParallel for multiple GPUs if available
</span><span class="n">device</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="nf">device</span><span class="p">(</span><span class="sh">"</span><span class="s">cuda</span><span class="sh">"</span> <span class="k">if</span> <span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="nf">is_available</span><span class="p">()</span> <span class="k">else</span> <span class="sh">"</span><span class="s">cpu</span><span class="sh">"</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Using device: </span><span class="si">{</span><span class="n">device</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>

<span class="k">if</span> <span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="nf">device_count</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Using </span><span class="si">{</span><span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="nf">device_count</span><span class="p">()</span><span class="si">}</span><span class="s"> GPUs</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">model</span> <span class="o">=</span> <span class="n">nn</span><span class="p">.</span><span class="nc">DataParallel</span><span class="p">(</span><span class="n">model</span><span class="p">)</span>  <span class="c1"># This will use all available GPUs
</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">model</span><span class="p">.</span><span class="nf">to</span><span class="p">(</span><span class="n">device</span><span class="p">)</span>

<span class="c1"># Mixup and CutMix
</span><span class="n">mixup_fn</span> <span class="o">=</span> <span class="n">Mixup</span><span class="p">(</span>
    <span class="n">mixup_alpha</span><span class="o">=</span><span class="mf">0.8</span><span class="p">,</span>
    <span class="n">cutmix_alpha</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span>
    <span class="n">cutmix_minmax</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
    <span class="n">prob</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span>  <span class="c1"># Reduced probability to allow some original images
</span>    <span class="n">switch_prob</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span>
    <span class="n">mode</span><span class="o">=</span><span class="sh">'</span><span class="s">batch</span><span class="sh">'</span><span class="p">,</span>
    <span class="n">label_smoothing</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span>
    <span class="n">num_classes</span><span class="o">=</span><span class="n">num_classes</span>
<span class="p">)</span>

<span class="c1"># Loss, Optimizer, and Scheduler
</span><span class="n">criterion</span> <span class="o">=</span> <span class="nc">SoftTargetCrossEntropy</span><span class="p">()</span>  <span class="c1"># For Mixup and CutMix
</span>
<span class="c1"># Using SGD with momentum for better fine-tuning
</span><span class="n">optimizer</span> <span class="o">=</span> <span class="n">optim</span><span class="p">.</span><span class="n">SGD</span><span class="p">(</span>
    <span class="nf">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">p</span><span class="p">:</span> <span class="n">p</span><span class="p">.</span><span class="n">requires_grad</span><span class="p">,</span> <span class="n">model</span><span class="p">.</span><span class="nf">parameters</span><span class="p">()),</span>
    <span class="n">lr</span><span class="o">=</span><span class="n">learning_rate</span><span class="p">,</span>
    <span class="n">momentum</span><span class="o">=</span><span class="mf">0.9</span><span class="p">,</span>
    <span class="n">weight_decay</span><span class="o">=</span><span class="n">weight_decay</span>
<span class="p">)</span>

<span class="c1"># Scheduler adjusted to steps per epoch
</span><span class="n">scheduler</span> <span class="o">=</span> <span class="nc">CosineAnnealingLR</span><span class="p">(</span><span class="n">optimizer</span><span class="p">,</span> <span class="n">T_max</span><span class="o">=</span><span class="n">num_epochs</span><span class="p">)</span>

<span class="c1"># Initialize AMP scaler for mixed precision
</span><span class="n">scaler</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">amp</span><span class="p">.</span><span class="nc">GradScaler</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="sh">'</span><span class="s">cuda</span><span class="sh">'</span><span class="p">)</span>  <span class="c1"># Updated instantiation
</span>
<span class="c1"># Training and Validation Loop
</span><span class="n">writer</span> <span class="o">=</span> <span class="nc">SummaryWriter</span><span class="p">()</span>  <span class="c1"># For TensorBoard logging
</span>
<span class="k">def</span> <span class="nf">train_one_epoch</span><span class="p">(</span><span class="n">epoch</span><span class="p">):</span>
    <span class="n">model</span><span class="p">.</span><span class="nf">train</span><span class="p">()</span>
    <span class="n">running_loss</span><span class="p">,</span> <span class="n">correct</span><span class="p">,</span> <span class="n">total</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>

    <span class="c1"># Progress bar for training loop
</span>    <span class="n">train_loader_tqdm</span> <span class="o">=</span> <span class="nf">tqdm</span><span class="p">(</span><span class="n">train_loader</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="s">Epoch </span><span class="si">{</span><span class="n">epoch</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s">/</span><span class="si">{</span><span class="n">num_epochs</span><span class="si">}</span><span class="s"> [Training]</span><span class="sh">"</span><span class="p">,</span> <span class="n">leave</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">batch_idx</span><span class="p">,</span> <span class="p">(</span><span class="n">images</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">train_loader_tqdm</span><span class="p">):</span>
        <span class="n">images</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="n">images</span><span class="p">.</span><span class="nf">to</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="n">non_blocking</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span> <span class="n">labels</span><span class="p">.</span><span class="nf">to</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="n">non_blocking</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

        <span class="c1"># Apply Mixup/CutMix
</span>        <span class="n">images</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="nf">mixup_fn</span><span class="p">(</span><span class="n">images</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>

        <span class="n">optimizer</span><span class="p">.</span><span class="nf">zero_grad</span><span class="p">()</span>

        <span class="k">with</span> <span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="n">amp</span><span class="p">.</span><span class="nf">autocast</span><span class="p">():</span>
            <span class="n">outputs</span> <span class="o">=</span> <span class="nf">model</span><span class="p">(</span><span class="n">images</span><span class="p">)</span>
            <span class="n">loss</span> <span class="o">=</span> <span class="nf">criterion</span><span class="p">(</span><span class="n">outputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>

        <span class="n">scaler</span><span class="p">.</span><span class="nf">scale</span><span class="p">(</span><span class="n">loss</span><span class="p">).</span><span class="nf">backward</span><span class="p">()</span>
        <span class="n">scaler</span><span class="p">.</span><span class="nf">step</span><span class="p">(</span><span class="n">optimizer</span><span class="p">)</span>
        <span class="n">scaler</span><span class="p">.</span><span class="nf">update</span><span class="p">()</span>

        <span class="n">running_loss</span> <span class="o">+=</span> <span class="n">loss</span><span class="p">.</span><span class="nf">item</span><span class="p">()</span> <span class="o">*</span> <span class="n">images</span><span class="p">.</span><span class="nf">size</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="n">total</span> <span class="o">+=</span> <span class="n">labels</span><span class="p">.</span><span class="nf">size</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

        <span class="c1"># Since labels are soft, calculate accuracy based on predicted class vs hard labels
</span>        <span class="n">_</span><span class="p">,</span> <span class="n">predicted</span> <span class="o">=</span> <span class="n">outputs</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">targets</span> <span class="o">=</span> <span class="n">labels</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">correct</span> <span class="o">+=</span> <span class="n">predicted</span><span class="p">.</span><span class="nf">eq</span><span class="p">(</span><span class="n">targets</span><span class="p">).</span><span class="nf">sum</span><span class="p">().</span><span class="nf">item</span><span class="p">()</span>

        <span class="c1"># Update progress bar (accuracy in percentage)
</span>        <span class="nf">if </span><span class="p">(</span><span class="n">batch_idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">log_interval</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="p">(</span><span class="n">batch_idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="nf">len</span><span class="p">(</span><span class="n">train_loader</span><span class="p">):</span>
            <span class="n">current_loss</span> <span class="o">=</span> <span class="n">loss</span><span class="p">.</span><span class="nf">item</span><span class="p">()</span>
            <span class="n">current_acc</span> <span class="o">=</span> <span class="mf">100.</span> <span class="o">*</span> <span class="n">correct</span> <span class="o">/</span> <span class="n">total</span>
            <span class="n">train_loader_tqdm</span><span class="p">.</span><span class="nf">set_postfix</span><span class="p">(</span><span class="n">loss</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">current_loss</span><span class="si">:</span><span class="p">.</span><span class="mi">4</span><span class="n">f</span><span class="si">}</span><span class="sh">"</span><span class="p">,</span> <span class="n">accuracy</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">current_acc</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">epoch_loss</span> <span class="o">=</span> <span class="n">running_loss</span> <span class="o">/</span> <span class="n">total</span>
    <span class="n">epoch_acc</span> <span class="o">=</span> <span class="mf">100.</span> <span class="o">*</span> <span class="n">correct</span> <span class="o">/</span> <span class="n">total</span>  <span class="c1"># Multiply by 100 to get percentage
</span>    <span class="n">writer</span><span class="p">.</span><span class="nf">add_scalar</span><span class="p">(</span><span class="sh">'</span><span class="s">Loss/train</span><span class="sh">'</span><span class="p">,</span> <span class="n">epoch_loss</span><span class="p">,</span> <span class="n">epoch</span><span class="p">)</span>
    <span class="n">writer</span><span class="p">.</span><span class="nf">add_scalar</span><span class="p">(</span><span class="sh">'</span><span class="s">Accuracy/train</span><span class="sh">'</span><span class="p">,</span> <span class="n">epoch_acc</span><span class="p">,</span> <span class="n">epoch</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Epoch [</span><span class="si">{</span><span class="n">epoch</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s">/</span><span class="si">{</span><span class="n">num_epochs</span><span class="si">}</span><span class="s">], Loss: </span><span class="si">{</span><span class="n">epoch_loss</span><span class="si">:</span><span class="p">.</span><span class="mi">4</span><span class="n">f</span><span class="si">}</span><span class="s">, Acc: </span><span class="si">{</span><span class="n">epoch_acc</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span>  <span class="c1"># Acc in %
</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">epoch</span><span class="p">):</span>
    <span class="n">model</span><span class="p">.</span><span class="nf">eval</span><span class="p">()</span>
    <span class="n">val_loss</span><span class="p">,</span> <span class="n">correct</span><span class="p">,</span> <span class="n">total</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>

    <span class="c1"># Progress bar for validation loop
</span>    <span class="n">val_loader_tqdm</span> <span class="o">=</span> <span class="nf">tqdm</span><span class="p">(</span><span class="n">val_loader</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="s">Epoch </span><span class="si">{</span><span class="n">epoch</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s">/</span><span class="si">{</span><span class="n">num_epochs</span><span class="si">}</span><span class="s"> [Validation]</span><span class="sh">"</span><span class="p">,</span> <span class="n">leave</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>

    <span class="n">criterion_val</span> <span class="o">=</span> <span class="n">nn</span><span class="p">.</span><span class="nc">CrossEntropyLoss</span><span class="p">()</span>  <span class="c1"># Standard loss for validation
</span>
    <span class="k">with</span> <span class="n">torch</span><span class="p">.</span><span class="nf">no_grad</span><span class="p">():</span>
        <span class="k">for</span> <span class="n">batch_idx</span><span class="p">,</span> <span class="p">(</span><span class="n">images</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">val_loader_tqdm</span><span class="p">):</span>
            <span class="n">images</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="n">images</span><span class="p">.</span><span class="nf">to</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="n">non_blocking</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span> <span class="n">labels</span><span class="p">.</span><span class="nf">to</span><span class="p">(</span><span class="n">device</span><span class="p">,</span> <span class="n">non_blocking</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

            <span class="k">with</span> <span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="n">amp</span><span class="p">.</span><span class="nf">autocast</span><span class="p">():</span>
                <span class="n">outputs</span> <span class="o">=</span> <span class="nf">model</span><span class="p">(</span><span class="n">images</span><span class="p">)</span>
                <span class="n">loss</span> <span class="o">=</span> <span class="nf">criterion_val</span><span class="p">(</span><span class="n">outputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>

            <span class="n">val_loss</span> <span class="o">+=</span> <span class="n">loss</span><span class="p">.</span><span class="nf">item</span><span class="p">()</span> <span class="o">*</span> <span class="n">images</span><span class="p">.</span><span class="nf">size</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="n">labels</span><span class="p">.</span><span class="nf">size</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="n">_</span><span class="p">,</span> <span class="n">predicted</span> <span class="o">=</span> <span class="n">outputs</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
            <span class="n">correct</span> <span class="o">+=</span> <span class="n">predicted</span><span class="p">.</span><span class="nf">eq</span><span class="p">(</span><span class="n">labels</span><span class="p">).</span><span class="nf">sum</span><span class="p">().</span><span class="nf">item</span><span class="p">()</span>

            <span class="c1"># Update progress bar (accuracy in percentage)
</span>            <span class="nf">if </span><span class="p">(</span><span class="n">batch_idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">log_interval</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="p">(</span><span class="n">batch_idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="nf">len</span><span class="p">(</span><span class="n">val_loader</span><span class="p">):</span>
                <span class="n">current_loss</span> <span class="o">=</span> <span class="n">loss</span><span class="p">.</span><span class="nf">item</span><span class="p">()</span>
                <span class="n">current_acc</span> <span class="o">=</span> <span class="mf">100.</span> <span class="o">*</span> <span class="n">correct</span> <span class="o">/</span> <span class="n">total</span>
                <span class="n">val_loader_tqdm</span><span class="p">.</span><span class="nf">set_postfix</span><span class="p">(</span><span class="n">loss</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">current_loss</span><span class="si">:</span><span class="p">.</span><span class="mi">4</span><span class="n">f</span><span class="si">}</span><span class="sh">"</span><span class="p">,</span> <span class="n">accuracy</span><span class="o">=</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">current_acc</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">epoch_loss</span> <span class="o">=</span> <span class="n">val_loss</span> <span class="o">/</span> <span class="n">total</span>
    <span class="n">epoch_acc</span> <span class="o">=</span> <span class="mf">100.</span> <span class="o">*</span> <span class="n">correct</span> <span class="o">/</span> <span class="n">total</span>  <span class="c1"># Multiply by 100 to get percentage
</span>    <span class="n">writer</span><span class="p">.</span><span class="nf">add_scalar</span><span class="p">(</span><span class="sh">'</span><span class="s">Loss/val</span><span class="sh">'</span><span class="p">,</span> <span class="n">epoch_loss</span><span class="p">,</span> <span class="n">epoch</span><span class="p">)</span>
    <span class="n">writer</span><span class="p">.</span><span class="nf">add_scalar</span><span class="p">(</span><span class="sh">'</span><span class="s">Accuracy/val</span><span class="sh">'</span><span class="p">,</span> <span class="n">epoch_acc</span><span class="p">,</span> <span class="n">epoch</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Validation Loss: </span><span class="si">{</span><span class="n">epoch_loss</span><span class="si">:</span><span class="p">.</span><span class="mi">4</span><span class="n">f</span><span class="si">}</span><span class="s">, Acc: </span><span class="si">{</span><span class="n">epoch_acc</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span>  <span class="c1"># Acc in %
</span>
    <span class="k">return</span> <span class="n">epoch_acc</span>

<span class="c1"># Main Training Loop
</span><span class="n">best_acc</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">epoch</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">num_epochs</span><span class="p">):</span>
    <span class="nf">train_one_epoch</span><span class="p">(</span><span class="n">epoch</span><span class="p">)</span>
    <span class="n">val_acc</span> <span class="o">=</span> <span class="nf">validate</span><span class="p">(</span><span class="n">epoch</span><span class="p">)</span>

    <span class="c1"># Scheduler step
</span>    <span class="n">scheduler</span><span class="p">.</span><span class="nf">step</span><span class="p">()</span>

    <span class="c1"># Save best model
</span>    <span class="k">if</span> <span class="n">val_acc</span> <span class="o">&gt;</span> <span class="n">best_acc</span><span class="p">:</span>
        <span class="n">best_acc</span> <span class="o">=</span> <span class="n">val_acc</span>
        <span class="n">os</span><span class="p">.</span><span class="nf">makedirs</span><span class="p">(</span><span class="sh">'</span><span class="s">./models</span><span class="sh">'</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
        <span class="c1"># If using DataParallel, save the underlying model
</span>        <span class="k">if</span> <span class="nf">isinstance</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">nn</span><span class="p">.</span><span class="n">DataParallel</span><span class="p">):</span>
            <span class="n">torch</span><span class="p">.</span><span class="nf">save</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="n">module</span><span class="p">.</span><span class="nf">state_dict</span><span class="p">(),</span> <span class="sh">'</span><span class="s">./models/best_vit_tiny_imagenet.pth</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">torch</span><span class="p">.</span><span class="nf">save</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="nf">state_dict</span><span class="p">(),</span> <span class="sh">'</span><span class="s">./models/best_vit_tiny_imagenet.pth</span><span class="sh">'</span><span class="p">)</span>
        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">New best model saved with accuracy: </span><span class="si">{</span><span class="n">best_acc</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Training complete. Best validation accuracy:</span><span class="sh">"</span><span class="p">,</span> <span class="n">best_acc</span><span class="p">)</span>

<span class="n">writer</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="LLM"/><category term="fine-tune"/><summary type="html"><![CDATA[In this post, I'll generally introduce how to fine-tune a ViT model on a tiny ImageNet dataset.]]></summary></entry><entry><title type="html">分类任务的评价指标以及与MIA的关系</title><link href="https://rhincodone.github.io/posts/2024-11-1-%E5%88%86%E7%B1%BB%E4%BB%BB%E5%8A%A1%E7%9A%84%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87%E4%BB%A5%E5%8F%8A%E4%B8%8EMIA%E7%9A%84%E5%85%B3%E7%B3%BB/" rel="alternate" type="text/html" title="分类任务的评价指标以及与MIA的关系"/><published>2024-11-01T00:00:00+00:00</published><updated>2024-11-01T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/%E5%88%86%E7%B1%BB%E4%BB%BB%E5%8A%A1%E7%9A%84%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87%E4%BB%A5%E5%8F%8A%E4%B8%8EMIA%E7%9A%84%E5%85%B3%E7%B3%BB</id><content type="html" xml:base="https://rhincodone.github.io/posts/2024-11-1-%E5%88%86%E7%B1%BB%E4%BB%BB%E5%8A%A1%E7%9A%84%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87%E4%BB%A5%E5%8F%8A%E4%B8%8EMIA%E7%9A%84%E5%85%B3%E7%B3%BB/"><![CDATA[<h1 id="机器学习模型评估指标详解">机器学习模型评估指标详解</h1> <p>以下是机器学习模型常用评估指标的详细说明，包括<strong>准确率</strong>、<strong>精确率</strong>、<strong>召回率</strong>、<strong>F1 值</strong>、<strong>AUC</strong> 和 <strong>G-mean</strong> 的定义、优缺点。</p> <hr/> <h3 id="1-准确率-accuracy">1. 准确率 (Accuracy)</h3> <ul> <li> <p><strong>定义</strong>：准确率是模型预测正确的样本占所有样本的比例。 \(\text{Accuracy} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}}\) 其中，TP 为真正例，TN 为真负例，FP 为假正例，FN 为假负例。</p> </li> <li><strong>优点</strong>：简单直观，适用于类别分布均衡的数据集。</li> <li><strong>缺点</strong>：对于类别不平衡的数据集效果较差，因为少数类的错误可能被多数类的正确预测掩盖。</li> </ul> <hr/> <h3 id="2-精确率-precision">2. 精确率 (Precision)</h3> <ul> <li> <p><strong>定义</strong>：精确率表示在预测为正类的样本中，真正为正类的比例。 \(\text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}}\)</p> </li> <li><strong>优点</strong>：在对误报容忍度较低的应用中（如癌症检测或欺诈检测）尤为重要。</li> <li><strong>缺点</strong>：当负类样本非常多而正类样本很少时，精确率可能较高，导致对召回率的忽视。</li> </ul> <hr/> <h3 id="3-召回率-recall">3. 召回率 (Recall)</h3> <ul> <li> <p><strong>定义</strong>：召回率表示所有实际为正类的样本中被正确预测为正类的比例。 \(\text{Recall} = \frac{\text{TP}}{\text{TP} + \text{FN}}\)</p> </li> <li><strong>优点</strong>：在对漏报敏感的应用（如疾病检测）中效果显著。</li> <li><strong>缺点</strong>：当模型倾向于将样本预测为正类时，召回率可能较高，但精确率会下降。</li> </ul> <hr/> <h3 id="4-f1-值-f1-score">4. F1 值 (F1 Score)</h3> <ul> <li> <p><strong>定义</strong>：F1 值是精确率和召回率的调和平均值，用于综合评估模型的精确度和召回度。 \(\text{F1 Score} = 2 \cdot \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}\)</p> </li> <li><strong>优点</strong>：适用于类别不平衡的数据集，因为它权衡了精确率和召回率。</li> <li><strong>缺点</strong>：不适用于只关注精确率或召回率的应用场景，因为它无法提供各个指标的详细信息。</li> </ul> <hr/> <h3 id="5-auc-area-under-curve">5. AUC (Area Under Curve)</h3> <ul> <li> <p><strong>定义</strong>：AUC 表示 ROC 曲线下的面积，ROC 曲线是通过绘制不同阈值下的 TPR（真正率）和 FPR（假正率）得到的曲线。 \(\text{AUC} = \int \text{ROC Curve}\)</p> </li> <li><strong>优点</strong>：不受类别分布影响，能够直观衡量模型的分类能力。AUC 越接近 1，模型效果越好。</li> <li><strong>缺点</strong>：对于类别不平衡严重的情况，AUC 可能掩盖少数类的错误分类问题。</li> </ul> <hr/> <h3 id="6-g-mean-几何平均">6. G-Mean (几何平均)</h3> <ul> <li> <p><strong>定义</strong>：G-mean 是模型在正类和负类上的分类效果的几何平均值，通常用于处理类别不平衡的数据。 \(\text{G-Mean} = \sqrt{\text{Recall}_{\text{positive}} \times \text{Recall}_{\text{negative}}}\)</p> </li> <li><strong>优点</strong>：能够平衡模型在不同类别上的表现，适用于类别不平衡的情况。</li> <li><strong>缺点</strong>：可能在极端不平衡数据上表现不佳，因为少数类的表现过于依赖召回率。</li> </ul> <hr/> <h3 id="总结">总结</h3> <table> <thead> <tr> <th>指标</th> <th>定义</th> <th>优点</th> <th>缺点</th> </tr> </thead> <tbody> <tr> <td>准确率</td> <td>所有正确预测的样本占所有样本的比例</td> <td>直观简单，适用于类别平衡的数据集</td> <td>类别不平衡时效果差</td> </tr> <tr> <td>精确率</td> <td>预测为正类的样本中真正为正类的比例</td> <td>适用于误报容忍度低的场景</td> <td>容易忽视召回率</td> </tr> <tr> <td>召回率</td> <td>实际为正类的样本中被正确预测为正类的比例</td> <td>适用于漏报敏感的场景</td> <td>容易忽视精确率</td> </tr> <tr> <td>F1 值</td> <td>精确率和召回率的调和平均值</td> <td>平衡精确率和召回率，适用于类别不平衡的数据</td> <td>无法提供精确率和召回率的详细信息</td> </tr> <tr> <td>AUC</td> <td>ROC 曲线下面积，表示模型对不同阈值下的整体表现</td> <td>不受类别分布影响，能够直观衡量模型分类能力</td> <td>严重不平衡数据时可能掩盖少数类错误</td> </tr> <tr> <td>G-Mean</td> <td>正类和负类召回率的几何平均值，适用于类别不平衡数据</td> <td>平衡模型在不同类别上的表现</td> <td>在极端不平衡数据上表现可能不佳</td> </tr> </tbody> </table> <hr/> <h2 id="tprfprtnrfnrl2-error-和-l1-error">TPR、FPR、TNR、FNR、L2 Error 和 L1 Error</h2> <h3 id="1-tpr-true-positive-rate">1. TPR (True Positive Rate)</h3> <ul> <li><strong>定义</strong>：TPR（真正例率）是所有实际为正类的样本中被正确预测为正类的比例，等同于<strong>召回率</strong>。 \(\text{TPR} = \frac{\text{TP}}{\text{TP} + \text{FN}}\)</li> </ul> <h3 id="2-fpr-false-positive-rate">2. FPR (False Positive Rate)</h3> <ul> <li><strong>定义</strong>：FPR（假正例率）是所有实际为负类的样本中被错误预测为正类的比例。 \(\text{FPR} = \frac{\text{FP}}{\text{FP} + \text{TN}}\)</li> </ul> <h3 id="3-tnr-true-negative-rate">3. TNR (True Negative Rate)</h3> <ul> <li><strong>定义</strong>：TNR（真负例率）是所有实际为负类的样本中被正确预测为负类的比例，也称<strong>特异性</strong>。 \(\text{TNR} = \frac{\text{TN}}{\text{TN} + \text{FP}}\)</li> </ul> <h3 id="4-fnr-false-negative-rate">4. FNR (False Negative Rate)</h3> <ul> <li><strong>定义</strong>：FNR（假负例率）是所有实际为正类的样本中被错误预测为负类的比例。 \(\text{FNR} = \frac{\text{FN}}{\text{FN} + \text{TP}}\)</li> </ul> <h3 id="5-l2-error-mean-squared-error-mse">5. L2 Error (Mean Squared Error, MSE)</h3> <ul> <li><strong>定义</strong>：L2误差是预测值与实际值之间差值的平方和的均值。 \(\text{L2 Error} = \frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2\)</li> </ul> <h3 id="6-l1-error-mean-absolute-error-mae">6. L1 Error (Mean Absolute Error, MAE)</h3> <ul> <li><strong>定义</strong>：L1误差是预测值与实际值之间差值的绝对值的均值。 \(\text{L1 Error} = \frac{1}{n} \sum_{i=1}^n |y_i - \hat{y}_i|\)</li> </ul> <hr/> <h2 id="为什么在-mia-中更关注低-fpr-下的-tpr">为什么在 MIA 中更关注低 FPR 下的 TPR？</h2> <p>在<strong>成员推断攻击</strong>（Membership Inference Attack, MIA）中，更关注在低 FPR（False Positive Rate）下的 TPR（True Positive Rate）。原因包括：</p> <ol> <li><strong>隐私风险</strong>：低 FPR 能降低误判非成员为成员的可能性。</li> <li><strong>误报影响</strong>：高 FPR 会导致大量误报，掩盖攻击模型的真实效果。</li> <li><strong>攻击强度</strong>：在极少误报情况下，高 TPR 表示攻击模型在严格条件下的攻击强度。</li> <li><strong>防御敏感性</strong>：低 FPR 下的 TPR 能更好地评估防御机制的有效性。</li> <li><strong>实际需求</strong>：在金融或医疗领域，低 FPR 的高 TPR 更符合实际隐私需求。</li> </ol> <p>低 FPR 下的 TPR 能帮助揭示模型在严格隐私保护条件下的风险。</p>]]></content><author><name></name></author><category term="MIA"/><category term="metrics"/><summary type="html"><![CDATA[本文主要介绍了分类任务的评价标准及优缺点和适用范围，以及MIA attack与各类指标的关系。]]></summary></entry><entry><title type="html">Membership Inferernce Attacks on LLM (Large Language Models)</title><link href="https://rhincodone.github.io/posts/2024-03-23-Machine-Unlearning-On-LLM/" rel="alternate" type="text/html" title="Membership Inferernce Attacks on LLM (Large Language Models)"/><published>2024-03-23T00:00:00+00:00</published><updated>2024-03-23T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/Machine-Unlearning-On-LLM</id><content type="html" xml:base="https://rhincodone.github.io/posts/2024-03-23-Machine-Unlearning-On-LLM/"><![CDATA[<h2 id="introduction">Introduction</h2> <p>Membership Inference Attacks (MIAs) are designed to determine if a specific data record was used in a model’s training set. Introduced by Shokri et al. in 2017[1], MIAs have since been recognized for their relevance to privacy concerns within machine learning. This introduction will cover the fundamental concept of MIAs and their initial application. Following that, we’ll explore the adaptation of MIAs to large-scale Large Language Models (LLMs) and identify the challenges that diminish MIAs’ effectiveness in this context. To conclude, the discussion will shift to prospective developments and the role MIAs may play in enhancing the privacy of LLMs.</p> <h2 id="membership-inference-attacks">Membership inference attacks</h2> <p>The intuition behind MIAs lies in overfitting of the model to the training data. Overfitting is a common challenge in machine learning, where a model learns too much from its training data, capturing excessive detail that hinders its ability to generalize to unseen data. This occurs when a model, after extensive training, performs exceptionally well on the training data (for instance, achieving 100% accuracy) but poorly on a testing dataset, effectively making random guesses. The root of this issue lies in the model memorizing specific details of the training images—such as the exact pixel positions—rather than learning the broader, general features necessary to distinguish between different individuals’ faces. Although overfitting cannot be completely eliminated due to the model’s inherent limitation of learning solely from its training dataset, various strategies can mitigate its effects.</p> <p>This concept of overfitting also underpins the differential performance of models on training versus non-training samples, evident through their loss function outputs. For example, a model might show lower loss (e.g., smaller cross-entropy) for training samples than for testing samples. This discrepancy is exploited in membership inference attacks, which aim to determine whether a specific sample was part of the model’s training set based on the model’s response to that sample.</p> <p>In early implementations of membership inference attacks, the approach involves splitting an original dataset into two parts: one for members (data included in the training set) and one for non-members (data excluded from the training set). The “member” data is used to train a target model, resulting in a model trained specifically on that subset. Subsequently, samples from both the member and non-member datasets are input into the trained model, which outputs a probability vector for each sample if the model is of the classification type. These vectors, along with labels indicating “member” or “non-member” status based on the sample’s origin, are combined with the sample’s true classification label to form a new dataset. This new dataset, referred to as the attack dataset, includes each sample’s probability vector, its true class label, and its membership label. An attack model—a binary classification model—is then trained on this attack dataset to discern whether a given sample was part of the model’s training set.</p> <h2 id="mia-on-llm">MIA on LLM</h2> <p>Although MIA has been deeply investigated in small-scale networks, in the era of large languge model (LLM), it is not studied on the LLM enough. Most of the works directly adopt the intuition of MIA-classify the members and non-members based on some indicators (The implementations of the attacks can be found at [6]):</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/MIALLM-480.webp 480w,/assets/img/MIALLM-800.webp 800w,/assets/img/MIALLM-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/MIALLM.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> <ol> <li> <p><strong>LOSS [2]:</strong> Considers the model’s computed loss over the target sample. \begin{equation}f(x;M) = L(x;M)\end{equation}</p> </li> <li> <p><strong>Reference-based [3]:</strong> Attempts to improve the precision of the LOSS attack and reduce the false negative rate by accounting for the intrinsic complexity of the target point \(x\) by calibrating \(L(x;M)\), with respect to another reference model \((M_{ref})\), which is trained on data from the same distribution as \(D\), but not necessarily the same data. \begin{equation}f(x;M) = L(x;M) - L(x;M_{ref})\end{equation}</p> </li> <li> <p><strong>Zlib Entropy [3]:</strong> Calibrates the sample’s loss under the target model using the sample’s zlib compression size. \begin{equation}f(x;M) = \frac{L(x;M)}{zlib(x)}\end{equation}</p> </li> <li> <p><strong>Min-k% Prob [4]:</strong> Uses the \(k\%\) of tokens with the lowest likelihoods to compute a score instead of averaging over all token probabilities as in loss. \begin{equation}f(x;M) = \frac{1}{|min-k(x)|} \sum_{x_i \in min-k(x)} -\log(p(x_i | x_1, …, x_{i-1}))\end{equation}</p> </li> <li> <p><strong>Neighborhood Attack [5]:</strong> Uses an estimate of the curvature of the loss function at a given sample, computed by perturbing the target sequence to create \(n\) ‘neighboring’ points, and comparing the loss of the target \(x\), with its neighbors \(\tilde{x}\). \begin{equation}f(x;M) = L(x;M) - \frac{1}{n} \sum_{i=1}^{n} L(\tilde{x}_i;M)\end{equation}</p> </li> </ol> <h2 id="why-mia-cares">Why MIA cares</h2> <p>Membership Inference Attacks (MIA) are significant for privacy because they can expose whether an individual’s data was used in training a machine learning model. This might seem technical but has real-world privacy implications, especially in sensitive contexts. For a simple example, consider a machine learning model trained on health records to predict disease outcomes. If an attacker can use MIA to determine that a particular individual’s data was used in the training set, they might indirectly learn something about that individual’s health status, even if the data was supposed to be anonymous.</p> <p>Imagine a hospital that develops a model to predict diabetes risk based on patient records. If an attacker can apply MIA to this model and discover that John Doe’s data was used in training, they could infer that John might have been at risk of or diagnosed with diabetes, information that’s supposed to be private. This scenario illustrates why MIA is a concern for privacy: it can lead to unintended disclosures of personal information, undermining the anonymity and confidentiality of sensitive data.</p> <h2 id="problems-in-mia">Problems in MIA</h2> <p>As research into Membership Inference Attacks (MIA) progresses, several complexities and challenges have emerged. A key question is the interpretation of the probabilities produced by MIA models. For instance, if an MIA model assigns a 60% probability to a sample being a “member” (i.e., part of the training data), the implications for privacy remain unclear. This uncertainty extends to minor modifications of the sample, such as altering a single pixel—does this still warrant a “member” classification, and what does that mean for privacy?</p> <p>Carlini et al. have highlighted that MIA tends to be more effective at identifying “non-member” records rather than “members.”[7] This observation suggests that the privacy risks associated with membership inference might not be as significant for member samples as previously thought.</p> <p>Furthermore, the nuances of Large Language Models (LLMs) and their susceptibility to MIAs warrant further exploration. Specific characteristics of LLMs, such as their capacity for data memorization, play a crucial role in how they might compromise the anonymity of training data. However, the full extent of these features’ impact on training data membership remains partially understood.</p> <p>Given these issues, the future and practical relevance of MIA are subjects of ongoing debate. As we continue to unravel the complexities of MIAs and their effects on privacy, it is crucial to refine our understanding of these attacks and their implications for the security of machine learning models.</p> <h2 id="potential-of-mia">Potential of MIA</h2> <p>Recent research highlights the potential of Membership Inference Attacks (MIA) for auditing the privacy of algorithms designed for differential privacy. Differential privacy provides a solid guarantee of privacy, leading to the proposal of differentially private machine learning algorithms, such as DP-SGD and DP-Adam. Users set a theoretical privacy budget, \(\epsilon_{theory}\), and a relaxation parameter, \(\delta\), aiming for the trained model to achieve \((\epsilon_{theory},\delta)\)-differential privacy. However, assessing a model’s actual privacy level has been challenging, as differential privacy offers a worst-case guarantee, suggesting that the practical privacy level might be more stringent (practical \(\epsilon\) is smaller than \(\epsilon_{theory}\)).</p> <p>Studies now indicate that MIA can estimate the lower bound of the practical \(\epsilon\), denoted as \(\epsilon_{LB}\). This suggests the actual \(\epsilon\) for a model’s privacy lies within the range \([\epsilon_{LB},\epsilon_{theory}]\), providing a clearer picture of its privacy assurances. This insight underscores MIA’s role in evaluating and ensuring the privacy of differentially private machine learning algorithms[8][9][10].</p> <p>Several differentially private fine-tuning techniques have been developed for Large Language Models (LLMs) to secure their differential privacy [11][12]. Despite these advancements, there remains a lack of research into the auditing of these models’ actual privacy levels. Therefore, a valuable direction for future work could be to employ Membership Inference Attacks (MIAs) to assess and audit the privacy of LLMs that have undergone differential privacy fine-tuning. This approach could provide a clearer understanding of how private the LLMs really are, beyond theoretical guarantees.</p> <h2 id="references">References</h2> <p>[1] Shokri, R., Stronati, M., Song, C., &amp; Shmatikov, V. (2017, May). Membership inference attacks against machine learning models. In 2017 IEEE symposium on security and privacy (SP) (pp. 3-18). IEEE.</p> <p>[2] Yeom, S., Giacomelli, I., Fredrikson, M., &amp; Jha, S. (2018, July). Privacy risk in machine learning: Analyzing the connection to overfitting. In 2018 IEEE 31st computer security foundations symposium (CSF) (pp. 268-282). IEEE.</p> <p>[3] Carlini, N., Tramer, F., Wallace, E., Jagielski, M., Herbert-Voss, A., Lee, K., … &amp; Raffel, C. (2021). Extracting training data from large language models. In 30th USENIX Security Symposium (USENIX Security 21) (pp. 2633-2650).</p> <p>[4] Shi, W., Ajith, A., Xia, M., Huang, Y., Liu, D., Blevins, T., … &amp; Zettlemoyer, L. (2023). Detecting pretraining data from large language models. arXiv preprint arXiv:2310.16789.</p> <p>[5] Mattern, J., Mireshghallah, F., Jin, Z., Schölkopf, B., Sachan, M., &amp; Berg-Kirkpatrick, T. (2023). Membership inference attacks against language models via neighbourhood comparison. arXiv preprint arXiv:2305.18462.</p> <p>[6] https://github.com/iamgroot42/mimir</p> <p>[7] N. Carlini, S. Chien, M. Nasr, S. Song, A. Terzis and F. Tramèr, “Membership Inference Attacks From First Principles,” 2022 IEEE Symposium on Security and Privacy (SP), San Francisco, CA, USA, 2022, pp. 1897-1914, doi: 10.1109/SP46214.2022.9833649.</p> <p>[8] Tramer, F., Terzis, A., Steinke, T., Song, S., Jagielski, M., &amp; Carlini, N. (2022). Debugging differential privacy: A case study for privacy auditing. arXiv preprint arXiv:2202.12219.</p> <p>[9] Nasr, M., Hayes, J., Steinke, T., Balle, B., Tramèr, F., Jagielski, M., … &amp; Terzis, A. (2023). Tight auditing of differentially private machine learning. In 32nd USENIX Security Symposium (USENIX Security 23) (pp. 1631-1648).</p> <p>[10] Steinke, T., Nasr, M., &amp; Jagielski, M. (2024). Privacy auditing with one (1) training run. Advances in Neural Information Processing Systems, 36.</p> <p>[11] Behnia, R., Ebrahimi, M. R., Pacheco, J., &amp; Padmanabhan, B. (2022, November). Ew-tune: A framework for privately fine-tuning large language models with differential privacy. In 2022 IEEE International Conference on Data Mining Workshops (ICDMW) (pp. 560-566). IEEE.</p> <p>[12] Singh, T., Aditya, H., Madisetti, V. K., &amp; Bahga, A. (2024). Whispered Tuning: Data Privacy Preservation in Fine-Tuning LLMs through Differential Privacy. Journal of Software Engineering and Applications, 17(1), 1-22.</p>]]></content><author><name></name></author><category term="Machine"/><category term="Unlearning"/><category term="MU"/><summary type="html"><![CDATA[In this post, I'll introduce what is membership inference attack, how it's used on LLM, and what's the potential problem on it.]]></summary></entry><entry><title type="html">A Foundation of Differential Privacy</title><link href="https://rhincodone.github.io/posts/2024-03-05-Differential-Privacy/" rel="alternate" type="text/html" title="A Foundation of Differential Privacy"/><published>2024-03-05T00:00:00+00:00</published><updated>2024-03-05T00:00:00+00:00</updated><id>https://rhincodone.github.io/posts/Differential-Privacy</id><content type="html" xml:base="https://rhincodone.github.io/posts/2024-03-05-Differential-Privacy/"><![CDATA[<h2 id="introduction-with-an-example">Introduction with an example</h2> <p>Differential privacy (DP) is a privacy-preserving concept in data analysis and statistics. The goal of differential privacy is to allow the inclusion of an individual’s data in a dataset for analysis while protecting the privacy of that individual.</p> <h2 id="example">Example</h2> <p>So, how does DP achieve this? Let’s take a simple example:</p> <p>Suppose you are part of a company that wants to calculate the average salary of its employees without revealing the salary of any specific employee. The company collects the following data:</p> <p><em>Employee A: $60,000</em> <em>Employee B: $70,000</em> <em>Employee C: $80,000</em> <em>Employee D: $90,000</em></p> <p><strong>Non-Differentially Private Calculation:</strong></p> <p>In a traditional average calculation, you might sum all salaries and divide by the number of employees: \begin{equation} \text{Average} = \frac{60,000 + 70,000 + 80,000 + 90,000}{4} = 75,000 \end{equation}</p> <p><strong>Differentially Private Calculation:</strong></p> <p>In a differentially private approach, you add random noise to the calculation to protect individual privacy. Let’s say you add random noise between -1,000 and +1,000 to each employee’s salary:</p> <p>\begin{equation} \text{Average} = \frac{60,000 + 70,000 + 80,000 + 90,000 + \text{noise}}{4} \end{equation}</p> <p>Here, the noise is a random value chosen from the range -1,000 to +1,000. This ensures that even if an individual’s salary changes slightly, it is challenging to determine which specific employee’s salary contributed to the final result.</p> <p>In essence, differential privacy aims to introduce uncertainty in the output distribution. Considering two datasets that differ only in one data record, a differentially private algorithm will generate output distributions that are slightly different for these two datasets. In other words, observers cannot discern which dataset the algorithm used from the output, and thus, they cannot determine whether a specific data record is in the dataset or not.</p>]]></content><author><name></name></author><category term="Differential"/><category term="privacy"/><category term="DP"/><summary type="html"><![CDATA[In this post, I'll generally introduce what is differential privacy with an example]]></summary></entry></feed>