Ejemplo n.º 1
0
def _check_onnx_export(net,
                       group_outputs=False,
                       shape_type=tuple,
                       extra_params={}):
    net.initialize()
    data = nd.random.uniform(0, 1, (1, 1024))
    output = _force_list(net(data))  # initialize weights
    net_sym = _optional_group(net(sym.Variable('data')), group_outputs)
    net_params = {
        name: param._reduce()
        for name, param in net.collect_params().items()
    }
    net_params.update(extra_params)
    with tempfile.TemporaryDirectory() as tmpdirname:
        onnx_file_path = os.path.join(tmpdirname, 'net.onnx')
        export_path = onnx_mxnet.export_model(
            sym=net_sym,
            params=net_params,
            input_shape=[shape_type(data.shape)],
            onnx_file_path=onnx_file_path)
        assert export_path == onnx_file_path
        # Try importing the model to symbol
        _assert_sym_equal(net_sym, onnx_mxnet.import_model(export_path)[0])

        # Try importing the model to gluon
        imported_net = onnx_mxnet.import_to_gluon(export_path, ctx=None)
        _assert_sym_equal(
            net_sym,
            _optional_group(imported_net(sym.Variable('data')), group_outputs))

        # Confirm network outputs are the same
        imported_net_output = _force_list(imported_net(data))
        for out, imp_out in zip(output, imported_net_output):
            mx.test_utils.assert_almost_equal(out.asnumpy(), imp_out.asnumpy())
def _check_onnx_export(net, group_outputs=False, shape_type=tuple, extra_params={}):
    net.initialize()
    data = nd.random.uniform(0, 1, (1, 1024))
    output = _force_list(net(data))  # initialize weights
    net_sym = _optional_group(net(sym.Variable('data')), group_outputs)
    net_params = {name:param._reduce() for name, param in net.collect_params().items()}
    net_params.update(extra_params)
    with tempfile.TemporaryDirectory() as tmpdirname:
        onnx_file_path = os.path.join(tmpdirname, 'net.onnx')
        export_path = onnx_mxnet.export_model(
            sym=net_sym,
            params=net_params,
            input_shape=[shape_type(data.shape)],
            onnx_file_path=onnx_file_path)
        assert export_path == onnx_file_path
        # Try importing the model to symbol
        _assert_sym_equal(net_sym, onnx_mxnet.import_model(export_path)[0])

        # Try importing the model to gluon
        imported_net = onnx_mxnet.import_to_gluon(export_path, ctx=None)
        _assert_sym_equal(net_sym, _optional_group(imported_net(sym.Variable('data')), group_outputs))

        # Confirm network outputs are the same
        imported_net_output = _force_list(imported_net(data))
        for out, imp_out in zip(output, imported_net_output):
            mx.test_utils.assert_almost_equal(out.asnumpy(), imp_out.asnumpy())
Ejemplo n.º 3
0
    def _run_model_on_fold(
        self,
        model: Any,
        task: 'OpenMLTask',
        X_train: Union[np.ndarray, scipy.sparse.spmatrix, pd.DataFrame],
        rep_no: int,
        fold_no: int,
        y_train: Optional[np.ndarray] = None,
        X_test: Optional[Union[np.ndarray, scipy.sparse.spmatrix,
                               pd.DataFrame]] = None,
    ) -> Tuple[np.ndarray, np.ndarray, 'OrderedDict[str, float]',
               Optional[OpenMLRunTrace], Optional[Any]]:
        """Run a model on a repeat,fold,subsample triplet of the task and return prediction
        information.

        Furthermore, it will measure run time measures in case multi-core behaviour allows this.
        * exact user cpu time will be measured if the number of cores is set (recursive throughout
        the model) exactly to 1
        * wall clock time will be measured if the number of cores is set (recursive throughout the
        model) to any given number (but not when it is set to -1)

        Returns the data that is necessary to construct the OpenML Run object. Is used by
        run_task_get_arff_content. Do not use this function unless you know what you are doing.

        Parameters
        ----------
        model : Any
            The UNTRAINED model to run. The model instance will be copied and not altered.
        task : OpenMLTask
            The task to run the model on.
        X_train : array-like
            Training data for the given repetition and fold.
        rep_no : int
            The repeat of the experiment (0-based; in case of 1 time CV, always 0)
        fold_no : int
            The fold nr of the experiment (0-based; in case of holdout, always 0)
        y_train : Optional[np.ndarray] (default=None)
            Target attributes for supervised tasks. In case of classification, these are integer
            indices to the potential classes specified by dataset.
        X_test : Optional, array-like (default=None)
            Test attributes to test for generalization in supervised tasks.

        Returns
        -------
        predictions : np.ndarray
            Model predictions.
        probabilities :  Optional, np.ndarray
            Predicted probabilities (only applicable for supervised classification tasks).
        user_defined_measures : OrderedDict[str, float]
            User defined measures that were generated on this fold
        trace : Optional, OpenMLRunTrace
            Hyperparameter optimization trace (only applicable for supervised tasks with
            hyperparameter optimization).
        additional_information: Optional, Any
            Additional information provided by the extension to be converted into additional files.
        """
        def _prediction_to_probabilities(y: np.ndarray,
                                         classes: List[Any]) -> np.ndarray:
            """Transforms predicted probabilities to match with OpenML class indices.

            Parameters
            ----------
            y : np.ndarray
                Predicted probabilities (possibly omitting classes if they were not present in the
                training data).
            classes : list
                List of classes known_predicted by the model, ordered by their index.

            Returns
            -------
            np.ndarray
            """
            # y: list or numpy array of predictions
            # model_classes: keras classifier mapping from original array id to
            # prediction index id
            if not isinstance(classes, list):
                raise ValueError(
                    'please convert model classes to list prior to '
                    'calling this fn')
            result = np.zeros((len(y), len(classes)), dtype=np.float32)
            for obs, prediction_idx in enumerate(y):
                result[obs][prediction_idx] = 1.0
            return result

        if isinstance(task, OpenMLSupervisedTask):
            if y_train is None:
                raise TypeError('argument y_train must not be of type None')
            if X_test is None:
                raise TypeError('argument X_test must not be of type None')

        # Save model to file and import it as MXNet model
        onnx.save(model, ONNX_FILE_PATH)
        model_mx = onnx_mxnet.import_to_gluon(ONNX_FILE_PATH, ctx=context)

        # Remove the saved file
        if os.path.exists(ONNX_FILE_PATH):
            os.remove(ONNX_FILE_PATH)

        # Reinitialize weights and bias
        model_mx.initialize(init=mx.init.Uniform(), force_reinit=True)

        # Sanitize train and test data
        X_train[np.isnan(X_train)] = sanitize_value
        if X_test is not None:
            X_test[np.isnan(X_test)] = sanitize_value

        user_defined_measures = OrderedDict(
        )  # type: 'OrderedDict[str, float]'

        try:

            if isinstance(task, OpenMLSupervisedTask):
                # Obtain loss function from configuration
                loss_fn = criterion_gen(task)

                # Define trainer using optimizer from configuration
                trainer = gluon.Trainer(model_mx.collect_params(), optimizer)

                # Calculate the number of batches using batch size from configuration
                nr_of_batches = math.ceil(X_train.shape[0] / batch_size)

                for j in range(epoch_count):
                    for i in range(nr_of_batches):
                        # Take current batch of input data and labels
                        input = nd.array(X_train[i * batch_size:(i + 1) *
                                                 batch_size])
                        if y_train is not None:
                            labels = nd.array(y_train[i * batch_size:(i + 1) *
                                                      batch_size])

                        # Train the model
                        with autograd.record():
                            output = model_mx(input)
                            loss = loss_fn(output, labels)

                        loss.backward()
                        trainer.step(input.shape[0])

        except AttributeError as e:
            # typically happens when training a regressor on classification task
            raise PyOpenMLError(str(e))

        if isinstance(task, OpenMLClassificationTask):
            model_classes = mx.nd.argmax(nd.array(y_train), axis=-1)

        # In supervised learning this returns the predictions for Y
        if isinstance(task, OpenMLSupervisedTask):
            pred_y = model_mx(nd.array(X_test))
            if isinstance(task, OpenMLClassificationTask):
                pred_y = mx.nd.argmax(pred_y, -1)
                pred_y = (pred_y.asnumpy()).astype(np.int64)
            if isinstance(task, OpenMLRegressionTask):
                pred_y = pred_y.asnumpy()
                pred_y = pred_y.reshape((-1))
        else:
            raise ValueError(task)

        if isinstance(task, OpenMLClassificationTask):

            try:
                proba_y = model_mx(nd.array(X_test)).asnumpy()
            except AttributeError:
                if task.class_labels is not None:
                    proba_y = _prediction_to_probabilities(
                        pred_y, list(task.class_labels))
                else:
                    raise ValueError('The task has no class labels')
            if task.class_labels is not None:
                if proba_y.shape[1] != len(task.class_labels):
                    # Remap the probabilities in case there was a class missing at training time
                    # By default, the classification targets are mapped to be zero-based indices
                    # to the actual classes. Therefore, the model_classes contain the correct
                    # indices to the correct probability array. Example:
                    # classes in the dataset: 0, 1, 2, 3, 4, 5
                    # classes in the training set: 0, 1, 2, 4, 5
                    # then we need to add a column full of zeros into the probabilities for class 3
                    # (because the rest of the library expects that the probabilities are ordered
                    # the same way as the classes are ordered).
                    proba_y_new = np.zeros(
                        (proba_y.shape[0], len(task.class_labels)))
                    for idx, model_class in enumerate(model_classes):
                        proba_y_new[:, model_class] = proba_y[:, idx]
                    proba_y = proba_y_new

                if proba_y.shape[1] != len(task.class_labels):
                    message = "Estimator only predicted for {}/{} classes!".format(
                        proba_y.shape[1],
                        len(task.class_labels),
                    )
                    warnings.warn(message)
                    openml.config.logger.warn(message)

        elif isinstance(task, OpenMLRegressionTask):
            proba_y = None
        else:
            raise TypeError(type(task))

        return pred_y, proba_y, user_defined_measures, None, None
    def __init__(self,
                 data_mean=None,
                 data_std=None,
                 mx_context=None,
                 batch_size=None,
                 **kwargs):
        super(Net_0, self).__init__(**kwargs)
        with self.name_scope():
            self.save_specific_params_list = []
            if data_mean:
                assert (data_std)
                self.input_normalization_data_ = ZScoreNormalization(
                    data_mean=data_mean['data_'], data_std=data_std['data_'])
            else:
                self.input_normalization_data_ = NoNormalization()

            lastEpoch = 0
            symbolFile = None
            weightFile = None
            onnxFile = None
            for file in os.listdir("pretrained"):
                if "network_name-" in file and ".json" in file:
                    symbolFile = file

                if "network_name-" in file and ".param" in file:
                    epochStr = file.replace(".params",
                                            "").replace("network_name-", "")
                    epoch = int(epochStr)
                    if epoch >= lastEpoch:
                        lastEpoch = epoch
                        weightFile = file

                if "network_name-" in file and ".onnx" in file:
                    onnxFile = file

            inputNames = ["data"]
            zeroInputs = [nd.zeros((1, 128), ctx=mx_context[0])]
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                if symbolFile and weightFile:
                    self.loadnetwork1_ = gluon.nn.SymbolBlock.imports(
                        "pretrained/" + symbolFile,
                        inputNames,
                        "pretrained/" + weightFile,
                        ctx=mx_context)
                elif onnxFile:
                    from mxnet.contrib import onnx as onnx_mxnet
                    self.loadnetwork1_ = onnx_mxnet.import_to_gluon(
                        "pretrained/" + onnxFile, ctx=mx_context)
                else:
                    raise FileNotFoundError(
                        "Model files were not found in 'pretrained'.")

            self.loadnetwork1_out_shape = self.loadnetwork1_(*zeroInputs).shape
            if self.loadnetwork1_out_shape != (1, 1, 768):
                outputSize = 1
                for x in (
                        1,
                        768,
                ):
                    outputSize = outputSize * x
                self.loadnetwork1_fc_ = gluon.nn.Dense(units=outputSize,
                                                       use_bias=False,
                                                       flatten=False)

            self.fc1_ = gluon.nn.Dense(units=33, use_bias=True, flatten=True)
            # fc1_, output shape: {[33,1,1]}

            pass