//  [python]
def fit(self, X, y):
        """Train a neural network model with embedding layers.

        Args:
            X (pandas.DataFrame): categorical features to create embeddings for
            y (pandas.Series): a target variable

        Returns:
            A trained EmbeddingEncoder object.
        """
        is_classification = y.nunique() == 2

        X_cat = self.lbe.fit_transform(X[self.cat_cols])
        if is_classification:
            assert np.isin(
                y, [0, 1]
            ).all(), "Target values should be 0 or 1 for classification."
            output_activation = "sigmoid"
            loss = "binary_crossentropy"
            metrics = [tf.keras.metrics.AUC()]
            monitor = "val_auc"
            mode = "max"
        else:
            output_activation = "linear"
            loss = "mse"
            metrics = ["mse"]
            monitor = "val_mse"
            mode = "min"

        n_uniq = [X_cat[col].nunique() for col in self.cat_cols]
        if self.cv:
            self.embs = []
            n_fold = self.cv.get_n_splits(X)
            for i_cv, (i_trn, i_val) in enumerate(self.cv.split(X, y), 1):
                i_trn, i_val = X.index[i_trn], X.index[i_val]
                model, self.n_emb, _ = self._get_model(
                    X_cat,
                    self.cat_cols,
                    self.num_cols,
                    n_uniq,
                    self.n_emb,
                    output_activation,
                )
                model.compile(optimizer=Adam(lr=0.01), loss=loss, metrics=metrics)

                features_trn = [X_cat.loc[i_trn, col] for col in self.cat_cols]
                features_val = [X_cat.loc[i_val, col] for col in self.cat_cols]
                if self.num_cols:
                    features_trn += [X.loc[i_trn, self.num_cols]]
                    features_val += [X.loc[i_val, self.num_cols]]

                es = EarlyStopping(
                    monitor=monitor,
                    min_delta=0.001,
                    patience=5,
                    verbose=1,
                    mode=mode,
                    baseline=None,
                    restore_best_weights=True,
                )
                rlr = ReduceLROnPlateau(
                    monitor=monitor, factor=0.5, patience=3, min_lr=1e-6, mode=mode
                )
                model.fit(
                    x=features_trn,
                    y=y[i_trn],
                    validation_data=(features_val, y[i_val]),
                    epochs=self.n_epoch,
                    batch_size=self.batch_size,
                    callbacks=[es, rlr],
                )

                for i_col, col in enumerate(self.cat_cols):
                    emb = model.get_layer(col + EMBEDDING_SUFFIX).get_weights()[0]
                    if i_cv == 1:
                        self.embs.append(emb / n_fold)
                    else:
                        self.embs[i_col] += emb / n_fold

        else:
            model, self.n_emb, _ = self._get_model(
                X_cat,
                self.cat_cols,
                self.num_cols,
                n_uniq,
                self.n_emb,
                output_activation,
            )
            model.compile(optimizer=Adam(lr=0.01), loss=loss, metrics=metrics)

            features = [X_cat[col] for col in self.cat_cols]
            if self.num_cols:
                features += [X[self.num_cols].values]

            es = EarlyStopping(
                monitor=monitor,
                min_delta=0.001,
                patience=5,
                verbose=1,
                mode=mode,
                baseline=None,
                restore_best_weights=True,
            )
            rlr = ReduceLROnPlateau(
                monitor=monitor, factor=0.5, patience=3, min_lr=1e-6, mode=mode
            )
            model.fit(
                x=features,
                y=y,
                epochs=self.n_epoch,
                validation_split=0.2,
                batch_size=self.batch_size,
                callbacks=[es, rlr],
            )

            self.embs = []
            for i, col in enumerate(self.cat_cols):
                self.embs.append(
                    model.get_layer(col + EMBEDDING_SUFFIX).get_weights()[0]
                )
                logger.debug("{}: {}".format(col, self.embs[i].shape))

        self.is_fitted = True
        return self