ferritin_plms/esm3/layers/
output_heads.rs1use crate::esm3::models::esm3::ESM3Config;
6use candle_core::{Module, Result, Tensor};
7use candle_nn::{self as nn, LayerNormConfig, VarBuilder};
8
9pub struct RegressionHead {
13 model: nn::Sequential,
14}
15
16impl RegressionHead {
17 pub fn load(vb: VarBuilder, d_in: usize, d_out: usize) -> Result<Self> {
18 let ln_conf = LayerNormConfig::from(1e-5);
19 let model = nn::seq()
20 .add(nn::linear(d_in, d_in, vb.pp("0"))?)
21 .add(nn::Activation::Gelu)
22 .add(nn::layer_norm(d_in, ln_conf, vb.pp("2"))?)
23 .add(nn::linear(d_in, d_out, vb.pp("3"))?);
24 Ok(Self { model })
25 }
26}
27
28impl Module for RegressionHead {
29 fn forward(&self, x: &Tensor) -> Result<Tensor> {
30 self.model.forward(x)
31 }
32}
33
34pub struct OutputHeads {
37 sequence_head: RegressionHead,
38 structure_head: RegressionHead,
39 ss8_head: RegressionHead,
40 sasa_head: RegressionHead,
41 function_head: RegressionHead,
42 residue_head: RegressionHead,
43 n_function_tracks: usize,
44 d_function_vocab: usize,
45}
46
47impl OutputHeads {
48 pub fn load(vb: VarBuilder, config: &ESM3Config) -> Result<Self> {
49 let d = config.d_model;
50 Ok(Self {
51 sequence_head: RegressionHead::load(
52 vb.pp("sequence_head"),
53 d,
54 config.d_sequence_vocab,
55 )?,
56 structure_head: RegressionHead::load(
57 vb.pp("structure_head"),
58 d,
59 config.d_structure_vocab,
60 )?,
61 ss8_head: RegressionHead::load(vb.pp("ss8_head"), d, config.d_ss8_vocab)?,
62 sasa_head: RegressionHead::load(vb.pp("sasa_head"), d, config.d_sasa_vocab)?,
63 function_head: RegressionHead::load(
64 vb.pp("function_head"),
65 d,
66 config.n_function_tracks * config.d_function_vocab,
67 )?,
68 residue_head: RegressionHead::load(vb.pp("residue_head"), d, config.d_residue_vocab)?,
69 n_function_tracks: config.n_function_tracks,
70 d_function_vocab: config.d_function_vocab,
71 })
72 }
73
74 pub fn forward(&self, x: &Tensor) -> Result<ESM3Output> {
80 let (b, l, _) = x.dims3()?;
81
82 let function_logits = self.function_head.forward(x)?.reshape((
84 b,
85 l,
86 self.n_function_tracks,
87 self.d_function_vocab,
88 ))?;
89
90 Ok(ESM3Output {
91 sequence_logits: Some(self.sequence_head.forward(x)?),
92 structure_logits: Some(self.structure_head.forward(x)?),
93 secondary_structure_logits: Some(self.ss8_head.forward(x)?),
94 sasa_logits: Some(self.sasa_head.forward(x)?),
95 function_logits: Some(function_logits),
96 residue_logits: Some(self.residue_head.forward(x)?),
97 embeddings: None,
98 })
99 }
100}
101
102#[derive(Debug)]
106pub struct ESM3Output {
107 pub sequence_logits: Option<Tensor>,
109 pub structure_logits: Option<Tensor>,
111 pub secondary_structure_logits: Option<Tensor>,
113 pub sasa_logits: Option<Tensor>,
115 pub function_logits: Option<Tensor>,
117 pub residue_logits: Option<Tensor>,
119 pub embeddings: Option<Tensor>,
121}