5
$\begingroup$

I'm working on a binary classification problem where the dataset is slightly imbalanced (30% class 0 | 70% class 1).

Most of my features are categorical with large number of categories. For example: one of them has 310 categories but the top 10 most frequently occurring variables account for ~50% of the training and test data. I was thinking of keeping these top k frequently occurring values and encoding all the other values as another category "others".

Would it be okay to do so?

Also, what kind of classifier would be optimal for such a task? I was looking at random forests. However, due to noisy data (too many categories, too many features) my model doesn't generalize too well (low recall and precision).

Thank you for your time.

PS: Data not time series

$\endgroup$

5 Answers 5

4
$\begingroup$

I used to work a lot with such data in the past.
When you have many categorical features with high cardinality, you must avoid one-hot encoding them because it consumes too much memory and above all trees built from them will be too deep and worse than trees built without one-hot encoding.
You need a Tree based model library implemented with native categorical feature support (i.e. not needing the categorical features to be one-hot encoded).
I suggest you to use one of those 4 implementations :
- CatBoost
- LightGBM
- H2O GBM
- H2O Random Forest
Scikit learn and XGBoost implementations still need one-hot encoded categorical variables so I don't recommend using one of these libraries if your dataset has high cardinality categorical variables (i.e. with more than about 10 levels/categories).
See this :

LightGBM offers good accuracy with integer-encoded categorical features. LightGBM applies Fisher (1958) to find the optimal split over categories as described here. This often performs better than one-hot encoding.

$\endgroup$
3
  • $\begingroup$ Do random forests in SKLearn have the ability to group non-contiguous integer/one-hot encoded variables? For instance, with one-hot encoding and only one split, it might be appropriate to group 0 and 5 in one category and 1, 2, and 3 in another category. However, for other integer variables with only one split, it should almost always make sense to group 0 and 1 before grouping 0 and 5. Does SKLearn treat all integer variables (one-hot encoded or not) as being linear for the purpose of determining splits? $\endgroup$ Apr 6, 2021 at 5:59
  • $\begingroup$ Just to expand on that a little, if SKLearn treats one-hot encoded variables as being linear, it might make sense to do some preprocessing to try to map categorical X classes to a spectrum (the details of that process would depend on the problem) rather than one-hot encoding them in whatever order they happen to appear. $\endgroup$ Apr 6, 2021 at 6:00
  • $\begingroup$ As of xgboost 2.0.0, it supports native categorical variables. $\endgroup$
    – truth
    Oct 7 at 23:32
1
$\begingroup$

"I was thinking of keeping these top k frequently occurring values and encoding all the other values as another category "others". Would it be okay to do so?", for me also it should be ok.

I have few more comments:

  1. You can also try with new features. That is combine multiple categorical features, instead of using all of them independently.
  2. Since you have many categorical features, one hot encoding of every categorical feature will generate a huge list of features, which may overfit your model. You can also try without One Hot Encoding as it's not always mandatory for Decision tree.
$\endgroup$
0
$\begingroup$

Hi and welcome to the forum. Just as an idea:

The strategy you suggested (extracting important classes in the X and leave the rest as "other") may work and it‘s worth a try. Make sure you don‘t throw away information by keeping the levels in the "other" category.

The alternative is (of course) to one-hot encode all classes.

In any case, I would check if regulation (by L2 or L1 norm) is useful.

Some background: L1 regulation can shrink features to zero, L2 regulation can shrink features but they never become zero.

So say you have a lot of one-hot encoded features but you have no idea which one are really important. Just let the computer do the job of selecting features by L1 regulation.

Method wise, the problem sounds like a candidate for boosting. Boosting is similar to random forest, but in addition, the algorithm tried to focus on especially hard to predict rows/observations. This is done by growing a lot of very small trees.

Prominent algorithms are LightGBM, Catboost, XGboost. They all offer support for regulation.

So I would start with "a lot" one-hot encoded features and boost with L1 regulation to get rid of irrelevant features.

$\endgroup$
0
$\begingroup$

Encoding categorical variables so that you do not lose information and do not add non-existent relationships between the categories is fundamental to achieving good performance from your model.

You can not simply LabelEncode your categories because they add non-existent relationships. For example, if you have a feature named 'color' which takes on three values - Red, Blue and Green and you encode Red as 1, Blue as 2 and Green as 3, this will imply relationships such as

$$Red < Blue < Green$$ $$Blue = (Red + Green)/2$$

Because of the curse of dimensionality, you can not use OneHotEncoder as that will inflate your feature space beyond your model's comprehension because of a relatively smaller dataset.

The approach of taking only top k frequently occurring categories will be suboptimal as you loose information. A better approach would be to use a FrequencyEncoder which replaces categories with their frequencies (or counts) of occurrence.

More sophisticated approaches like Target Encoding and Contrast Coding Schemes which take target variable into account when encoding categories are known to perform better in cases of high cardinality categories.

If some of your categories have string values which are not domain-specific you can convert them into meaningful vectors using pre-trained Word2Vec. If any of your categories contain long text (e.g. description of an event), you can train your own Word2Vec on sentences built from values of such a category. By taking a weighted-average of the vectors from a sentence, you can encode sentences.

As far as models are concerned, with the right kind of encoding, Random Forests and Gradient Boosted Machines will work just fine. SVMs and Vanilla Neural Networks are also worth considering. To boost your accuracy you can definitely use XGBoost.

$\endgroup$
0
$\begingroup$

If you're using python and sklearn I'd suggest you take a look at http://contrib.scikit-learn.org/categorical-encoding/

There's a large number of different encoding schemes you can experiment with. Many of them have parameters such as smoothing for the TargetEncoder which you can select using hyper-parameter optimisation to ensure you don't overfit.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.