{
  "id": 415372,
  "title": "UPDATED: Almost certainly corner cases in test data - and some hints for solving scoring failures (Tensorflow)",
  "url": "/competitions/asl-fingerspelling/discussion/415372",
  "author_name": "Wondering Alice",
  "post_date": "2023-06-06T08:09:53.589000",
  "votes": 37,
  "comment_count": 5,
  "views": 0,
  "content": "<hr>\n<p><strong>Original post</strong></p>\n<hr>\n<p>I recently managed to get all my pre- and postprocessing through the scoring pipeline (Tensorflow). Although I won't share my code here at this point, I will share a few things, as well as what I have learned from this experience:</p>\n<p>I started from the message by <a href=\"https://www.kaggle.com/mdecoster\" target=\"_blank\">@mdecoster</a> that there were probably empty samples in the test set (or maybe invalid parquet files or entries that result in empty samples). <br>\nThe first step that allowed me to make progress was to add a custom \"CatchEmpty\" layer at the very input of my model (right after the remove nan's line that is also in my dummy submission). This detects empty input samples and replaces them with a single-timestep dummy zeros frame. So the code roughly becomes (<code>loaded_model</code> is the model I trained, saved to disk and reloaded in my TfLite creation notebook, <code>CustomPreprocessing()</code> and <code>CustomPostprocessing()</code> are placeholders for custom layers I wrote):</p>\n<pre><code>    inputs = tf.keras.Input(shape=(NUM_FEATURES,), dtype=tf.float32, name=)\n    x = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n    x = CatchEmpty()(x)                         \n    x = CustomPreprocessing()(x)  \n    x = loaded_model(x)\n    x = CustomPostprocessing()(x)      \n    out = tf.keras.layers.Activation(, name=)(x_out)\n    inference_model = tf.keras.Model(inputs=inputs, outputs=out)\n</code></pre>\n<p>Starting from  the information from <a href=\"https://www.kaggle.com/sohier\" target=\"_blank\">@sohier</a> that many of the submission failures were due to dimension mismatches and from my earlier insight that indeed some dimension mismatches did not cause errors or warnings in my local notebook, I started stepping through each individual line of my pre- and postprocessing code and printing out the tensors and tensor shapes for three situations: <br>\n(1) multiple \"normal\" train set frames as <code>inputs</code> (selected to mimic specific cases)<br>\n(2) a single \"normal\" train set frame as <code>inputs</code>  (selected to mimic specific cases)<br>\n(3) an empty input generated as  <code>tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)</code><br>\n(4) an all-zeros input <code>tf.zeros([1, NUM_FEATURES], dtype = tf.dtypes.float32)</code><br>\nThis led to a number of corrections in my code, again making sure to catch a number of possible very specific situations.</p>\n<p>After making sure in this way that all standard tf functions (as well as my model) received tensors with their expected input shapes, I found that all functions I used in the previous ASL-ISLR competition did in fact work. For example, my current successful code uses things like   <code>where</code>, <code>reduce_sum</code>, <code>not_equal</code>, <code>gather</code>, <code>cond</code>, <code>ones_like</code>, <code>zeros_like</code>, etc.</p>\n<p>Note that this does not guarantee that all functionalities in conversions from PyTorch also work (I'm quite happy with using Tensorflow).</p>\n<hr>\n<p><strong>Update:</strong> </p>\n<hr>\n<p>Out of curiosity I did a few more tests</p>\n<p>(1) removed everything from my <code>CatchEmpty()</code> layer except <code>x = x[None]</code>   -&gt; <strong>PASSED scoring</strong>    (??)<br>\n(2) moved <code>x = x[None]</code>  back to where it originally was -- after  <code>CustomPreprocessing()</code> -- and changed the code in <code>CustomPreprocessing()</code> from working with 3D tensors back to working with 2D tensors (without changing the operators and with careful checking of all dimensions and corner cases)  -&gt; <strong>FAILED scoring</strong>    (??)</p>\n<p>So now I'm not sure anymore that mere empty samples of the form <code>tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)</code> are the corner case that causes the scoring failures. However, <strong>having</strong> <code>x = x[None]</code> <strong>in front seems to be crucial for getting things to work</strong> , but since I'm not sure <strong>exactly</strong> what this does behind the screen, I have no clue what we're dealing with …</p>",
  "messages": [
    {
      "id": 2289537,
      "postDate": "2023-06-06T08:09:53.590Z",
      "content": "<hr>\n<p><strong>Original post</strong></p>\n<hr>\n<p>I recently managed to get all my pre- and postprocessing through the scoring pipeline (Tensorflow). Although I won't share my code here at this point, I will share a few things, as well as what I have learned from this experience:</p>\n<p>I started from the message by <a href=\"https://www.kaggle.com/mdecoster\" target=\"_blank\">@mdecoster</a> that there were probably empty samples in the test set (or maybe invalid parquet files or entries that result in empty samples). <br>\nThe first step that allowed me to make progress was to add a custom \"CatchEmpty\" layer at the very input of my model (right after the remove nan's line that is also in my dummy submission). This detects empty input samples and replaces them with a single-timestep dummy zeros frame. So the code roughly becomes (<code>loaded_model</code> is the model I trained, saved to disk and reloaded in my TfLite creation notebook, <code>CustomPreprocessing()</code> and <code>CustomPostprocessing()</code> are placeholders for custom layers I wrote):</p>\n<pre><code>    inputs = tf.keras.Input(shape=(NUM_FEATURES,), dtype=tf.float32, name=)\n    x = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n    x = CatchEmpty()(x)                         \n    x = CustomPreprocessing()(x)  \n    x = loaded_model(x)\n    x = CustomPostprocessing()(x)      \n    out = tf.keras.layers.Activation(, name=)(x_out)\n    inference_model = tf.keras.Model(inputs=inputs, outputs=out)\n</code></pre>\n<p>Starting from  the information from <a href=\"https://www.kaggle.com/sohier\" target=\"_blank\">@sohier</a> that many of the submission failures were due to dimension mismatches and from my earlier insight that indeed some dimension mismatches did not cause errors or warnings in my local notebook, I started stepping through each individual line of my pre- and postprocessing code and printing out the tensors and tensor shapes for three situations: <br>\n(1) multiple \"normal\" train set frames as <code>inputs</code> (selected to mimic specific cases)<br>\n(2) a single \"normal\" train set frame as <code>inputs</code>  (selected to mimic specific cases)<br>\n(3) an empty input generated as  <code>tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)</code><br>\n(4) an all-zeros input <code>tf.zeros([1, NUM_FEATURES], dtype = tf.dtypes.float32)</code><br>\nThis led to a number of corrections in my code, again making sure to catch a number of possible very specific situations.</p>\n<p>After making sure in this way that all standard tf functions (as well as my model) received tensors with their expected input shapes, I found that all functions I used in the previous ASL-ISLR competition did in fact work. For example, my current successful code uses things like   <code>where</code>, <code>reduce_sum</code>, <code>not_equal</code>, <code>gather</code>, <code>cond</code>, <code>ones_like</code>, <code>zeros_like</code>, etc.</p>\n<p>Note that this does not guarantee that all functionalities in conversions from PyTorch also work (I'm quite happy with using Tensorflow).</p>\n<hr>\n<p><strong>Update:</strong> </p>\n<hr>\n<p>Out of curiosity I did a few more tests</p>\n<p>(1) removed everything from my <code>CatchEmpty()</code> layer except <code>x = x[None]</code>   -&gt; <strong>PASSED scoring</strong>    (??)<br>\n(2) moved <code>x = x[None]</code>  back to where it originally was -- after  <code>CustomPreprocessing()</code> -- and changed the code in <code>CustomPreprocessing()</code> from working with 3D tensors back to working with 2D tensors (without changing the operators and with careful checking of all dimensions and corner cases)  -&gt; <strong>FAILED scoring</strong>    (??)</p>\n<p>So now I'm not sure anymore that mere empty samples of the form <code>tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)</code> are the corner case that causes the scoring failures. However, <strong>having</strong> <code>x = x[None]</code> <strong>in front seems to be crucial for getting things to work</strong> , but since I'm not sure <strong>exactly</strong> what this does behind the screen, I have no clue what we're dealing with …</p>",
      "rawMarkdown": "---------------------------------------\n**Original post**\n\n---------------------------------------\n\nI recently managed to get all my pre- and postprocessing through the scoring pipeline (Tensorflow). Although I won't share my code here at this point, I will share a few things, as well as what I have learned from this experience:\n\nI started from the message by @mdecoster that there were probably empty samples in the test set (or maybe invalid parquet files or entries that result in empty samples). \nThe first step that allowed me to make progress was to add a custom \"CatchEmpty\" layer at the very input of my model (right after the remove nan's line that is also in my dummy submission). This detects empty input samples and replaces them with a single-timestep dummy zeros frame. So the code roughly becomes (```loaded_model``` is the model I trained, saved to disk and reloaded in my TfLite creation notebook, ```CustomPreprocessing()``` and ```CustomPostprocessing()``` are placeholders for custom layers I wrote):\n\n``` python\n    inputs = tf.keras.Input(shape=(NUM_FEATURES,), dtype=tf.float32, name=\"inputs\")\n    x = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n    x = CatchEmpty()(x)                         # this layer starts with the dimension extension x=x[None] \n    x = CustomPreprocessing()(x)  \n    x = loaded_model(x)\n    x = CustomPostprocessing()(x)      # this also contains the dimension reduction x=x[0,:,:] \n    out = tf.keras.layers.Activation(\"linear\", name=\"outputs\")(x_out)\n    inference_model = tf.keras.Model(inputs=inputs, outputs=out)\n```\n\nStarting from  the information from @sohier that many of the submission failures were due to dimension mismatches and from my earlier insight that indeed some dimension mismatches did not cause errors or warnings in my local notebook, I started stepping through each individual line of my pre- and postprocessing code and printing out the tensors and tensor shapes for three situations: \n(1) multiple \"normal\" train set frames as ```inputs``` (selected to mimic specific cases)\n(2) a single \"normal\" train set frame as ```inputs```  (selected to mimic specific cases)\n(3) an empty input generated as  ```tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)```\n(4) an all-zeros input ```tf.zeros([1, NUM_FEATURES], dtype = tf.dtypes.float32)```\nThis led to a number of corrections in my code, again making sure to catch a number of possible very specific situations.\n\nAfter making sure in this way that all standard tf functions (as well as my model) received tensors with their expected input shapes, I found that all functions I used in the previous ASL-ISLR competition did in fact work. For example, my current successful code uses things like   ```where```, ```reduce_sum```, ```not_equal```, ```gather```, ```cond```, ```ones_like```, ```zeros_like```, etc.\n\nNote that this does not guarantee that all functionalities in conversions from PyTorch also work (I'm quite happy with using Tensorflow).\n\n---------------------------------------\n**Update:** \n\n---------------------------------------\n\nOut of curiosity I did a few more tests\n\n(1) removed everything from my ```CatchEmpty()``` layer except ```x = x[None]```   -> **PASSED scoring**    (??)\n(2) moved ```x = x[None]```  back to where it originally was -- after  ```CustomPreprocessing()``` -- and changed the code in ```CustomPreprocessing()``` from working with 3D tensors back to working with 2D tensors (without changing the operators and with careful checking of all dimensions and corner cases)  -> **FAILED scoring**    (??)\n\nSo now I'm not sure anymore that mere empty samples of the form ```tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)``` are the corner case that causes the scoring failures. However, **having** ```x = x[None]``` **in front seems to be crucial for getting things to work** , but since I'm not sure **exactly** what this does behind the screen, I have no clue what we're dealing with ...\n",
      "votes": 37
    },
    {
      "id": 2290730,
      "postDate": "2023-06-07T04:22:00.513Z",
      "content": "<p>Thank you. I successfully made preprocessing into submission. x = x[None] at the starting of preprocessing certainly worked.</p>",
      "rawMarkdown": "Thank you. I successfully made preprocessing into submission. x = x[None] at the starting of preprocessing certainly worked.",
      "votes": 4
    },
    {
      "id": 2311786,
      "postDate": "2023-06-21T13:01:28.060Z",
      "content": "<p>I just changed my preprocessing function. The old version didn't include any indexing operations, and <code>x=x[None]</code>was placed after this.</p>\n<p>Now, I have added some index operations, and they cause an error. However, placing <code>x=x[None]</code> before these operations helped.</p>\n<p>I believe the main issue lies in the indexing operations.</p>\n<p>I am thankful for this post as a reminder. I think this post should be pinned.</p>",
      "rawMarkdown": "I just changed my preprocessing function. The old version didn't include any indexing operations, and `x=x[None] `was placed after this.\n\nNow, I have added some index operations, and they cause an error. However, placing `x=x[None]` before these operations helped.\n\nI believe the main issue lies in the indexing operations.\n\nI am thankful for this post as a reminder. I think this post should be pinned.",
      "votes": 1
    },
    {
      "id": 2292716,
      "postDate": "2023-06-08T15:38:54.027Z",
      "content": "<p>I couldn't help but applaud when I saw that the scoring process started and didn't fail even after three minutes.</p>",
      "rawMarkdown": "I couldn't help but applaud when I saw that the scoring process started and didn't fail even after three minutes.",
      "votes": 1
    },
    {
      "id": 2291098,
      "postDate": "2023-06-07T10:22:36.143Z",
      "content": "<p>Thanks! This is really good investigative work. Will give it a try :)</p>\n<p>EDIT: It worked! My model was failing on empty inputs - once this was fixed, and after a few attempts to work around bugs in the TFLite converter, I was able to get it working. Thanks a lot!</p>",
      "rawMarkdown": "Thanks! This is really good investigative work. Will give it a try :)\n\nEDIT: It worked! My model was failing on empty inputs - once this was fixed, and after a few attempts to work around bugs in the TFLite converter, I was able to get it working. Thanks a lot!",
      "votes": 2
    },
    {
      "id": 2313976,
      "postDate": "2023-06-23T05:07:12.457Z",
      "content": "<p>Thanks for your sharing, it help me a lot!</p>",
      "rawMarkdown": "Thanks for your sharing, it help me a lot!"
    }
  ],
  "comments": [
    {
      "id": 2290730,
      "author_name": "Rohith Ingilela",
      "author_url": "",
      "post_date": "2023-06-07T04:22:00.513000",
      "content": "<p>Thank you. I successfully made preprocessing into submission. x = x[None] at the starting of preprocessing certainly worked.</p>",
      "votes": 4,
      "replies": []
    },
    {
      "id": 2311786,
      "author_name": "Kolya Forrat",
      "author_url": "",
      "post_date": "2023-06-21T13:01:28.060000",
      "content": "<p>I just changed my preprocessing function. The old version didn't include any indexing operations, and <code>x=x[None]</code>was placed after this.</p>\n<p>Now, I have added some index operations, and they cause an error. However, placing <code>x=x[None]</code> before these operations helped.</p>\n<p>I believe the main issue lies in the indexing operations.</p>\n<p>I am thankful for this post as a reminder. I think this post should be pinned.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 2292716,
      "author_name": "canlion",
      "author_url": "",
      "post_date": "2023-06-08T15:38:54.027000",
      "content": "<p>I couldn't help but applaud when I saw that the scoring process started and didn't fail even after three minutes.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 2291098,
      "author_name": "anokas",
      "author_url": "",
      "post_date": "2023-06-07T10:22:36.143000",
      "content": "<p>Thanks! This is really good investigative work. Will give it a try :)</p>\n<p>EDIT: It worked! My model was failing on empty inputs - once this was fixed, and after a few attempts to work around bugs in the TFLite converter, I was able to get it working. Thanks a lot!</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 2313976,
      "author_name": "treeleaves30760",
      "author_url": "",
      "post_date": "2023-06-23T05:07:12.457000",
      "content": "<p>Thanks for your sharing, it help me a lot!</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "2289537": "---------------------------------------\n**Original post**\n\n---------------------------------------\n\nI recently managed to get all my pre- and postprocessing through the scoring pipeline (Tensorflow). Although I won't share my code here at this point, I will share a few things, as well as what I have learned from this experience:\n\nI started from the message by @mdecoster that there were probably empty samples in the test set (or maybe invalid parquet files or entries that result in empty samples). \nThe first step that allowed me to make progress was to add a custom \"CatchEmpty\" layer at the very input of my model (right after the remove nan's line that is also in my dummy submission). This detects empty input samples and replaces them with a single-timestep dummy zeros frame. So the code roughly becomes (```loaded_model``` is the model I trained, saved to disk and reloaded in my TfLite creation notebook, ```CustomPreprocessing()``` and ```CustomPostprocessing()``` are placeholders for custom layers I wrote):\n\n``` python\n    inputs = tf.keras.Input(shape=(NUM_FEATURES,), dtype=tf.float32, name=\"inputs\")\n    x = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n    x = CatchEmpty()(x)                         # this layer starts with the dimension extension x=x[None] \n    x = CustomPreprocessing()(x)  \n    x = loaded_model(x)\n    x = CustomPostprocessing()(x)      # this also contains the dimension reduction x=x[0,:,:] \n    out = tf.keras.layers.Activation(\"linear\", name=\"outputs\")(x_out)\n    inference_model = tf.keras.Model(inputs=inputs, outputs=out)\n```\n\nStarting from  the information from @sohier that many of the submission failures were due to dimension mismatches and from my earlier insight that indeed some dimension mismatches did not cause errors or warnings in my local notebook, I started stepping through each individual line of my pre- and postprocessing code and printing out the tensors and tensor shapes for three situations: \n(1) multiple \"normal\" train set frames as ```inputs``` (selected to mimic specific cases)\n(2) a single \"normal\" train set frame as ```inputs```  (selected to mimic specific cases)\n(3) an empty input generated as  ```tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)```\n(4) an all-zeros input ```tf.zeros([1, NUM_FEATURES], dtype = tf.dtypes.float32)```\nThis led to a number of corrections in my code, again making sure to catch a number of possible very specific situations.\n\nAfter making sure in this way that all standard tf functions (as well as my model) received tensors with their expected input shapes, I found that all functions I used in the previous ASL-ISLR competition did in fact work. For example, my current successful code uses things like   ```where```, ```reduce_sum```, ```not_equal```, ```gather```, ```cond```, ```ones_like```, ```zeros_like```, etc.\n\nNote that this does not guarantee that all functionalities in conversions from PyTorch also work (I'm quite happy with using Tensorflow).\n\n---------------------------------------\n**Update:** \n\n---------------------------------------\n\nOut of curiosity I did a few more tests\n\n(1) removed everything from my ```CatchEmpty()``` layer except ```x = x[None]```   -> **PASSED scoring**    (??)\n(2) moved ```x = x[None]```  back to where it originally was -- after  ```CustomPreprocessing()``` -- and changed the code in ```CustomPreprocessing()``` from working with 3D tensors back to working with 2D tensors (without changing the operators and with careful checking of all dimensions and corner cases)  -> **FAILED scoring**    (??)\n\nSo now I'm not sure anymore that mere empty samples of the form ```tf.zeros([0, NUM_FEATURES], dtype = tf.dtypes.float32)``` are the corner case that causes the scoring failures. However, **having** ```x = x[None]``` **in front seems to be crucial for getting things to work** , but since I'm not sure **exactly** what this does behind the screen, I have no clue what we're dealing with ...\n",
    "2290730": "Thank you. I successfully made preprocessing into submission. x = x[None] at the starting of preprocessing certainly worked.",
    "2311786": "I just changed my preprocessing function. The old version didn't include any indexing operations, and `x=x[None] `was placed after this.\n\nNow, I have added some index operations, and they cause an error. However, placing `x=x[None]` before these operations helped.\n\nI believe the main issue lies in the indexing operations.\n\nI am thankful for this post as a reminder. I think this post should be pinned.",
    "2292716": "I couldn't help but applaud when I saw that the scoring process started and didn't fail even after three minutes.",
    "2291098": "Thanks! This is really good investigative work. Will give it a try :)\n\nEDIT: It worked! My model was failing on empty inputs - once this was fixed, and after a few attempts to work around bugs in the TFLite converter, I was able to get it working. Thanks a lot!",
    "2313976": "Thanks for your sharing, it help me a lot!"
  }
}