Metadata-Version: 2.4
Name: nrfunc
Version: 1.1.0
Summary: 神经区函数算法：成熟模型的函数化压缩与产物生成库（函数化 + 生成物）
Author-email: lph <414561114@qq.com>
License-Expression: MIT
Keywords: quantization,model-compression,region,functionalization,sharding
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: torch>=2.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Provides-Extra: memory
Requires-Dist: psutil; extra == "memory"
Dynamic: license-file

# nrfunc —— 神经区函数算法（函数化 + 生成物）

## 一、原理

**已训练好的成熟模型**里，一层权重有 `n` 个输出单元（神经元/卷积核/注意力头），
传统上每个单元独立存 `D` 个权重（共 `n×D`）。但很多单元其实是「同类函数」——
功能相近、参数冗余。

本库把这些单元聚成 `K` 个「区」（`K ≪ n`），**同区共用一个「区域函数」**表达：

- **0 阶**：每区一个质心（均值向量），参数从 `n×D` 降到 `K×D`
- **1 阶**：每区 = 均值 + 前 `r` 个主成分（截断 SVD，即低秩），另存每单元 `n×r` 投影系数

再给每个单元存一个「归属索引」（`log₂K` 位，记它属于哪一区）。于是整体的存储，
从「`n` 份独立权重」变成「`K` 份共享函数 + `n` 份归属索引」——**这就是体积压缩的来源**。

```
训练 ── 模型 ── 成熟模型 ──[ 函数化 + 生成物 ]──> 部署
                              ↑
                        本库只负责这一段
```

- **上游（不是本库的活）**：训练、模型定义、蒸馏、微调、量化感知训练（QAT）。
- **本库只做两件事**：① 函数化（把权重重新表达为区域函数 + 归属索引）；
  ② 生成物（区域函数参数 + 索引 + 投影系数 + 量化打包 + 分片存储 + 价值对比）。
- **下游（也不是本库的活）**：把生成物接入推理/部署。生成物可经 `reconstruct()`
  还原成近似权重、**当模型权重用**，但真正跑起来是下游的活。

## 二、收益评估

函数化的收益，落在**体积 / 内存 / CPU / GPU** 四个维度（一个词：**用少量精度，换体积与内存**）：

| 维度 | 收益 | 一句话结论 |
|------|------|-----------|
| 体积 | **恒省**（8bit 量化，参数量 `n×D → K×D`） | 确定收益，最直观 |
| 内存 | 有条件地省 | 只在 `K×(1+r) < n` 时净省，且看部署方式 |
| CPU | 有条件地省 | 大模型（K≪n）+ Rust/GPU 才兑现，numpy 小模型可能更慢 |
| GPU 显存 | 随函数部署省 | 与「内存·函数部署」同口径 |

**本机真实实测（代表性数据）**：

| 例子 | 层 | 体积省 | 内存·函数部署省 | 精度掉点 |
|------|-----|--------|----------------|---------|
| MNIST MLP | fc1 128×784 | 95.9% | 83.8% | 2.98pt |
| 真实大 CNN | 最大卷积层 features.17 | 92.9% | 71.4% | 2.75pt |
| 玩具 ViT | wq 64×64 | 90.5% | 62.4% | 0.71pt |

> 数据口径：固定种子可复现；掉点均为「函数化后 vs 原始模型」的精度差，红线 <3pt
> （库自带 `auto_alloc` 自适应分配器守住）。完整四维一表见下文「价值证明」。

## 三、使用注意事项

1. **体积 ≠ 内存**：体积用 8bit 量化能省 90%+，但运行时内存是 float32 常驻，省得少；
   且**内存省不省取决于部署方式**——`reconstruct()` 还原回稠密时内存一点不省，
   只有走 `functional_forward()`（不还原、只常驻紧凑参数）才省。
2. **CPU 不是函数化的卖点**：numpy 参考实现的 1 阶前向受 Python 循环 + gather 限制，
   小模型可能慢于 BLAS 稠密前向；提速只在「K≪n 的大模型 + 编译语言（Rust）/GPU」兑现。
3. **按层判断，别一刀切**：小层/首层函数化可能「内存反涨」甚至「掉点崩盘」。
   用 `auto_alloc(W, eval_fn=...)` 逐层自适应（自动跳过不划算的层）最稳。
4. **处理对象是一层权重、不是整个模型**：本库处理「一层权重矩阵」这个实例无关单元；
   GPT 级大模型方向只做接口预留 + 理论预演，**不负责验证**（需 ≥80GB 级多卡）。

详见下文「责任边界」。

---

## 安装

```bash
pip install nrfunc          # 用户安装（发布后从包仓库安装）
```

依赖：`numpy`、`torch`。

开发者（本地源码开发）可编辑安装：

```bash
pip install -e ".[dev]"      # 含 pytest / pytest-cov / mypy
```

可选依赖（按需安装，不装也不影响函数化 + 生成物主链路）：

```bash
pip install -e ".[memory]"   # psutil：rss_mb() 实测进程内存（不装时返回 None）
```

> `psutil` 是「软依赖」：只在 `rss_mb()` 测真实内存时需要；未安装时 `rss_mb()`
> 返回 `None`（而非 0，避免误导），库其余功能完全不受影响。

## 快速开始

```python
import numpy as np
import nrfunc

# 1) 你已训练好的成熟模型：抽出一层权重（任意框架，这里给 numpy）
W = np.random.default_rng(0).standard_normal((256, 128)).astype(np.float32)

# 2) 函数化：256 个输出单元 → 16 个区域函数（1 阶低秩，每区 8 个主成分）
res = nrfunc.regionify(W, signal='G', K=16, order=1, r=8)
print(f"区域数 K={res['K']}，解释方差={res['explained']:.3f}")

# 3) 生成物 · 价值对比（体积 / 内存；CPU/GPU 需传实测参数，
#    完整四维一表落地见 examples 里的 show_value()）
tbl = nrfunc.compare_value(W, res, bits_before=32, bits_after=8)
print(tbl['_table'])

# 4) 生成物 · 量化打包（把区域函数参数量化成可部署字节）
packed, scale, n_out, n_in = nrfunc.quantize_weights(res['means'], bits=8)

# 5) 生成物 · 分散存储到 4 个节点，并行读取
store = nrfunc.build_store(res, n_shards=4)
params = store.region_read_many([0, 1, 2, 3])

# 6) 生成物 → 重建权重：还原成近似权重，可当模型权重用（下游再接入推理）
recon = nrfunc.reconstruct(res)   # (256, 128)
print(f"重建权重 shape={recon.shape}，保真度={res['explained']:.3f}")
```

---

## API 参考（参数 / 用法 / 注意事项）

> 下面是全部公开函数的签名与参数说明，按模块分组。注意：本库处理对象是「一层
> 权重矩阵」`(n, D)`（n=神经元/卷积核/头数，D=每单元参数量），不是整个模型。

### 1. 函数化（core）

**`regionify(rows, signal='G', K=None, order=0, r=None, iters=60, seed=0, activations=None, groups=None, assign=None, n_init=1)`** —— 分区函数化统一入口，返回 dict。

| 参数 | 说明 |
|------|------|
| `rows` | `(n, D)` 权重行向量（numpy 或可转 numpy 的数组） |
| `signal` | `'G'` 几何（k-means）/ `'F'` 功能（余弦聚类，需 `activations`）/ `'S'` 结构（按边界切，需 `groups`） |
| `K` | 分区数。省略时默认 `sqrt(n)`；`signal='S'` 由 `groups` 决定、可省略 |
| `order` | `0`=质心 / `1`=低秩（默认 0） |
| `r` | `order=1` 时每区主成分数，省略默认 `sqrt(D)` |
| `iters` | 聚类迭代次数（G/F 用） |
| `seed` | 随机种子（库内 mulberry32，固定 seed 跨平台可复现） |
| `activations` | `signal='F'` 所需的 `(n, T)` 激活响应矩阵 |
| `groups` | `signal='S'` 所需的 `(n,)` 结构归属（层号/头号/通道号） |
| `assign` | 可选，已算好的 `(n,)` 归属，传入时跳过聚类直接构造（auto_alloc 复用） |
| `n_init` | 多起点重跑次数（G/F），>1 时尝试多个确定性种子取保真最高；默认 1 |

返回 dict 关键字段：`signal`/`order`/`K`/`assign`(n,)/`n`/`D`/`explained`，以及按阶数的参数——0 阶 `centroids`(K,D)；1 阶 `means`(K,D) + `components`(K,r,D) + `coeffs`(n,r)。

**`regionify_hierarchical(rows, signal='G', K_top=None, K_sub=None, order=0, r=None, iters=60, seed=0, activations=None)`** —— 多尺度树分区（先粗分大区、再区内细分），叶子区总数 ≤ `K_top×K_sub`。仅支持 `'G'/'F'`（`'S'` 结构边界本就不需层次聚类）。返回与 `regionify` 同构、可直接 `reconstruct()`。

**`reconstruct(result)`** —— 把区域函数还原成近似权重 `(n, D)`。0 阶=归属质心；1 阶=区均值+投影修正。

**`functional_forward(result, x)`** —— 函数形式前向，**不还原稠密权重**，`y = x @ W^T` 的等价计算。`x` 形状 `(..., D)`，返回 `(..., n)`。这是「为提速」的路径（共享函数只算一次），数值与先 `reconstruct()` 再前向一致（浮点误差内）。

**`regionify_transformer_block(block, signal='S', order=1, r=None)`** —— GPT 级接口预留，**不做验证**（需 ≥80GB 多卡）。普通 Transformer 请用 `regionify(signal='S', groups=...)`。

### 2. 自适应分配器（auto_alloc）

**`auto_alloc(rows, signal='G', activations=None, groups=None, budget=None, distortion=None, eval_fn=None, K_grid=None, r_grid=None, r_max=None, auto_probe=True, probe_energy=0.95, probe_cap=256, iters=60, seed=0, float_bits=32)`** —— 给一层自动挑最优 `(order,K,r)`，或判「跳过」。

| 参数 | 说明 |
|------|------|
| `rows` / `signal` / `activations` / `groups` | 同 `regionify` |
| `budget` | 可选，函数化后字节上限；原权重已 ≤ budget 则直接跳过 |
| `distortion` | 可选，失真度 = 允许的 EV 掉点上限（0~1）。给定时追加硬约束 `explained ≥ 1 - distortion`；默认 None（走省/保真加权，不设保真硬下限） |
| `eval_fn` | 可选，真实精度回调 `eval_fn(result)->bool`，True=接受；这是「掉点<阈值」的**可靠**实现 |
| `K_grid` / `r_grid` | 可选候选网格；默认 K 含 K=1（全局低秩）+ 2 的幂 + sqrt(n)，r 由谱探测自适应生成 |
| `r_max` | 可选，1 阶主成分数上限（对 r 候选截断） |
| `auto_probe` | 是否启用谱探测（默认 True）；关闭则 r 回退固定网格 |
| `probe_energy` / `probe_cap` | 谱探测的累积能量阈值（默认 0.95）/ 规模上限（默认 256） |
| `iters` / `seed` / `float_bits` | 聚类迭代 / 随机种子 / 内存口径位宽（默认 32） |

返回 dict 关键字段：`decision`（`'order1'`/`'order0'`/`'skip'`）、`result`（跳过为 None）、`order`/`K`/`r`（跳过为 None）、`saving`（节省率，正=省；跳过=0）、`explained`（重构保真度，跳过为 None）、`skipped_reason`（仅 skip 时非空）、`bytes_before`/`bytes_after`、`n_candidates`/`n_tried`、`r_est`（谱探测估计的有效维度）。

**注意**：`eval_fn` 的返回语义是「接受 = True」。你在 auto_alloc 之外自行实现掉点护栏时的写法见 `examples/python/_common.py::make_drop_guard`。

### 3. 生成物 · 量化 / 分片 / 二进制（io）

**`quantize_weights(w, bits=4)`** —— per-row 对称量化，返回 `(packed_bytes, scale, n_out, n_in)`。`bits` 仅 4/8。接受 numpy 或 torch 张量。

**`dequantize_weights(packed, scale, n_out, n_in, bits=4)`** —— 反量化回 float32。

**`packed_bytes(num_params, bits=4)`** —— 按位宽估算字节数（不含 scale 元数据）。

**`build_store(result, n_shards=1)`** —— 构建分片存储，返回 `ShardedRegionStore`。

**`ShardedRegionStore.region_read(region_id)` / `region_read_many(ids)`** —— 读区域函数参数；`region_read_many` 跨分片多线程并行。`placement()` 看分布、`load_balance()` 看负载。

**`to_bytes(result, bits=8)` / `from_bytes(data)`** —— 把整个生成物打成一段紧凑二进制字节块（**降 IO 频率与体积**），或反向解码。`bits`=8/4/32：8=INT8、4=INT4（真打包、体积再减半）、32=float32 无损。

> 字节格式：23 字节小端头（`NRFN` magic + version/order/bits/K/n/D/r）+ 区域函数参数 + assign 索引。
> `from_bytes` 只还原结构元数据+参数+assign，**不还原 signal/explained 等标量**（需自行保留）。
> 跨语言消费示例见 `examples/code/`（Go/Java/Rust/C++ 读同一段二进制）。

### 4. 价值证明 / 基准（utils）

**`size_bytes_raw(n, D, bits=32)`** —— 函数化前字节数。

**`size_bytes_regionalized(result, bits=8, index_bits_override=None)`** —— 函数化后字节数（含 1 阶投影系数与归属索引）。`index_bits_override` 可选，覆盖归属索引位宽（默认按 `ceil(log2(K))` 自动算）。

**`compare_value(rows, result, bits_before=32, bits_after=8, cpu_before_ns=None, cpu_after_ns=None, gpu_before_mb=None, gpu_after_mb=None, mem_scale=1.0)`** —— 生成四维对比表（体积/内存/CPU/GPU），返回 dict（含 `_table` 格式化字符串）。

**`cpu_time(fn, *args, iters=20, warmup=3)`** —— 同机同批 CPU 前向耗时（ns/次）。

**`gpu_memory_bytes(fn, *args, device='cuda')`** —— 实测显存（字节），无 CUDA 返回 None。

**`bench_single(fn, x, ...)` / `bench_batch(fn, batch, ...)`** —— torch 单样本延迟 / 批量吞吐（取最快轮）。

**`rss_mb()`** —— 进程常驻内存（MB），需 `psutil`（软依赖）；未装返回 None。

### 全局注意事项

1. **`assign` 数组是 int32**，`to_bytes`/`from_bytes` 里也按 int32 处理，别和权重 float 混。
2. **1 阶净省的近似充要条件是 `K×(1+r)<n`**，不满足就别函数化（auto_alloc 会先验剪枝）。
3. **掉点红线 <3pt**（库各示例的统一口径），衡量口径是「函数化后 vs 原始模型」的精度差；单层的 `single_drop` 可为负（重建恰好更优），叠加掉点因误差累积而略大于单层之和。
4. **体积≠内存**：体积是量化位宽口径（能省 90%+），内存是 float32 常驻（省得少）；且内存省不省看部署方式（`reconstruct` 不省，`functional_forward` 才省）。
5. **CPU 提速有条件**：只在「K≪n 大层 + Rust/GPU」兑现，numpy 小模型可能更慢。

## 分区信号分型

一刀切 k-means 只对「小 MLP」成立。大模型权重空间分层、置换不变，必须按底层模型分型：

| 模型底层 | 分区信号 | 含义 | 入口 |
|---------|---------|------|------|
| 小 MLP | `G` 几何 | 权重几何 ≈ 功能，按欧氏距离 k-means | `regionify(signal='G')` |
| CNN | `F` 功能 | 功能同构的核权重几何可远，按激活响应余弦聚类 | `regionify(signal='F', activations=...)` |
| Transformer | `S` 结构 | 头/层是并行功能模块，按结构边界切分不混聚 | `regionify(signal='S', groups=...)` |
| GPT 级 | `S`+`F`+低秩 | 结构边界 + 功能聚类 + FFN 低秩 | `regionify_transformer_block()`（仅预演，不验证） |

除「分区信号」这一维，分区尺度还有一维「多尺度树」（先粗分区成大区，再每区内细分小区）：

- `regionify_hierarchical(rows, signal='G', K_top=8, K_sub=4, order=1, r=8)`：两层树，叶子区 ≤ `K_top × K_sub`，树深（叶子数）可调——叶子越多、压缩越弱、保真越高。
- 四个方向（A 功能聚类 / B 多尺度树 / C 阶数升级 / D 逐层区域化）的可运行实例见 `examples/python/four_directions_demo.py`，共用同一数据集，保证可用性。

### 自适应分配器 auto_alloc（不用手动挑 K/r）

手动选 K / r / 阶数容易踩坑：小层或首层函数化可能「内存反涨」甚至「掉点崩盘」。
`auto_alloc()` 逐层自动搜 `(order, K, r, 跳过)`，两阶段「auto」：

- **评估演算 → 深造推算**：入口谱探测估计该层「有效维度」（`compute_uv=False` 只算奇异值 + 超大规模均匀抽样，克制资源），据此自适应生成 r 候选（而非固定 [1,2,4,8]）；K 含 K=1 全局低秩模式（成熟精炼权重无聚类结构时的最优解）
- **硬约束「净省」**：内存绝不反涨（`K×(1+r)<n` 先验剪枝，省去必然反涨的候选）
- **掉点约束两层**：目标函数「省/保真加权」几何平均 `√(saving×explained)` 自动在省与保之间取平衡 → `distortion`（可选硬约束）→ `eval_fn`（真实精度回调，最可靠）
- **主动跳过**：该层函数化不划算时直接跳过，而不是硬凑一个劣化结果

```python
alloc = nrfunc.auto_alloc(W, eval_fn=lambda res: 你的真实精度掉点 < 阈值)
# alloc['decision'] 为 'order1' / 'order0'（{order,K,r}）或 'skip'（skipped_reason 说明为什么）
```

实测把 5 个真实模型里「反涨」的层全部转成净省、掉点全压 <3pt（见
`examples/python/auto_alloc_demo.py`）。

## 价值证明：函数化前 vs 后四维对比

四个维度——**体积 / 内存 / CPU / GPU**——库都有对应能力，不是只有体积：

| 维度 | 函数化前 | 函数化后 | 来源 |
|------|---------|---------|------|
| 体积 | `n×D×bits` | `K×D×bits + n×log₂K`（含 1 阶投影系数） | 参数量 × 位宽 |
| 内存 | `n×D×32bit` 常驻 | 见「部署方式」 | `size_bytes_regionalized()` |
| CPU | 稠密前向 `x@Wᵀ` | 函数前向 `functional_forward` | `cpu_time()` 实测（单样本+批量） |
| GPU | 原始权重（显存 + 前向） | 紧凑参数（显存 + 函数前向） | 实测（需 CUDA，显存+单样本+批量） |

压缩率来自：不再存 `n×D` 个独立权重，只存 `K` 个共享函数 + `n` 个归属索引。

**四维已实测落地**：`examples/python/mnist_mlp_classification.py` 用 `show_value()` 在同一张表里
打印全部四维（`fc1` 层 128×784，auto_alloc 自动选 K=1/r=17 的实测）：

| 维度 | 函数化前 | 函数化后 | 节省率 |
|------|---------|---------|--------|
| 体积（8bit 存储） | 401,408 B | 16,288 B | **95.9%** |
| 内存·还原部署（float32） | 401,408 B | 401,408 B | 0%（还原回稠密，内存不省） |
| 内存·函数部署（float32） | 401,408 B | 65,152 B | **83.8%** |
| GPU 显存（float32 常驻） | 0.4 MB | 0.1 MB | **83.5%** |
| GPU 单样本延迟 | 稠密前向 | 函数前向 | 见「函数形式前向」 |
| GPU 批量吞吐 | 稠密前向 | 函数前向 | 见「函数形式前向」 |

> 诚实口径（关键，别只看一张表）：
> - **体积 ≠ 内存**：体积用 8bit 量化能省 95.9%，但运行时内存是 float32 常驻，只省 83.8%；
>   而且**内存省不省取决于部署方式**——`reconstruct()` 还原回稠密 float32 时内存一点不省，
>   只有走 `functional_forward()` 函数部署（不还原、只常驻紧凑参数）才省内存。
> - **CPU 不是函数化的卖点**：numpy 参考实现里 `functional_forward` 的 1 阶小模型
>   受 Python 循环 + gather 限制，可能慢于 BLAS 稠密前向；提速只在「K≪n 的大模型 +
>   编译语言（Rust）/ GPU」里兑现（见下「函数形式前向」的 0 阶 29.9× / 1 阶 1.62×）。
> - **GPU 显存**这里只给 float32 常驻口径（与「内存·函数部署」同数）；GPU 上的
>   函数前向提速需 CUDA/Rust kernel，numpy 参考实现不含。`show_value()` 会给 GPU 侧
>   补上**单样本延迟 + 批量吞吐**（torch 真实 CUDA 前向，与 CPU 侧对称对齐），让
>   CPU / GPU 两端的「显存 / 耗时」都能并排对比；但 GPU 函数前向的提速潜力仍需
>   Rust/CUDA kernel 才兑现，此处的 torch 实测是「同一 CUDA 环境」下的可比口径。
> - 内存/显存是「存储占用」口径，不等于运行时峰值分配；CPU/GPU 只保证同机同批可比。

## 函数形式前向：不还原权重，直接按生成物算

`reconstruct()` 是「还原成稠密权重再算」，推理速度与原始权重一致、精度有损。另一条**为提速**设计的路径是 `functional_forward()`——不还原、直接用生成物算，共享的区域函数只算一次再按归属广播，省掉 K≪n 时的重复乘：

- **0 阶**：`y = (x @ centroids^T)[:, assign]` —— 只算 K 次内积，再查表广播回 n 个单元
- **1 阶**：`y = (x @ means^T)[:, assign] + Σ_j coeffs[i,j]·(components[assign[i],j] @ x)`

数值上等价于先 `reconstruct()` 再前向（浮点误差内一致）。本机实测提速（n=1024, D=512, K=16, r=8）：

| 阶数 | 单样本延迟 | 批量吞吐（B=1024） | 体积 |
|------|-----------|-------------------|------|
| 0 阶 | **29.9×** | 1.80× | 省 99.6% |
| 1 阶 | **1.62×** | 0.55× | 省 96.1% |

> 诚实声明：numpy 参考实现下，**0 阶提速干净兑现**；**1 阶批量未兑现理论 6.4×**（低秩修正的 gather / 小 K 矩阵乘在 numpy 里开销大）。1 阶的完整提速需在编译语言（Rust）/ GPU 里兑现——那里 gather 廉价、无 Python 开销，这正是下游部署（演算服务）该做的事。
>
> 这条「Rust/GPU 才兑现」的判断已有**端到端参照**：`examples/project` 的 13.77M 检测大模型上，函数化 fc2（2048×4097 宽层、K=32 r=8）用 Rust 二进制整网前向，**CPU 快 1.93~2.65x、GPU 快 1.31~1.38x**，数值自检 9.2e-14 一致（详见 `examples/project/README.md` 的 comparison.log）。

## 权重分散存储拓扑

区域函数权重不必集中单节点，可分散多节点分片 + IO 并行读取：

- 动机①：大规模权重单节点放不下，分片是唯一出路（呼应张量/模型并行）。
- 动机②：高并发批量读取会打爆单节点权重读取吞吐，分片后 IO 并行、吞吐随分片数扩展。
- `ShardedRegionStore` 把 K 个区域函数按 `region_id` 散列到 n 个分片，`region_read_many()` 多线程并行拉取。
- `n_shards=1` 退化为「集中单节点」。

## 嵌入式设备可行性（大模型上边缘）

本库能把「大模型上嵌入式」的**体积/内存**这堵墙撬动，但它只做「压缩 + 生成物」，
不含推理运行时——产物要能在嵌入式跑，必须有一个 C/Rust 推理 kernel 去消费它。

### 关键：本库能撬动哪几堵墙

| 瓶颈 | 本库能否解决 |
|------|-------------|
| ① 存储体积（FLASH 放不下） | ✅ 能（量化 + 函数化直接压字节） |
| ② 运行内存（RAM 装不下） | ✅ 部分能（函数部署不还原，条件 `K×(1+r)<n`） |
| ③ 算力（推理太慢） | ⚠️ 间接（需 Rust/C 实现 + 大层才兑现） |
| ④ 推理框架（嵌入式无 PyTorch） | ❌ 不能（库只产生成物，不产可执行引擎） |

### 估算：给定内存预算，函数化 + 量化能装下多大模型

仅算「权重存储」字节（不含激活缓冲），量化 f32→i8=4×、f32→i4=8×，函数化再压
约 7~17 倍（取决于 `K/n`，此处统一取保守中值 12×；可复现脚本
`examples/python/embedded_feasibility.py`）：

| 模型（参数量） | f32 体积 | f32函数化 | i8函数化 | i4函数化 |
|---------------|---------|----------|----------|----------|
| 小 MLP（0.5M） | 1.9 MB | 0.16MB | 0.04MB | 0.02MB |
| 中 CNN（5M） | 19.1 MB | 1.59MB | 0.40MB | 0.20MB |
| 较大 CNN（25M） | 95.4 MB | 7.95MB | 1.99MB | 0.99MB |
| 大 ViT（100M） | 381.5 MB | 31.79MB | 7.95MB | 3.97MB |

三档内存预算下的「装得下」判定（取最省 i4 口径）：

| 模型（参数量） | 512MB | 64MB | 8MB |
|---------------|-------|------|-----|
| 小 MLP（0.5M） | ✓ | ✓ | ✓ |
| 中 CNN（5M） | ✓ | ✓ | ✓ |
| 较大 CNN（25M） | ✓ | ✓ | ✓ |
| 大 ViT（100M） | ✓ | ✓ | ✓（i4 3.97MB） |

三档设备分水岭：
- **MCU 级（STM32/ESP32，KB~MB RAM）**：基本不可行——即便 i4 压进体积，
  MCU 也没有算力跑它，本库只能当「存储端压缩」。
- **边缘 SoC（RK3588/树莓派，GB 级）**：最佳落点——中模型轻松装下、且「又省又稳」。
- **中间档（64MB / 8MB 级）**：25M 参数 i8 即过 64MB，100M 需 i4 才稳妥。

> 诚实边界：① 上表只算权重、不含激活缓冲（嵌入式运行时激活常比权重更吃内存）；
> ② 掉点口径：跨规模 MLP 扫描的实测（`scale_scan.py`）+ 真实 ResNet50 的函数化验证；真实大 CNN/ResNet50
> 层函数化掉点可压到 ±0.5pt（见 aitest 结论），但小层（h=64）叠加掉点仍会到 4.16pt——
> 「装得下」与「不掉点」都取决于层冗余度；
> ③ 「装得下」≠「跑得动」，推理框架与算力是另一堵更硬的墙。

## 责任边界

- 几何分区 `G` + 0/1 阶函数：**已实证可用**。
- 功能分区 `F`：**已实现 + 已实证**——真实大 CNN（VGG 风格 6 卷积层，585,066 参数）全 6 卷积层函数化后测试准确率 99.59% → 96.84%（掉 2.75pt，固定种子可复现值）、最大卷积层体积省 92.9%（见 `examples/python/cnn_classification.py`）。
- 结构分区 `S`、多尺度树 `regionify_hierarchical`：**已实现**，均有实例 + 防回归测试（生成物可 `reconstruct()` 还原），但尚未在真实 Transformer/ViT 上验证精度，属「待验证」而非「已验证」。
- 函数形式前向 `functional_forward`：**已实现** + 防回归测试（函数前向 == 还原前向，浮点误差内一致）。0 阶单样本提速 29.9× 已实证；1 阶批量提速需 Rust/GPU 兑现（numpy 参考实现受 gather 限制）。
- 自适应分配器 `auto_alloc`：**已实现 + 已实证**（合成数据验证机制，真实精度须 `eval_fn` 兑底）——逐层搜 `(order,K,r,跳过)` + 硬约束净省 + 谱探测自适应 r 候选 + 省/保真加权目标，把反涨层转净省。
- GPT 级：`regionify_transformer_block()` 只做接口预留、不做验证（需 ≥80GB 级多卡 + ≥256GB 内存）。谁有条件谁验证。

## 图像分类示例（examples/，真实 MNIST）

分型表的每一档，都配一个**真实图像分类（MNIST）**示例。每个示例都是「**训练 → 模型 → 函数化 → 生成物 → 部署使用**」这条完整链路的实例——MNIST 图像分类只是「训练/模型」上游环节的载体，让函数化有真实权重可切、部署有真实准确率可测。运行（需 `torch`）：

```bash
python examples/python/mlp_classification.py          # [已验证] 小 MLP
python examples/python/mnist_mlp_classification.py    # [已验证] MNIST MLP
python examples/python/cnn_feature_clustering.py      # [未验证] 小 CNN + F 功能（接口演示）
python examples/python/cnn_classification.py          # [已验证] 真实大 CNN（VGG 风格 6 卷积层）
python examples/python/transformer_structure_partition.py  # [未验证] Transformer + S 结构
python examples/python/hierarchical_multiscale.py     # [未验证] 多尺度树
python examples/python/gpt_preview.py                 # [未验证] GPT 级预演（纯理论）
python examples/python/auto_alloc_demo.py             # 自适应分配器（把反涨层转净省）
python examples/python/multilayer_autoalloc.py        # 参差式逐层函数化（多层 fc 各层独立决策 + 叠加测掉点）
```

另有两个纯推算 script（不训练、无 MNIST，快速可跑）：

```bash
python examples/python/embedded_feasibility.py  # [估算] 嵌入式：内存预算能装下多大模型（量化的体积推演）
python examples/python/gpt_extrapolation.py     # [推断] GPT 级收益外推（三条规律 + 跨规模扫描 + K=1 低秩证据）
```

| 示例 | 分型档 | 分区信号 | 数据集 | 状态 |
|------|--------|---------|--------|------|
| `mlp_classification.py` | 小 MLP | `G` 几何 | MNIST（下采样 7×7） | ✅ 已验证 |
| `mnist_mlp_classification.py` | MNIST MLP | `G` 几何 | MNIST（28×28） | ✅ 已验证 |
| `cnn_feature_clustering.py` | CNN | `F` 功能 | MNIST | ⚠️ 未验证（小 CNN 接口演示） |
| `cnn_classification.py` | 真实大 CNN | `F` 功能 | MNIST（28×28） | ✅ 已验证 |
| `transformer_structure_partition.py` | Transformer | `S` 结构 | MNIST（玩具 ViT） | ⚠️ 未验证 |
| `hierarchical_multiscale.py` | 多尺度树 | `G` | MNIST（下采样） | ⚠️ 未验证 |
| `gpt_preview.py` | GPT 级 | `S`+`F`+低秩 | 纯理论 | ⚠️ 预演不验证 |
| `multilayer_autoalloc.py` | MNIST MLP（多层 fc） | `G` 几何（参差式逐层） | MNIST（28×28） | ✅ 已验证 |

> 「已验证」= 本项目已实证精度/压缩达标；「未验证」= 接口可跑、生成物可还原、
> 但尚未在真实规模的 Transformer/GPT 上验证精度。数据集统一用 MNIST：图像分类是
> MLP/CNN/玩具 ViT 的天然试金石，能给出真实的「函数化前后准确率」对比；
> CNN 档用真实大 CNN（VGG 风格 6 卷积层，测试 99.59% → 96.84%，掉 2.75pt，
> 固定种子可复现值）
> 证明 F 功能分区在真实规模上成立；Transformer 档用玩具 ViT（真实 MNIST 训练，
> 测试 94.99% → 94.28%，掉 0.71pt）证明 S 结构分区按头切正确、生成物可还原，
> 真实 ViT/LLM 精度未验证；GPT 档为纯理论预演。
> `multilayer_autoalloc.py`（参差式逐层）用 784→512→256→10 的三层 fc，各层独立
> auto_alloc（不划算的 fc3 自动 skip），整体省 81.6%、叠加掉点 2.17pt——比单层
> 函数化更能体现「逐层各取所需」与「误差累积」两条诚实口径。

### 完整链路五阶段（每个示例都走这条）

| 阶段 | 谁负责 | 在示例里的对应 |
|------|--------|---------------|
| ① 训练 | 上游（非库） | `_common.train_model()` 在 MNIST 上训练小网络 |
| ② 模型 | 上游（非库） | 训练好的 `model`，抽出要函数化的一层权重 `W` |
| ③ 函数化 | **库** | `nrfunc.regionify(W, signal=..., K=..., order=...)` |
| ④ 生成物 | **库** | `show_value()`/`compare_value()` 价值四维（体积/内存/CPU/GPU）+ `quantize_weights()` 量化打包 + `build_store()` 分片存储 |
| ⑤ 部署使用 | 下游（非库） | `reconstruct()` 还原权重 → 塞回模型 → 测准确率 |

库只负责 **③ 函数化 + ④ 生成物** 两段；**①② 训练/模型、⑤ 部署** 是上下游，
示例为了给出真实权重和真实准确率，把它们也一并跑通，构成「训练 → 模型 → 函数化 →
生成物 → 部署使用」的完整闭环。

## 目录结构

```
nrfunc/
├── src/nrfunc/
│   ├── core/
│   │   ├── region.py          # 区划分（功能区 / 旁区）
│   │   ├── functionalize.py   # 函数化核心（k-means / 低秩 / F/S 分型）
│   │   └── auto_alloc.py      # 自适应分配器（逐层搜 (order,K,r,跳过)）
│   ├── io/
│   │   ├── serialize.py       # 生成物 · 量化打包
│   │   └── sharding.py        # 生成物 · 分散存储
│   ├── utils/
│   │   ├── benchmark.py       # 性能基准
│   │   └── value.py           # 价值证明四维对比
│   └── _rand.py               # 确定性随机（复现）
├── tests/
└── examples/
    ├── python/
    │   ├── _common.py                      # 共享：路径引导 + MNIST 加载 + 训练/评估助手
    │   ├── _run_all.py                     # 一键跑全部示例（UTF-8 日志落盘）
    │   ├── functionalize_demo.py           # 端到端：函数化 → 生成物 → 重建权重（合成数据）
    │   ├── four_directions_demo.py         # 四方向（A/B/C/D）各一实例，共用合成数据集
    │   ├── functional_forward_demo.py      # 函数形式前向：正确性 + 稠密 vs 函数提速
    │   ├── auto_alloc_demo.py              # 自适应分配器：把反涨层转净省
    │   ├── multilayer_autoalloc.py         # 参差式逐层函数化（多层 fc 各层独立决策 + 叠加测掉点）
    │   │
    │   │  # ── 估算 / 推断（纯推算，无训练，快）──
    │   ├── embedded_feasibility.py         # [估算] 嵌入式设备可行性：内存预算能装下多大模型
    │   ├── gpt_extrapolation.py            # [推断] GPT 级收益外推：三条规律 + 跨规模扫描 + K=1 低秩证据
    │   │
    │   │  # ── 图像分类示例（真实 MNIST，含训练上游 + 函数化 + 精度对比）──
    │   ├── mlp_classification.py           # [已验证] 小 MLP（下采样 MNIST）+ G 几何
    │   ├── mnist_mlp_classification.py     # [已验证] MNIST MLP（784→128→64→10）+ G 几何
    │   ├── cnn_feature_clustering.py       # [未验证] 小 CNN + F 功能（按激活响应聚）
    │   ├── cnn_classification.py           # [已验证] 真实大 CNN（VGG 风格 6 卷积层）+ F 功能
    │   ├── transformer_structure_partition.py  # [未验证] 玩具 ViT（真实 MNIST）+ S 结构（按头切）
    │   ├── hierarchical_multiscale.py      # [未验证] 小 MLP + B 多尺度树（先粗后细）
    │   └── gpt_preview.py                  # [未验证] GPT 级 S+F+低秩 组合预演（纯理论）
    ├── rust/                               # Rust 版前向实测（CPU 零依赖 + GPU cudarc/cuBLAS，见该目录报告）
    └── project/                            # 多对象检测大模型端到端（传统 vs 函数化两种部署对比）
```

## 测试

```bash
pytest tests -q
```

## 推断：GPT 这类超大模型的收益

> 本节是**基于实测规律的外推，不是验证结论**。库内对 GPT 级只做接口预留
> （`regionify_transformer_block()`）+ 理论预演（`examples/python/gpt_preview.py`），
> 真实收益需 ≥80GB 级多卡验证，本机做不到。请把它当「方向性判断」。

### 从小模型到大模型，三条实测规律

| 规律 | 实测证据（固定种子） |
|------|--------------------|
| **体积省钱随冗余度上升** | 小 MLP 省 82% → 大 CNN 92.9%（最大层） → 玩具 ViT 90.5%，越大越省 |
| **内存/显存靠「K≪n」才兑现** | 充要条件 `K×(1+r)<n`，小层会反涨、大层净省 |
| **CPU 提速只在「大模型 + Rust/GPU」兑现** | numpy 小模型反慢，大层（K≪n）才转正 |

### 跨规模实测：层越宽，函数化越「又省又稳」

同 MNIST、同 seed、3 隐层 MLP（784→h→h→h→10），只改隐层宽度 h、逐层参差式函数化
（`scale_scan.py` 用 `multilayer_autoalloc.py` 的逐层机制跑 6 个宽度档的对照扫描，
新版 auto_alloc：K=1 全局低秩 + 谱探测 + 3pt 掉点红线）：

| 隐层宽 h | 参数量 | 叠加掉点 | 整体节省率 |
|---------|--------|---------|-----------|
| 64 | 5.9 万 | 4.16pt | 71.7% |
| 128 | 13.5 万 | 1.82pt | 79.6% |
| 256 | 33.5 万 | 1.01pt | 82.8% |
| 512 | 93.2 万 | 0.19pt | 82.7% |
| 1024 | 291.3 万 | 0.08pt | 85.3% |
| 2048 | 1002.1 万 | -0.06pt | 84.4% |

> 注：上表是「等宽三隐层 784→h→h→h→10」的缩放扫描，逐层 auto_alloc 用 3pt 掉点红线
> 约束单层（叠加掉点因误差累积可略超单层红线，如 h=64 的 4.16pt）；窄层 h=64 掉点超 3pt
> 属于「窄层扫描观察值、非达标记录」。正式示例
> `multilayer_autoalloc.py` 用的是「递减 784→512→256→10」（省 81.6%、掉 2.17pt），
> 两者结构不同，数字不可直接互换。

两条清晰趋势（新版 nrfunc 下的诚实值）：
- **掉点在跨过某临界宽度后「断崖式收敛」**（h=128 起掉点就压进 2pt 内，h=256 起 <1.1pt、
  到 h=2048 甚至 -0.06pt 精度反升），比旧版（到 h=1024 才稳在 <1.5pt）收敛得更早、更狠；
- **节省率整体随宽度上升、但不再严格单调**（71.7%→85.3% 区间内小幅波动），
  因为新版 auto_alloc 会为 3pt 保真红线主动牺牲一点压缩，换取掉点大幅下降——
  「省得多」与「掉得少」在宽层同时成立的判断依然成立。

这正是「fc 层极宽时，参差式函数化优势被放大」的直接证据——GPT 的 FFN 层
正是典型的极宽 fc 层，按此趋势收益只会更显著。

### 成熟模型的直接证据：K=1 全局低秩（ResNet50）

上述规律在**真实成熟 ResNet50**上得到进一步验证（101 类花草识别，13.77M 参数）：

- 旧版 `auto_alloc`（K 网格缺 K=1、r 网格过窄）对 layer2~4 的 13 个卷积层**全部判 skip**（总省 0%）；
- 新版（谱探测 + K=1 全局低秩 + distortion 约束）**14 层全部函数化，总省 11.2%，叠加掉点 -0.44pt**（精度不降反升）。

关键启示：**成熟精炼的卷积核权重「没有几何聚类结构、只有低秩结构」**，K=1 全局低秩
（等价 PCA）才是正解。这直接支撑了「GPT 的 FFN/注意力层用 K=1 + 低秩 + 结构切分组合
函数化」的可行性——GPT 的 FFN 层同样是「成熟、无聚类、低秩」的宽层。

### 按这三条规律外推 GPT 级

1. **体积 / 内存：收益大概率显著更高**
   GPT 的 FFN 层、注意力层参数规模巨大（单层 n 可达数千、D 数千），`K≪n`
   天然成立、参数冗余充分。外推：体积省可能到 95%+、内存净省空间比小模型大得多。
2. **CPU：首次有「真提速」的土壤**
   小模型测不出提速，是因为 K 不够小、BLAS 稠密占优；GPT 层 `K≪n`，函数前向
   共享计算 + 查表广播的收益才会浮现——但**前提是 Rust/CUDA kernel 兑现**，
   numpy 参考实现仍会受 gather/循环拖累。
3. **掉点：分型手段能兜住，但「不验证」是硬边界**
   实测里 `F` 功能分区（大 CNN 掉 2.75pt）、`S` 结构分区（玩具 ViT 掉 0.71pt）
   都在 <3pt 内，且 `auto_alloc` 的 `eval_fn` 能逐层把掉点压住。理论上 GPT 级
   用「S（按头/层切）+ F（功能聚类）+ FFN 低秩」组合分型，同样有机会守住红线——
   但这只是推断，**GPT 级的真实掉点没有验证**。

### 为什么不直接给结论

- 本机 12G 显存 + 16G 内存，加载不了 GPT 级权重，**无法实测**；
- GPT 的权重/激活分布、冗余结构与小模型不同，前面的规律**不能保证线性外推**；
- 这正对应库的诚实边界：GPT 级「谁有条件谁验证」，本库只提供接口与理论预演。

---

如果你有条件（≥80GB 级多卡 + 大内存），欢迎用 `regionify_transformer_block()`
的接口骨架 + 上述分型思路做真实验证，那是本节推断能否成立的最终判据。

---

> 算法逻辑由本人提出，算法推演实现由AI推断

## License

MIT
