P-NET:生物学先验驱动的稀疏可见神经网络
PNETModel
00 Remarks
网络结构完全由 PathwayHierarchy 所描述的生物层级所决定:
输入层(每基因 3 个改变特征) ──► 基因层 ──► 5 层通路层(逐级抽象)
│ │ │
└──► sigmoid 预测头 ◄──────┴────────────┘ (每一个隐藏层都挂一个预测头)
每一个隐藏层都由一个 MaskedDenseLayer 实现,其连接拓扑由二值掩码约束; 每一个隐藏层之后都挂一个 PredictionHead 做深度监督, 最终的概率输出为所有预测头输出的平均值。
01 Syntax
02 Methods
| Name | Overloads | Summary |
|---|---|---|
| .ctor | 1 | 创建 P-NET 模型 |
| SetDeepSupervisionWeights | 1 | 按照深度线性递增的方式重新分配深度监督预测头的损失权重 |
| Forward | 1 | 前向传播 |
| Predict | 1 | 对给定样本做预测,返回每一个样本的患病概率 |
| PredictSingle | 1 | 对单个样本做预测 |
| ComputeLoss | 1 | 计算深度监督加权二元交叉熵损失 |
| Backward | 1 | 反向传播:累积所有层与所有预测头的梯度 |
| ZeroGrad | 1 | 清零所有层与所有预测头之中累积的梯度 |
| CollectAll | 1 | 按照固定顺序收集全部可训练参数与对应的梯度 |
| GetParameters | 1 | 收集全部可训练参数 |
| GetGradients | 1 | 收集全部梯度,顺序与 PNETModel.GetParameters() 一致 |
| PrintArchitecture | 1 | 生成网络结构的文字描述 |
03 Properties
| Name | Overloads | Summary |
|---|---|---|
| Hierarchy | 1 | 构建当前网络所使用的生物层级本体 |
| Layers | 1 | 逐层排列的掩码稀疏层,第 0 项为基因层 |
| Heads | 1 | 与 PNETModel.Layers 一一对应的深度监督预测头 |
| InputSize | 1 | 输入层节点数量,等于基因数量的 3 倍 |
| LayerCount | 1 | 隐藏层数量,等于 1 层基因层加上所有通路层 |
| HeadWeights | 1 | 每一个预测头在总损失中所占的权重,索引与 PNETModel.Heads 一致 |
| TrainableParameterCount | 1 | 网络中实际可训练的参数数量 |
| DenseParameterCount | 1 | 若所有层都采用稠密连接时的参数数量,用于评估稀疏化带来的压缩比 |
04 Members
创建 P-NET 模型
| Name | Type | Description |
|---|---|---|
hierarchy | PathwayHierarchy | 生物层级本体 |
layers | IEnumerable(Of MaskedDenseLayer) | 逐层排列的掩码稀疏层 |
heads | IEnumerable(Of PredictionHead) | 与 layers 一一对应的深度监督预测头 |
Double)按照深度线性递增的方式重新分配深度监督预测头的损失权重
权重在设置之前会被归一化,使得所有预测头的权重之和等于 1, 这样总损失的数值尺度不会随着网络层数的变化而变化。
| Name | Type | Description |
|---|---|---|
lambda | Double | 深度加权系数:第 |
Tensor)前向传播
| Name | Type | Description |
|---|---|---|
x | Tensor | 输入特征矩阵,形状为 [N, InputSize],元素为 0 或者 1 的二值改变特征 |
包含全部中间结果的前向传播结果对象
Tensor)对给定样本做预测,返回每一个样本的患病概率
| Name | Type | Description |
|---|---|---|
x | Tensor | 输入特征矩阵,形状为 [N, InputSize] |
概率数组,取值范围为 (0, 1)
Double())对单个样本做预测
| Name | Type | Description |
|---|---|---|
features | Double() | 长度为 PNETModel.InputSize 的特征向量 |
患病概率,取值范围为 (0, 1)
计算深度监督加权二元交叉熵损失
总损失为各个预测头损失的加权平均:L = Σ_l w_l · BCE(y, p_l), 其中 w_l 来自 PNETModel.HeadWeights,且已经在 PNETModel.SetDeepSupervisionWeights() 中被归一化为和为 1。
| Name | Type | Description |
|---|---|---|
result | PNETForwardResult | 前向传播结果 |
y | Double() | 真实标签数组,元素取值为 0 或者 1 |
positiveWeight | Double | 正样本类别权重 |
negativeWeight | Double | 负样本类别权重 |
加权之后的平均损失值
反向传播:累积所有层与所有预测头的梯度
每一个隐藏层的激活值同时接收两路梯度:一路来自挂在它自己后面的预测头, 另一路来自更深的层反向传播回来的梯度,二者相加之后再传入该层的反向传播。
梯度在这里已经被除以了批大小,因此 MaskedDenseLayer.Backward() 与 PredictionHead.Backward() 内部只做原始累加, 最终得到的是整个批次上的平均梯度。
| Name | Type | Description |
|---|---|---|
result | PNETForwardResult | 前向传播结果,必须是对本次待求梯度的同一批输入做前向传播所得到的 |
y | Double() | 真实标签数组,元素取值为 0 或者 1 |
positiveWeight | Double | 正样本类别权重 |
negativeWeight | Double | 负样本类别权重 |
清零所有层与所有预测头之中累积的梯度
List(Of Tensor), List(Of Tensor))按照固定顺序收集全部可训练参数与对应的梯度
模型与优化器之间只通过这两个列表解耦, 因此后续替换 SGD / 加权 Adam 等优化器时不需要改动模型本身。
| Name | Type | Description |
|---|---|---|
parameters | List(Of Tensor) | 参数收集列表 |
gradients | List(Of Tensor) | 梯度收集列表 |
收集全部可训练参数
参数张量列表,顺序与 PNETModel.GetGradients() 一致
收集全部梯度,顺序与 PNETModel.GetParameters() 一致
梯度张量列表
生成网络结构的文字描述
包含逐层节点数、连接数、参数量以及稀疏压缩比的多行文本
构建当前网络所使用的生物层级本体
层级本体对象
逐层排列的掩码稀疏层,第 0 项为基因层
掩码层列表
与 PNETModel.Layers 一一对应的深度监督预测头
预测头列表
输入层节点数量,等于基因数量的 3 倍
输入特征维度
隐藏层数量,等于 1 层基因层加上所有通路层
隐藏层数量
每一个预测头在总损失中所占的权重,索引与 PNETModel.Heads 一致
越深的层节点数越少、可训练参数越少、拟合越困难, 因此这里给深层的预测头分配更高的损失权重以平衡各层的梯度贡献。
损失权重数组
网络中实际可训练的参数数量
可训练参数数量
若所有层都采用稠密连接时的参数数量,用于评估稀疏化带来的压缩比
论文指出:P-NET 仅约 7.1 万个权重, 而同等节点数的稠密网络需要超过 2.7 亿个权重,参数量下降 3 到 4 个数量级, 这正是 P-NET 在小样本上优于稠密网络的根本原因 —— 先验约束起到了超强正则化的作用。
稠密网络的参数数量