English | 中文
AdaptoFlux 是一种基于“方法池 + 路径搜索”的智能算法框架,核心思路是通过组合基础函数构造动态计算路径,以类似DFG的图结构进行组织,并支持路径可解释性与结构优化。
主要特点:
- 使用函数池(包括 MLP、随机森林等)作为推理构件;
- 构建动态数据流图,实现模块化计算与路径组合;
- 支持自定义“坍缩函数”作为最终输出结构;
- 训练中结合“路径熵 + 冗余惩罚 + 指导值”进行结构调整;
- 可用于符号回归、小样本建模、结构搜索、逻辑组合等任务。
一种基于方法池(包含多种类型的函数的集合)实现智能的算法
🚧 本项目目前为开发阶段(WIP)。功能尚不完整,API 可能会变更。
AdaptoFlux是一种基于方法池的智能算法。不同于传统的深度学习,该算法通过生成一个基于路径的操作流程,实现智能计算和优化。通过对方法池和坍缩函数的操作,该算法拥有极强的兼容性和较强的可解释性。在通过小样本数据生成经验公式上有一定优势。如果我们能找到一种最基础的方法池,通过方法池的自进化机制对各个任务分别特化,该算法有很大的潜力。
- 模型化简和新函数生成部分仍在开发中。
- 正在编写基于该算法在不修改MLP模型情况优化 MLP的示例代码,并持续优化。
- 正在重构ATF部分代码,使用DFG结构
- 进一步优化模型化简过程,提高计算效率。
- 完善新函数生成机制,以增强算法适用性。
- 完成并优化 MLP 优化示例代码,使其更具参考价值。
- 载入模型后在原模型基础上训练
- 从模型中提取一部分已完成的路径进行重新训练
- 根据不同的输入数据选择不同的方法池进行路径选择,对数据分组选择不同的方法池
- 从当前模型中切除一块路径,记录输入数据点数和输出数据点数,重新训练一个新路径使得输入和输出和原本路径相同,以此进行优化网络
- 加一个方法池装饰器记录函数输入输出类型
- 多方法池分别处理不同的数据
- 使用遗传算法对方法池的自动选择
- 在游戏引擎中实现使用该框架的npc
- 创建新的 conda 环境:
conda create -n AdaptoFlux python=3.12
conda activate AdaptoFlux
- 克隆仓库:
git clone https://github.com/gugugu12138/AdaptoFlux.git
cd AdaptoFlux
- 安装依赖:
pip install -r requirements.txt
注: 使用的方法池需要额外配置环境
AdaptoFlux的训练和推理基于方法池进行运行,通过修改methods.py中的函数,为AdaptoFlux提供不同的选择,达到更好的效果。 (你甚至可以往方法池里面塞随机森林和MLP模型)
从输入数据到输出结果的处理过程。数据沿着动态生成的路径逐层进行特征提取和转换,每一层级执行特定的任务,并最终通过 坍缩函数 将中间表示转化为目标形式的过程。
可选的转换操作,用于在基于动态生成路径的数据流处理过程中,从路径末端提取经过逐层操作后的数据,并将其转化为具有特定目标格式的输出。
具体而言,当网络中的某些值与 指导值 存在直接关系时,坍缩函数通过聚合或总结操作,将复杂的中间表示简化为更简洁的目标形式。
其输入可以是单个节点的特征向量,也可以是整个路径末端的综合数据,输出则根据任务需求定制,例如概率分布、类别标签或其他所需格式。
(与方法池同理,坍缩函数可以灵活选择算法,如使用MLP作为坍缩函数,在使用类似于mlp的坍缩函数是,模型可以视为一个在坍缩函数所用模型前的数据预处理器,使得数据更适合坍缩函数使用模型以使得效果增强)
对于长度高于2的一维纯数值数据,提供了一种通用的坍缩函数area,该函数的介绍Energy
用于指导神经的生长或退化。(实际上是一种特殊的损失)
-
指标分类与层级划分:
类别 示例指标 调整目标 影响权重 核心任务 准确率、F1分数 直接优化任务性能 高(α) 路径质量 路径熵、路径深度 保障探索与架构健康 中(β) 计算效率 内存占用、FLOPs 抑制资源浪费 低(γ) 损失控制 MSE、RMSE、交叉熵 训练初期调整优化方向,后期减少影响 变(δ) -
多指标融合公式
$$ 指导值 = \sum \omega_i \cdot 核心指标_i + \sum \phi_j \cdot 路径指标_j - \sum \psi_k \cdot 效率指标_k - \delta \cdot 损失值 $$ -
示例计算公式:
其中,$P(路径_{\text{i}})$ 表示第 i 类路径的出现频率(统计窗口内的占比)。
方法池是一组预定义的函数操作集合,每个方法都包含:
- 函数体(Function Body)
- 输入参数个数(Input Count)
- 输出参数个数(Output Count)
该池用于支持 AdaptoFlux 图模型的动态构建与优化。
只包含映射函数的方法池。
只包含动作函数的方法池。
- 生成初始模型 使用process_random_method函数生成多份指定层数的模型(这一部分不进行损失计算)(或结合replace_random_elements一定程度上优化) 对比模型,选择性能最佳的初始模型。
- 修改初始模型图节点 对于初始模型中的每一个功能节点,从某个方向的某一层开始,逐个比较可替换的节点(输入输出维度相同的节点),对比修改节点后损失大小,选择性能最佳的节点。重复扫描多次。(此时每次更新损失必定小于等于前一次,必定收敛)
- 生成化简模型 随机生成输入输出维度与某一部分图相同的模型,对比两者在一定范围内的输入输出,使用性能更好的模型替换图中所有相同的图,重复此流程。
- 生成新方法池 训练过程中,将表现优异的部分切块,迭代为新的方法池,一定轮次后使用新方法池。
利用遗传算法对方法池进行压缩,结合类贪心算法作为基础叠层策略,实施四步式优化中的节点级优化、结构化简和方法池演化,并考虑数据流随层数的自然衰减效应,AdaptoFlux将原始指数级的搜索空间压缩至多项式级别。使问题从理论上不可解变为工程上完全可行。
目前思路是使用遗传算法,将初始输入的总方法池切分为多个子方法池后使用遗传算法选择损失下降最快或者概率上升最快(指导值上升速度最快)的方法池 具体来说比如方法池中有200个方法,期望最终方法池中有8个方法,从200个方法池中分出25组方法池,根据每个池的指导值上升速度选择最优的几个进行遗传算法,最终选择最优的方法池进行训练。
-
输入层处理
- 初始数据点数量:n
- 按照方法池规则随机分组
- 对每个分组执行对应函数
-
迭代处理
- 处理后将数据还原并重新分组
- 重复流程直至到达路径末端
-
输出生成
- 对尾部数据应用坍缩函数
- 生成最终网络输出
Iₐ
:函数a的输入/输出数据量比H
:每层数据期望减少比例k
:方法池函数总数Wₐ
:函数a的被选概率
核心公式
在不同训练阶段采用不同的方法池进行处理,可以实现对数据的扩维,修改,降维。 从该公式可以发现,通过对随机选取方法的适量修改,可以很简单的控制输入和坍缩层前的维度,对于大部分激活函数都有很强的兼容性。
n₀
:初始数据量L
:模型层数nₗ
:第L层数据量
对于已经训练得到的的路径,我们可以提取出使用的方法池,生成一个该方法池可用的随机数据列表, 从该数据列表中按照不同长度切割成多个二维列表,将这些二维列表作为数据进行有限制(如限制层数)无监督训练, 将训练出的多个路径做对比,如输入和输出完全相同(或大部分相同),认为该两条路径等效,对它们的指标进行判断(如路径深度,运行速度等), 在原路径中使用更优的路径替换掉原部分
类型 | 特性 | 反向推导能力 |
---|---|---|
双射函数池 | 所有函数为双射 | 完全可逆 |
单射函数池 | 所有函数为单射 | 可逆(需额外信息) |
满射函数池 | 所有函数为满射 | 多输入对应单输出 |
条件:任意一组(c,d)互质
当所有组合皆为合法时,该公式等效于:
其中:
- $ N_{\text{paths}}^{(l)} $ :第 $ l $ 层的总函数选择组合数(即穷举空间大小)
- $ \text{prev_combo} $ :上一层(第 $ l-1 $ 层)的所有可能函数组合
- $ C_{\text{current}}(\text{prev_combo}) $ :在该输入结构下当前层的函数选择组合数,计算方式为:
其中:
- $ n_l $ :当前层的输入节点数(由上一层输出决定)
- $ F_i^{(l)} $ :第 $ i $ 个输入节点的方法池(函数集合)
注:当某个节点方法池为空时,将其视为只有一个方法,即 $ |F_i^{(l)}| = 1 $
- 每一层的组合数 $ N_{\text{paths}}^{(l)} $ 是由前一层所有可能的组合所决定的。
- 对于每一个前一层的组合 $ \text{prev_combo} $,当前层根据其输出结构确定输入节点数量 $ n_l $,并据此计算该结构下的函数选择组合数 $ C_{\text{current}}(\text{prev_combo}) $。
- 所有前一层组合对应的当前层分支数加总,得到当前层的总组合数。
- 当前层每个输入节点可以独立地从其方法池中选择一个函数。
- 因此,若当前层有 $ n_l $ 个输入节点,且每个节点的方法池分别为 $ F_1^{(l)}, F_2^{(l)}, ..., F_{n_l}^{(l)}
$,则组合数为: $ $ C_{\text{current}} = \prod_{i=1}^{n_l} |F_i^{(l)}| $$
- 每个 $ \text{prev_combo} $ 可能导致不同的输入结构(即不同数量和类型的数据点),从而影响下一层的 $ n_l $ 和 $ F_i^{(l)} $。
- 这意味着,即使在相同层,不同 $ \text{prev_combo} $ 可能导致不同的 $ C_{\text{current}} $。
- 初始数据量:$ n_0 = 1 $
- 函数池:
- $ f_1 $: 输入1个数据 → 输出1个数据
- $ f_2 $: 输入1个数据 → 输出2个数据
- 层数:2层
- 输入数据点数:$ n_0 = 1 $
- 方法池:$ F = {f_1, f_2} $
- 组合数:$ C_{\text{current}} = |F| = 2 $
- 每个组合对应不同的输出结构:
- 若选 $ f_1 $:输出1个数据
- 若选 $ f_2 $:输出2个数据
✅ 第1层组合数:2
→ 对应两种不同的输入结构用于第2层
- 输入节点数:1
- 方法池:$ F = {f_1, f_2} $
- 组合数:$ C_{\text{current}} = 2^1 = 2 $
- 输入节点数:2
- 方法池:每个节点可选 $ f_1, f_2 $
- 组合数:$ C_{\text{current}} = 2^2 = 4 $
背景
假设我们有一个非常简化的模型,它由两个层次组成(
- 组合A: 输入维度为 2,输出维度为 3。
- 组合B: 输入维度为 2,输出维度为 4。
- 组合C: 输入维度为 3,输出维度为 5。
- 组合D: 输入维度为 4,输出维度为 6。
初始输入维度为 2。
解空间 是该算法能够探索的所有非等效 DFG 图所生成的输出结果的集合。
每个 DFG 图代表一种函数组合路径,但只有当其输出与其他图不同时,才被视为一个新的“解”。
示例
在给定的例子中,有四种可能的路径组合:
- A → C
- A → D
- B → C
- B → D
我们运行这些路径后得到它们的输出结果,设为:
- 输出1:
$o_1$ - 输出2:
$o_2$ - 输出3:
$o_1$ (与第一条路径等效) - 输出4:
$o_3$
那么实际的非等效输出集合为:
因此,解空间的大小为:
解空间定义公式
解空间大小公式
也可以写作:
其中:
-
$\mathcal{P}$ :所有路径组合构成的集合,$\mathcal{P} = {p_1, p_2, ..., p_N}$ -
$f(p_i)$ :路径$p_i$ 对应的输出结果(可以是向量、哈希值或某种特征表示) -
$|\mathcal{P}|$ :总路径数; -
$k$ :等效类的数量(即不同输出的数量); -
$n_i$ :第$i$ 个等效类包含的路径数(满足$\sum n_i = |\mathcal{P}|$ )
- 输入空间增长公式
$$T = R^C$$ T
:输入空间大小R
:函数输入数量均值C
:函数调用总次数
- 通过添加随机变量实现单射转换
- 支持输出到唯一输入的映射
当没有直接输入时,可以通过使用一个动作池作为方法池,我们可以使用一个周期信号作为输入,通过动作池中的动作函数组合获取数据(或者使得指导函数趋向目标),以此来实现模型的构建。
(这部分理论可行,之后会把图和完整概念放上来)
集成运算中,将各个基分类器的输出作为模型的输入,使用简单的位运算和带权运算作为方法池 可结合多个分类器