{
  "id": 66260,
  "title": "How are you dealing with high cardinality?",
  "url": "/competitions/ga-customer-revenue-prediction/discussion/66260",
  "author_name": "CoreyJamesLevinson",
  "post_date": "2018-09-19T18:29:36.805000",
  "votes": 16,
  "comment_count": 17,
  "views": 0,
  "content": "<p>There are many categorical columns in this dataset where the cardinality is extremely high. Because of this, if you are one-hot encoding, you create a surplus of columns. Also, there are a lot of unique categories in the test set that are not seen in the training set.</p>\n\n<p>How are you dealing with columns like <code>geoNetwork.city</code>, <code>geoNetwork.country</code>, <code>geoNetwork.metro</code>, <code>trafficSource.adContent</code>, <code>trafficSource.keyword</code>, etc.</p>",
  "messages": [
    {
      "id": 390576,
      "postDate": "2018-09-20T13:07:43.277Z",
      "content": "<p>Here are a range of options:</p>\n\n<p><strong>Easy, but probably not great</strong>:</p>\n\n<ul>\n<li>One-hot-encoding</li>\n<li>Simple label-encoding, treat column as numerical</li>\n</ul>\n\n<p><strong>Pretty easy, possibly better</strong>:</p>\n\n<ul>\n<li>Frequency encoding: map categories to their count of occurrence, treat column as numerical. In theory this should be strictly better than label-encoding, as it allows categories to still be split based on their specific values, but conveys some information about inter-category relationships (frequency differences) that may provide signal. </li>\n<li>Assuming tree-methods (e.g. lgb), use a category partitioning method. In the case of lgb, this means using label encoding in conjunction with lgb's <code>categorical_feature</code> setting, explained here: <a href=\"https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html\">https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html</a>. This may take some hyperparameter tuning to work well.</li>\n</ul>\n\n<p><strong>Some more effort, but possibly more effective</strong>:</p>\n\n<ul>\n<li><p>OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality.</p></li>\n<li><p>Target encoding: described in early posts (replace categories with mean value of target for that category). Can be tricky to use without overfitting (make sure to generate target-encoded values out-of-sample).</p></li>\n<li><p>Engineer numerical features that are sufficient for capturing the signal conveyed by a categorical feature, then exclude the original categorical feature. This is conceptually similar to frequency/target encoding, where you're summarizing category information via some numeric quantity. For example, maybe the mean page-views per day of the month would be a reasonable substitute for a day of the month categorical feature.</p></li>\n</ul>\n\n<p><strong>Harder, more experimental</strong>:</p>\n\n<ul>\n<li>Replace category columns with dense embeddings learned from a neural network.</li>\n</ul>",
      "rawMarkdown": "Here are a range of options:\n\n**Easy, but probably not great**:\n\n - One-hot-encoding\n - Simple label-encoding, treat column as numerical\n\n**Pretty easy, possibly better**:\n\n - Frequency encoding: map categories to their count of occurrence, treat column as numerical. In theory this should be strictly better than label-encoding, as it allows categories to still be split based on their specific values, but conveys some information about inter-category relationships (frequency differences) that may provide signal. \n - Assuming tree-methods (e.g. lgb), use a category partitioning method. In the case of lgb, this means using label encoding in conjunction with lgb's `categorical_feature` setting, explained here: https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html. This may take some hyperparameter tuning to work well.\n\n**Some more effort, but possibly more effective**:\n\n - OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality.\n\n - Target encoding: described in early posts (replace categories with mean value of target for that category). Can be tricky to use without overfitting (make sure to generate target-encoded values out-of-sample).\n\n - Engineer numerical features that are sufficient for capturing the signal conveyed by a categorical feature, then exclude the original categorical feature. This is conceptually similar to frequency/target encoding, where you're summarizing category information via some numeric quantity. For example, maybe the mean page-views per day of the month would be a reasonable substitute for a day of the month categorical feature.\n\n\n \n\n**Harder, more experimental**:\n\n - Replace category columns with dense embeddings learned from a neural network.",
      "votes": 35,
      "replies": [
        {
          "id": 390734,
          "postDate": "2018-09-20T18:36:25.867Z",
          "content": "<p>Nice overview, thanks!</p>\n\n<p>I'll add feature hashing (aka 'the hashing trick') to that list.</p>",
          "rawMarkdown": "Nice overview, thanks!\n\nI'll add feature hashing (aka 'the hashing trick') to that list."
        }
      ]
    },
    {
      "id": 390113,
      "postDate": "2018-09-19T18:29:36.807Z",
      "content": "<p>There are many categorical columns in this dataset where the cardinality is extremely high. Because of this, if you are one-hot encoding, you create a surplus of columns. Also, there are a lot of unique categories in the test set that are not seen in the training set.</p>\n\n<p>How are you dealing with columns like <code>geoNetwork.city</code>, <code>geoNetwork.country</code>, <code>geoNetwork.metro</code>, <code>trafficSource.adContent</code>, <code>trafficSource.keyword</code>, etc.</p>",
      "rawMarkdown": "There are many categorical columns in this dataset where the cardinality is extremely high. Because of this, if you are one-hot encoding, you create a surplus of columns. Also, there are a lot of unique categories in the test set that are not seen in the training set.\n\nHow are you dealing with columns like `geoNetwork.city`, `geoNetwork.country`, `geoNetwork.metro`, `trafficSource.adContent`, `trafficSource.keyword`, etc.",
      "votes": 16
    },
    {
      "id": 393476,
      "postDate": "2018-09-25T12:51:26.953Z",
      "content": "<p>There was already a nice summary by <a href=\"/aquatic\">@aquatic</a>. Just to add my 5 cents: </p>\n\n<ul>\n<li>an example of several target-encoding implementations (some of which already include regularisation to avoid data leaks): <a href=\"https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated\">https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated</a>;</li>\n<li>Catboost is your friend, when it comes to categorical features, as it implements several schemes for categorical encoding with minimised/eliminated(?) data leakage;</li>\n<li>I personally reduce cardinality simply by identifying all classes within a categorical, that appear with frequency below 0.1% (guesstimated number).  In practice I merge them into a new class within category.This allows to reduce cardinality down to ~20 per each category (note that this removes somes info, that is there)</li>\n</ul>",
      "rawMarkdown": "There was already a nice summary by @aquatic. Just to add my 5 cents: \n\n- an example of several target-encoding implementations (some of which already include regularisation to avoid data leaks): https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated;\n- Catboost is your friend, when it comes to categorical features, as it implements several schemes for categorical encoding with minimised/eliminated(?) data leakage;\n- I personally reduce cardinality simply by identifying all classes within a categorical, that appear with frequency below 0.1% (guesstimated number).  In practice I merge them into a new class within category.This allows to reduce cardinality down to ~20 per each category (note that this removes somes info, that is there)",
      "votes": 5
    },
    {
      "id": 390324,
      "postDate": "2018-09-20T03:12:02.720Z",
      "content": "<p>Target-mean encoding can be done.  It works better with smaller cardinalities, but my guess is it would be better than just a simple \"factorize\" into numbers transformation.  What it is, you have a categorical column with values a, b, c, ..., z.  You find the mean of the target of all rows where the value is a, and that mean value replaces a.  Similarly for b, c, ..., z.  Optionally factorize the target means to make it ordinal, but I'm not sure that's really better.</p>\n\n<p><a href=\"https://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv\">https://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv</a> (where I learned about it--you can audit the course for free and learn more than this too)</p>\n\n<p><a href=\"http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html\">http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html</a></p>\n\n<p>or google \"target mean encoding\" for more.</p>",
      "rawMarkdown": "Target-mean encoding can be done.  It works better with smaller cardinalities, but my guess is it would be better than just a simple \"factorize\" into numbers transformation.  What it is, you have a categorical column with values a, b, c, ..., z.  You find the mean of the target of all rows where the value is a, and that mean value replaces a.  Similarly for b, c, ..., z.  Optionally factorize the target means to make it ordinal, but I'm not sure that's really better.\n\nhttps://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv (where I learned about it--you can audit the course for free and learn more than this too)\n\nhttp://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html\n\nor google \"target mean encoding\" for more.",
      "votes": 1,
      "replies": [
        {
          "id": 390383,
          "postDate": "2018-09-20T05:41:24.463Z",
          "content": "<p>Check Olivier's kernel <a href=\"https://www.kaggle.com/ogrellier/python-target-encoding-for-categorical-features\">Target encoding</a> and  mine <a href=\"https://www.kaggle.com/alexfir/target-encoding-using-variance\">Target encoding using variance</a>.</p>",
          "rawMarkdown": "Check Olivier's kernel [Target encoding][1] and  mine [Target encoding using variance][2].\n\n\n  [1]: https://www.kaggle.com/ogrellier/python-target-encoding-for-categorical-features\n  [2]: https://www.kaggle.com/alexfir/target-encoding-using-variance",
          "votes": 1
        }
      ]
    },
    {
      "id": 390178,
      "postDate": "2018-09-19T20:25:51.130Z",
      "content": "<p>That's a good question. Using OHE for all columns is a very bad ideia, so one option is using just label encoding with the categorical_features parameter (LightGBM). Another option is using binary encoder and a third is mixing ohe and le (ohe for columns with low cardinality maybe).</p>\n\n<p>For now, I'm using label encoder with the sklearn LabelEncoder, so you can fit all labels from both train and test and them transform. But there are many options for trying.</p>",
      "rawMarkdown": "That's a good question. Using OHE for all columns is a very bad ideia, so one option is using just label encoding with the categorical_features parameter (LightGBM). Another option is using binary encoder and a third is mixing ohe and le (ohe for columns with low cardinality maybe).\n\nFor now, I'm using label encoder with the sklearn LabelEncoder, so you can fit all labels from both train and test and them transform. But there are many options for trying.",
      "votes": 1
    },
    {
      "id": 390124,
      "postDate": "2018-09-19T18:44:36.107Z",
      "content": "<p>Label encoding is quite a good way of dealing with categorical variables if you use tree-based models.</p>",
      "rawMarkdown": "Label encoding is quite a good way of dealing with categorical variables if you use tree-based models.",
      "votes": 1,
      "replies": [
        {
          "id": 390126,
          "postDate": "2018-09-19T18:46:57.037Z",
          "content": "<p>Why? Don't you have worries that the model will think that if <code>Zurich = 2*Chicago</code> then the inferences will be bad?</p>",
          "rawMarkdown": "Why? Don't you have worries that the model will think that if `Zurich = 2*Chicago` then the inferences will be bad?",
          "votes": 1
        },
        {
          "id": 390139,
          "postDate": "2018-09-19T18:59:40.893Z",
          "content": "<p>Sometimes it is okay to use label encoding for tree based models, because they are simply looking for places to split the data, they are not multiplying inputs by weights.</p>",
          "rawMarkdown": "Sometimes it is okay to use label encoding for tree based models, because they are simply looking for places to split the data, they are not multiplying inputs by weights.",
          "votes": 1
        }
      ]
    },
    {
      "id": 395680,
      "postDate": "2018-09-29T06:02:58.880Z",
      "content": "<p>I'm using le with category partitioning method, but I get a good improvement when leaving features with high cardinality as simple numeric features (this recomendation is on lgbms documentation and seems to work)</p>",
      "rawMarkdown": "I'm using le with category partitioning method, but I get a good improvement when leaving features with high cardinality as simple numeric features (this recomendation is on lgbms documentation and seems to work)"
    },
    {
      "id": 391148,
      "postDate": "2018-09-21T10:33:30.220Z",
      "content": "<p>In general, how do you decide whether to use one-hot encoding or label encoding? Are there any criteria for which one you should use for categorical-encoding? (although I know it depends on the situation)</p>\n\n<p>I usually used one-hot when encoding categorial variables.\nHowever, I saw some public kernels using label encoding in this competition, so I wondered.</p>",
      "rawMarkdown": "In general, how do you decide whether to use one-hot encoding or label encoding? Are there any criteria for which one you should use for categorical-encoding? (although I know it depends on the situation)\n\nI usually used one-hot when encoding categorial variables.\nHowever, I saw some public kernels using label encoding in this competition, so I wondered.",
      "replies": [
        {
          "id": 393062,
          "postDate": "2018-09-24T19:26:25.693Z",
          "content": "<p>I was scared to use One-hot encoding in this competition, because the cardinality was large. In the previous Home Credit Default Risk competition, the largest cardinality was like 25, so I was comfortable using one-hot encoding. However, this competition has some categories, like city, with over 900 unique values. This is a problem for two reasons: </p>\n\n<ol>\n<li>Many models begin to suffer when the number of columns is too large</li>\n<li>Might not have enough RAM to fit every column</li>\n</ol>\n\n<p>This makes me reluctant to use one-hot encoding; the other methods above seem much better suited, albeit [strikethrough]theoretically they shouldn't be as powerful.[/strikethrough]</p>\n\n<p>Joe Eddy's comment below is a lot better!</p>",
          "rawMarkdown": "I was scared to use One-hot encoding in this competition, because the cardinality was large. In the previous Home Credit Default Risk competition, the largest cardinality was like 25, so I was comfortable using one-hot encoding. However, this competition has some categories, like city, with over 900 unique values. This is a problem for two reasons: \n\n1. Many models begin to suffer when the number of columns is too large\n2. Might not have enough RAM to fit every column\n\nThis makes me reluctant to use one-hot encoding; the other methods above seem much better suited, albeit [strikethrough]theoretically they shouldn't be as powerful.[/strikethrough]\n\nJoe Eddy's comment below is a lot better!",
          "votes": 1
        },
        {
          "id": 393161,
          "postDate": "2018-09-24T22:42:20.573Z",
          "content": "<p>Thanks for your reply! I'll use one-hot and label encoding properly, and seek to find out some other method to be effective for this competition.</p>",
          "rawMarkdown": "Thanks for your reply! I'll use one-hot and label encoding properly, and seek to find out some other method to be effective for this competition.",
          "votes": 1
        },
        {
          "id": 393479,
          "postDate": "2018-09-25T12:58:49.740Z",
          "content": "<p>OHE often produces suboptimal results when working with tree-based methods like gradient boosted trees. The reason is that since each individual category corresponds to only 1 column, a tree can only make a single category on/off splitting comparison at a time and would need to grow very deep in order to recreate more sophisticated category partitioning. Naturally this means that the problem is worse when you're working with higher cardinality category features, but even at low cardinality it's usually not ideal (the exception is when some category values matter much more than others and/or the simplicity of the OHE format makes the model more robust to noise in the categories). So I tend not to use OHE when using tree methods, except possibly to achieve some model diversity.</p>\n\n<p>This is a good discussion: <a href=\"https://roamanalytics.com/2016/10/28/are-categorical-variables-getting-lost-in-your-random-forests/\">https://roamanalytics.com/2016/10/28/are-categorical-variables-getting-lost-in-your-random-forests/</a> </p>",
          "rawMarkdown": "OHE often produces suboptimal results when working with tree-based methods like gradient boosted trees. The reason is that since each individual category corresponds to only 1 column, a tree can only make a single category on/off splitting comparison at a time and would need to grow very deep in order to recreate more sophisticated category partitioning. Naturally this means that the problem is worse when you're working with higher cardinality category features, but even at low cardinality it's usually not ideal (the exception is when some category values matter much more than others and/or the simplicity of the OHE format makes the model more robust to noise in the categories). So I tend not to use OHE when using tree methods, except possibly to achieve some model diversity.\n\nThis is a good discussion: https://roamanalytics.com/2016/10/28/are-categorical-variables-getting-lost-in-your-random-forests/ ",
          "votes": 5
        },
        {
          "id": 393516,
          "postDate": "2018-09-25T14:03:45.973Z",
          "content": "<p><a href=\"/aquatic\">@aquatic</a> Thank you for the clarification. On a related topic, it has puzzled me why <code>totals.bounces</code> was not seen as super important to gradient boosted machines. Maybe it's because it's binary, and therefore appears to be like one-hot encoded? How can we forced gradient boost machines to attempt to use binary variables first, that we think are important, before trying to split on other variables?</p>",
          "rawMarkdown": "@aquatic Thank you for the clarification. On a related topic, it has puzzled me why `totals.bounces` was not seen as super important to gradient boosted machines. Maybe it's because it's binary, and therefore appears to be like one-hot encoded? How can we forced gradient boost machines to attempt to use binary variables first, that we think are important, before trying to split on other variables?"
        }
      ]
    },
    {
      "id": 391091,
      "postDate": "2018-09-21T08:57:59.680Z",
      "content": "<p>Hi my first choice as is OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality. So far it seems that this will yield some intresting and meaningfull categories. </p>",
      "rawMarkdown": "Hi my first choice as is OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality. So far it seems that this will yield some intresting and meaningfull categories. "
    },
    {
      "id": 390144,
      "postDate": "2018-09-19T19:21:10.233Z",
      "rawMarkdown": "",
      "isDeleted": true
    }
  ],
  "comments": [
    {
      "id": 390576,
      "author_name": "Joe Eddy",
      "author_url": "",
      "post_date": "2018-09-20T13:07:43.277000",
      "content": "<p>Here are a range of options:</p>\n\n<p><strong>Easy, but probably not great</strong>:</p>\n\n<ul>\n<li>One-hot-encoding</li>\n<li>Simple label-encoding, treat column as numerical</li>\n</ul>\n\n<p><strong>Pretty easy, possibly better</strong>:</p>\n\n<ul>\n<li>Frequency encoding: map categories to their count of occurrence, treat column as numerical. In theory this should be strictly better than label-encoding, as it allows categories to still be split based on their specific values, but conveys some information about inter-category relationships (frequency differences) that may provide signal. </li>\n<li>Assuming tree-methods (e.g. lgb), use a category partitioning method. In the case of lgb, this means using label encoding in conjunction with lgb's <code>categorical_feature</code> setting, explained here: <a href=\"https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html\">https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html</a>. This may take some hyperparameter tuning to work well.</li>\n</ul>\n\n<p><strong>Some more effort, but possibly more effective</strong>:</p>\n\n<ul>\n<li><p>OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality.</p></li>\n<li><p>Target encoding: described in early posts (replace categories with mean value of target for that category). Can be tricky to use without overfitting (make sure to generate target-encoded values out-of-sample).</p></li>\n<li><p>Engineer numerical features that are sufficient for capturing the signal conveyed by a categorical feature, then exclude the original categorical feature. This is conceptually similar to frequency/target encoding, where you're summarizing category information via some numeric quantity. For example, maybe the mean page-views per day of the month would be a reasonable substitute for a day of the month categorical feature.</p></li>\n</ul>\n\n<p><strong>Harder, more experimental</strong>:</p>\n\n<ul>\n<li>Replace category columns with dense embeddings learned from a neural network.</li>\n</ul>",
      "votes": 35,
      "replies": [
        {
          "id": 390734,
          "author_name": "Toby Cheese",
          "author_url": "",
          "post_date": "2018-09-20T18:36:25.867000",
          "content": "<p>Nice overview, thanks!</p>\n\n<p>I'll add feature hashing (aka 'the hashing trick') to that list.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 393476,
      "author_name": "Misha Lisovyi",
      "author_url": "",
      "post_date": "2018-09-25T12:51:26.953000",
      "content": "<p>There was already a nice summary by <a href=\"/aquatic\">@aquatic</a>. Just to add my 5 cents: </p>\n\n<ul>\n<li>an example of several target-encoding implementations (some of which already include regularisation to avoid data leaks): <a href=\"https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated\">https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated</a>;</li>\n<li>Catboost is your friend, when it comes to categorical features, as it implements several schemes for categorical encoding with minimised/eliminated(?) data leakage;</li>\n<li>I personally reduce cardinality simply by identifying all classes within a categorical, that appear with frequency below 0.1% (guesstimated number).  In practice I merge them into a new class within category.This allows to reduce cardinality down to ~20 per each category (note that this removes somes info, that is there)</li>\n</ul>",
      "votes": 5,
      "replies": []
    },
    {
      "id": 390324,
      "author_name": "Todd D. Vance",
      "author_url": "",
      "post_date": "2018-09-20T03:12:02.720000",
      "content": "<p>Target-mean encoding can be done.  It works better with smaller cardinalities, but my guess is it would be better than just a simple \"factorize\" into numbers transformation.  What it is, you have a categorical column with values a, b, c, ..., z.  You find the mean of the target of all rows where the value is a, and that mean value replaces a.  Similarly for b, c, ..., z.  Optionally factorize the target means to make it ordinal, but I'm not sure that's really better.</p>\n\n<p><a href=\"https://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv\">https://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv</a> (where I learned about it--you can audit the course for free and learn more than this too)</p>\n\n<p><a href=\"http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html\">http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html</a></p>\n\n<p>or google \"target mean encoding\" for more.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 390383,
          "author_name": "Alexander Firsov",
          "author_url": "",
          "post_date": "2018-09-20T05:41:24.463000",
          "content": "<p>Check Olivier's kernel <a href=\"https://www.kaggle.com/ogrellier/python-target-encoding-for-categorical-features\">Target encoding</a> and  mine <a href=\"https://www.kaggle.com/alexfir/target-encoding-using-variance\">Target encoding using variance</a>.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 390178,
      "author_name": "Aguiar",
      "author_url": "",
      "post_date": "2018-09-19T20:25:51.130000",
      "content": "<p>That's a good question. Using OHE for all columns is a very bad ideia, so one option is using just label encoding with the categorical_features parameter (LightGBM). Another option is using binary encoder and a third is mixing ohe and le (ohe for columns with low cardinality maybe).</p>\n\n<p>For now, I'm using label encoder with the sklearn LabelEncoder, so you can fit all labels from both train and test and them transform. But there are many options for trying.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 390124,
      "author_name": "Andrey Lukyanenko",
      "author_url": "",
      "post_date": "2018-09-19T18:44:36.107000",
      "content": "<p>Label encoding is quite a good way of dealing with categorical variables if you use tree-based models.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 390126,
          "author_name": "CoreyJamesLevinson",
          "author_url": "",
          "post_date": "2018-09-19T18:46:57.037000",
          "content": "<p>Why? Don't you have worries that the model will think that if <code>Zurich = 2*Chicago</code> then the inferences will be bad?</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 390139,
          "author_name": "Andrey Lukyanenko",
          "author_url": "",
          "post_date": "2018-09-19T18:59:40.893000",
          "content": "<p>Sometimes it is okay to use label encoding for tree based models, because they are simply looking for places to split the data, they are not multiplying inputs by weights.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 395680,
      "author_name": "Aguiar",
      "author_url": "",
      "post_date": "2018-09-29T06:02:58.880000",
      "content": "<p>I'm using le with category partitioning method, but I get a good improvement when leaving features with high cardinality as simple numeric features (this recomendation is on lgbms documentation and seems to work)</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 391148,
      "author_name": "Tak",
      "author_url": "",
      "post_date": "2018-09-21T10:33:30.220000",
      "content": "<p>In general, how do you decide whether to use one-hot encoding or label encoding? Are there any criteria for which one you should use for categorical-encoding? (although I know it depends on the situation)</p>\n\n<p>I usually used one-hot when encoding categorial variables.\nHowever, I saw some public kernels using label encoding in this competition, so I wondered.</p>",
      "votes": 0,
      "replies": [
        {
          "id": 393062,
          "author_name": "CoreyJamesLevinson",
          "author_url": "",
          "post_date": "2018-09-24T19:26:25.693000",
          "content": "<p>I was scared to use One-hot encoding in this competition, because the cardinality was large. In the previous Home Credit Default Risk competition, the largest cardinality was like 25, so I was comfortable using one-hot encoding. However, this competition has some categories, like city, with over 900 unique values. This is a problem for two reasons: </p>\n\n<ol>\n<li>Many models begin to suffer when the number of columns is too large</li>\n<li>Might not have enough RAM to fit every column</li>\n</ol>\n\n<p>This makes me reluctant to use one-hot encoding; the other methods above seem much better suited, albeit [strikethrough]theoretically they shouldn't be as powerful.[/strikethrough]</p>\n\n<p>Joe Eddy's comment below is a lot better!</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 393161,
          "author_name": "Tak",
          "author_url": "",
          "post_date": "2018-09-24T22:42:20.573000",
          "content": "<p>Thanks for your reply! I'll use one-hot and label encoding properly, and seek to find out some other method to be effective for this competition.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 393479,
          "author_name": "Joe Eddy",
          "author_url": "",
          "post_date": "2018-09-25T12:58:49.740000",
          "content": "<p>OHE often produces suboptimal results when working with tree-based methods like gradient boosted trees. The reason is that since each individual category corresponds to only 1 column, a tree can only make a single category on/off splitting comparison at a time and would need to grow very deep in order to recreate more sophisticated category partitioning. Naturally this means that the problem is worse when you're working with higher cardinality category features, but even at low cardinality it's usually not ideal (the exception is when some category values matter much more than others and/or the simplicity of the OHE format makes the model more robust to noise in the categories). So I tend not to use OHE when using tree methods, except possibly to achieve some model diversity.</p>\n\n<p>This is a good discussion: <a href=\"https://roamanalytics.com/2016/10/28/are-categorical-variables-getting-lost-in-your-random-forests/\">https://roamanalytics.com/2016/10/28/are-categorical-variables-getting-lost-in-your-random-forests/</a> </p>",
          "votes": 5,
          "replies": []
        },
        {
          "id": 393516,
          "author_name": "CoreyJamesLevinson",
          "author_url": "",
          "post_date": "2018-09-25T14:03:45.973000",
          "content": "<p><a href=\"/aquatic\">@aquatic</a> Thank you for the clarification. On a related topic, it has puzzled me why <code>totals.bounces</code> was not seen as super important to gradient boosted machines. Maybe it's because it's binary, and therefore appears to be like one-hot encoded? How can we forced gradient boost machines to attempt to use binary variables first, that we think are important, before trying to split on other variables?</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 391091,
      "author_name": "juske",
      "author_url": "",
      "post_date": "2018-09-21T08:57:59.680000",
      "content": "<p>Hi my first choice as is OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality. So far it seems that this will yield some intresting and meaningfull categories. </p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 390144,
      "author_name": "",
      "author_url": "",
      "post_date": "2018-09-19T19:21:10.233000",
      "content": "",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "390576": "Here are a range of options:\n\n**Easy, but probably not great**:\n\n - One-hot-encoding\n - Simple label-encoding, treat column as numerical\n\n**Pretty easy, possibly better**:\n\n - Frequency encoding: map categories to their count of occurrence, treat column as numerical. In theory this should be strictly better than label-encoding, as it allows categories to still be split based on their specific values, but conveys some information about inter-category relationships (frequency differences) that may provide signal. \n - Assuming tree-methods (e.g. lgb), use a category partitioning method. In the case of lgb, this means using label encoding in conjunction with lgb's `categorical_feature` setting, explained here: https://lightgbm.readthedocs.io/en/latest/Advanced-Topics.html. This may take some hyperparameter tuning to work well.\n\n**Some more effort, but possibly more effective**:\n\n - OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality.\n\n - Target encoding: described in early posts (replace categories with mean value of target for that category). Can be tricky to use without overfitting (make sure to generate target-encoded values out-of-sample).\n\n - Engineer numerical features that are sufficient for capturing the signal conveyed by a categorical feature, then exclude the original categorical feature. This is conceptually similar to frequency/target encoding, where you're summarizing category information via some numeric quantity. For example, maybe the mean page-views per day of the month would be a reasonable substitute for a day of the month categorical feature.\n\n\n \n\n**Harder, more experimental**:\n\n - Replace category columns with dense embeddings learned from a neural network.",
    "390113": "There are many categorical columns in this dataset where the cardinality is extremely high. Because of this, if you are one-hot encoding, you create a surplus of columns. Also, there are a lot of unique categories in the test set that are not seen in the training set.\n\nHow are you dealing with columns like `geoNetwork.city`, `geoNetwork.country`, `geoNetwork.metro`, `trafficSource.adContent`, `trafficSource.keyword`, etc.",
    "393476": "There was already a nice summary by @aquatic. Just to add my 5 cents: \n\n- an example of several target-encoding implementations (some of which already include regularisation to avoid data leaks): https://www.kaggle.com/mlisovyi/9-ways-to-treat-categorical-features-updated;\n- Catboost is your friend, when it comes to categorical features, as it implements several schemes for categorical encoding with minimised/eliminated(?) data leakage;\n- I personally reduce cardinality simply by identifying all classes within a categorical, that appear with frequency below 0.1% (guesstimated number).  In practice I merge them into a new class within category.This allows to reduce cardinality down to ~20 per each category (note that this removes somes info, that is there)",
    "390324": "Target-mean encoding can be done.  It works better with smaller cardinalities, but my guess is it would be better than just a simple \"factorize\" into numbers transformation.  What it is, you have a categorical column with values a, b, c, ..., z.  You find the mean of the target of all rows where the value is a, and that mean value replaces a.  Similarly for b, c, ..., z.  Optionally factorize the target means to make it ordinal, but I'm not sure that's really better.\n\nhttps://www.coursera.org/lecture/competitive-data-science/concept-of-mean-encoding-b5Gxv (where I learned about it--you can audit the course for free and learn more than this too)\n\nhttp://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/target-encoding.html\n\nor google \"target mean encoding\" for more.",
    "390178": "That's a good question. Using OHE for all columns is a very bad ideia, so one option is using just label encoding with the categorical_features parameter (LightGBM). Another option is using binary encoder and a third is mixing ohe and le (ohe for columns with low cardinality maybe).\n\nFor now, I'm using label encoder with the sklearn LabelEncoder, so you can fit all labels from both train and test and them transform. But there are many options for trying.",
    "390124": "Label encoding is quite a good way of dealing with categorical variables if you use tree-based models.",
    "395680": "I'm using le with category partitioning method, but I get a good improvement when leaving features with high cardinality as simple numeric features (this recomendation is on lgbms documentation and seems to work)",
    "391148": "In general, how do you decide whether to use one-hot encoding or label encoding? Are there any criteria for which one you should use for categorical-encoding? (although I know it depends on the situation)\n\nI usually used one-hot when encoding categorial variables.\nHowever, I saw some public kernels using label encoding in this competition, so I wondered.",
    "391091": "Hi my first choice as is OHE/encoding in conjunction with careful preprocessing. Exclude/combine rare category values, drop values/columns that are not informative, determine meaningful larger groupings that allow you to reduce cardinality. So far it seems that this will yield some intresting and meaningfull categories. ",
    "390144": ""
  }
}