text: """
  File contains functions used to train Naive Bayes.
  
  Author: Dominik Macko
  """
  
  from typing import Dict, Any, Union, Callable, Tuple, List
  
  import numpy as np
  import pandas as pd
  from sklearn.naive_bayes import ComplementNB, GaussianNB
  from sklearn.metrics import f1_score
  
  from .generic import train_model, train_gridsearchcv_model
  
  def get_inverse_class_priors(train_y: pd.Series) -> List[float]:
      """Gets inverse class priors for the classes found in given series."""
      
      probabilities = train_y.value_counts(normalize=True).to_list()
      inv = [(1 - p) for p in probabilities]
      return [p / sum(inv) for p in inv]
  
  def naive_bayes_best_params_surroundings(best_params: Dict[str, Any]) -> Dict[str, Any]:
      """Get best parameters surroundings for random forest."""
      
      alpha = best_params["alpha"]
      return {
          "alpha": [alpha - 0.05, alpha, min(alpha + 0.05, 1.0)]
      }
  
  def train_complement_naive_bayes(train_X: np.array,
                                   train_y: np.array,
                                   validation_X: np.array,
                                   validation_y: np.array,
                                   scoring: Union[str, Callable[[Any, np.array, np.array], int]]="f1_macro",
                                   n_jobs: int=8,
                                   verbose: int=3
                                  ) -> Tuple[ComplementNB, pd.DataFrame]:
      """Trains complement naive bayes by searching for optimal alpha smoothing term.
      
      train_X - training set features
      train_y - training set targets
      validation_X - validation set features
      validation_y - validation set targets
      scoring - scikit scoring function to use
      n_jobs - threads to use
      verbose - scikit verbose level to use
      
      returns (model, history dataframe)
      """
      
      grid = {
          "alpha": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
      }
      return train_model(
          ComplementNB(),
          train_gridsearchcv_model,
          train_gridsearchcv_model,
          grid,
          naive_bayes_best_params_surroundings,
          train_X,
          train_y,
          validation_X,
          validation_y,
          scoring=scoring,
          n_jobs=n_jobs,
          verbose=verbose,
      )
  
  def train_gaussian_naive_bayes(train_X: np.array,
                                 train_y: np.array,
                                 validation_X: np.array,
                                 validation_y: np.array,
                                 use_inverse_priors: bool=True
                                ) -> Tuple[GaussianNB, float]:
      """Trains Gaussian naive bayes and returns it with score on validation set.
      
      train_X - training set features
      train_y - training set targets
      validation_X - validation set features
      validation_y - validation set targets
      use_inverse_priors - specifies whether to use inverse class priors
      
      returns (model, f1_score on validation set)
      """
  
      if use_inverse_priors:
          model = GaussianNB(priors=get_inverse_class_priors(pd.Series(train_y.ravel())))
      else:
          model = GaussianNB()
      model.fit(train_X, train_y.ravel())
      validation_pred_y = model.predict(validation_X)
      return (model, 
              f1_score(validation_y.ravel(), validation_pred_y, average="weighted"))
  
  