Пример #1
0
def keras_evaluate(keras_model, eval_dataset_fn, save, keras_model_pkg,
                   validation_metrics):
    model_metrics = []
    if hasattr(keras_model_pkg, "eval_metrics_fn"):
        metrics_functions = keras_model_pkg.eval_metrics_fn()
        for key, func in metrics_functions.items():
            func.__name__ = key
            model_metrics.append(func)
    # use WITH specified metrics if it's not default.
    if validation_metrics != ["Accuracy"]:
        keras_metrics = metrics.get_keras_metrics(validation_metrics)
    else:
        if len(model_metrics) > 0:
            keras_metrics = model_metrics
        else:
            # default
            keras_metrics = metrics.get_keras_metrics(["Accuracy"])
    has_custom_evaluate_func = hasattr(keras_model, 'sqlflow_evaluate_loop')

    if not has_custom_evaluate_func:
        # compile the model with default arguments only for evaluation
        # (run forward only).
        keras_model.compile(loss=keras_model_pkg.loss, metrics=keras_metrics)

    eval_dataset = eval_dataset_fn()

    def get_features(sample, label):
        return sample

    eval_dataset_x = eval_dataset.map(get_features)

    if has_custom_evaluate_func:
        result = keras_model.sqlflow_evaluate_loop(eval_dataset,
                                                   validation_metrics)
    else:
        one_batch = next(iter(eval_dataset_x))
        # NOTE: must run predict one batch to initialize parameters
        # see: https://www.tensorflow.org/alpha/guide/keras/saving_and_serializing#saving_subclassed_models # noqa: E501
        keras_model.predict_on_batch(one_batch)
        keras_model.load_weights(save)
        result = keras_model.evaluate(eval_dataset)

    assert (len(result) == len(validation_metrics) + 1)
    result_metrics = dict()
    for idx, m in enumerate(["loss"] + validation_metrics):
        result_metrics[m] = result[idx]
    return result_metrics
Пример #2
0
def keras_compile(estimator, model_params, metric_names):
    # remove optimizer param from model_params and use it when call "compile()"
    optimizer = None
    loss = None
    if "optimizer" in model_params:
        optimizer = model_params["optimizer"]
        del model_params["optimizer"]
    if "loss" in model_params:
        loss = model_params["loss"]
        del model_params["loss"]

    classifier_pkg = sys.modules[estimator.__module__]
    model_metrics = []
    if hasattr(classifier_pkg, "eval_metrics_fn"):
        metrics_functions = classifier_pkg.eval_metrics_fn()
        for key, func in metrics_functions.items():
            func.__name__ = key
            model_metrics.append(func)
    # use WITH specified metrics if it's not default.
    if metric_names != ["Accuracy"]:
        keras_metrics = metrics.get_keras_metrics(metric_names)
    else:
        if len(model_metrics) > 0:
            keras_metrics = model_metrics
        else:
            keras_metrics = metrics.get_keras_metrics(["Accuracy"])

    # setting optimizer
    has_none_optimizer = False
    if optimizer is None:
        # use keras model default optimizer if optimizer is not specified in
        # WITH clause.
        members = inspect.getmembers(classifier_pkg)
        # default optimizer
        optimizer = tf.keras.optimizers.Adagrad(lr=0.001)
        for m, func in members:
            if m == "optimizer":
                optimizer = classifier_pkg.optimizer()
                if optimizer is None:
                    has_none_optimizer = True
                    warnings.warn('optimizer() returns None')

    if loss is None:
        members = inspect.getmembers(classifier_pkg)
        # FIXME(typhoonzero): default loss may cause error if model's output
        # shape does not fit.
        loss = "sparse_categorical_crossentropy"
        for m, func in members:
            if m == "loss":
                loss = classifier_pkg.loss

    classifier = init_model_with_feature_column(
        estimator, model_params, has_none_optimizer=has_none_optimizer)

    # FIXME(sneaxiy): some models defined by other framework (not TensorFlow or
    # XGBoost) may return None optimizer.
    # For example:
    # https://github.com/sql-machine-learning/models/blob/ce970d14a524e20de10a645c99b6bf8724be17d9/sqlflow_models/arima_with_stl_decomposition.py#L123  # noqa: E501
    if has_none_optimizer:
        assert hasattr(
            classifier,
            "sqlflow_train_loop"), "optimizer() should not return None"
    else:
        classifier.compile(optimizer=optimizer,
                           loss=loss,
                           metrics=keras_metrics)

    return classifier, has_none_optimizer