{
  "id": 106468,
  "title": "#2 solution 🤖 Quantum Uncertainty 🤖",
  "url": "/competitions/champs-scalar-coupling/discussion/106468",
  "author_name": "Andrés Miguel Torrubia Sáez",
  "post_date": "2019-08-29T16:05:42.651000",
  "votes": 177,
  "comment_count": 49,
  "views": 0,
  "content": "<p>We want to thank Kaggle and CHAMPs for organizing such an awesome competition: </p>\n\n<ul>\n<li>No leakage.</li>\n<li>Same distribution in train, private and public test (very stable CV vs. LB, public LB vs. private LB). This is very relevant in other competitions given so many participants when the 3 distributions are different some winners (not all, e.g. <a href=\"https://www.kaggle.com/c/microsoft-malware-prediction/discussion/84069#latest-499864\">CPMP approach to manually align test ~ train in the Microsoft malware comp</a>) are just lucky they fit private test distribution by chance; not the case here. </li>\n<li>Inspiring and useful science problem hopefully used for good purposes as described in the context (new drugs, etc.).</li>\n</ul>\n\n<p>Neither my teammate <a href=\"/pavelgonchar\">@pavelgonchar</a> nor I had any previous domain expertise and we made the decision early on that we would tackle this problem using a very pure deep learning way: letting the model build the features for us, not the other way around (b/c obviously we were at a disadvantage if we tried to become quantum experts in 1 month… hence our team name 🤖Quantum Uncertainty🤖 we didn't know if our yet-to-be-developed approach was going to work).</p>\n\n<p>Our solution had two major parts: 1) the input representation and 2) deep learning architecture.</p>\n\n<p><strong>Input representation</strong></p>\n\n<p>This is in our opinion the key part: we take a molecule and a source atom and move it so the source atom is @ (0,0,0). For each molecule we create N molecule siblings (N being as many source atoms are defined for that molecule), and each molecule sibling is translated so its source is at (0,0,0). </p>\n\n<p>The <code>x</code> (input) are three arrays of dimension 29 (maximum number of atoms): </p>\n\n<p>1) <code>x,y,z</code> position of each atom, \n2) <code>atom type</code> index (C=0, H=1, etc…)\n3) <code>j-coupling type</code> index (1JHC=0,'2JHH=1,etc.)</p>\n\n<p>Padding is done by placing -1 in <code>atom type</code> index and <code>j-coupling type</code> for molecules which have less than 29 atoms.</p>\n\n<p>The <code>y</code> (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.</p>\n\n<p>Note that there is no graph information nor any other manually engineered features.</p>\n\n<p><strong>Data augmentation</strong></p>\n\n<p>We did two types of data augmentation:\n- Rotations: which worked and were useful in our first attempt model: pointnet-based, but proved worthless in the final models (atomic transformer).\n- J-coupling symmetry: as described <a href=\"https://www.kaggle.com/c/champs-scalar-coupling/discussion/94706#latest-563148\">in this discussion</a></p>\n\n<p><strong>First attempt: Pointnet-inspired architecture (got up to -2.28200 LB)</strong></p>\n\n<p>Our input representation is basically a point cloud: an unordered set of elements with absolute positions <code>x,y,z</code> and two attributes <code>atom type</code> and <code>j-coupling type</code>. We modified the <a href=\"https://arxiv.org/abs/1612.00593\">Pointnet</a> architecture to regress j-couplings. Training was a bit unstable and we tried many variations of the architecture, swapping FC layers by linear (fixed) projections (Hadamard), adding coulomb matrix as input, etc. </p>\n\n<p>While this worked OK and got us to -2.28200 LB (ensembling a few models) we felt that this architecture was limited by the extreme pooling/bottleneck operation so we decided to explore other architectures: meet the Atomic Transformer.</p>\n\n<p><strong>Final architecture: meet the Atomic Transformer</strong></p>\n\n<p>You may know that the recent NLP revolution is mostly due to the transformer architecture described in the <a href=\"https://arxiv.org/abs/1706.03762\">Attention is all you need paper</a>. The vanilla transformer architecture uses a very clever technique to add positional encodings that are needed for position-dependent input, such as language. </p>\n\n<p>Our input representation is a set, which means we can (and should) remove positional encoding. Prior to this competition we had no experience with transformers either but there's a section in <a href=\"https://www.youtube.com/watch?v=Kedt2or9xlo\">Lex Fridman MIT podcast interviewing Orion Vinyals</a> where he mentions the inherent position invariance of a barebone transformer encoder layer. This immediately triggered the idea of using transformer layers (encoders) stacked taking as an input <code>x,y,z</code> (normalized but otherwise as-is), and <code>atom type</code> and <code>j-coupling type</code> embeddings; just concatenated… nothing fancy. </p>\n\n<p>The dimension of the embeddings was such that the total dimension of the input vectors was <code>d_model</code> (as normally reference in transformer literature). We started with 256 and got immediately great results surpassing our pointnet-inspired architecture so we followed this path.</p>\n\n<p>We trained a total of 14 models, with varying dimensions from 512 to 2048 and layers from 6 to 24. Each model parameter size ranged from ~12M to ~100M (biggest model).</p>\n\n<p>We trained some models from scratch, others we fine-tuned. We also fine-tuned a few models on the troublesome j-couplings: reaching -2.12 CV on 1JHC on and -2.19 CV on 1JHN.</p>\n\n<p>Our best score is an ensemble of 14 models achieving private LB of -3.22349, and our best single model achieved private LB of -3.16234, again just with <code>x,y,z</code>, <code>atom type</code> and <code>j-coupling type</code> inputs (no QM9, etc.).</p>\n\n<p><strong>What didn't work</strong></p>\n\n<p>Many things! We tried:</p>\n\n<ul>\n<li>Multi-task learning using contributions and other organization provided values.</li>\n<li>Dropout: We tried multiple attempts to add dropout at various stages (embeddings, encoder layers, pre-decoder, etc.). None of them worked.</li>\n<li>Knock-out: We added a variation in which as input we deleted 10% of the input atoms, the idea being that the model would build an internal representation of the missing atoms. Surprisingly this worked in that the model still converged nicely but failed to reduce train ~ val gap.</li>\n<li>Rotations and TTA in Atomic Transformer: it didn't reduce train ~ val gap and didn't produce meaningful TTA gains.</li>\n<li>Deep decoder: Our decoder is just a projection of ~ the model dimension to 1 (scalar coupling). We tried adding more expressive power to the decoder but this didn't help.</li>\n<li>Fp16 training. This worked for models of dimensions 256 but as training evolved gave <code>NaN</code>s despite numerous attempts to fix it.</li>\n</ul>\n\n<p><strong>Source code</strong></p>\n\n<p>We will make source code available once we do clean up. It's a single jupyter notebook using FastAI. Be patient.</p>\n\n<p><strong>Computational resources</strong></p>\n\n<p>We had more ideas than computational resources, even if our computational resources were not tiny:\n- 3 x 2080 Ti + 128 Gb RAM + 16c32t processor\n- 2 x 1080 Ti + 64 Gb RAM + 8c16t processor\n- Rented 8+ 2080 Ti + 64 Gb RAM + 16c32t processor (multiple machines rented as needed)</p>\n\n<p><strong>Final thoughts</strong></p>\n\n<p>This was our most fun and hardest competition so far:\n- Challenging problem\n- Most teams in top 5 had domain experts (although we went <em>domainless</em> as part of our strategy)\n- Hungry computational resources.</p>\n\n<p>Even if we lost #1 position just a few hours before competition end we feel very excited we were able to achieve such [useful results for the organizers] (<a href=\"https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312\">https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312</a>). In retrospect we believe a single model of the Atomic Transformer may achieve ever better results with further training.</p>\n\n<p>Best - Pavel &amp; Andres</p>\n\n<p>p.s. No graph NNs. We though graphs as manually engineered features that the model can infer by itself.</p>",
  "messages": [
    {
      "id": 612141,
      "postDate": "2019-08-29T16:05:42.650Z",
      "content": "<p>We want to thank Kaggle and CHAMPs for organizing such an awesome competition: </p>\n\n<ul>\n<li>No leakage.</li>\n<li>Same distribution in train, private and public test (very stable CV vs. LB, public LB vs. private LB). This is very relevant in other competitions given so many participants when the 3 distributions are different some winners (not all, e.g. <a href=\"https://www.kaggle.com/c/microsoft-malware-prediction/discussion/84069#latest-499864\">CPMP approach to manually align test ~ train in the Microsoft malware comp</a>) are just lucky they fit private test distribution by chance; not the case here. </li>\n<li>Inspiring and useful science problem hopefully used for good purposes as described in the context (new drugs, etc.).</li>\n</ul>\n\n<p>Neither my teammate <a href=\"/pavelgonchar\">@pavelgonchar</a> nor I had any previous domain expertise and we made the decision early on that we would tackle this problem using a very pure deep learning way: letting the model build the features for us, not the other way around (b/c obviously we were at a disadvantage if we tried to become quantum experts in 1 month… hence our team name 🤖Quantum Uncertainty🤖 we didn't know if our yet-to-be-developed approach was going to work).</p>\n\n<p>Our solution had two major parts: 1) the input representation and 2) deep learning architecture.</p>\n\n<p><strong>Input representation</strong></p>\n\n<p>This is in our opinion the key part: we take a molecule and a source atom and move it so the source atom is @ (0,0,0). For each molecule we create N molecule siblings (N being as many source atoms are defined for that molecule), and each molecule sibling is translated so its source is at (0,0,0). </p>\n\n<p>The <code>x</code> (input) are three arrays of dimension 29 (maximum number of atoms): </p>\n\n<p>1) <code>x,y,z</code> position of each atom, \n2) <code>atom type</code> index (C=0, H=1, etc…)\n3) <code>j-coupling type</code> index (1JHC=0,'2JHH=1,etc.)</p>\n\n<p>Padding is done by placing -1 in <code>atom type</code> index and <code>j-coupling type</code> for molecules which have less than 29 atoms.</p>\n\n<p>The <code>y</code> (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.</p>\n\n<p>Note that there is no graph information nor any other manually engineered features.</p>\n\n<p><strong>Data augmentation</strong></p>\n\n<p>We did two types of data augmentation:\n- Rotations: which worked and were useful in our first attempt model: pointnet-based, but proved worthless in the final models (atomic transformer).\n- J-coupling symmetry: as described <a href=\"https://www.kaggle.com/c/champs-scalar-coupling/discussion/94706#latest-563148\">in this discussion</a></p>\n\n<p><strong>First attempt: Pointnet-inspired architecture (got up to -2.28200 LB)</strong></p>\n\n<p>Our input representation is basically a point cloud: an unordered set of elements with absolute positions <code>x,y,z</code> and two attributes <code>atom type</code> and <code>j-coupling type</code>. We modified the <a href=\"https://arxiv.org/abs/1612.00593\">Pointnet</a> architecture to regress j-couplings. Training was a bit unstable and we tried many variations of the architecture, swapping FC layers by linear (fixed) projections (Hadamard), adding coulomb matrix as input, etc. </p>\n\n<p>While this worked OK and got us to -2.28200 LB (ensembling a few models) we felt that this architecture was limited by the extreme pooling/bottleneck operation so we decided to explore other architectures: meet the Atomic Transformer.</p>\n\n<p><strong>Final architecture: meet the Atomic Transformer</strong></p>\n\n<p>You may know that the recent NLP revolution is mostly due to the transformer architecture described in the <a href=\"https://arxiv.org/abs/1706.03762\">Attention is all you need paper</a>. The vanilla transformer architecture uses a very clever technique to add positional encodings that are needed for position-dependent input, such as language. </p>\n\n<p>Our input representation is a set, which means we can (and should) remove positional encoding. Prior to this competition we had no experience with transformers either but there's a section in <a href=\"https://www.youtube.com/watch?v=Kedt2or9xlo\">Lex Fridman MIT podcast interviewing Orion Vinyals</a> where he mentions the inherent position invariance of a barebone transformer encoder layer. This immediately triggered the idea of using transformer layers (encoders) stacked taking as an input <code>x,y,z</code> (normalized but otherwise as-is), and <code>atom type</code> and <code>j-coupling type</code> embeddings; just concatenated… nothing fancy. </p>\n\n<p>The dimension of the embeddings was such that the total dimension of the input vectors was <code>d_model</code> (as normally reference in transformer literature). We started with 256 and got immediately great results surpassing our pointnet-inspired architecture so we followed this path.</p>\n\n<p>We trained a total of 14 models, with varying dimensions from 512 to 2048 and layers from 6 to 24. Each model parameter size ranged from ~12M to ~100M (biggest model).</p>\n\n<p>We trained some models from scratch, others we fine-tuned. We also fine-tuned a few models on the troublesome j-couplings: reaching -2.12 CV on 1JHC on and -2.19 CV on 1JHN.</p>\n\n<p>Our best score is an ensemble of 14 models achieving private LB of -3.22349, and our best single model achieved private LB of -3.16234, again just with <code>x,y,z</code>, <code>atom type</code> and <code>j-coupling type</code> inputs (no QM9, etc.).</p>\n\n<p><strong>What didn't work</strong></p>\n\n<p>Many things! We tried:</p>\n\n<ul>\n<li>Multi-task learning using contributions and other organization provided values.</li>\n<li>Dropout: We tried multiple attempts to add dropout at various stages (embeddings, encoder layers, pre-decoder, etc.). None of them worked.</li>\n<li>Knock-out: We added a variation in which as input we deleted 10% of the input atoms, the idea being that the model would build an internal representation of the missing atoms. Surprisingly this worked in that the model still converged nicely but failed to reduce train ~ val gap.</li>\n<li>Rotations and TTA in Atomic Transformer: it didn't reduce train ~ val gap and didn't produce meaningful TTA gains.</li>\n<li>Deep decoder: Our decoder is just a projection of ~ the model dimension to 1 (scalar coupling). We tried adding more expressive power to the decoder but this didn't help.</li>\n<li>Fp16 training. This worked for models of dimensions 256 but as training evolved gave <code>NaN</code>s despite numerous attempts to fix it.</li>\n</ul>\n\n<p><strong>Source code</strong></p>\n\n<p>We will make source code available once we do clean up. It's a single jupyter notebook using FastAI. Be patient.</p>\n\n<p><strong>Computational resources</strong></p>\n\n<p>We had more ideas than computational resources, even if our computational resources were not tiny:\n- 3 x 2080 Ti + 128 Gb RAM + 16c32t processor\n- 2 x 1080 Ti + 64 Gb RAM + 8c16t processor\n- Rented 8+ 2080 Ti + 64 Gb RAM + 16c32t processor (multiple machines rented as needed)</p>\n\n<p><strong>Final thoughts</strong></p>\n\n<p>This was our most fun and hardest competition so far:\n- Challenging problem\n- Most teams in top 5 had domain experts (although we went <em>domainless</em> as part of our strategy)\n- Hungry computational resources.</p>\n\n<p>Even if we lost #1 position just a few hours before competition end we feel very excited we were able to achieve such [useful results for the organizers] (<a href=\"https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312\">https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312</a>). In retrospect we believe a single model of the Atomic Transformer may achieve ever better results with further training.</p>\n\n<p>Best - Pavel &amp; Andres</p>\n\n<p>p.s. No graph NNs. We though graphs as manually engineered features that the model can infer by itself.</p>",
      "rawMarkdown": "We want to thank Kaggle and CHAMPs for organizing such an awesome competition: \n\n- No leakage.\n- Same distribution in train, private and public test (very stable CV vs. LB, public LB vs. private LB). This is very relevant in other competitions given so many participants when the 3 distributions are different some winners (not all, e.g. [CPMP approach to manually align test ~ train in the Microsoft malware comp](https://www.kaggle.com/c/microsoft-malware-prediction/discussion/84069#latest-499864)) are just lucky they fit private test distribution by chance; not the case here. \n- Inspiring and useful science problem hopefully used for good purposes as described in the context (new drugs, etc.).\n\nNeither my teammate @pavelgonchar nor I had any previous domain expertise and we made the decision early on that we would tackle this problem using a very pure deep learning way: letting the model build the features for us, not the other way around (b/c obviously we were at a disadvantage if we tried to become quantum experts in 1 month… hence our team name 🤖Quantum Uncertainty🤖 we didn't know if our yet-to-be-developed approach was going to work).\n\nOur solution had two major parts: 1) the input representation and 2) deep learning architecture.\n\n**Input representation**\n\nThis is in our opinion the key part: we take a molecule and a source atom and move it so the source atom is @ (0,0,0). For each molecule we create N molecule siblings (N being as many source atoms are defined for that molecule), and each molecule sibling is translated so its source is at (0,0,0). \n\nThe `x` (input) are three arrays of dimension 29 (maximum number of atoms): \n\n1) `x,y,z` position of each atom, \n2) `atom type` index (C=0, H=1, etc…)\n3) `j-coupling type` index (1JHC=0,'2JHH=1,etc.)\n\nPadding is done by placing -1 in `atom type` index and `j-coupling type` for molecules which have less than 29 atoms.\n\nThe `y` (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\n\nNote that there is no graph information nor any other manually engineered features.\n\n**Data augmentation**\n\nWe did two types of data augmentation:\n- Rotations: which worked and were useful in our first attempt model: pointnet-based, but proved worthless in the final models (atomic transformer).\n- J-coupling symmetry: as described [in this discussion](https://www.kaggle.com/c/champs-scalar-coupling/discussion/94706#latest-563148)\n\n**First attempt: Pointnet-inspired architecture (got up to -2.28200 LB)**\n\nOur input representation is basically a point cloud: an unordered set of elements with absolute positions `x,y,z` and two attributes `atom type` and `j-coupling type`. We modified the [Pointnet](https://arxiv.org/abs/1612.00593) architecture to regress j-couplings. Training was a bit unstable and we tried many variations of the architecture, swapping FC layers by linear (fixed) projections (Hadamard), adding coulomb matrix as input, etc. \n\nWhile this worked OK and got us to -2.28200 LB (ensembling a few models) we felt that this architecture was limited by the extreme pooling/bottleneck operation so we decided to explore other architectures: meet the Atomic Transformer.\n\n**Final architecture: meet the Atomic Transformer**\n\nYou may know that the recent NLP revolution is mostly due to the transformer architecture described in the [Attention is all you need paper](https://arxiv.org/abs/1706.03762). The vanilla transformer architecture uses a very clever technique to add positional encodings that are needed for position-dependent input, such as language. \n\nOur input representation is a set, which means we can (and should) remove positional encoding. Prior to this competition we had no experience with transformers either but there's a section in [Lex Fridman MIT podcast interviewing Orion Vinyals](https://www.youtube.com/watch?v=Kedt2or9xlo) where he mentions the inherent position invariance of a barebone transformer encoder layer. This immediately triggered the idea of using transformer layers (encoders) stacked taking as an input `x,y,z` (normalized but otherwise as-is), and `atom type` and `j-coupling type` embeddings; just concatenated… nothing fancy. \n\nThe dimension of the embeddings was such that the total dimension of the input vectors was `d_model` (as normally reference in transformer literature). We started with 256 and got immediately great results surpassing our pointnet-inspired architecture so we followed this path.\n\nWe trained a total of 14 models, with varying dimensions from 512 to 2048 and layers from 6 to 24. Each model parameter size ranged from ~12M to ~100M (biggest model).\n\nWe trained some models from scratch, others we fine-tuned. We also fine-tuned a few models on the troublesome j-couplings: reaching -2.12 CV on 1JHC on and -2.19 CV on 1JHN.\n\nOur best score is an ensemble of 14 models achieving private LB of -3.22349, and our best single model achieved private LB of -3.16234, again just with `x,y,z`, `atom type` and `j-coupling type` inputs (no QM9, etc.).\n\n**What didn't work**\n\nMany things! We tried:\n\n- Multi-task learning using contributions and other organization provided values.\n- Dropout: We tried multiple attempts to add dropout at various stages (embeddings, encoder layers, pre-decoder, etc.). None of them worked.\n- Knock-out: We added a variation in which as input we deleted 10% of the input atoms, the idea being that the model would build an internal representation of the missing atoms. Surprisingly this worked in that the model still converged nicely but failed to reduce train ~ val gap.\n- Rotations and TTA in Atomic Transformer: it didn't reduce train ~ val gap and didn't produce meaningful TTA gains.\n- Deep decoder: Our decoder is just a projection of ~ the model dimension to 1 (scalar coupling). We tried adding more expressive power to the decoder but this didn't help.\n- Fp16 training. This worked for models of dimensions 256 but as training evolved gave `NaN`s despite numerous attempts to fix it.\n\n**Source code**\n\nWe will make source code available once we do clean up. It's a single jupyter notebook using FastAI. Be patient.\n\n**Computational resources**\n\nWe had more ideas than computational resources, even if our computational resources were not tiny:\n- 3 x 2080 Ti + 128 Gb RAM + 16c32t processor\n- 2 x 1080 Ti + 64 Gb RAM + 8c16t processor\n- Rented 8+ 2080 Ti + 64 Gb RAM + 16c32t processor (multiple machines rented as needed)\n\n**Final thoughts**\n\nThis was our most fun and hardest competition so far:\n- Challenging problem\n- Most teams in top 5 had domain experts (although we went *domainless* as part of our strategy)\n- Hungry computational resources.\n\nEven if we lost #1 position just a few hours before competition end we feel very excited we were able to achieve such [useful results for the organizers] (https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312). In retrospect we believe a single model of the Atomic Transformer may achieve ever better results with further training.\n\nBest - Pavel &amp; Andres\n\np.s. No graph NNs. We though graphs as manually engineered features that the model can infer by itself.",
      "votes": 176
    },
    {
      "id": 679449,
      "postDate": "2019-11-22T19:36:03.223Z",
      "content": "<p>Hi Andres, very inspired by your approach. Is the notebook available for us to study, could you point me to it?</p>",
      "rawMarkdown": "Hi Andres, very inspired by your approach. Is the notebook available for us to study, could you point me to it?",
      "votes": 3
    },
    {
      "id": 612258,
      "postDate": "2019-08-29T17:23:27.777Z",
      "content": "<p>Very impressive how having machine learning expertise and no domain knowledge can get you a podium, it truely amazes me. Congrats <a href=\"/antorsae\">@antorsae</a> </p>",
      "rawMarkdown": "Very impressive how having machine learning expertise and no domain knowledge can get you a podium, it truely amazes me. Congrats @antorsae ",
      "votes": 3
    },
    {
      "id": 612153,
      "postDate": "2019-08-29T16:13:52.203Z",
      "content": "<p>Thanks, very impressive solution.  In a way my team mates approached the problem in a way similar to yours, by representing every atom position relative to the two atoms for which scaling is computed.  But you way is a bit different as you keep the coordinates, while they worked with distances and angles.  That using coordinates works that well is a bit of  a surprise to me.  If I were the organizers then i would have applied random rotations to the data...  This said, again, congrats on the approach.  I'll need to reread this to full grasp it.  </p>\n\n<p>I forgot the most important: congrats on the end result and the incredible lead during the competition.</p>",
      "rawMarkdown": "Thanks, very impressive solution.  In a way my team mates approached the problem in a way similar to yours, by representing every atom position relative to the two atoms for which scaling is computed.  But you way is a bit different as you keep the coordinates, while they worked with distances and angles.  That using coordinates works that well is a bit of  a surprise to me.  If I were the organizers then i would have applied random rotations to the data...  This said, again, congrats on the approach.  I'll need to reread this to full grasp it.  \n\nI forgot the most important: congrats on the end result and the incredible lead during the competition.",
      "votes": 3,
      "replies": [
        {
          "id": 612189,
          "postDate": "2019-08-29T16:40:23.483Z",
          "content": "<p>And thanks for citing my solution in Malware! ;)</p>",
          "rawMarkdown": "And thanks for citing my solution in Malware! ;)",
          "votes": 2
        },
        {
          "id": 612391,
          "postDate": "2019-08-29T18:59:13.183Z",
          "content": "<p>Yeah! I liked the notion of alining distributions. In the IEEE fraud one I am trying to do the same automatically with deep learning instead of manual alignment. Not proven yet.</p>",
          "rawMarkdown": "Yeah! I liked the notion of alining distributions. In the IEEE fraud one I am trying to do the same automatically with deep learning instead of manual alignment. Not proven yet.",
          "votes": 1
        },
        {
          "id": 614292,
          "postDate": "2019-08-31T10:18:51.947Z",
          "content": "<p>I tried to code it, and it led to a second dataset, but it performed worse than the fully manual one  I guess my pretrained NN (in my brain) worked better ;)</p>",
          "rawMarkdown": "I tried to code it, and it led to a second dataset, but it performed worse than the fully manual one  I guess my pretrained NN (in my brain) worked better ;)"
        }
      ]
    },
    {
      "id": 612260,
      "postDate": "2019-08-29T17:24:17.397Z",
      "content": "<p>I just want to say that your team's work is very impressive, and I certainly look forward to reading the implementation in more detail! For one, we also use transformer architecture, but it was a graph transformer. I think Zico will make a post about it sometime soon.</p>",
      "rawMarkdown": "I just want to say that your team's work is very impressive, and I certainly look forward to reading the implementation in more detail! For one, we also use transformer architecture, but it was a graph transformer. I think Zico will make a post about it sometime soon.",
      "votes": 4,
      "replies": [
        {
          "id": 612435,
          "postDate": "2019-08-29T19:43:37.003Z",
          "content": "<p>Thanks! You made us sweat a lot in the final hours. It was fun tough and we learned a few lessons in those final hours.</p>",
          "rawMarkdown": "Thanks! You made us sweat a lot in the final hours. It was fun tough and we learned a few lessons in those final hours.",
          "votes": 1
        },
        {
          "id": 612470,
          "postDate": "2019-08-29T20:05:57.970Z",
          "content": "<p>On the day before the last day, we were very excited to finally try surpassing you guys! But we were 0.001 short... and couldn't do anything about it until the next day. =)</p>\n\n<p>Since your transformer graph does not satisfy physics requirement of rotation/translation invariance by construction, can you comment on how much data augmentation you need to do to get good result, as well as the extra training resource / compute needed correspondingly? Your single model achieving -3.16 is really quite impressive considering that your architecture does not satisfy physics rules by construction!</p>",
          "rawMarkdown": "On the day before the last day, we were very excited to finally try surpassing you guys! But we were 0.001 short... and couldn't do anything about it until the next day. =)\n\nSince your transformer graph does not satisfy physics requirement of rotation/translation invariance by construction, can you comment on how much data augmentation you need to do to get good result, as well as the extra training resource / compute needed correspondingly? Your single model achieving -3.16 is really quite impressive considering that your architecture does not satisfy physics rules by construction!",
          "votes": 2
        }
      ]
    },
    {
      "id": 685920,
      "postDate": "2019-12-02T14:26:34.703Z",
      "content": "<p>Congrats!</p>",
      "rawMarkdown": "Congrats!",
      "votes": 1
    },
    {
      "id": 662722,
      "postDate": "2019-10-31T22:53:02.790Z",
      "content": "<p>Congratulations! Impressed that not used graph NNs but used transformer based architectures to deal with set, together with the position translation for target atom.</p>",
      "rawMarkdown": "Congratulations! Impressed that not used graph NNs but used transformer based architectures to deal with set, together with the position translation for target atom.",
      "votes": 1
    },
    {
      "id": 644660,
      "postDate": "2019-10-09T06:35:20.663Z",
      "content": "<p>Hi,</p>\n\n<p>Thanks a lot for sharing your solution and code. I was reading your code and I have a question: In your code atom-transfomer-good-norm-pytorch, the result under the line learner.summary() shows two emdedding layers and two dropout layers at the end. Where do they come from? I can't find them in the forward method of your AtomTorchTransformer. I apologize if the question is too detailed and thanks in advance.</p>",
      "rawMarkdown": "Hi,\n\nThanks a lot for sharing your solution and code. I was reading your code and I have a question: In your code atom-transfomer-good-norm-pytorch, the result under the line learner.summary() shows two emdedding layers and two dropout layers at the end. Where do they come from? I can't find them in the forward method of your AtomTorchTransformer. I apologize if the question is too detailed and thanks in advance.",
      "votes": 1,
      "replies": [
        {
          "id": 644889,
          "postDate": "2019-10-09T13:34:21.777Z",
          "content": "<p>Check this code in the <code>AtomTransformer</code>  constructor:</p>\n\n<p><code>\n        n_atom_embedding = d_model//2\n        n_type_embedding = d_model - n_atom_embedding - 3 #- 1 - 1 -1 \n        self.type_embedding = nn.Embedding(len(types)+1,n_type_embedding)\n        self.atom_embedding = nn.Embedding(len(atoms)+1,n_atom_embedding)\n        self.drop_type, self.drop_atom = nn.Dropout(embed_p), nn.Dropout(embed_p)\n</code></p>",
          "rawMarkdown": "Check this code in the `AtomTransformer`  constructor:\n\n```\n        n_atom_embedding = d_model//2\n        n_type_embedding = d_model - n_atom_embedding - 3 #- 1 - 1 -1 \n        self.type_embedding = nn.Embedding(len(types)+1,n_type_embedding)\n        self.atom_embedding = nn.Embedding(len(atoms)+1,n_atom_embedding)\n        self.drop_type, self.drop_atom = nn.Dropout(embed_p), nn.Dropout(embed_p)\n```"
        },
        {
          "id": 645360,
          "postDate": "2019-10-10T03:19:14.207Z",
          "content": "<p>I see. I just want to clarify one thing then. In the learner.summary(), it only shows what layers are in the neural network regardless their order, am I right? Because the order of layers in learner.summary() seems to be different from the forward propagation order in the forward method. And those two embedding layers should show up at the beginning before going to transformer.</p>",
          "rawMarkdown": "I see. I just want to clarify one thing then. In the learner.summary(), it only shows what layers are in the neural network regardless their order, am I right? Because the order of layers in learner.summary() seems to be different from the forward propagation order in the forward method. And those two embedding layers should show up at the beginning before going to transformer."
        },
        {
          "id": 645427,
          "postDate": "2019-10-10T05:53:59.577Z",
          "content": "<p>Correct</p>",
          "rawMarkdown": "Correct"
        },
        {
          "id": 646125,
          "postDate": "2019-10-10T22:09:14.377Z",
          "content": "<p>Thank you very much!</p>",
          "rawMarkdown": "Thank you very much!"
        }
      ]
    },
    {
      "id": 616487,
      "postDate": "2019-09-03T07:10:27.467Z",
      "content": "<p>Congratulations <a href=\"/antorsae\">@antorsae</a> <a href=\"/pavelgonchar\">@pavelgonchar</a> .Thank you for the approach and waiting for the notebook. The one thing that is inspirational for me is that though you don't have any domain expertise, you understand and solve the problem using DeepLearning techniques.</p>",
      "rawMarkdown": "Congratulations @antorsae @pavelgonchar .Thank you for the approach and waiting for the notebook. The one thing that is inspirational for me is that though you don't have any domain expertise, you understand and solve the problem using DeepLearning techniques.",
      "votes": 1
    },
    {
      "id": 615668,
      "postDate": "2019-09-02T08:18:17.627Z",
      "content": "<p>Congratulations, good job</p>",
      "rawMarkdown": "Congratulations, good job",
      "votes": 1
    },
    {
      "id": 615365,
      "postDate": "2019-09-01T20:35:51.600Z",
      "content": "<p>Really looking forward to your solution, especially as a fellow fastai community member.  Your team really inspired us to keep striving in the final weeks of the competition.  Sub -3 didn't feel achievable until we saw you pull it off.</p>",
      "rawMarkdown": "Really looking forward to your solution, especially as a fellow fastai community member.  Your team really inspired us to keep striving in the final weeks of the competition.  Sub -3 didn't feel achievable until we saw you pull it off.",
      "votes": 1
    },
    {
      "id": 613390,
      "postDate": "2019-08-30T13:15:31.037Z",
      "content": "<p>Congratulations, you guys are inspirations. </p>",
      "rawMarkdown": "Congratulations, you guys are inspirations. ",
      "votes": 1
    },
    {
      "id": 613261,
      "postDate": "2019-08-30T11:11:49.883Z",
      "content": "<p>Congrats!!</p>",
      "rawMarkdown": "Congrats!!",
      "votes": 1
    },
    {
      "id": 613184,
      "postDate": "2019-08-30T09:32:05.710Z",
      "content": "<p>amazing work</p>",
      "rawMarkdown": "amazing work",
      "votes": 1
    },
    {
      "id": 612930,
      "postDate": "2019-08-30T05:14:15.730Z",
      "content": "<p>Congrats <a href=\"/antorsae\">@antorsae</a> and thanks for sharing.</p>",
      "rawMarkdown": "Congrats @antorsae and thanks for sharing.",
      "votes": 1
    },
    {
      "id": 612842,
      "postDate": "2019-08-30T03:23:39.580Z",
      "content": "<p>Congratulations! Amazing solutions! :-)</p>",
      "rawMarkdown": "Congratulations! Amazing solutions! :-)",
      "votes": 1
    },
    {
      "id": 612762,
      "postDate": "2019-08-30T01:43:47.027Z",
      "content": "<p>Congratulations! I'm very excited to learn from your solutions.</p>",
      "rawMarkdown": "Congratulations! I'm very excited to learn from your solutions.",
      "votes": 1
    },
    {
      "id": 612517,
      "postDate": "2019-08-29T20:54:15.050Z",
      "content": "<p>I'm just impressed by the way of using xyz coordinates. Need to read more bout Trnasformer Encoders.</p>\n\n<p>Thank you <a href=\"/antorsae\">@antorsae</a> for sharing the solution and congratulation for your creativity!</p>",
      "rawMarkdown": "I'm just impressed by the way of using xyz coordinates. Need to read more bout Trnasformer Encoders.\n\nThank you @antorsae for sharing the solution and congratulation for your creativity!",
      "votes": 1
    },
    {
      "id": 612406,
      "postDate": "2019-08-29T19:14:51.297Z",
      "content": "<p>Thanks for sharing!\nWhen you say \"The y (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\"\nWhich atom index do you place the j-coupling values, as there are two atoms participating in a coupling?</p>",
      "rawMarkdown": "Thanks for sharing!\nWhen you say \"The y (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\"\nWhich atom index do you place the j-coupling values, as there are two atoms participating in a coupling?",
      "votes": 1,
      "replies": [
        {
          "id": 612430,
          "postDate": "2019-08-29T19:39:04.393Z",
          "content": "<p>Say there are N source/reference atoms (<code>atom_index_0</code> in the csv file) for a given molecule. We build N sibling molecules, and for each the GT is the array of 29 atoms (max) where we place valid j-couplings at target (<code>atom_index_1</code> in the csv) indices.</p>",
          "rawMarkdown": "Say there are N source/reference atoms (`atom_index_0` in the csv file) for a given molecule. We build N sibling molecules, and for each the GT is the array of 29 atoms (max) where we place valid j-couplings at target (`atom_index_1` in the csv) indices."
        },
        {
          "id": 612440,
          "postDate": "2019-08-29T19:44:51.760Z",
          "content": "<p>Oh, so each coupling gets its own datapoint? We have one datapoint per molecule, that confused me.</p>",
          "rawMarkdown": "Oh, so each coupling gets its own datapoint? We have one datapoint per molecule, that confused me."
        },
        {
          "id": 612453,
          "postDate": "2019-08-29T19:53:36.653Z",
          "content": "<p>Yes.</p>\n\n<p>We started building a Molecule Transformer which had all couplings in one shot (diff input representation) but stopped it bc we focussed on training the Atomic Transformer instead.</p>",
          "rawMarkdown": "Yes.\n\nWe started building a Molecule Transformer which had all couplings in one shot (diff input representation) but stopped it bc we focussed on training the Atomic Transformer instead."
        }
      ]
    },
    {
      "id": 612252,
      "postDate": "2019-08-29T17:17:01.987Z",
      "content": "<p>I am not sure that I understand your Input representation. Could you give a simply example, say for H2O? Thanks</p>",
      "rawMarkdown": "I am not sure that I understand your Input representation. Could you give a simply example, say for H2O? Thanks",
      "votes": 1
    },
    {
      "id": 612239,
      "postDate": "2019-08-29T17:10:27.217Z",
      "content": "<p>Congrats!! Thank you for sharing. I look forward to seeing your code :D</p>",
      "rawMarkdown": "Congrats!! Thank you for sharing. I look forward to seeing your code :D",
      "votes": 1
    },
    {
      "id": 613298,
      "postDate": "2019-08-30T12:04:02.160Z",
      "content": "<p>Congratulations! You are not using graph NN. Amazing ideas! I think it would be an excellent paper if you wrote it up your ideas. </p>",
      "rawMarkdown": "Congratulations! You are not using graph NN. Amazing ideas! I think it would be an excellent paper if you wrote it up your ideas. ",
      "votes": 2
    },
    {
      "id": 612569,
      "postDate": "2019-08-29T21:36:50.697Z",
      "content": "<p>looking forward to the code! Thanks for sharing</p>",
      "rawMarkdown": "looking forward to the code! Thanks for sharing",
      "votes": 2
    },
    {
      "id": 612501,
      "postDate": "2019-08-29T20:36:44.797Z",
      "content": "<p>Very impressive and the right way to go with AI discovery.  Like the domainless approach!  Congratulations!</p>",
      "rawMarkdown": "Very impressive and the right way to go with AI discovery.  Like the domainless approach!  Congratulations!",
      "votes": 2
    },
    {
      "id": 612474,
      "postDate": "2019-08-29T20:09:03.203Z",
      "content": "<p>Congratulations! Looking forward to exploring your code, I'm very interested in solutions without domain knowledge.\nBtw, I just realized that we are form the same city lol</p>",
      "rawMarkdown": "Congratulations! Looking forward to exploring your code, I'm very interested in solutions without domain knowledge.\nBtw, I just realized that we are form the same city lol",
      "votes": 2
    },
    {
      "id": 612269,
      "postDate": "2019-08-29T17:29:57.993Z",
      "content": "<p>Really impressed to see that you were able to push a pure Tranformer Encoder to such great performances. I tried using a straightforward Transformer model as well on a set of engineered features (no raw coordinates), but wasn't able to get results anywhere near as good as yours. Like you said, I think the key is your input representation creating the N sibling molecules. </p>\n\n<p>Congrats on second place and the beautiful approach.</p>",
      "rawMarkdown": "Really impressed to see that you were able to push a pure Tranformer Encoder to such great performances. I tried using a straightforward Transformer model as well on a set of engineered features (no raw coordinates), but wasn't able to get results anywhere near as good as yours. Like you said, I think the key is your input representation creating the N sibling molecules. \n\nCongrats on second place and the beautiful approach.",
      "votes": 2
    },
    {
      "id": 612172,
      "postDate": "2019-08-29T16:27:23.473Z",
      "content": "<p>Congrats.....\nGreat Work...\nThanks for Sharing...!! <a href=\"/antorsae\">@antorsae</a> </p>",
      "rawMarkdown": "Congrats.....\nGreat Work...\nThanks for Sharing...!! @antorsae "
    },
    {
      "id": 612432,
      "postDate": "2019-08-29T19:40:41.273Z",
      "content": "<p>Great work, looking forward to seeing the notebook</p>",
      "rawMarkdown": "Great work, looking forward to seeing the notebook",
      "votes": 1
    },
    {
      "id": 781190,
      "postDate": "2020-03-21T02:38:02.537Z",
      "content": "<p>I look forward to seeing your code :D, now too</p>",
      "rawMarkdown": "I look forward to seeing your code :D, now too",
      "replies": [
        {
          "id": 823848,
          "postDate": "2020-04-28T00:29:40.910Z",
          "content": "<p>He published his code 8 months ago in <a href=\"https://github.com/antorsae/champs-scalar-coupling\">github</a>.</p>",
          "rawMarkdown": "He published his code 8 months ago in [github](https://github.com/antorsae/champs-scalar-coupling).",
          "votes": 1
        }
      ]
    },
    {
      "id": 718185,
      "postDate": "2020-01-14T06:28:11.320Z",
      "content": "<p>Impressive!</p>",
      "rawMarkdown": "Impressive!"
    },
    {
      "id": 612599,
      "postDate": "2019-08-29T22:17:53.037Z",
      "content": "<p>Awesome. Thanks for sharing. Any estimate as to how much money you guys spent on this?</p>",
      "rawMarkdown": "Awesome. Thanks for sharing. Any estimate as to how much money you guys spent on this?",
      "replies": [
        {
          "id": 614181,
          "postDate": "2019-08-31T07:12:21.793Z",
          "content": "<p>In my case I bought a 3rd 2080 Ti which I will be using more. In renting I spent ~70$ in vast.ai</p>",
          "rawMarkdown": "In my case I bought a 3rd 2080 Ti which I will be using more. In renting I spent ~70$ in vast.ai",
          "votes": 1
        }
      ]
    },
    {
      "id": 618474,
      "postDate": "2019-09-05T08:37:25.403Z",
      "rawMarkdown": "",
      "votes": 1,
      "isDeleted": true
    },
    {
      "id": 618278,
      "postDate": "2019-09-05T04:23:00.593Z",
      "content": "<p>Congratulations and thanks for sharing</p>",
      "rawMarkdown": "Congratulations and thanks for sharing",
      "votes": 1
    },
    {
      "id": 616456,
      "postDate": "2019-09-03T06:33:03.167Z",
      "content": "<p>Congrats and thanks a lot for sharing.</p>",
      "rawMarkdown": "Congrats and thanks a lot for sharing.",
      "votes": 1
    },
    {
      "id": 612986,
      "postDate": "2019-08-30T06:25:48.727Z",
      "content": "<p>Thank you  for sharing!</p>",
      "rawMarkdown": "Thank you  for sharing!",
      "votes": 1
    },
    {
      "id": 612786,
      "postDate": "2019-08-30T02:19:29.727Z",
      "content": "<p>Congratulations! Thanks for sharing!</p>",
      "rawMarkdown": "Congratulations! Thanks for sharing!",
      "votes": 1
    }
  ],
  "comments": [
    {
      "id": 679449,
      "author_name": "whyvr",
      "author_url": "",
      "post_date": "2019-11-22T19:36:03.223000",
      "content": "<p>Hi Andres, very inspired by your approach. Is the notebook available for us to study, could you point me to it?</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 612258,
      "author_name": "Michel ML",
      "author_url": "",
      "post_date": "2019-08-29T17:23:27.777000",
      "content": "<p>Very impressive how having machine learning expertise and no domain knowledge can get you a podium, it truely amazes me. Congrats <a href=\"/antorsae\">@antorsae</a> </p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 612153,
      "author_name": "CPMP",
      "author_url": "",
      "post_date": "2019-08-29T16:13:52.203000",
      "content": "<p>Thanks, very impressive solution.  In a way my team mates approached the problem in a way similar to yours, by representing every atom position relative to the two atoms for which scaling is computed.  But you way is a bit different as you keep the coordinates, while they worked with distances and angles.  That using coordinates works that well is a bit of  a surprise to me.  If I were the organizers then i would have applied random rotations to the data...  This said, again, congrats on the approach.  I'll need to reread this to full grasp it.  </p>\n\n<p>I forgot the most important: congrats on the end result and the incredible lead during the competition.</p>",
      "votes": 3,
      "replies": [
        {
          "id": 612189,
          "author_name": "CPMP",
          "author_url": "",
          "post_date": "2019-08-29T16:40:23.483000",
          "content": "<p>And thanks for citing my solution in Malware! ;)</p>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 612391,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-08-29T18:59:13.183000",
          "content": "<p>Yeah! I liked the notion of alining distributions. In the IEEE fraud one I am trying to do the same automatically with deep learning instead of manual alignment. Not proven yet.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 614292,
          "author_name": "CPMP",
          "author_url": "",
          "post_date": "2019-08-31T10:18:51.947000",
          "content": "<p>I tried to code it, and it led to a second dataset, but it performed worse than the fully manual one  I guess my pretrained NN (in my brain) worked better ;)</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 612260,
      "author_name": "Jonathan Mailoa",
      "author_url": "",
      "post_date": "2019-08-29T17:24:17.397000",
      "content": "<p>I just want to say that your team's work is very impressive, and I certainly look forward to reading the implementation in more detail! For one, we also use transformer architecture, but it was a graph transformer. I think Zico will make a post about it sometime soon.</p>",
      "votes": 4,
      "replies": [
        {
          "id": 612435,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-08-29T19:43:37.003000",
          "content": "<p>Thanks! You made us sweat a lot in the final hours. It was fun tough and we learned a few lessons in those final hours.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 612470,
          "author_name": "Jonathan Mailoa",
          "author_url": "",
          "post_date": "2019-08-29T20:05:57.970000",
          "content": "<p>On the day before the last day, we were very excited to finally try surpassing you guys! But we were 0.001 short... and couldn't do anything about it until the next day. =)</p>\n\n<p>Since your transformer graph does not satisfy physics requirement of rotation/translation invariance by construction, can you comment on how much data augmentation you need to do to get good result, as well as the extra training resource / compute needed correspondingly? Your single model achieving -3.16 is really quite impressive considering that your architecture does not satisfy physics rules by construction!</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 685920,
      "author_name": "Sean McConnell",
      "author_url": "",
      "post_date": "2019-12-02T14:26:34.703000",
      "content": "<p>Congrats!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 662722,
      "author_name": "corochann",
      "author_url": "",
      "post_date": "2019-10-31T22:53:02.790000",
      "content": "<p>Congratulations! Impressed that not used graph NNs but used transformer based architectures to deal with set, together with the position translation for target atom.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 644660,
      "author_name": "Dondon2019",
      "author_url": "",
      "post_date": "2019-10-09T06:35:20.663000",
      "content": "<p>Hi,</p>\n\n<p>Thanks a lot for sharing your solution and code. I was reading your code and I have a question: In your code atom-transfomer-good-norm-pytorch, the result under the line learner.summary() shows two emdedding layers and two dropout layers at the end. Where do they come from? I can't find them in the forward method of your AtomTorchTransformer. I apologize if the question is too detailed and thanks in advance.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 644889,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-10-09T13:34:21.777000",
          "content": "<p>Check this code in the <code>AtomTransformer</code>  constructor:</p>\n\n<p><code>\n        n_atom_embedding = d_model//2\n        n_type_embedding = d_model - n_atom_embedding - 3 #- 1 - 1 -1 \n        self.type_embedding = nn.Embedding(len(types)+1,n_type_embedding)\n        self.atom_embedding = nn.Embedding(len(atoms)+1,n_atom_embedding)\n        self.drop_type, self.drop_atom = nn.Dropout(embed_p), nn.Dropout(embed_p)\n</code></p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 645360,
          "author_name": "Dondon2019",
          "author_url": "",
          "post_date": "2019-10-10T03:19:14.207000",
          "content": "<p>I see. I just want to clarify one thing then. In the learner.summary(), it only shows what layers are in the neural network regardless their order, am I right? Because the order of layers in learner.summary() seems to be different from the forward propagation order in the forward method. And those two embedding layers should show up at the beginning before going to transformer.</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 645427,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-10-10T05:53:59.577000",
          "content": "<p>Correct</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 646125,
          "author_name": "Dondon2019",
          "author_url": "",
          "post_date": "2019-10-10T22:09:14.377000",
          "content": "<p>Thank you very much!</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 616487,
      "author_name": "Deep Chatterjee",
      "author_url": "",
      "post_date": "2019-09-03T07:10:27.467000",
      "content": "<p>Congratulations <a href=\"/antorsae\">@antorsae</a> <a href=\"/pavelgonchar\">@pavelgonchar</a> .Thank you for the approach and waiting for the notebook. The one thing that is inspirational for me is that though you don't have any domain expertise, you understand and solve the problem using DeepLearning techniques.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 615668,
      "author_name": "Sems Kurtoglu",
      "author_url": "",
      "post_date": "2019-09-02T08:18:17.627000",
      "content": "<p>Congratulations, good job</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 615365,
      "author_name": "Even",
      "author_url": "",
      "post_date": "2019-09-01T20:35:51.600000",
      "content": "<p>Really looking forward to your solution, especially as a fellow fastai community member.  Your team really inspired us to keep striving in the final weeks of the competition.  Sub -3 didn't feel achievable until we saw you pull it off.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 613390,
      "author_name": "Pankaj Joshi",
      "author_url": "",
      "post_date": "2019-08-30T13:15:31.037000",
      "content": "<p>Congratulations, you guys are inspirations. </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 613261,
      "author_name": "Murat Sarıbaş",
      "author_url": "",
      "post_date": "2019-08-30T11:11:49.883000",
      "content": "<p>Congrats!!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 613184,
      "author_name": "Xiao-Chuan",
      "author_url": "",
      "post_date": "2019-08-30T09:32:05.710000",
      "content": "<p>amazing work</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612930,
      "author_name": "Joel Hanson",
      "author_url": "",
      "post_date": "2019-08-30T05:14:15.730000",
      "content": "<p>Congrats <a href=\"/antorsae\">@antorsae</a> and thanks for sharing.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612842,
      "author_name": "FGPC",
      "author_url": "",
      "post_date": "2019-08-30T03:23:39.580000",
      "content": "<p>Congratulations! Amazing solutions! :-)</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612762,
      "author_name": "Zhuang Jia",
      "author_url": "",
      "post_date": "2019-08-30T01:43:47.027000",
      "content": "<p>Congratulations! I'm very excited to learn from your solutions.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612517,
      "author_name": "Alexandre Sauvé",
      "author_url": "",
      "post_date": "2019-08-29T20:54:15.050000",
      "content": "<p>I'm just impressed by the way of using xyz coordinates. Need to read more bout Trnasformer Encoders.</p>\n\n<p>Thank you <a href=\"/antorsae\">@antorsae</a> for sharing the solution and congratulation for your creativity!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612406,
      "author_name": "Goran Rakocevic",
      "author_url": "",
      "post_date": "2019-08-29T19:14:51.297000",
      "content": "<p>Thanks for sharing!\nWhen you say \"The y (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\"\nWhich atom index do you place the j-coupling values, as there are two atoms participating in a coupling?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 612430,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-08-29T19:39:04.393000",
          "content": "<p>Say there are N source/reference atoms (<code>atom_index_0</code> in the csv file) for a given molecule. We build N sibling molecules, and for each the GT is the array of 29 atoms (max) where we place valid j-couplings at target (<code>atom_index_1</code> in the csv) indices.</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 612440,
          "author_name": "Goran Rakocevic",
          "author_url": "",
          "post_date": "2019-08-29T19:44:51.760000",
          "content": "<p>Oh, so each coupling gets its own datapoint? We have one datapoint per molecule, that confused me.</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 612453,
          "author_name": "Andrés Miguel Torrubia Sáez",
          "author_url": "",
          "post_date": "2019-08-29T19:53:36.653000",
          "content": "<p>Yes.</p>\n\n<p>We started building a Molecule Transformer which had all couplings in one shot (diff input representation) but stopped it bc we focussed on training the Atomic Transformer instead.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 612252,
      "author_name": "Zhenlan",
      "author_url": "",
      "post_date": "2019-08-29T17:17:01.987000",
      "content": "<p>I am not sure that I understand your Input representation. Could you give a simply example, say for H2O? Thanks</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612239,
      "author_name": "Zhenlan",
      "author_url": "",
      "post_date": "2019-08-29T17:10:27.217000",
      "content": "<p>Congrats!! Thank you for sharing. I look forward to seeing your code :D</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 613298,
      "author_name": "XiaokangWang",
      "author_url": "",
      "post_date": "2019-08-30T12:04:02.160000",
      "content": "<p>Congratulations! You are not using graph NN. Amazing ideas! I think it would be an excellent paper if you wrote it up your ideas. </p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 612569,
      "author_name": "CoreyJamesLevinson",
      "author_url": "",
      "post_date": "2019-08-29T21:36:50.697000",
      "content": "<p>looking forward to the code! Thanks for sharing</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 612501,
      "author_name": "Patrick Chan",
      "author_url": "",
      "post_date": "2019-08-29T20:36:44.797000",
      "content": "<p>Very impressive and the right way to go with AI discovery.  Like the domainless approach!  Congratulations!</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 612474,
      "author_name": "guiferviz",
      "author_url": "",
      "post_date": "2019-08-29T20:09:03.203000",
      "content": "<p>Congratulations! Looking forward to exploring your code, I'm very interested in solutions without domain knowledge.\nBtw, I just realized that we are form the same city lol</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 612269,
      "author_name": "Robin N",
      "author_url": "",
      "post_date": "2019-08-29T17:29:57.993000",
      "content": "<p>Really impressed to see that you were able to push a pure Tranformer Encoder to such great performances. I tried using a straightforward Transformer model as well on a set of engineered features (no raw coordinates), but wasn't able to get results anywhere near as good as yours. Like you said, I think the key is your input representation creating the N sibling molecules. </p>\n\n<p>Congrats on second place and the beautiful approach.</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 612172,
      "author_name": "Ailurophile",
      "author_url": "",
      "post_date": "2019-08-29T16:27:23.473000",
      "content": "<p>Congrats.....\nGreat Work...\nThanks for Sharing...!! <a href=\"/antorsae\">@antorsae</a> </p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 612432,
      "author_name": "JM",
      "author_url": "",
      "post_date": "2019-08-29T19:40:41.273000",
      "content": "<p>Great work, looking forward to seeing the notebook</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 781190,
      "author_name": "yuquan.li",
      "author_url": "",
      "post_date": "2020-03-21T02:38:02.537000",
      "content": "<p>I look forward to seeing your code :D, now too</p>",
      "votes": 0,
      "replies": [
        {
          "id": 823848,
          "author_name": "XiaokangWang",
          "author_url": "",
          "post_date": "2020-04-28T00:29:40.910000",
          "content": "<p>He published his code 8 months ago in <a href=\"https://github.com/antorsae/champs-scalar-coupling\">github</a>.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 718185,
      "author_name": "Alberto Rekena",
      "author_url": "",
      "post_date": "2020-01-14T06:28:11.320000",
      "content": "<p>Impressive!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 612599,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-08-29T22:17:53.037000",
      "content": "",
      "votes": 0,
      "replies": [
        {
          "id": 614181,
          "author_name": "",
          "author_url": "",
          "post_date": "2019-08-31T07:12:21.793000",
          "content": "",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 618474,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-09-05T08:37:25.403000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 618278,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-09-05T04:23:00.593000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 616456,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-09-03T06:33:03.167000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612986,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-08-30T06:25:48.727000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 612786,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-08-30T02:19:29.727000",
      "content": "",
      "votes": 1,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "612141": "We want to thank Kaggle and CHAMPs for organizing such an awesome competition: \n\n- No leakage.\n- Same distribution in train, private and public test (very stable CV vs. LB, public LB vs. private LB). This is very relevant in other competitions given so many participants when the 3 distributions are different some winners (not all, e.g. [CPMP approach to manually align test ~ train in the Microsoft malware comp](https://www.kaggle.com/c/microsoft-malware-prediction/discussion/84069#latest-499864)) are just lucky they fit private test distribution by chance; not the case here. \n- Inspiring and useful science problem hopefully used for good purposes as described in the context (new drugs, etc.).\n\nNeither my teammate @pavelgonchar nor I had any previous domain expertise and we made the decision early on that we would tackle this problem using a very pure deep learning way: letting the model build the features for us, not the other way around (b/c obviously we were at a disadvantage if we tried to become quantum experts in 1 month… hence our team name 🤖Quantum Uncertainty🤖 we didn't know if our yet-to-be-developed approach was going to work).\n\nOur solution had two major parts: 1) the input representation and 2) deep learning architecture.\n\n**Input representation**\n\nThis is in our opinion the key part: we take a molecule and a source atom and move it so the source atom is @ (0,0,0). For each molecule we create N molecule siblings (N being as many source atoms are defined for that molecule), and each molecule sibling is translated so its source is at (0,0,0). \n\nThe `x` (input) are three arrays of dimension 29 (maximum number of atoms): \n\n1) `x,y,z` position of each atom, \n2) `atom type` index (C=0, H=1, etc…)\n3) `j-coupling type` index (1JHC=0,'2JHH=1,etc.)\n\nPadding is done by placing -1 in `atom type` index and `j-coupling type` for molecules which have less than 29 atoms.\n\nThe `y` (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\n\nNote that there is no graph information nor any other manually engineered features.\n\n**Data augmentation**\n\nWe did two types of data augmentation:\n- Rotations: which worked and were useful in our first attempt model: pointnet-based, but proved worthless in the final models (atomic transformer).\n- J-coupling symmetry: as described [in this discussion](https://www.kaggle.com/c/champs-scalar-coupling/discussion/94706#latest-563148)\n\n**First attempt: Pointnet-inspired architecture (got up to -2.28200 LB)**\n\nOur input representation is basically a point cloud: an unordered set of elements with absolute positions `x,y,z` and two attributes `atom type` and `j-coupling type`. We modified the [Pointnet](https://arxiv.org/abs/1612.00593) architecture to regress j-couplings. Training was a bit unstable and we tried many variations of the architecture, swapping FC layers by linear (fixed) projections (Hadamard), adding coulomb matrix as input, etc. \n\nWhile this worked OK and got us to -2.28200 LB (ensembling a few models) we felt that this architecture was limited by the extreme pooling/bottleneck operation so we decided to explore other architectures: meet the Atomic Transformer.\n\n**Final architecture: meet the Atomic Transformer**\n\nYou may know that the recent NLP revolution is mostly due to the transformer architecture described in the [Attention is all you need paper](https://arxiv.org/abs/1706.03762). The vanilla transformer architecture uses a very clever technique to add positional encodings that are needed for position-dependent input, such as language. \n\nOur input representation is a set, which means we can (and should) remove positional encoding. Prior to this competition we had no experience with transformers either but there's a section in [Lex Fridman MIT podcast interviewing Orion Vinyals](https://www.youtube.com/watch?v=Kedt2or9xlo) where he mentions the inherent position invariance of a barebone transformer encoder layer. This immediately triggered the idea of using transformer layers (encoders) stacked taking as an input `x,y,z` (normalized but otherwise as-is), and `atom type` and `j-coupling type` embeddings; just concatenated… nothing fancy. \n\nThe dimension of the embeddings was such that the total dimension of the input vectors was `d_model` (as normally reference in transformer literature). We started with 256 and got immediately great results surpassing our pointnet-inspired architecture so we followed this path.\n\nWe trained a total of 14 models, with varying dimensions from 512 to 2048 and layers from 6 to 24. Each model parameter size ranged from ~12M to ~100M (biggest model).\n\nWe trained some models from scratch, others we fine-tuned. We also fine-tuned a few models on the troublesome j-couplings: reaching -2.12 CV on 1JHC on and -2.19 CV on 1JHN.\n\nOur best score is an ensemble of 14 models achieving private LB of -3.22349, and our best single model achieved private LB of -3.16234, again just with `x,y,z`, `atom type` and `j-coupling type` inputs (no QM9, etc.).\n\n**What didn't work**\n\nMany things! We tried:\n\n- Multi-task learning using contributions and other organization provided values.\n- Dropout: We tried multiple attempts to add dropout at various stages (embeddings, encoder layers, pre-decoder, etc.). None of them worked.\n- Knock-out: We added a variation in which as input we deleted 10% of the input atoms, the idea being that the model would build an internal representation of the missing atoms. Surprisingly this worked in that the model still converged nicely but failed to reduce train ~ val gap.\n- Rotations and TTA in Atomic Transformer: it didn't reduce train ~ val gap and didn't produce meaningful TTA gains.\n- Deep decoder: Our decoder is just a projection of ~ the model dimension to 1 (scalar coupling). We tried adding more expressive power to the decoder but this didn't help.\n- Fp16 training. This worked for models of dimensions 256 but as training evolved gave `NaN`s despite numerous attempts to fix it.\n\n**Source code**\n\nWe will make source code available once we do clean up. It's a single jupyter notebook using FastAI. Be patient.\n\n**Computational resources**\n\nWe had more ideas than computational resources, even if our computational resources were not tiny:\n- 3 x 2080 Ti + 128 Gb RAM + 16c32t processor\n- 2 x 1080 Ti + 64 Gb RAM + 8c16t processor\n- Rented 8+ 2080 Ti + 64 Gb RAM + 16c32t processor (multiple machines rented as needed)\n\n**Final thoughts**\n\nThis was our most fun and hardest competition so far:\n- Challenging problem\n- Most teams in top 5 had domain experts (although we went *domainless* as part of our strategy)\n- Hungry computational resources.\n\nEven if we lost #1 position just a few hours before competition end we feel very excited we were able to achieve such [useful results for the organizers] (https://www.kaggle.com/c/champs-scalar-coupling/discussion/98375#latest-569312). In retrospect we believe a single model of the Atomic Transformer may achieve ever better results with further training.\n\nBest - Pavel &amp; Andres\n\np.s. No graph NNs. We though graphs as manually engineered features that the model can infer by itself.",
    "679449": "Hi Andres, very inspired by your approach. Is the notebook available for us to study, could you point me to it?",
    "612258": "Very impressive how having machine learning expertise and no domain knowledge can get you a podium, it truely amazes me. Congrats @antorsae ",
    "612153": "Thanks, very impressive solution.  In a way my team mates approached the problem in a way similar to yours, by representing every atom position relative to the two atoms for which scaling is computed.  But you way is a bit different as you keep the coordinates, while they worked with distances and angles.  That using coordinates works that well is a bit of  a surprise to me.  If I were the organizers then i would have applied random rotations to the data...  This said, again, congrats on the approach.  I'll need to reread this to full grasp it.  \n\nI forgot the most important: congrats on the end result and the incredible lead during the competition.",
    "612260": "I just want to say that your team's work is very impressive, and I certainly look forward to reading the implementation in more detail! For one, we also use transformer architecture, but it was a graph transformer. I think Zico will make a post about it sometime soon.",
    "685920": "Congrats!",
    "662722": "Congratulations! Impressed that not used graph NNs but used transformer based architectures to deal with set, together with the position translation for target atom.",
    "644660": "Hi,\n\nThanks a lot for sharing your solution and code. I was reading your code and I have a question: In your code atom-transfomer-good-norm-pytorch, the result under the line learner.summary() shows two emdedding layers and two dropout layers at the end. Where do they come from? I can't find them in the forward method of your AtomTorchTransformer. I apologize if the question is too detailed and thanks in advance.",
    "616487": "Congratulations @antorsae @pavelgonchar .Thank you for the approach and waiting for the notebook. The one thing that is inspirational for me is that though you don't have any domain expertise, you understand and solve the problem using DeepLearning techniques.",
    "615668": "Congratulations, good job",
    "615365": "Really looking forward to your solution, especially as a fellow fastai community member.  Your team really inspired us to keep striving in the final weeks of the competition.  Sub -3 didn't feel achievable until we saw you pull it off.",
    "613390": "Congratulations, you guys are inspirations. ",
    "613261": "Congrats!!",
    "613184": "amazing work",
    "612930": "Congrats @antorsae and thanks for sharing.",
    "612842": "Congratulations! Amazing solutions! :-)",
    "612762": "Congratulations! I'm very excited to learn from your solutions.",
    "612517": "I'm just impressed by the way of using xyz coordinates. Need to read more bout Trnasformer Encoders.\n\nThank you @antorsae for sharing the solution and congratulation for your creativity!",
    "612406": "Thanks for sharing!\nWhen you say \"The y (ground truth) is just an array of dimension 29 containing j-couplings located at target atom indices.\"\nWhich atom index do you place the j-coupling values, as there are two atoms participating in a coupling?",
    "612252": "I am not sure that I understand your Input representation. Could you give a simply example, say for H2O? Thanks",
    "612239": "Congrats!! Thank you for sharing. I look forward to seeing your code :D",
    "613298": "Congratulations! You are not using graph NN. Amazing ideas! I think it would be an excellent paper if you wrote it up your ideas. ",
    "612569": "looking forward to the code! Thanks for sharing",
    "612501": "Very impressive and the right way to go with AI discovery.  Like the domainless approach!  Congratulations!",
    "612474": "Congratulations! Looking forward to exploring your code, I'm very interested in solutions without domain knowledge.\nBtw, I just realized that we are form the same city lol",
    "612269": "Really impressed to see that you were able to push a pure Tranformer Encoder to such great performances. I tried using a straightforward Transformer model as well on a set of engineered features (no raw coordinates), but wasn't able to get results anywhere near as good as yours. Like you said, I think the key is your input representation creating the N sibling molecules. \n\nCongrats on second place and the beautiful approach.",
    "612172": "Congrats.....\nGreat Work...\nThanks for Sharing...!! @antorsae ",
    "612432": "Great work, looking forward to seeing the notebook",
    "781190": "I look forward to seeing your code :D, now too",
    "718185": "Impressive!",
    "612599": "Awesome. Thanks for sharing. Any estimate as to how much money you guys spent on this?",
    "618474": "",
    "618278": "Congratulations and thanks for sharing",
    "616456": "Congrats and thanks a lot for sharing.",
    "612986": "Thank you  for sharing!",
    "612786": "Congratulations! Thanks for sharing!"
  },
  "complete": true,
  "source": "existing_discussion",
  "competition_id": 14313,
  "competition_slug": "champs-scalar-coupling",
  "team_id": 3251377,
  "solution_url": "/competitions/champs-scalar-coupling/writeups/quantum-uncertainty-2-solution-quantum-uncertainty"
}