def _predict_with_probabilities(self, input_dataset, batch_size=None, 
        verbose=True):
        """
        Predict with probabilities. The core prediction part that both 
        `evaluate` and `predict` share.

        Returns an SFrame with two columns, self.target, and "probabilities".

        The column with column name, self.target, contains the predictions made
        by the model for the provided dataset.

        The "probabilities" column contains the probabilities for each class 
        that the model predicted for the data provided to the function.
        """

        from .._mxnet import _mxnet_utils
        import mxnet as _mx
        from ._sframe_loader import SFrameClassifierIter as _SFrameClassifierIter

        is_stroke_input = (input_dataset[self.feature].dtype != _tc.Image)
        dataset = _extensions._drawing_classifier_prepare_data(
                input_dataset, self.feature) if is_stroke_input else input_dataset
    
        batch_size = self.batch_size if batch_size is None else batch_size
        loader = _SFrameClassifierIter(dataset, batch_size,
                    class_to_index=self._class_to_index,
                    feature_column=self.feature,
                    target_column=self.target,
                    load_labels=False,
                    shuffle=False,
                    iterations=1)

        dataset_size = len(dataset)
        ctx = _mxnet_utils.get_mxnet_context()

        index = 0
        last_time = 0
        done = False

        from turicreate import SArrayBuilder
        from array import array

        classes = self.classes
        all_predicted_builder = SArrayBuilder(dtype=type(classes[0]))
        all_probabilities_builder = SArrayBuilder(dtype=array)

        for batch in loader:
            if batch.pad is not None:
                size = batch_size - batch.pad
                batch_data = _mx.nd.slice_axis(batch.data[0], 
                    axis=0, begin=0, end=size)
            else:
                batch_data = batch.data[0]
                size = batch_size

            num_devices = min(batch_data.shape[0], len(ctx))
            split_data = _mx.gluon.utils.split_and_load(batch_data, ctx_list=ctx[:num_devices], even_split=False)

            for data in split_data:
                z = self._model(data).asnumpy()
                predicted = list(map(lambda x: classes[x], z.argmax(axis=1)))
                split_length = z.shape[0]
                all_predicted_builder.append_multiple(predicted)
                all_probabilities_builder.append_multiple(z.tolist())
                index += split_length
                if index == dataset_size - 1:
                    done = True

                cur_time = _time.time()
                # Do not print progress if only a few samples are predicted
                if verbose and (dataset_size >= 5
                    and cur_time > last_time + 10 or done):
                    print('Predicting {cur_n:{width}d}/{max_n:{width}d}'.format(
                        cur_n = index + 1,
                        max_n = dataset_size,
                        width = len(str(dataset_size))))
                    last_time = cur_time

        return (_tc.SFrame({self.target: all_predicted_builder.close(),
                            'probability': all_probabilities_builder.close()}))
Predict with probabilities. The core prediction part that both 
        `evaluate` and `predict` share.

        Returns an SFrame with two columns, self.target, and "probabilities".

        The column with column name, self.target, contains the predictions made
        by the model for the provided dataset.

        The "probabilities" column contains the probabilities for each class 
        that the model predicted for the data provided to the function.