nrfunc 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
nrfunc-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ # sdist 收录范围:核心包由 pyproject 的 packages.find 自动纳入;
2
+ # 此文件额外把 tests 一并打进 sdist(wheel 不含),便于下游审计与复测。
3
+ include README.md
4
+ include LICENSE
5
+ recursive-include tests *.py
nrfunc-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,553 @@
1
+ Metadata-Version: 2.4
2
+ Name: nrfunc
3
+ Version: 1.0.0
4
+ Summary: 神经区函数算法:成熟模型的函数化压缩与产物生成库(函数化 + 生成物)
5
+ Author-email: lph <414561114@qq.com>
6
+ License-Expression: MIT
7
+ Keywords: quantization,model-compression,region,functionalization,sharding
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: numpy>=1.24
14
+ Requires-Dist: torch>=2.0
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest; extra == "dev"
17
+ Requires-Dist: pytest-cov; extra == "dev"
18
+ Requires-Dist: mypy; extra == "dev"
19
+ Provides-Extra: memory
20
+ Requires-Dist: psutil; extra == "memory"
21
+ Dynamic: license-file
22
+
23
+ # nrfunc —— 神经区函数算法(函数化 + 生成物)
24
+
25
+ ## 一、原理
26
+
27
+ **已训练好的成熟模型**里,一层权重有 `n` 个输出单元(神经元/卷积核/注意力头),
28
+ 传统上每个单元独立存 `D` 个权重(共 `n×D`)。但很多单元其实是「同类函数」——
29
+ 功能相近、参数冗余。
30
+
31
+ 本库把这些单元聚成 `K` 个「区」(`K ≪ n`),**同区共用一个「区域函数」**表达:
32
+
33
+ - **0 阶**:每区一个质心(均值向量),参数从 `n×D` 降到 `K×D`
34
+ - **1 阶**:每区 = 均值 + 前 `r` 个主成分(截断 SVD,即低秩),另存每单元 `n×r` 投影系数
35
+
36
+ 再给每个单元存一个「归属索引」(`log₂K` 位,记它属于哪一区)。于是整体的存储,
37
+ 从「`n` 份独立权重」变成「`K` 份共享函数 + `n` 份归属索引」——**这就是体积压缩的来源**。
38
+
39
+ ```
40
+ 训练 ── 模型 ── 成熟模型 ──[ 函数化 + 生成物 ]──> 部署
41
+
42
+ 本库只负责这一段
43
+ ```
44
+
45
+ - **上游(不是本库的活)**:训练、模型定义、蒸馏、微调、量化感知训练(QAT)。
46
+ - **本库只做两件事**:① 函数化(把权重重新表达为区域函数 + 归属索引);
47
+ ② 生成物(区域函数参数 + 索引 + 投影系数 + 量化打包 + 分片存储 + 价值对比)。
48
+ - **下游(也不是本库的活)**:把生成物接入推理/部署。生成物可经 `reconstruct()`
49
+ 还原成近似权重、**当模型权重用**,但真正跑起来是下游的活。
50
+
51
+ ## 二、收益评估
52
+
53
+ 函数化的收益,落在**体积 / 内存 / CPU / GPU** 四个维度(一个词:**用少量精度,换体积与内存**):
54
+
55
+ | 维度 | 收益 | 一句话结论 |
56
+ |------|------|-----------|
57
+ | 体积 | **恒省**(8bit 量化,参数量 `n×D → K×D`) | 确定收益,最直观 |
58
+ | 内存 | 有条件地省 | 只在 `K×(1+r) < n` 时净省,且看部署方式 |
59
+ | CPU | 有条件地省 | 大模型(K≪n)+ Rust/GPU 才兑现,numpy 小模型可能更慢 |
60
+ | GPU 显存 | 随函数部署省 | 与「内存·函数部署」同口径 |
61
+
62
+ **本机真实实测(代表性数据)**:
63
+
64
+ | 例子 | 层 | 体积省 | 内存·函数部署省 | 精度掉点 |
65
+ |------|-----|--------|----------------|---------|
66
+ | MNIST MLP | fc1 128×784 | 96.2% | 84.9% | 1.63pt |
67
+ | 真实大 CNN | 6 卷积层 | 89.2% | 62.3% | 0.37pt |
68
+ | 玩具 ViT | wq 64×64 | 90.5% | 62.4% | 0.71pt |
69
+
70
+ > 数据口径:固定种子可复现;掉点均为「函数化后 vs 原始模型」的精度差,红线 <5pt
71
+ > (库自带 `auto_alloc` 自适应分配器守住)。完整四维一表见下文「价值证明」。
72
+
73
+ ## 三、使用注意事项
74
+
75
+ 1. **体积 ≠ 内存**:体积用 8bit 量化能省 90%+,但运行时内存是 float32 常驻,省得少;
76
+ 且**内存省不省取决于部署方式**——`reconstruct()` 还原回稠密时内存一点不省,
77
+ 只有走 `functional_forward()`(不还原、只常驻紧凑参数)才省。
78
+ 2. **CPU 不是函数化的卖点**:numpy 参考实现的 1 阶前向受 Python 循环 + gather 限制,
79
+ 小模型可能慢于 BLAS 稠密前向;提速只在「K≪n 的大模型 + 编译语言(Rust)/GPU」兑现。
80
+ 3. **按层判断,别一刀切**:小层/首层函数化可能「内存反涨」甚至「掉点崩盘」。
81
+ 用 `auto_alloc(W, eval_fn=...)` 逐层自适应(自动跳过不划算的层)最稳。
82
+ 4. **处理对象是一层权重、不是整个模型**:本库处理「一层权重矩阵」这个实例无关单元;
83
+ GPT 级大模型方向只做接口预留 + 理论预演,**不负责验证**(需 ≥80GB 级多卡)。
84
+
85
+ 详见下文「责任边界」。
86
+
87
+ ---
88
+
89
+ ## 安装
90
+
91
+ ```bash
92
+ pip install nrfunc # 用户安装(发布后从包仓库安装)
93
+ ```
94
+
95
+ 依赖:`numpy`、`torch`。
96
+
97
+ 开发者(本地源码开发)可编辑安装:
98
+
99
+ ```bash
100
+ pip install -e ".[dev]" # 含 pytest / pytest-cov / mypy
101
+ ```
102
+
103
+ 可选依赖(按需安装,不装也不影响函数化 + 生成物主链路):
104
+
105
+ ```bash
106
+ pip install -e ".[memory]" # psutil:rss_mb() 实测进程内存(不装时返回 None)
107
+ ```
108
+
109
+ > `psutil` 是「软依赖」:只在 `rss_mb()` 测真实内存时需要;未安装时 `rss_mb()`
110
+ > 返回 `None`(而非 0,避免误导),库其余功能完全不受影响。
111
+
112
+ ## 快速开始
113
+
114
+ ```python
115
+ import numpy as np
116
+ import nrfunc
117
+
118
+ # 1) 你已训练好的成熟模型:抽出一层权重(任意框架,这里给 numpy)
119
+ W = np.random.default_rng(0).standard_normal((256, 128)).astype(np.float32)
120
+
121
+ # 2) 函数化:256 个输出单元 → 16 个区域函数(1 阶低秩,每区 8 个主成分)
122
+ res = nrfunc.regionify(W, signal='G', K=16, order=1, r=8)
123
+ print(f"区域数 K={res['K']},解释方差={res['explained']:.3f}")
124
+
125
+ # 3) 生成物 · 价值对比(体积 / 内存;CPU/GPU 需传实测参数,
126
+ # 完整四维一表落地见 examples 里的 show_value())
127
+ tbl = nrfunc.compare_value(W, res, bits_before=32, bits_after=8)
128
+ print(tbl['_table'])
129
+
130
+ # 4) 生成物 · 量化打包(把区域函数参数量化成可部署字节)
131
+ packed, scale, n_out, n_in = nrfunc.quantize_weights(res['means'], bits=8)
132
+
133
+ # 5) 生成物 · 分散存储到 4 个节点,并行读取
134
+ store = nrfunc.build_store(res, n_shards=4)
135
+ params = store.region_read_many([0, 1, 2, 3])
136
+
137
+ # 6) 生成物 → 重建权重:还原成近似权重,可当模型权重用(下游再接入推理)
138
+ recon = nrfunc.reconstruct(res) # (256, 128)
139
+ print(f"重建权重 shape={recon.shape},保真度={res['explained']:.3f}")
140
+ ```
141
+
142
+ ---
143
+
144
+ ## API 参考(参数 / 用法 / 注意事项)
145
+
146
+ > 下面是全部公开函数的签名与参数说明,按模块分组。注意:本库处理对象是「一层
147
+ > 权重矩阵」`(n, D)`(n=神经元/卷积核/头数,D=每单元参数量),不是整个模型。
148
+
149
+ ### 1. 函数化(core)
150
+
151
+ **`regionify(rows, signal='G', K=None, order=0, r=None, iters=60, seed=0, activations=None, groups=None, assign=None, n_init=1)`** —— 分区函数化统一入口,返回 dict。
152
+
153
+ | 参数 | 说明 |
154
+ |------|------|
155
+ | `rows` | `(n, D)` 权重行向量(numpy 或可转 numpy 的数组) |
156
+ | `signal` | `'G'` 几何(k-means)/ `'F'` 功能(余弦聚类,需 `activations`)/ `'S'` 结构(按边界切,需 `groups`) |
157
+ | `K` | 分区数。省略时默认 `sqrt(n)`;`signal='S'` 由 `groups` 决定、可省略 |
158
+ | `order` | `0`=质心 / `1`=低秩(默认 0) |
159
+ | `r` | `order=1` 时每区主成分数,省略默认 `sqrt(D)` |
160
+ | `iters` | 聚类迭代次数(G/F 用) |
161
+ | `seed` | 随机种子(库内 mulberry32,固定 seed 跨平台可复现) |
162
+ | `activations` | `signal='F'` 所需的 `(n, T)` 激活响应矩阵 |
163
+ | `groups` | `signal='S'` 所需的 `(n,)` 结构归属(层号/头号/通道号) |
164
+ | `assign` | 可选,已算好的 `(n,)` 归属,传入时跳过聚类直接构造(auto_alloc 复用) |
165
+ | `n_init` | 多起点重跑次数(G/F),>1 时尝试多个确定性种子取保真最高;默认 1 |
166
+
167
+ 返回 dict 关键字段:`signal`/`order`/`K`/`assign`(n,)/`n`/`D`/`explained`,以及按阶数的参数——0 阶 `centroids`(K,D);1 阶 `means`(K,D) + `components`(K,r,D) + `coeffs`(n,r)。
168
+
169
+ **`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()`。
170
+
171
+ **`reconstruct(result)`** —— 把区域函数还原成近似权重 `(n, D)`。0 阶=归属质心;1 阶=区均值+投影修正。
172
+
173
+ **`functional_forward(result, x)`** —— 函数形式前向,**不还原稠密权重**,`y = x @ W^T` 的等价计算。`x` 形状 `(..., D)`,返回 `(..., n)`。这是「为提速」的路径(共享函数只算一次),数值与先 `reconstruct()` 再前向一致(浮点误差内)。
174
+
175
+ **`regionify_transformer_block(block, signal='S', order=1, r=None)`** —— GPT 级接口预留,**不做验证**(需 ≥80GB 多卡)。普通 Transformer 请用 `regionify(signal='S', groups=...)`。
176
+
177
+ ### 2. 自适应分配器(auto_alloc)
178
+
179
+ **`auto_alloc(rows, signal='G', activations=None, groups=None, budget=None, tol_ev=None, eval_fn=None, fidelity_margin=0.3, K_grid=None, r_grid=None, r_max=None, iters=60, seed=0, float_bits=32)`** —— 给一层自动挑最优 `(order,K,r)`,或判「跳过」。
180
+
181
+ | 参数 | 说明 |
182
+ |------|------|
183
+ | `rows` / `signal` / `activations` / `groups` | 同 `regionify` |
184
+ | `budget` | 可选,函数化后字节上限;原权重已 ≤ budget 则直接跳过 |
185
+ | `tol_ev` | 可选,重构保真度(explained)绝对下限;注意 explained 跨信号不可比,故默认不启用 |
186
+ | `eval_fn` | 可选,真实精度回调 `eval_fn(result)->bool`,True=接受;这是「掉点<阈值」的**可靠**实现 |
187
+ | `fidelity_margin` | 默认 0.3,相对保真保护:排除重构保真比同层最优低 0.3 以上的候选;传 None 关闭 |
188
+ | `K_grid` / `r_grid` | 可选候选网格,默认 K=2 的幂≤n(补 sqrt(n))、r=[1,2,4,8] |
189
+ | `r_max` | 可选,1 阶主成分数上限(对 r_grid 截断) |
190
+ | `float_bits` | 内存口径位宽,默认 32 |
191
+
192
+ 返回 dict 关键字段:`decision`(`'order1'`/`'order0'`/`'skip'`)、`result`(跳过为 None)、`order`/`K`/`r`(跳过为 None)、`saving`(节省率,正=省;跳过=0)、`skipped_reason`(仅 skip 时非空)、`bytes_before`/`bytes_after`、`n_candidates`/`n_tried`。
193
+
194
+ **注意**:`eval_fn` 的返回语义是「接受 = True」。你在 auto_alloc 之外自行实现掉点护栏时的写法见 `examples/python/_common.py::make_drop_guard`。
195
+
196
+ ### 3. 生成物 · 量化 / 分片 / 二进制(io)
197
+
198
+ **`quantize_weights(w, bits=4)`** —— per-row 对称量化,返回 `(packed_bytes, scale, n_out, n_in)`。`bits` 仅 4/8。接受 numpy 或 torch 张量。
199
+
200
+ **`dequantize_weights(packed, scale, n_out, n_in, bits=4)`** —— 反量化回 float32。
201
+
202
+ **`packed_bytes(num_params, bits=4)`** —— 按位宽估算字节数(不含 scale 元数据)。
203
+
204
+ **`build_store(result, n_shards=1)`** —— 构建分片存储,返回 `ShardedRegionStore`。
205
+
206
+ **`ShardedRegionStore.region_read(region_id)` / `region_read_many(ids)`** —— 读区域函数参数;`region_read_many` 跨分片多线程并行。`placement()` 看分布、`load_balance()` 看负载。
207
+
208
+ **`to_bytes(result, bits=8)` / `from_bytes(data)`** —— 把整个生成物打成一段紧凑二进制字节块(**降 IO 频率与体积**),或反向解码。`bits`=8/4/32:8=INT8、4=INT4(真打包、体积再减半)、32=float32 无损。
209
+
210
+ > 字节格式:23 字节小端头(`NRFN` magic + version/order/bits/K/n/D/r)+ 区域函数参数 + assign 索引。
211
+ > `from_bytes` 只还原结构元数据+参数+assign,**不还原 signal/explained 等标量**(需自行保留)。
212
+ > 跨语言消费示例见 `examples/code/`(Go/Java/Rust/C++ 读同一段二进制)。
213
+
214
+ ### 4. 价值证明 / 基准(utils)
215
+
216
+ **`size_bytes_raw(n, D, bits=32)`** —— 函数化前字节数。
217
+
218
+ **`size_bytes_regionalized(result, bits=8, index_bits_override=None)`** —— 函数化后字节数(含 1 阶投影系数与归属索引)。`index_bits_override` 可选,覆盖归属索引位宽(默认按 `ceil(log2(K))` 自动算)。
219
+
220
+ **`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` 格式化字符串)。
221
+
222
+ **`cpu_time(fn, *args, iters=20, warmup=3)`** —— 同机同批 CPU 前向耗时(ns/次)。
223
+
224
+ **`gpu_memory_bytes(fn, *args, device='cuda')`** —— 实测显存(字节),无 CUDA 返回 None。
225
+
226
+ **`bench_single(fn, x, ...)` / `bench_batch(fn, batch, ...)`** —— torch 单样本延迟 / 批量吞吐(取最快轮)。
227
+
228
+ **`rss_mb()`** —— 进程常驻内存(MB),需 `psutil`(软依赖);未装返回 None。
229
+
230
+ ### 全局注意事项
231
+
232
+ 1. **`assign` 数组是 int32**,`to_bytes`/`from_bytes` 里也按 int32 处理,别和权重 float 混。
233
+ 2. **1 阶净省的近似充要条件是 `K×(1+r)<n`**,不满足就别函数化(auto_alloc 会先验剪枝)。
234
+ 3. **掉点红线 <5pt**(库各示例的统一口径),衡量口径是「函数化后 vs 原始模型」的精度差;单层的 `single_drop` 可为负(重建恰好更优),叠加掉点因误差累积而略大于单层之和。
235
+ 4. **体积≠内存**:体积是量化位宽口径(能省 90%+),内存是 float32 常驻(省得少);且内存省不省看部署方式(`reconstruct` 不省,`functional_forward` 才省)。
236
+ 5. **CPU 提速有条件**:只在「K≪n 大层 + Rust/GPU」兑现,numpy 小模型可能更慢。
237
+
238
+ ## 分区信号分型
239
+
240
+ 一刀切 k-means 只对「小 MLP」成立。大模型权重空间分层、置换不变,必须按底层模型分型:
241
+
242
+ | 模型底层 | 分区信号 | 含义 | 入口 |
243
+ |---------|---------|------|------|
244
+ | 小 MLP | `G` 几何 | 权重几何 ≈ 功能,按欧氏距离 k-means | `regionify(signal='G')` |
245
+ | CNN | `F` 功能 | 功能同构的核权重几何可远,按激活响应余弦聚类 | `regionify(signal='F', activations=...)` |
246
+ | Transformer | `S` 结构 | 头/层是并行功能模块,按结构边界切分不混聚 | `regionify(signal='S', groups=...)` |
247
+ | GPT 级 | `S`+`F`+低秩 | 结构边界 + 功能聚类 + FFN 低秩 | `regionify_transformer_block()`(仅预演,不验证) |
248
+
249
+ 除「分区信号」这一维,分区尺度还有一维「多尺度树」(先粗分区成大区,再每区内细分小区):
250
+
251
+ - `regionify_hierarchical(rows, signal='G', K_top=8, K_sub=4, order=1, r=8)`:两层树,叶子区 ≤ `K_top × K_sub`,树深(叶子数)可调——叶子越多、压缩越弱、保真越高。
252
+ - 四个方向(A 功能聚类 / B 多尺度树 / C 阶数升级 / D 逐层区域化)的可运行实例见 `examples/python/four_directions_demo.py`,共用同一数据集,保证可用性。
253
+
254
+ ### 自适应分配器 auto_alloc(不用手动挑 K/r)
255
+
256
+ 手动选 K / r / 阶数容易踩坑:小层或首层函数化可能「内存反涨」甚至「掉点崩盘」。
257
+ `auto_alloc()` 逐层自动搜 `(order, K, r, 跳过)`:
258
+
259
+ - **硬约束「净省」**:内存绝不反涨(`K×(1+r)<n` 先验剪枝,省去必然反涨的候选)
260
+ - **三层掉点约束**:`fidelity_margin`(相对保真,默认 0.3)防「省最多」砸穿精度 →
261
+ `tol_ev`(绝对保真下限)→ `eval_fn`(真实精度回调,最可靠)
262
+ - **主动跳过**:该层函数化不划算时直接跳过,而不是硬凑一个劣化结果
263
+
264
+ ```python
265
+ alloc = nrfunc.auto_alloc(W, eval_fn=lambda res: 你的真实精度掉点 < 阈值)
266
+ # alloc['decision'] 为 'ok'({order,K,r})或 'skip'(skipped_reason 说明为什么)
267
+ ```
268
+
269
+ 实测把 5 个真实模型里「反涨」的层全部转成净省、掉点全压 <5pt(见
270
+ `examples/python/auto_alloc_demo.py`)。
271
+
272
+ ## 价值证明:函数化前 vs 后四维对比
273
+
274
+ 四个维度——**体积 / 内存 / CPU / GPU**——库都有对应能力,不是只有体积:
275
+
276
+ | 维度 | 函数化前 | 函数化后 | 来源 |
277
+ |------|---------|---------|------|
278
+ | 体积 | `n×D×bits` | `K×D×bits + n×log₂K`(含 1 阶投影系数) | 参数量 × 位宽 |
279
+ | 内存 | `n×D×32bit` 常驻 | 见「部署方式」 | `size_bytes_regionalized()` |
280
+ | CPU | 稠密前向 `x@Wᵀ` | 函数前向 `functional_forward` | `cpu_time()` 实测(单样本+批量) |
281
+ | GPU | 原始权重(显存 + 前向) | 紧凑参数(显存 + 函数前向) | 实测(需 CUDA,显存+单样本+批量) |
282
+
283
+ 压缩率来自:不再存 `n×D` 个独立权重,只存 `K` 个共享函数 + `n` 个归属索引。
284
+
285
+ **四维已实测落地**:`examples/python/mnist_mlp_classification.py` 用 `show_value()` 在同一张表里
286
+ 打印全部四维(`fc1` 层 128×784、K=16、order=1、r=4 的实测):
287
+
288
+ | 维度 | 函数化前 | 函数化后 | 节省率 |
289
+ |------|---------|---------|--------|
290
+ | 体积(8bit 存储) | 401,408 B | 63,296 B | **84.2%** |
291
+ | 内存·还原部署(float32) | 401,408 B | 401,408 B | 0%(还原回稠密,内存不省) |
292
+ | 内存·函数部署(float32) | 401,408 B | 252,992 B | **37.0%** |
293
+ | GPU 显存(float32 常驻) | 0.4 MB | 0.2 MB | **37.0%** |
294
+ | GPU 单样本延迟 | 稠密前向 | 函数前向 | 见「函数形式前向」 |
295
+ | GPU 批量吞吐 | 稠密前向 | 函数前向 | 见「函数形式前向」 |
296
+
297
+ > 诚实口径(关键,别只看一张表):
298
+ > - **体积 ≠ 内存**:体积用 8bit 量化能省 84%,但运行时内存是 float32 常驻,只省 37%;
299
+ > 而且**内存省不省取决于部署方式**——`reconstruct()` 还原回稠密 float32 时内存一点不省,
300
+ > 只有走 `functional_forward()` 函数部署(不还原、只常驻紧凑参数)才省内存。
301
+ > - **CPU 不是函数化的卖点**:numpy 参考实现里 `functional_forward` 的 1 阶小模型
302
+ > 受 Python 循环 + gather 限制,可能慢于 BLAS 稠密前向;提速只在「K≪n 的大模型 +
303
+ > 编译语言(Rust)/ GPU」里兑现(见下「函数形式前向」的 0 阶 29.9× / 1 阶 1.62×)。
304
+ > - **GPU 显存**这里只给 float32 常驻口径(与「内存·函数部署」同数);GPU 上的
305
+ > 函数前向提速需 CUDA/Rust kernel,numpy 参考实现不含。`show_value()` 会给 GPU 侧
306
+ > 补上**单样本延迟 + 批量吞吐**(torch 真实 CUDA 前向,与 CPU 侧对称对齐),让
307
+ > CPU / GPU 两端的「显存 / 耗时」都能并排对比;但 GPU 函数前向的提速潜力仍需
308
+ > Rust/CUDA kernel 才兑现,此处的 torch 实测是「同一 CUDA 环境」下的可比口径。
309
+ > - 内存/显存是「存储占用」口径,不等于运行时峰值分配;CPU/GPU 只保证同机同批可比。
310
+
311
+ ## 函数形式前向:不还原权重,直接按生成物算
312
+
313
+ `reconstruct()` 是「还原成稠密权重再算」,推理速度与原始权重一致、精度有损。另一条**为提速**设计的路径是 `functional_forward()`——不还原、直接用生成物算,共享的区域函数只算一次再按归属广播,省掉 K≪n 时的重复乘:
314
+
315
+ - **0 阶**:`y = (x @ centroids^T)[:, assign]` —— 只算 K 次内积,再查表广播回 n 个单元
316
+ - **1 阶**:`y = (x @ means^T)[:, assign] + Σ_j coeffs[i,j]·(components[assign[i],j] @ x)`
317
+
318
+ 数值上等价于先 `reconstruct()` 再前向(浮点误差内一致)。本机实测提速(n=1024, D=512, K=16, r=8):
319
+
320
+ | 阶数 | 单样本延迟 | 批量吞吐(B=1024) | 体积 |
321
+ |------|-----------|-------------------|------|
322
+ | 0 阶 | **29.9×** | 1.80× | 省 99.6% |
323
+ | 1 阶 | **1.62×** | 0.55× | 省 96.1% |
324
+
325
+ > 诚实声明:numpy 参考实现下,**0 阶提速干净兑现**;**1 阶批量未兑现理论 6.4×**(低秩修正的 gather / 小 K 矩阵乘在 numpy 里开销大)。1 阶的完整提速需在编译语言(Rust)/ GPU 里兑现——那里 gather 廉价、无 Python 开销,这正是下游部署(演算服务)该做的事。
326
+
327
+ ## 权重分散存储拓扑
328
+
329
+ 区域函数权重不必集中单节点,可分散多节点分片 + IO 并行读取:
330
+
331
+ - 动机①:大规模权重单节点放不下,分片是唯一出路(呼应张量/模型并行)。
332
+ - 动机②:高并发批量读取会打爆单节点权重读取吞吐,分片后 IO 并行、吞吐随分片数扩展。
333
+ - `ShardedRegionStore` 把 K 个区域函数按 `region_id` 散列到 n 个分片,`region_read_many()` 多线程并行拉取。
334
+ - `n_shards=1` 退化为「集中单节点」。
335
+
336
+ ## 嵌入式设备可行性(大模型上边缘)
337
+
338
+ 本库能把「大模型上嵌入式」的**体积/内存**这堵墙撬动,但它只做「压缩 + 生成物」,
339
+ 不含推理运行时——产物要能在嵌入式跑,必须有一个 C/Rust 推理 kernel 去消费它。
340
+
341
+ ### 关键:本库能撬动哪几堵墙
342
+
343
+ | 瓶颈 | 本库能否解决 |
344
+ |------|-------------|
345
+ | ① 存储体积(FLASH 放不下) | ✅ 能(量化 + 函数化直接压字节) |
346
+ | ② 运行内存(RAM 装不下) | ✅ 部分能(函数部署不还原,条件 `K×(1+r)<n`) |
347
+ | ③ 算力(推理太慢) | ⚠️ 间接(需 Rust/C 实现 + 大层才兑现) |
348
+ | ④ 推理框架(嵌入式无 PyTorch) | ❌ 不能(库只产生成物,不产可执行引擎) |
349
+
350
+ ### 估算:给定内存预算,函数化 + 量化能装下多大模型
351
+
352
+ 仅算「权重存储」字节(不含激活缓冲),量化 f32→i8=4×、f32→i4=8×,函数化再压
353
+ 约 7~17 倍(取决于 `K/n`,层越宽越赚):
354
+
355
+ | 模型(参数量) | f32 体积 | 预算 | f32函数化 | i8函数化 | i4函数化 | 结论 |
356
+ |---------------|---------|------|-----------|-----------|-----------|------|
357
+ | 小 MLP(0.5M) | 1.9 MB | 512MB | 0.11MB ✓ | 0.03MB ✓ | 0.01MB ✓ | 轻松 |
358
+ | 中 CNN(5M) | 19.1 MB | 512MB | 1.83MB ✓ | 0.46MB ✓ | 0.23MB ✓ | 轻松 |
359
+ | 中 CNN(5M) | 19.1 MB | 64MB | 1.83MB ✓ | 0.46MB ✓ | 0.23MB ✓ | 轻松 |
360
+ | 较大 CNN(25M) | 95.4 MB | 64MB | 11.4MB ✓ | 2.86MB ✓ | 1.43MB ✓ | 可行 |
361
+ | 大 ViT(100M) | 381.5 MB | 64MB | 54.9MB ✓ | 13.7MB ✓ | 6.87MB ✓ | 勉强 |
362
+ | 大 ViT(100M) | 381.5 MB | **8MB** | 54.9MB ✗ | 13.7MB ✗ | **6.87MB ✓** | 仅 i4 能过 |
363
+
364
+ 三档设备分水岭:
365
+ - **MCU 级(STM32/ESP32,KB~MB RAM)**:基本不可行——即便 i4 塞进 6.87MB,
366
+ MCU 也没有算力跑它,本库只能当「存储端压缩」。
367
+ - **边缘 SoC(RK3588/树莓派,GB 级)**:最佳落点——中模型轻松装下、且「又省又稳」。
368
+ - **中间档(64MB 级)**:25M 参数可行,100M 需 i4 才勉强。
369
+
370
+ > 诚实边界:① 上表只算权重、不含激活缓冲(嵌入式运行时激活常比权重更吃内存);
371
+ > ② 掉点是跨规模 MLP 实测的外推,非 ViT/CNN 真实验证值(小层压狠了会掉到 14pt,
372
+ > 大层才压得住 <3pt);③ 「装得下」≠「跑得动」,推理框架与算力是另一堵更硬的墙。
373
+
374
+ ## 责任边界
375
+
376
+ - 几何分区 `G` + 0/1 阶函数:**已实证可用**。
377
+ - 功能分区 `F`:**已实现 + 已实证**——真实大 CNN(VGG 风格 6 卷积层,585,066 参数)全 6 卷积层函数化后测试准确率 99.59% → 99.22%(掉 0.37pt,固定种子可复现值)、卷积层体积省 89.2%(见 `examples/python/cnn_classification.py`)。
378
+ - 结构分区 `S`、多尺度树 `regionify_hierarchical`:**已实现**,均有实例 + 防回归测试(生成物可 `reconstruct()` 还原),但尚未在真实 Transformer/ViT 上验证精度,属「待验证」而非「已验证」。
379
+ - 函数形式前向 `functional_forward`:**已实现** + 防回归测试(函数前向 == 还原前向,浮点误差内一致)。0 阶单样本提速 29.9× 已实证;1 阶批量提速需 Rust/GPU 兑现(numpy 参考实现受 gather 限制)。
380
+ - 自适应分配器 `auto_alloc`:**已实现 + 已实证**(合成数据验证机制,真实精度须 `eval_fn` 兑底)——逐层搜 `(order,K,r,跳过)` + 硬约束净省 + 三层掉点约束,把反涨层转净省。
381
+ - GPT 级:`regionify_transformer_block()` 只做接口预留、不做验证(需 ≥80GB 级多卡 + ≥256GB 内存)。谁有条件谁验证。
382
+
383
+ ## 图像分类示例(examples/,真实 MNIST)
384
+
385
+ 分型表的每一档,都配一个**真实图像分类(MNIST)**示例。每个示例都是「**训练 → 模型 → 函数化 → 生成物 → 部署使用**」这条完整链路的实例——MNIST 图像分类只是「训练/模型」上游环节的载体,让函数化有真实权重可切、部署有真实准确率可测。运行(需 `torch`):
386
+
387
+ ```bash
388
+ python examples/python/mlp_classification.py # [已验证] 小 MLP
389
+ python examples/python/mnist_mlp_classification.py # [已验证] MNIST MLP
390
+ python examples/python/cnn_feature_clustering.py # [未验证] 小 CNN + F 功能(接口演示)
391
+ python examples/python/cnn_classification.py # [已验证] 真实大 CNN(VGG 风格 6 卷积层)
392
+ python examples/python/transformer_structure_partition.py # [未验证] Transformer + S 结构
393
+ python examples/python/hierarchical_multiscale.py # [未验证] 多尺度树
394
+ python examples/python/gpt_preview.py # [未验证] GPT 级预演(纯理论)
395
+ python examples/python/auto_alloc_demo.py # 自适应分配器(把反涨层转净省)
396
+ python examples/python/multilayer_autoalloc.py # 参差式逐层函数化(多层 fc 各层独立决策 + 叠加测掉点)
397
+ ```
398
+
399
+ | 示例 | 分型档 | 分区信号 | 数据集 | 状态 |
400
+ |------|--------|---------|--------|------|
401
+ | `mlp_classification.py` | 小 MLP | `G` 几何 | MNIST(下采样 7×7) | ✅ 已验证 |
402
+ | `mnist_mlp_classification.py` | MNIST MLP | `G` 几何 | MNIST(28×28) | ✅ 已验证 |
403
+ | `cnn_feature_clustering.py` | CNN | `F` 功能 | MNIST | ⚠️ 未验证(小 CNN 接口演示) |
404
+ | `cnn_classification.py` | 真实大 CNN | `F` 功能 | MNIST(28×28) | ✅ 已验证 |
405
+ | `transformer_structure_partition.py` | Transformer | `S` 结构 | MNIST(玩具 ViT) | ⚠️ 未验证 |
406
+ | `hierarchical_multiscale.py` | 多尺度树 | `G` | MNIST(下采样) | ⚠️ 未验证 |
407
+ | `gpt_preview.py` | GPT 级 | `S`+`F`+低秩 | 纯理论 | ⚠️ 预演不验证 |
408
+ | `multilayer_autoalloc.py` | MNIST MLP(多层 fc) | `G` 几何(参差式逐层) | MNIST(28×28) | ✅ 已验证 |
409
+
410
+ > 「已验证」= 本项目已实证精度/压缩达标;「未验证」= 接口可跑、生成物可还原、
411
+ > 但尚未在真实规模的 Transformer/GPT 上验证精度。数据集统一用 MNIST:图像分类是
412
+ > MLP/CNN/玩具 ViT 的天然试金石,能给出真实的「函数化前后准确率」对比;
413
+ > CNN 档用真实大 CNN(VGG 风格 6 卷积层,测试 99.59% → 99.22%,掉 0.37pt,
414
+ > 固定种子可复现值)
415
+ > 证明 F 功能分区在真实规模上成立;Transformer 档用玩具 ViT(真实 MNIST 训练,
416
+ > 测试 95.0% → 94.3%,掉 0.71pt)证明 S 结构分区按头切正确、生成物可还原,
417
+ > 真实 ViT/LLM 精度未验证;GPT 档为纯理论预演。
418
+ > `multilayer_autoalloc.py`(参差式逐层)用 784→512→256→10 的三层 fc,各层独立
419
+ > auto_alloc(不划算的 fc3 自动 skip),整体省 86.1%、叠加掉点 2.91pt——比单层
420
+ > 函数化更能体现「逐层各取所需」与「误差累积」两条诚实口径。
421
+
422
+ ### 完整链路五阶段(每个示例都走这条)
423
+
424
+ | 阶段 | 谁负责 | 在示例里的对应 |
425
+ |------|--------|---------------|
426
+ | ① 训练 | 上游(非库) | `_common.train_model()` 在 MNIST 上训练小网络 |
427
+ | ② 模型 | 上游(非库) | 训练好的 `model`,抽出要函数化的一层权重 `W` |
428
+ | ③ 函数化 | **库** | `nrfunc.regionify(W, signal=..., K=..., order=...)` |
429
+ | ④ 生成物 | **库** | `show_value()`/`compare_value()` 价值四维(体积/内存/CPU/GPU)+ `quantize_weights()` 量化打包 + `build_store()` 分片存储 |
430
+ | ⑤ 部署使用 | 下游(非库) | `reconstruct()` 还原权重 → 塞回模型 → 测准确率 |
431
+
432
+ 库只负责 **③ 函数化 + ④ 生成物** 两段;**①② 训练/模型、⑤ 部署** 是上下游,
433
+ 示例为了给出真实权重和真实准确率,把它们也一并跑通,构成「训练 → 模型 → 函数化 →
434
+ 生成物 → 部署使用」的完整闭环。
435
+
436
+ ## 目录结构
437
+
438
+ ```
439
+ nrfunc/
440
+ ├── src/nrfunc/
441
+ │ ├── core/
442
+ │ │ ├── region.py # 区划分(功能区 / 旁区)
443
+ │ │ ├── functionalize.py # 函数化核心(k-means / 低秩 / F/S 分型)
444
+ │ │ └── auto_alloc.py # 自适应分配器(逐层搜 (order,K,r,跳过))
445
+ │ ├── io/
446
+ │ │ ├── serialize.py # 生成物 · 量化打包
447
+ │ │ └── sharding.py # 生成物 · 分散存储
448
+ │ ├── utils/
449
+ │ │ ├── benchmark.py # 性能基准
450
+ │ │ └── value.py # 价值证明四维对比
451
+ │ └── _rand.py # 确定性随机(复现)
452
+ ├── tests/
453
+ └── examples/
454
+ ├── python/
455
+ │ ├── _common.py # 共享:路径引导 + MNIST 加载 + 训练/评估助手
456
+ │ ├── _run_all.py # 一键跑全部示例(UTF-8 日志落盘)
457
+ │ ├── functionalize_demo.py # 端到端:函数化 → 生成物 → 重建权重(合成数据)
458
+ │ ├── four_directions_demo.py # 四方向(A/B/C/D)各一实例,共用合成数据集
459
+ │ ├── functional_forward_demo.py # 函数形式前向:正确性 + 稠密 vs 函数提速
460
+ │ ├── auto_alloc_demo.py # 自适应分配器:把反涨层转净省
461
+ │ ├── multilayer_autoalloc.py # 参差式逐层函数化(多层 fc 各层独立决策 + 叠加测掉点)
462
+ │ │
463
+ │ │ # ── 图像分类示例(真实 MNIST,含训练上游 + 函数化 + 精度对比)──
464
+ │ ├── mlp_classification.py # [已验证] 小 MLP(下采样 MNIST)+ G 几何
465
+ │ ├── mnist_mlp_classification.py # [已验证] MNIST MLP(784→128→64→10)+ G 几何
466
+ │ ├── cnn_feature_clustering.py # [未验证] 小 CNN + F 功能(按激活响应聚)
467
+ │ ├── cnn_classification.py # [已验证] 真实大 CNN(VGG 风格 6 卷积层)+ F 功能
468
+ │ ├── transformer_structure_partition.py # [未验证] 玩具 ViT(真实 MNIST)+ S 结构(按头切)
469
+ │ ├── hierarchical_multiscale.py # [未验证] 小 MLP + B 多尺度树(先粗后细)
470
+ │ └── gpt_preview.py # [未验证] GPT 级 S+F+低秩 组合预演(纯理论)
471
+ ├── rust/ # Rust 版 CPU 前向实测(见该目录 README)
472
+ └── project/ # 多对象检测大模型端到端(传统 vs 函数化两种部署对比)
473
+ ```
474
+
475
+ ## 测试
476
+
477
+ ```bash
478
+ pytest tests -q
479
+ ```
480
+
481
+ ## 推断:GPT 这类超大模型的收益
482
+
483
+ > 本节是**基于实测规律的外推,不是验证结论**。库内对 GPT 级只做接口预留
484
+ > (`regionify_transformer_block()`)+ 理论预演(`examples/python/gpt_preview.py`),
485
+ > 真实收益需 ≥80GB 级多卡验证,本机做不到。请把它当「方向性判断」。
486
+
487
+ ### 从小模型到大模型,三条实测规律
488
+
489
+ | 规律 | 实测证据(固定种子) |
490
+ |------|--------------------|
491
+ | **体积省钱随冗余度上升** | 小 MLP 省 82% → 大 CNN 89% → 玩具 ViT 90.5%,越大越省 |
492
+ | **内存/显存靠「K≪n」才兑现** | 充要条件 `K×(1+r)<n`,小层会反涨、大层净省 |
493
+ | **CPU 提速只在「大模型 + Rust/GPU」兑现** | numpy 小模型反慢,大层(K≪n)才转正 |
494
+
495
+ ### 跨规模实测:层越宽,函数化越「又省又稳」
496
+
497
+ 同 MNIST、同 seed、3 隐层 MLP(784→h→h→h→10),只改隐层宽度 h、逐层参差式函数化
498
+ (`multilayer_autoalloc.py` 的逐层机制跑 6 个宽度档的对照扫描):
499
+
500
+ | 隐层宽 h | 参数量 | 叠加掉点 | 整体节省率 |
501
+ |---------|--------|---------|-----------|
502
+ | 64 | 5.9 万 | 14.50pt | 61.6% |
503
+ | 128 | 13 万 | 6.63pt | 72.4% |
504
+ | 256 | 33 万 | 8.40pt | 80.2% |
505
+ | 512 | 93 万 | 3.31pt | 87.2% |
506
+ | 1024 | 291 万 | 1.39pt | 87.3% |
507
+ | 2048 | 1002 万 | 1.29pt | 89.3% |
508
+
509
+ > 注:上表是「等宽三隐层 784→h→h→h→10」的缩放扫描;正式示例
510
+ > `multilayer_autoalloc.py` 用的是「递减 784→512→256→10」(省 86.1%、掉 2.91pt),
511
+ > 两者结构不同,数字不可直接互换。
512
+
513
+ 两条清晰趋势:
514
+ - **节省率严格单调上升**(61.6% → 89.3%),冗余越足、压缩越狠;
515
+ - **掉点在跨过某临界宽度后「断崖式收敛」**(h=1024 起掉点稳在 <1.5pt),
516
+ 层够宽时「省得多」与「掉得少」从矛盾变成同时成立。
517
+
518
+ 这正是「fc 层极宽时,参差式函数化优势被放大」的直接证据——GPT 的 FFN 层
519
+ 正是典型的极宽 fc 层,按此趋势收益只会更显著。
520
+
521
+ ### 按这三条规律外推 GPT 级
522
+
523
+ 1. **体积 / 内存:收益大概率显著更高**
524
+ GPT 的 FFN 层、注意力层参数规模巨大(单层 n 可达数千、D 数千),`K≪n`
525
+ 天然成立、参数冗余充分。外推:体积省可能到 95%+、内存净省空间比小模型大得多。
526
+ 2. **CPU:首次有「真提速」的土壤**
527
+ 小模型测不出提速,是因为 K 不够小、BLAS 稠密占优;GPT 层 `K≪n`,函数前向
528
+ 共享计算 + 查表广播的收益才会浮现——但**前提是 Rust/CUDA kernel 兑现**,
529
+ numpy 参考实现仍会受 gather/循环拖累。
530
+ 3. **掉点:分型手段能兜住,但「不验证」是硬边界**
531
+ 实测里 `F` 功能分区(大 CNN 掉 0.37pt)、`S` 结构分区(玩具 ViT 掉 0.71pt)
532
+ 都在 <5pt 内,且 `auto_alloc` 的 `eval_fn` 能逐层把掉点压住。理论上 GPT 级
533
+ 用「S(按头/层切)+ F(功能聚类)+ FFN 低秩」组合分型,同样有机会守住红线——
534
+ 但这只是推断,**GPT 级的真实掉点没有验证**。
535
+
536
+ ### 为什么不直接给结论
537
+
538
+ - 本机 12G 显存 + 16G 内存,加载不了 GPT 级权重,**无法实测**;
539
+ - GPT 的权重/激活分布、冗余结构与小模型不同,前面的规律**不能保证线性外推**;
540
+ - 这正对应库的诚实边界:GPT 级「谁有条件谁验证」,本库只提供接口与理论预演。
541
+
542
+ ---
543
+
544
+ 如果你有条件(≥80GB 级多卡 + 大内存),欢迎用 `regionify_transformer_block()`
545
+ 的接口骨架 + 上述分型思路做真实验证,那是本节推断能否成立的最终判据。
546
+
547
+ ---
548
+
549
+ > 算法逻辑由本人提出,算法推演实现由AI推断
550
+
551
+ ## License
552
+
553
+ MIT