Exemplo n.º 1
0
    def __init__(self,
                 table_header=None,
                 table_description=None,
                 col_header=None,
                 cell_values=None,
                 raw_cell_values=None,
                 col_types=None,
                 row_header=None,
                 col_formats=None):
        """
        Create new H2OTwoDimTable object.

        :param table_header: Header for the entire table.
        :param table_description: Longer description of the table.
        :param col_header: list of column names (used in conjunction with)
        :param cell_values: table values, as an array of individual rows
        :param raw_cell_values:
        :param col_types:
        :param row_header: ignored.
        :param col_formats: ignored.
        """
        assert_is_type(table_header, None, str)
        assert_is_type(table_description, None, str)
        assert_is_type(col_header, None, [str])
        assert_is_type(col_types, None, [str])
        assert_is_type(
            cell_values, None,
            I([[object]], lambda m: all(len(row) == len(m[0]) for row in m)))
        self._table_header = table_header
        self._table_description = table_description
        self._col_header = col_header
        self._col_types = col_types
        self._cell_values = cell_values or self._parse_values(
            raw_cell_values, col_types)
Exemplo n.º 2
0
    def start(jar_path=None, nthreads=-1, enable_assertions=True, max_mem_size=None, min_mem_size=None,
              ice_root=None, port="54321+", verbose=True):
        """
        Start new H2O server on the local machine.

        :param jar_path: Path to the h2o.jar executable. If not given, then we will search for h2o.jar in the
            locations returned by `._jar_paths()`.
        :param nthreads: Number of threads in the thread pool. This should be related to the number of CPUs used.
            -1 means use all CPUs on the host. A positive integer specifies the number of CPUs directly.
        :param enable_assertions: If True, pass `-ea` option to the JVM.
        :param max_mem_size: Maximum heap size (jvm option Xmx), in bytes.
        :param min_mem_size: Minimum heap size (jvm option Xms), in bytes.
        :param ice_root: A directory where H2O stores its temporary files. Default location is determined by
            tempfile.mkdtemp().
        :param port: Port where to start the new server. This could be either an integer, or a string of the form
            "DDDDD+", indicating that the server should start looking for an open port starting from DDDDD and up.
        :param verbose: If True, then connection info will be printed to the stdout.

        :returns: a new H2OLocalServer instance
        """
        assert_is_type(jar_path, None, str)
        assert_is_type(port, None, int, str)
        assert_is_type(nthreads, -1, BoundInt(1, 4096))
        assert_is_type(enable_assertions, bool)
        assert_is_type(min_mem_size, None, int)
        assert_is_type(max_mem_size, None, BoundInt(1 << 25))
        assert_is_type(ice_root, None, I(str, os.path.isdir))
        if jar_path:
            assert_satisfies(jar_path, jar_path.endswith("h2o.jar"))

        if min_mem_size is not None and max_mem_size is not None and min_mem_size > max_mem_size:
            raise H2OValueError("`min_mem_size`=%d is larger than the `max_mem_size`=%d" % (min_mem_size, max_mem_size))
        if port is None: port = "54321+"
        baseport = None
        # TODO: get rid of this port gimmick and have 2 separate parameters.
        if is_type(port, str):
            if port.isdigit():
                port = int(port)
            else:
                if not(port[-1] == "+" and port[:-1].isdigit()):
                    raise H2OValueError("`port` should be of the form 'DDDD+', where D is a digit. Got: %s" % port)
                baseport = int(port[:-1])
                port = 0

        hs = H2OLocalServer()
        hs._verbose = bool(verbose)
        hs._jar_path = hs._find_jar(jar_path)
        hs._ice_root = ice_root
        if not ice_root:
            hs._ice_root = tempfile.mkdtemp()
            hs._tempdir = hs._ice_root

        if verbose: print("Attempting to start a local H2O server...")
        hs._launch_server(port=port, baseport=baseport, nthreads=int(nthreads), ea=enable_assertions,
                          mmax=max_mem_size, mmin=min_mem_size)
        if verbose: print("  Server is running at %s://%s:%d" % (hs.scheme, hs.ip, hs.port))
        atexit.register(lambda: hs.shutdown())
        return hs
Exemplo n.º 3
0
    def start(jar_path=None,
              nthreads=-1,
              enable_assertions=True,
              max_mem_size=None,
              min_mem_size=None,
              ice_root=None,
              log_dir=None,
              log_level=None,
              max_log_file_size=None,
              port="54321+",
              name=None,
              extra_classpath=None,
              verbose=True,
              jvm_custom_args=None,
              bind_to_localhost=True):
        """
        Start new H2O server on the local machine.

        :param jar_path: Path to the h2o.jar executable. If not given, then we will search for h2o.jar in the
            locations returned by `._jar_paths()`.
        :param nthreads: Number of threads in the thread pool. This should be related to the number of CPUs used.
            -1 means use all CPUs on the host. A positive integer specifies the number of CPUs directly.
        :param enable_assertions: If True, pass `-ea` option to the JVM.
        :param max_mem_size: Maximum heap size (jvm option Xmx), in bytes.
        :param min_mem_size: Minimum heap size (jvm option Xms), in bytes.
        :param log_dir: Directory for H2O logs to be stored if a new instance is started. Default directory is determined
            by H2O internally.
        :param log_level: The logger level for H2O if a new instance is started.
        :param max_log_file_size: Maximum size of INFO and DEBUG log files. The file is rolled over after a specified 
            size has been reached. (The default is 3MB. Minimum is 1MB and maximum is 99999MB)
        :param ice_root: A directory where H2O stores its temporary files. Default location is determined by
            tempfile.mkdtemp().
        :param port: Port where to start the new server. This could be either an integer, or a string of the form
            "DDDDD+", indicating that the server should start looking for an open port starting from DDDDD and up.
        :param name: name of the h2o cluster to be started
        :param extra_classpath: List of paths to libraries that should be included on the Java classpath.
        :param verbose: If True, then connection info will be printed to the stdout.
        :param jvm_custom_args: Custom, user-defined arguments for the JVM H2O is instantiated in
        :param bind_to_localhost: A flag indicating whether access to the H2O instance should be restricted to the local
            machine (default) or if it can be reached from other computers on the network.
            Only applicable when H2O is started from the Python client.

        :returns: a new H2OLocalServer instance
        """
        assert_is_type(jar_path, None, str)
        assert_is_type(port, None, int, str)
        assert_is_type(name, None, str)
        assert_is_type(nthreads, -1, BoundInt(1, 4096))
        assert_is_type(enable_assertions, bool)
        assert_is_type(min_mem_size, None, int)
        assert_is_type(max_mem_size, None, BoundInt(1 << 25))
        assert_is_type(log_dir, str, None)
        assert_is_type(log_level, str, None)
        assert_satisfies(
            log_level, log_level
            in [None, "TRACE", "DEBUG", "INFO", "WARN", "ERRR", "FATA"])
        assert_is_type(max_log_file_size, str, None)
        assert_is_type(ice_root, None, I(str, os.path.isdir))
        assert_is_type(extra_classpath, None, [str])
        assert_is_type(jvm_custom_args, list, None)
        assert_is_type(bind_to_localhost, bool)
        if jar_path:
            assert_satisfies(jar_path, jar_path.endswith("h2o.jar"))

        if min_mem_size is not None and max_mem_size is not None and min_mem_size > max_mem_size:
            raise H2OValueError(
                "`min_mem_size`=%d is larger than the `max_mem_size`=%d" %
                (min_mem_size, max_mem_size))
        if port is None: port = "54321+"
        baseport = None
        # TODO: get rid of this port gimmick and have 2 separate parameters.
        if is_type(port, str):
            if port.isdigit():
                port = int(port)
            else:
                if not (port[-1] == "+" and port[:-1].isdigit()):
                    raise H2OValueError(
                        "`port` should be of the form 'DDDD+', where D is a digit. Got: %s"
                        % port)
                baseport = int(port[:-1])
                port = 0

        hs = H2OLocalServer()
        hs._verbose = bool(verbose)
        hs._jar_path = hs._find_jar(jar_path)
        hs._extra_classpath = extra_classpath
        hs._ice_root = ice_root
        hs._name = name
        if not ice_root:
            hs._ice_root = tempfile.mkdtemp()
            hs._tempdir = hs._ice_root

        if verbose: print("Attempting to start a local H2O server...")
        hs._launch_server(port=port,
                          baseport=baseport,
                          nthreads=int(nthreads),
                          ea=enable_assertions,
                          mmax=max_mem_size,
                          mmin=min_mem_size,
                          jvm_custom_args=jvm_custom_args,
                          bind_to_localhost=bind_to_localhost,
                          log_dir=log_dir,
                          log_level=log_level,
                          max_log_file_size=max_log_file_size)
        if verbose:
            print("  Server is running at %s://%s:%d" %
                  (hs.scheme, hs.ip, hs.port))
        atexit.register(lambda: hs.shutdown())
        return hs
Exemplo n.º 4
0
    def std_coef_plot(self, num_of_features=None, server=False):
        """
        Plot a GLM model's standardized coefficient magnitudes.

        :param num_of_features: the number of features shown in the plot.
        :param server: ?

        :returns: None.
        """
        assert_is_type(num_of_features, None, I(int, lambda x: x > 0))

        # check that model is a glm
        if self._model_json["algo"] != "glm":
            raise H2OValueError("This function is available for GLM models only")

        plt = _get_matplotlib_pyplot(server)
        if not plt: return

        # get unsorted tuple of labels and coefficients
        unsorted_norm_coef = self.coef_norm().items()
        # drop intercept value then sort tuples by the coefficient's absolute value
        drop_intercept = [tup for tup in unsorted_norm_coef if tup[0] != "Intercept"]
        norm_coef = sorted(drop_intercept, key=lambda x: abs(x[1]), reverse=True)

        signage = []
        for element in norm_coef:
            # if positive including zero, color blue, else color orange (use same colors as Flow)
            if element[1] >= 0:
                signage.append("#1F77B4")  # blue
            else:
                signage.append("#FF7F0E")  # dark orange

        # get feature labels and their corresponding magnitudes
        feature_labels = [tup[0] for tup in norm_coef]
        norm_coef_magn = [abs(tup[1]) for tup in norm_coef]
        # specify bar centers on the y axis, but flip the order so largest bar appears at top
        pos = range(len(feature_labels))[::-1]
        # specify the bar lengths
        val = norm_coef_magn

        # check number of features, default is all the features
        if num_of_features is None:
            num_of_features = len(val)

        # plot horizontal plot
        fig, ax = plt.subplots(1, 1, figsize=(14, 10))
        # create separate plot for the case where num_of_features = 1
        if num_of_features == 1:
            plt.barh(pos[0], val[0],
                     align="center", height=0.8, color=signage[0], edgecolor="none")
            # Hide the right and top spines, color others grey
            ax.spines["right"].set_visible(False)
            ax.spines["top"].set_visible(False)
            ax.spines["bottom"].set_color("#7B7B7B")
            ax.spines["left"].set_color("#7B7B7B")
            # Only show ticks on the left and bottom spines
            ax.yaxis.set_ticks_position("left")
            ax.xaxis.set_ticks_position("bottom")
            plt.yticks([0], feature_labels[0])
            ax.margins(y=0.5)

        else:
            plt.barh(pos[0:num_of_features], val[0:num_of_features],
                     align="center", height=0.8, color=signage[0:num_of_features], edgecolor="none")
            # Hide the right and top spines, color others grey
            ax.spines["right"].set_visible(False)
            ax.spines["top"].set_visible(False)
            ax.spines["bottom"].set_color("#7B7B7B")
            ax.spines["left"].set_color("#7B7B7B")
            # Only show ticks on the left and bottom spines
            ax.yaxis.set_ticks_position("left")
            ax.xaxis.set_ticks_position("bottom")
            plt.yticks(pos[0:num_of_features], feature_labels[0:num_of_features])
            ax.margins(y=0.05)

        # generate custom fake lines that will be used as legend entries:
        # check if positive and negative values exist
        # if positive create positive legend
        if "#1F77B4" in signage[0:num_of_features] and "#FF7F0E" not in signage[0:num_of_features]:
            color_ids = {"Positive": "#1F77B4"}
            markers = [plt.Line2D([0, 0], [0, 0], color=color, marker="s", linestyle="")
                       for color in signage[0:num_of_features]]
            lgnd = plt.legend(markers, color_ids, numpoints=1, loc="best", frameon=False, fontsize=13)
            lgnd.legendHandles[0]._legmarker.set_markersize(10)
        # if neg create neg legend
        elif "#FF7F0E" in signage[0:num_of_features] and "#1F77B4" not in signage[0:num_of_features]:
            color_ids = {"Negative": "#FF7F0E"}
            markers = [plt.Line2D([0, 0], [0, 0], color=color, marker="s", linestyle="")
                       for color in set(signage[0:num_of_features])]
            lgnd = plt.legend(markers, color_ids, numpoints=1, loc="best", frameon=False, fontsize=13)
            lgnd.legendHandles[0]._legmarker.set_markersize(10)
        # if both provide both colors in legend
        else:
            color_ids = {"Positive": "#1F77B4", "Negative": "#FF7F0E"}
            markers = [plt.Line2D([0, 0], [0, 0], color=color, marker="s", linestyle="")
                       for color in set(signage[0:num_of_features])]
            lgnd = plt.legend(markers, color_ids, numpoints=1, loc="best", frameon=False, fontsize=13)
            lgnd.legendHandles[0]._legmarker.set_markersize(10)
            lgnd.legendHandles[1]._legmarker.set_markersize(10)

        # Hide the right and top spines, color others grey
        ax.spines["right"].set_visible(False)
        ax.spines["top"].set_visible(False)
        ax.spines["bottom"].set_color("#7B7B7B")
        ax.spines["left"].set_color("#7B7B7B")

        # Only show ticks on the left and bottom spines
        # ax.yaxis.set_ticks_position("left")
        # ax.xaxis.set_ticks_position("bottom")
        plt.yticks(pos[0:num_of_features], feature_labels[0:num_of_features])
        plt.tick_params(axis="x", which="minor", bottom="off", top="off",  labelbottom="off")
        plt.title("Standardized Coef. Magnitudes: H2O GLM", fontsize=20)
        # plt.axis("tight")
        # show plot
        if not server: plt.show()
Exemplo n.º 5
0
def test_asserts():
    """Test type-checking functionality."""
    def assert_error(*args, **kwargs):
        """Check that assert_is_type() with given arguments throws an error."""
        try:
            assert_is_type(*args, **kwargs)
            raise RuntimeError("Failed to throw an exception")
        except H2OTypeError as e:
            # Check whether the message can stringify properly
            message = str(e)
            assert len(message) < 1000
            return

    class A(object):
        pass

    class B(A):
        pass

    class C(A):
        pass

    class D(B, C):
        pass

    assert_is_type(3, int)
    assert_is_type(2**100, int)
    assert_is_type("3", str)
    assert_is_type(u"3", str)
    assert_is_type("foo", u"foo")
    assert_is_type(u"foo", "foo")
    assert_is_type("I", *list("ABCDEFGHIJKL"))
    assert_is_type(False, bool)
    assert_is_type(43, str, bool, int)
    assert_is_type(4 / 3, int, float)
    assert_is_type(None, None)
    assert_is_type(None, A, str, None)
    assert_is_type([], [float])
    assert_is_type([1, 4, 5], [int])
    assert_is_type([1.0, 2, 5], [int, float])
    assert_is_type([[2.0, 3.1, 0], [2, 4.4, 1.1], [-1, 0]], [[int, float]])
    assert_is_type([1, None, 2], [int, float, None])
    assert_is_type({1, 5, 1, 1, 3}, {int})
    assert_is_type({1, "hello", 3}, {int, str})
    assert_is_type({"foo": 1, "bar": 2}, {str: int})
    assert_is_type({
        "foo": 3,
        "bar": [5],
        "baz": None
    }, {str: U(int, None, [int])})
    assert_is_type({
        "foo": 1,
        "bar": 2
    }, {
        "foo": int,
        "bar": U(int, float, None),
        "baz": bool
    })
    assert_is_type((1, 3), (int, int))
    assert_is_type(("a", "b", "c"), (int, int, int), (str, str, str))
    assert_is_type([1, [2], [{3}]], [int, [int], [{3}]])
    assert_is_type(A(), None, A)
    assert_is_type(B(), None, A)
    assert_is_type(C(), A, B)
    assert_is_type(D(), I(A, B, C))
    assert_is_type(A, type)
    for a in range(-2, 5):
        assert_is_type(a, -2, -1, 0, 1, 2, 3, 4)
    assert_is_type(1, numeric)
    assert_is_type(2.2, numeric)
    assert_is_type(1, I(numeric, object))

    assert_error(3, str)
    assert_error("Z", *list("ABCDEFGHIJKL"))
    assert_error(u"Z", "a", "...", "z")
    assert_error("X", u"x")
    assert_error(0, bool)
    assert_error(0, float, str, bool, None)
    assert_error([1, 5], [float])
    assert_error((1, 3), (int, str), (str, int), (float, float))
    assert_error(A(), None, B)
    assert_error(A, A)
    assert_error({
        "foo": 1,
        "bar": "2"
    }, {
        "foo": int,
        "bar": U(int, float, None)
    })
    assert_error(3, 0, 2, 4)
    assert_error(None, numeric)
    assert_error("sss", numeric)
    assert_error(B(), I(A, B, C))
    assert_error(2, I(int, str))

    url_regex = r"^(https?)://((?:[\w-]+\.)*[\w-]+):(\d+)/?$"
    assert_matches("Hello, world!", r"^(\w+), (\w*)!$")
    assert_matches("http://127.0.0.1:3233/", url_regex)
    m = assert_matches("https://localhost:54321", url_regex)
    assert m.group(1) == "https"
    assert m.group(2) == "localhost"
    assert m.group(3) == "54321"

    x = 5
    assert_satisfies(x, x < 1000)
    assert_satisfies(x, x**x > 1000)
    assert_satisfies(url_regex, url_regex.lower() == url_regex)
    try:
        assert_satisfies(url_regex, url_regex.upper() == url_regex)
    except H2OValueError as e:
        assert "url_regex.upper() == url_regex" in str(
            e), "Error message is bad: " + str(e)
Exemplo n.º 6
0
def test_asserts():
    """Test type-checking functionality."""
    def assert_error(*args, **kwargs):
        """Check that assert_is_type() with given arguments throws an error."""
        try:
            assert_is_type(*args, **kwargs)
            raise RuntimeError("Failed to throw an exception")
        except H2OTypeError as exc:
            # Check whether the message can stringify properly
            message = str(exc)
            assert len(message) < 1000
            return

    class A(object):
        """Dummy A."""

    class B(A):
        """Dummy B."""

    class C(A):
        """Dummy C."""

    class D(B, C):
        """Dummy D."""

    assert_is_type(3, int)
    assert_is_type(2**100, int)
    assert_is_type("3", str)
    assert_is_type(u"3", str)
    assert_is_type("foo", u"foo")
    assert_is_type(u"foo", "foo")
    assert_is_type("I", *list("ABCDEFGHIJKL"))
    assert_is_type(False, bool)
    assert_is_type(43, str, bool, int)
    assert_is_type(4 / 3, int, float)
    assert_is_type(None, None)
    assert_is_type(None, A, str, None)
    assert_is_type([], [float])
    assert_is_type([1, 4, 5], [int])
    assert_is_type([1.0, 2, 5], [int, float])
    assert_is_type([[2.0, 3.1, 0], [2, 4.4, 1.1], [-1, 0]], [[int, float]])
    assert_is_type([1, None, 2], [int, float, None])
    assert_is_type({1, 5, 1, 1, 3}, {int})
    assert_is_type({1, "hello", 3}, {int, str})
    assert_is_type({"foo": 1, "bar": 2}, {str: int})
    assert_is_type({"foo": 3, "bar": [5], "baz": None}, {str: U(int, None, [int])})
    assert_is_type({"foo": 1, "bar": 2}, {"foo": int, "bar": U(int, float, None), "baz": bool})
    assert_is_type({}, {"spam": int, "egg": int})
    assert_is_type({"spam": 10}, {"spam": int, "egg": int})
    assert_is_type({"egg": 1}, {"spam": int, "egg": int})
    assert_is_type({"egg": 1, "spam": 10}, {"spam": int, "egg": int})
    assert_is_type({"egg": 1, "spam": 10}, Dict(egg=int, spam=int))
    assert_is_type({"egg": 1, "spam": 10}, Dict(egg=int, spam=int, ham=U(int, None)))
    assert_is_type((1, 3), (int, int))
    assert_is_type(("a", "b", "c"), (int, int, int), (str, str, str))
    assert_is_type((1, 3, 4, 7, 11, 18), Tuple(int))
    assert_is_type((1, 3, "spam", 3, "egg"), Tuple(int, str))
    assert_is_type([1, [2], [{3}]], [int, [int], [{3}]])
    assert_is_type(A(), None, A)
    assert_is_type(B(), None, A)
    assert_is_type(C(), A, B)
    assert_is_type(D(), I(A, B, C))
    assert_is_type(A, type)
    assert_is_type(B, lambda aa: issubclass(aa, A))
    for a in range(-2, 5):
        assert_is_type(a, -2, -1, 0, 1, 2, 3, 4)
    assert_is_type(1, numeric)
    assert_is_type(2.2, numeric)
    assert_is_type(1, I(numeric, object))
    assert_is_type(34, I(int, NOT(0)))
    assert_is_type(["foo", "egg", "spaam"], [I(str, NOT("spam"))])
    assert_is_type(H2OFrame(), h2oframe)
    assert_is_type([[2.0, 3.1, 0], [2, 4.4, 1.1], [-1, 0, 0]],
                   I([[numeric]], lambda v: all(len(vi) == len(v[0]) for vi in v)))
    assert_is_type([None, None, float('nan'), None, "N/A"], [None, "N/A", I(float, math.isnan)])

    assert_error(3, str)
    assert_error(0, float)
    assert_error("Z", *list("ABCDEFGHIJKL"))
    assert_error(u"Z", "a", "...", "z")
    assert_error("X", u"x")
    assert_error(0, bool)
    assert_error(0, float, str, bool, None)
    assert_error([1, 5], [float])
    assert_error((1, 3), (int, str), (str, int), (float, float))
    assert_error(A(), None, B)
    assert_error(A, A)
    assert_error(A, lambda aa: issubclass(aa, B))
    assert_error(135, I(int, lambda x: 0 <= x <= 100))
    assert_error({"foo": 1, "bar": "2"}, {"foo": int, "bar": U(int, float, None)})
    assert_error(3, 0, 2, 4)
    assert_error(None, numeric)
    assert_error("sss", numeric)
    assert_error(B(), I(A, B, C))
    assert_error(2, I(int, str))
    assert_error(0, I(int, NOT(0)))
    assert_error(None, NOT(None))
    assert_error((1, 3, "2", 3), Tuple(int))
    assert_error({"spam": 10}, Dict(spam=int, egg=int))
    assert_error({"egg": 5}, Dict(spam=int, egg=int))
    assert_error(False, h2oframe, pandas_dataframe, numpy_ndarray)
    assert_error([[2.0, 3.1, 0], [2, 4.4, 1.1], [-1, 0]],
                 I([[numeric]], lambda v: all(len(vi) == len(v[0]) for vi in v)))
    try:
        # Cannot use `assert_error` here because typechecks module cannot detect args in (*args, *kwargs)
        assert_is_type(10000000, I(int, lambda port: 1 <= port <= 65535))
        assert False, "Failed to throw an exception"
    except H2OTypeError as e:
        assert "integer & 1 <= port <= 65535" in str(e), "Bad error message: '%s'" % e

    url_regex = r"^(https?)://((?:[\w-]+\.)*[\w-]+):(\d+)/?$"
    assert_matches("Hello, world!", r"^(\w+), (\w*)!$")
    assert_matches("http://127.0.0.1:3233/", url_regex)
    m = assert_matches("https://localhost:54321", url_regex)
    assert m.group(1) == "https"
    assert m.group(2) == "localhost"
    assert m.group(3) == "54321"

    x = 5
    assert_satisfies(x, x < 1000)
    assert_satisfies(x, x ** x > 1000)
    assert_satisfies(url_regex, url_regex.lower() == url_regex)
    try:
        assert_satisfies(url_regex, url_regex.upper() == url_regex)
    except H2OValueError as e:
        assert "url_regex.upper() == url_regex" in str(e), "Error message is bad: " + str(e)

    try:
        import pandas
        import numpy
        assert_is_type(pandas.DataFrame(), pandas_dataframe)
        assert_is_type(numpy.ndarray(shape=(5,)), numpy_ndarray)
    except ImportError:
        pass
Exemplo n.º 7
0
    def _std_coef_plot(self,
                       num_of_features=None,
                       server=False,
                       save_plot_path=None):
        """
        Plot a GLM model"s standardized coefficient magnitudes.

        :param num_of_features: the number of features shown in the plot.
        :param server: if true set server settings to matplotlib and show the graph
        :param save_plot_path: a path to save the plot via using matplotlib function savefig

        :returns: object that contains the resulting figure (can be accessed using result.figure())
        """
        assert_is_type(num_of_features, None, I(int, lambda x: x > 0))

        plt = get_matplotlib_pyplot(server)
        if not plt: return decorate_plot_result(figure=RAISE_ON_FIGURE_ACCESS)

        # get unsorted tuple of labels and coefficients
        unsorted_norm_coef = self.coef_norm().items()
        # drop intercept value then sort tuples by the coefficient"s absolute value
        drop_intercept = [
            tup for tup in unsorted_norm_coef if tup[0] != "Intercept"
        ]
        norm_coef = sorted(drop_intercept,
                           key=lambda x: abs(x[1]),
                           reverse=True)

        signage = []
        for element in norm_coef:
            # if positive including zero, color blue, else color orange (use same colors as Flow)
            if element[1] >= 0:
                signage.append("#1F77B4")  # blue
            else:
                signage.append("#FF7F0E")  # dark orange

        # get feature labels and their corresponding magnitudes
        feature_labels = [tup[0] for tup in norm_coef]
        norm_coef_magn = [abs(tup[1]) for tup in norm_coef]
        # specify bar centers on the y axis, but flip the order so largest bar appears at top
        pos = range(len(feature_labels))[::-1]
        # specify the bar lengths
        val = norm_coef_magn

        # check number of features, default is all the features
        if num_of_features is None:
            num_of_features = len(val)

        # plot horizontal plot
        fig, ax = plt.subplots(1, 1, figsize=(14, 10))
        # create separate plot for the case where num_of_features = 1
        if num_of_features == 1:
            plt.barh(pos[0],
                     val[0],
                     align="center",
                     height=0.8,
                     color=signage[0],
                     edgecolor="none")
            # Hide the right and top spines, color others grey
            ax.spines["right"].set_visible(False)
            ax.spines["top"].set_visible(False)
            ax.spines["bottom"].set_color("#7B7B7B")
            ax.spines["left"].set_color("#7B7B7B")
            # Only show ticks on the left and bottom spines
            ax.yaxis.set_ticks_position("left")
            ax.xaxis.set_ticks_position("bottom")
            plt.yticks([0], feature_labels[0])
            ax.margins(None, 0.5)

        else:
            plt.barh(pos[0:num_of_features],
                     val[0:num_of_features],
                     align="center",
                     height=0.8,
                     color=signage[0:num_of_features],
                     edgecolor="none")
            # Hide the right and top spines, color others grey
            ax.spines["right"].set_visible(False)
            ax.spines["top"].set_visible(False)
            ax.spines["bottom"].set_color("#7B7B7B")
            ax.spines["left"].set_color("#7B7B7B")
            # Only show ticks on the left and bottom spines
            ax.yaxis.set_ticks_position("left")
            ax.xaxis.set_ticks_position("bottom")
            plt.yticks(pos[0:num_of_features],
                       feature_labels[0:num_of_features])
            ax.margins(None, 0.05)

        # generate custom fake lines that will be used as legend entries:
        # check if positive and negative values exist
        # if positive create positive legend
        if "#1F77B4" in signage[0:num_of_features] and "#FF7F0E" not in signage[
                0:num_of_features]:
            color_ids = ("Positive", )
            markers = [
                plt.Line2D([0, 0], [0, 0],
                           color=color,
                           marker="s",
                           linestyle="",
                           markersize=10)
                for color in set(signage[0:num_of_features])
            ]
            plt.legend(markers,
                       color_ids,
                       numpoints=1,
                       loc="best",
                       frameon=False,
                       fontsize=13)
        # if neg create neg legend
        elif "#FF7F0E" in signage[
                0:num_of_features] and "#1F77B4" not in signage[
                    0:num_of_features]:
            color_ids = ("Negative", )
            markers = [
                plt.Line2D([0, 0], [0, 0],
                           color=color,
                           marker="s",
                           linestyle="",
                           markersize=10)
                for color in set(signage[0:num_of_features])
            ]
            plt.legend(markers,
                       color_ids,
                       numpoints=1,
                       loc="best",
                       frameon=False,
                       fontsize=13)
        # if both provide both colors in legend
        else:
            color_ids = ("Positive", "Negative")
            markers = [
                plt.Line2D([0, 0], [0, 0],
                           color=color,
                           marker="s",
                           linestyle="",
                           markersize=10) for color in ['#1F77B4', '#FF7F0E']
            ]  # blue should always be positive, orange negative
            plt.legend(markers,
                       color_ids,
                       numpoints=1,
                       loc="best",
                       frameon=False,
                       fontsize=13)

        # Hide the right and top spines, color others grey
        ax.spines["right"].set_visible(False)
        ax.spines["top"].set_visible(False)
        ax.spines["bottom"].set_color("#7B7B7B")
        ax.spines["left"].set_color("#7B7B7B")

        # Only show ticks on the left and bottom spines
        plt.yticks(pos[0:num_of_features], feature_labels[0:num_of_features])
        plt.tick_params(axis="x",
                        which="minor",
                        bottom="off",
                        top="off",
                        labelbottom="off")
        plt.title("Standardized Coef. Magnitudes: H2O GLM", fontsize=20)
        if save_plot_path is not None:
            plt.savefig(fname=save_plot_path)
        # show plot
        if server:
            plt.show()
        return decorate_plot_result(figure=fig)