# Buggy code
def __init__(
    self,
    path: str,
    problem_type: str,
    scheduler_options=None,
    eval_metric=None,
    stopping_metric=None,
    num_classes=None,
    low_memory=False,
    feature_types_metadata=None,
    kfolds=0,
    n_repeats=1,
    stack_ensemble_levels=0,
    time_limit=None,
    save_data=False,
    save_bagged_folds=True,
    random_seed=0,
    verbosity=2,
):
    self.path = path
    self.problem_type = problem_type
    self.feature_types_metadata = feature_types_metadata
    self.save_data = save_data
    self.random_seed = random_seed  # Integer value added to the stack level to get the random_seed for kfold splits or the train/val split if bagging is disabled
    self.verbosity = verbosity
    if eval_metric is not None:
        self.eval_metric = eval_metric
    else:
        self.eval_metric = infer_eval_metric(problem_type=self.problem_type)

    # stopping_metric is used to early stop all models except for aux models.
    if stopping_metric is not None:
        self.stopping_metric = stopping_metric
    elif self.eval_metric.name == "roc_auc":
        self.stopping_metric = log_loss
    else:
        self.stopping_metric = self.eval_metric

    self.eval_metric_expects_y_pred = scorer_expects_y_pred(scorer=self.eval_metric)
    logger.log(
        25,
        "AutoGluon will gauge predictive performance using evaluation metric: %s"
        % self.eval_metric.name,
    )
    if not self.eval_metric_expects_y_pred:
        logger.log(
            25,
            "This metric expects predicted probabilities rather than predicted class labels, so you'll need to use predict_proba() instead of predict()",
        )

    logger.log(20, "To change this, specify the eval_metric argument of fit()")
    logger.log(
        25,
        "AutoGluon will early stop models using evaluation metric: %s"
        % self.stopping_metric.name,
    )
    self.num_classes = num_classes
    self.feature_prune = False  # will be set to True if feature-pruning is turned on.
    self.low_memory = low_memory
    self.bagged_mode = True if kfolds >= 2 else False
    if self.bagged_mode:
        self.kfolds = (
            kfolds  # int number of folds to do model bagging, < 2 means disabled
        )
        self.stack_ensemble_levels = stack_ensemble_levels
        self.stack_mode = True if self.stack_ensemble_levels >= 1 else False
        self.n_repeats = n_repeats
    else:
        self.kfolds = 0
        self.stack_ensemble_levels = 0
        self.stack_mode = False
        self.n_repeats = 1
    self.save_bagged_folds = save_bagged_folds

    self.hyperparameters = {}  # TODO: This is currently required for fetching stacking layer models. Consider incorporating more elegantly

    # self.models_level_all['core'][0] # Includes base models
    # self.models_level_all['core'][1] # Stacker level 1
    # self.models_level_all['aux1'][1] # Stacker level 1 aux models, such as weighted_ensemble
    # self.models_level_all['core'][2] # Stacker level 2
    self.models_level = defaultdict(dd_list)

    self.model_best = None

    self.model_performance = {}  # TODO: Remove in future, use networkx.
    self.model_paths = {}
    self.model_types = {}  # Outer type, can be BaggedEnsemble, StackEnsemble (Type that is able to load the model)
    self.model_types_inner = {}  # Inner type, if Ensemble then it is the type of the inner model (May not be able to load with this type)
    self.models = {}
    self.model_graph = nx.DiGraph()
    self.model_full_dict = {}  # Dict of normal Model -> FULL Model
    self.reset_paths = False

    self.hpo_results = {}  # Stores summary of HPO process
    # Scheduler attributes:
    if scheduler_options is not None:
        self.scheduler_func = scheduler_options[0]  # unpack tuple
        self.scheduler_options = scheduler_options[1]
    else:
        self.scheduler_func = None
        self.scheduler_options = None

    self.time_limit = time_limit
    if self.time_limit is None:
        self.time_limit = 1e7
        self.ignore_time_limit = True
    else:
        self.ignore_time_limit = False
    self.time_train_start = None
    self.time_train_level_start = None
    self.time_limit_per_level = self.time_limit / (self.stack_ensemble_levels + 1)

    self.num_rows_train = None
    self.num_cols_train = None

    self.is_data_saved = False

    self.regress_preds_asprobas = False  # whether to treat regression predictions as class-probabilities (during distillation)


# Traceback (ValueError)
File delimiter for ../input/house-prices-advanced-regression-techniques/test.csv inferred as ',' (comma). If this is incorrect, please manually load the data as a pandas DataFrame.
Loaded data from: ../input/house-prices-advanced-regression-techniques/test.csv | Columns = 80 / 80 | Rows = 1459 -> 1459
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-48-91455d7b9940> in <module>
1 test_data = task.Dataset(file_path=os.path.join(in_dir, job, 'test.csv'))
2
----> 3 preds = model.predict(test_data)

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/task/tabular_prediction/predictor.py in predict(self, dataset, model, as_pandas, use_pred_cache, add_to_pred_cache)
130         """
131         dataset = self.__get_dataset(dataset)
--> 132         return self._learner.predict(X=dataset, model=model, as_pandas=as_pandas, use_pred_cache=use_pred_cache, add_to_pred_cache=add_to_pred_cache)
133
134     def predict_proba(self, dataset, model=None, as_pandas=False, as_multiclass=False):

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/utils/tabular/ml/learner/abstract_learner.py in predict(self, X, model, as_pandas, use_pred_cache, add_to_pred_cache)
127
128         if len(X_cache_miss) > 0:
--> 129             y_pred_proba = self.predict_proba(X=X_cache_miss, model=model, inverse_transform=False)
130             problem_type = self.trainer_problem_type or self.problem_type
131             y_pred = get_pred_from_proba(y_pred_proba=y_pred_proba, problem_type=problem_type)

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/utils/tabular/ml/learner/abstract_learner.py in predict_proba(self, X, model, as_pandas, as_multiclass, inverse_transform)
92     # TODO: Add pred_proba_cache functionality as in predict()
93     def predict_proba(self, X: DataFrame, model=None, as_pandas=False, as_multiclass=False, inverse_transform=True):
---> 94         X = self.transform_features(X)
95         y_pred_proba = self.load_trainer().predict_proba(X, model=model)
96         if inverse_transform:

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/utils/tabular/ml/learner/abstract_learner.py in transform_features(self, X)
216     def transform_features(self, X):
217         for feature_generator in self.feature_generators:
--> 218             X = feature_generator.transform(X)
219         return X
220

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/utils/tabular/utils/decorators.py in inner1(*args, **kwargs)
12         begin = time.time()
13
---> 14         output = func(*args, **kwargs)
15
16         # storing time after function execution

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/autogluon/utils/tabular/features/abstract_feature_generator.py in transform(self, X)
183             raise ValueError(f'Required columns are missing from the provided dataset. Missing columns: {missing_cols}')
184
--> 185         X = X.astype(self.features_init_types)
186         X.reset_index(drop=True, inplace=True)
187         X_features = self.generate_features(X)

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/generic.py in astype(self, dtype, copy, errors, **kwargs)
5863                     results.append(
5864                         col.astype(
-> 5865                             dtype=dtype[col_name], copy=copy, errors=errors, **kwargs
5866                         )
5867                     )

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/generic.py in astype(self, dtype, copy, errors, **kwargs)
5880             # else, only a single dtype is given
5881             new_data = self._data.astype(
-> 5882                 dtype=dtype, copy=copy, errors=errors, **kwargs
5883             )
5884             return self._constructor(new_data).__finalize__(self)

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/internals/managers.py in astype(self, dtype, **kwargs)
579
580     def astype(self, dtype, **kwargs):
--> 581         return self.apply("astype", dtype=dtype, **kwargs)
582
583     def convert(self, **kwargs):

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/internals/managers.py in apply(self, f, axes, filter, do_integrity_check, consolidate, **kwargs)
436                     kwargs[k] = obj.reindex(b_items, axis=axis, copy=align_copy)
437
--> 438             applied = getattr(b, f)(**kwargs)
439             result_blocks = _extend_blocks(applied, result_blocks)
440

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/internals/blocks.py in astype(self, dtype, copy, errors, values, **kwargs)
557
558     def astype(self, dtype, copy=False, errors="raise", values=None, **kwargs):
--> 559         return self._astype(dtype, copy=copy, errors=errors, values=values, **kwargs)
560
561     def _astype(self, dtype, copy=False, errors="raise", values=None, **kwargs):

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/internals/blocks.py in _astype(self, dtype, copy, errors, values, **kwargs)
641                     # _astype_nansafe works fine with 1-d only
642                     vals1d = values.ravel()
--> 643                     values = astype_nansafe(vals1d, dtype, copy=True, **kwargs)
644
645                 # TODO(extension)

~/miniconda3/envs/autogluon/lib/python3.7/site-packages/pandas/core/dtypes/cast.py in astype_nansafe(arr, dtype, copy, skipna)
698         if not np.isfinite(arr).all():
699             raise ValueError(
--> 700                 "Cannot convert non-finite values (NA or inf) to " "integer"
701             )
702

ValueError: Cannot convert non-finite values (NA or inf) to integer

# Fixed code
def __init__(
    self,
    path: str,
    problem_type: str,
    scheduler_options=None,
    eval_metric=None,
    stopping_metric=None,
    num_classes=None,
    low_memory=False,
    feature_metadata=None,
    kfolds=0,
    n_repeats=1,
    stack_ensemble_levels=0,
    time_limit=None,
    save_data=False,
    save_bagged_folds=True,
    random_seed=0,
    verbosity=2,
):
    self.path = path
    self.problem_type = problem_type
    self.feature_metadata = feature_metadata
    self.save_data = save_data
    self.random_seed = random_seed  # Integer value added to the stack level to get the random_seed for kfold splits or the train/val split if bagging is disabled
    self.verbosity = verbosity
    if eval_metric is not None:
        self.eval_metric = eval_metric
    else:
        self.eval_metric = infer_eval_metric(problem_type=self.problem_type)

    # stopping_metric is used to early stop all models except for aux models.
    if stopping_metric is not None:
        self.stopping_metric = stopping_metric
    elif self.eval_metric.name == "roc_auc":
        self.stopping_metric = log_loss
    else:
        self.stopping_metric = self.eval_metric

    self.eval_metric_expects_y_pred = scorer_expects_y_pred(scorer=self.eval_metric)
    logger.log(
        25,
        "AutoGluon will gauge predictive performance using evaluation metric: %s"
        % self.eval_metric.name,
    )
    if not self.eval_metric_expects_y_pred:
        logger.log(
            25,
            "This metric expects predicted probabilities rather than predicted class labels, so you'll need to use predict_proba() instead of predict()",
        )

    logger.log(20, "To change this, specify the eval_metric argument of fit()")
    logger.log(
        25,
        "AutoGluon will early stop models using evaluation metric: %s"
        % self.stopping_metric.name,
    )
    self.num_classes = num_classes
    self.feature_prune = False  # will be set to True if feature-pruning is turned on.
    self.low_memory = low_memory
    self.bagged_mode = True if kfolds >= 2 else False
    if self.bagged_mode:
        self.kfolds = (
            kfolds  # int number of folds to do model bagging, < 2 means disabled
        )
        self.stack_ensemble_levels = stack_ensemble_levels
        self.stack_mode = True if self.stack_ensemble_levels >= 1 else False
        self.n_repeats = n_repeats
    else:
        self.kfolds = 0
        self.stack_ensemble_levels = 0
        self.stack_mode = False
        self.n_repeats = 1
    self.save_bagged_folds = save_bagged_folds

    self.hyperparameters = {}  # TODO: This is currently required for fetching stacking layer models. Consider incorporating more elegantly

    # self.models_level_all['core'][0] # Includes base models
    # self.models_level_all['core'][1] # Stacker level 1
    # self.models_level_all['aux1'][1] # Stacker level 1 aux models, such as weighted_ensemble
    # self.models_level_all['core'][2] # Stacker level 2
    self.models_level = defaultdict(dd_list)

    self.model_best = None

    self.model_performance = {}  # TODO: Remove in future, use networkx.
    self.model_paths = {}
    self.model_types = {}  # Outer type, can be BaggedEnsemble, StackEnsemble (Type that is able to load the model)
    self.model_types_inner = {}  # Inner type, if Ensemble then it is the type of the inner model (May not be able to load with this type)
    self.models = {}
    self.model_graph = nx.DiGraph()
    self.model_full_dict = {}  # Dict of normal Model -> FULL Model
    self.reset_paths = False

    self.hpo_results = {}  # Stores summary of HPO process
    # Scheduler attributes:
    if scheduler_options is not None:
        self.scheduler_func = scheduler_options[0]  # unpack tuple
        self.scheduler_options = scheduler_options[1]
    else:
        self.scheduler_func = None
        self.scheduler_options = None

    self.time_limit = time_limit
    if self.time_limit is None:
        self.time_limit = 1e7
        self.ignore_time_limit = True
    else:
        self.ignore_time_limit = False
    self.time_train_start = None
    self.time_train_level_start = None
    self.time_limit_per_level = self.time_limit / (self.stack_ensemble_levels + 1)

    self.num_rows_train = None
    self.num_cols_train = None

    self.is_data_saved = False

    self.regress_preds_asprobas = False  # whether to treat regression predictions as class-probabilities (during distillation)