<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _get_base_estimators(self, X):
 """Takes special care of estimators using custom kernel function Parameters X : array, shape = (n_samples, n_features) Samples to pre-compute kernel matrix from. Returns ------- base_estimators : list Same as `self.base_estimators`, expect that estimators with custom kernel function use ``kernel='precomputed'``. kernel_cache : dict Maps estimator name to kernel matrix. Use this for cross-validation instead of `X`. """

        base_estimators = []

        kernel_cache = {}
        kernel_fns = {}
        for i, (name, estimator) in enumerate(self.base_estimators):
            if hasattr(estimator, 'kernel') and callable(estimator.kernel):
                if not hasattr(estimator, '_get_kernel'):
                    raise ValueError(
                        'estimator %s uses a custom kernel function, but does not have a _get_kernel method' % name)

                kernel_mat = kernel_fns.get(estimator.kernel, None)
                if kernel_mat is None:
                    kernel_mat = estimator._get_kernel(X)
                    kernel_cache[i] = kernel_mat
                    kernel_fns[estimator.kernel] = kernel_mat

                kernel_cache[i] = kernel_mat

                # We precompute kernel, but only for training, for testing use original custom kernel function
                kernel_estimator = clone(estimator)
                kernel_estimator.set_params(kernel='precomputed')
                base_estimators.append((name, kernel_estimator))
            else:
                base_estimators.append((name, estimator))

        return base_estimators, kernel_cache