Skip to content

Commit

Permalink
Improve PySS3's verbosity level handling (#1)
Browse files Browse the repository at this point in the history
In response to Issue #1, the way in which PySS3 handled the level of
verbosity was redesigned in order to give the user greater control
through a clearer interface.
Now PySS3 supports the following 3 levels of verbosity:

- ``0`` (quiet): do not output any message (only error messages)
- ``1`` (normal): default behavior, display only warning messages and
                  progress bars [*]
- ``2`` (verbose): display also the informative non-essential messages

Besides, now the following built-in constants can also be used to refer
to these 3 values: ``VERBOSITY.QUIET``, ``VERBOSITY.NORMAL``, and
``VERBOSITY.VERBOSE``, respectively.
In addition, a ``set_verbosity`` function has been added to the main
module, for the user to change the verbosity level.
For example, let's suppose we want to set the verbosity level to
'quiet', then we could use:

>>> import pyss3
...
>>> pyss3.set_verbosity(0)
...

or, equivalently:

>>> import pyss3
>>> from pyss3 import VERBOSITY
...
>>> pyss3.set_verbosity(VERBOSITY.QUIET)
...

To carry out this update, the ``Print`` class was partially redesigned,
and therefore, as it can be seen, the source code of all the modules
had to be modified as well (to be compatible with the new ``Print``
design).

[*] Note that, unlike before, PySS3 will now, by default, only show
progress bars (plus warning or error messages).

Resolves: #1
  • Loading branch information
sergioburdisso committed Feb 11, 2020
1 parent 85939da commit 216be41
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 66 deletions.
49 changes: 42 additions & 7 deletions pyss3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from time import time
from tqdm import tqdm
from math import pow, tanh
from .util import Print, Preproc as Pp
from .util import Print, VERBOSITY, Preproc as Pp

# python 2 and 3 compatibility
from functools import reduce
Expand All @@ -39,6 +39,8 @@
STR_MODEL_FOLDER = "ss3_models"
STR_MODEL_EXT = "ss3m"

VERBOSITY = VERBOSITY # to allow "from pyss3 import VERBOSITY"

NAME = 0
VOCAB = 1

Expand Down Expand Up @@ -2025,14 +2027,12 @@ def fit(self, x_train, y_train, n_grams=1, prep=True, leave_pbar=True):
y_train = list(cats)

Print.info("about to start training", offset=1)
Print.quiet_begin()
for i in tqdm(range(len(x_train)), desc=" Training", leave=leave_pbar):
for i in tqdm(range(len(x_train)), desc=" Training",
leave=leave_pbar, disable=Print.is_quiet()):
self.learn(
x_train[i], y_train[i],
n_grams=n_grams, prep=prep, update=False
)

Print.quiet_end()
self.__prune_tries__()
Print.info("finished --time: %.1fs" % (time() - stime), offset=1)
self.update_values(force=True)
Expand All @@ -2058,7 +2058,7 @@ def predict_proba(self, x_test, prep=True, leave_pbar=True):
classify = self.classify
return [
classify(x, sort=False)
for x in tqdm(x_test, desc=" Classification")
for x in tqdm(x_test, desc=" Classification", disable=Print.is_quiet())
]

def predict(
Expand Down Expand Up @@ -2117,7 +2117,8 @@ def predict(

y_pred = [
classify(doc, def_cat=def_cat, labels=labels, prep=prep)
for doc in tqdm(x_test, desc=" Classification", leave=leave_pbar)
for doc in tqdm(x_test, desc=" Classification",
leave=leave_pbar, disable=Print.is_quiet())
]

Print.info("finished --time: %.1fs" % (time() - stime), offset=1)
Expand Down Expand Up @@ -2237,6 +2238,40 @@ def vdiv(v0, v1):
return [v0[i] / v1[i] if v1[i] else 0 for i in xrange(len(v0))]


def set_verbosity(level):
"""
Set the verbosity level.
- ``0`` (quiet): do not output any message (only error messages)
- ``1`` (normal): default behavior, display only warning messages and progress bars
- ``2`` (verbose): display also the informative non-essential messages
The following built-in constants can also be used to refer to these 3 values:
``VERBOSITY.QUIET``, ``VERBOSITY.NORMAL``, and ``VERBOSITY.VERBOSE``, respectively.
For example, if you want PySS3 to hide everything, even progress bars, you could simply do:
>>> import pyss3
...
>>> pyss3.set_verbosity(0)
...
>>> # here's the rest of your code :D
or, equivalently:
>>> import pyss3
>>> from pyss3 import VERBOSITY
...
>>> pyss3.set_verbosity(VERBOSITY.QUIET)
...
>>> # here's the rest of your code :D
:param level: the verbosity level
:type level: int
"""
Print.set_verbosity(level)


# aliases
SS3.set_smoothness = SS3.set_s
SS3.get_smoothness = SS3.get_s
Expand Down
31 changes: 16 additions & 15 deletions pyss3/cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from sklearn.model_selection import StratifiedKFold

from .server import Server
from .util import Print, Dataset, RecursiveDefaultDict
from .util import Print, VERBOSITY, Dataset, RecursiveDefaultDict
from . import \
SS3, InvalidCategoryError, STR_MODEL_EXT, \
STR_UNKNOWN_CATEGORY, IDX_UNKNOWN_CATEGORY, __version__
Expand Down Expand Up @@ -873,9 +873,9 @@ def delete_results_slpa(rh_metric, hparams, only_count=False, best=True):

def delete_results(data_path, method, def_cat, hparams, only_count=False):
"""Remove evaluations from history."""
Print.quiet_begin()
Print.verbosity_region_begin(VERBOSITY.QUIET)
load_results_history()
Print.quiet_end()
Print.verbosity_region_end()

rh = RESULTS_HISTORY
hps = hparams
Expand Down Expand Up @@ -975,9 +975,9 @@ def evaluations_remove(data_path, method, def_cat, hparams):
if input() == 'Y':
delete_results(data_path, method, def_cat, hparams)
if RESULTS_HISTORY:
Print.quiet_begin()
Print.verbosity_region_begin(VERBOSITY.QUIET)
save_results_history()
Print.quiet_end()
Print.verbosity_region_end()
else:
rh_file = path.join(
CLF.__models_folder__,
Expand Down Expand Up @@ -1037,7 +1037,7 @@ def k_fold_validation(
except GetTestDataError:
return

Print.set_quiet(True)
Print.set_verbosity(VERBOSITY.NORMAL)
model_name = CLF.get_name()
method = k_fold2method(k_fold)

Expand Down Expand Up @@ -1074,15 +1074,14 @@ def k_fold_validation(

progress_bar.update(1)
except KeyboardInterrupt:
Print.set_quiet(False)
Print.set_verbosity(VERBOSITY.VERBOSE)
print()
Print.warn("Interrupted!")
pass

progress_bar.close()
CLF = SS3(name=model_name)
CLF.load_model()
Print.set_quiet(False)
Print.set_verbosity(VERBOSITY.VERBOSE)

Print.show()
k_fold_classification_report(
Expand Down Expand Up @@ -1114,7 +1113,7 @@ def grid_search_loop(
method = k_fold2method(k_fold)
S, L, P, _ = CLF.get_hyperparameters()

Print.quiet_begin()
Print.verbosity_region_begin(VERBOSITY.QUIET)
try:
for s, l, p in slp_list:
CLF.set_hyperparameters(s, l, p)
Expand Down Expand Up @@ -1165,7 +1164,7 @@ def grid_search_loop(
progress_bar.update(1)
progress_desc.update(1)
except KeyboardInterrupt:
Print.set_quiet(False)
Print.set_verbosity(VERBOSITY.VERBOSE)
print()
Print.warn("Interrupted!")

Expand All @@ -1176,7 +1175,7 @@ def grid_search_loop(
CLF.set_hyperparameters(S, L, P)
CLF.update_values()

Print.quiet_end()
Print.verbosity_region_end()


def grid_search(
Expand Down Expand Up @@ -1211,7 +1210,7 @@ def grid_search(
except GetTestDataError:
return

Print.set_quiet(True)
Print.set_verbosity(VERBOSITY.NORMAL)
model_name = CLF.get_name()
s, l, p, a = CLF.get_hyperparameters()

Expand Down Expand Up @@ -1241,15 +1240,15 @@ def grid_search(

progress_bar.update(1)
except KeyboardInterrupt:
Print.set_quiet(False)
Print.set_verbosity(VERBOSITY.VERBOSE)
print()
Print.warn("Interrupted!")

progress_bar.close()
CLF = SS3(name=model_name)
CLF.load_model()
CLF.set_hyperparameters(s, l, p, a)
Print.set_quiet(False)
Print.set_verbosity(VERBOSITY.VERBOSE)

Print.warn(
"Suggestion: use the command 'plot %s' to visualize the results"
Expand Down Expand Up @@ -2607,6 +2606,8 @@ def main():
prompt = SS3Prompt()
prompt.prompt = '(pyss3) >>> '
prompt.doc_header = "Documented commands (type help <command>):"

Print.set_verbosity(VERBOSITY.VERBOSE)
Print.info(
'PySS3 Command Line v%s | Sergio Burdisso (sergio.burdisso@gmail.com).\n'
'PySS3 comes with ABSOLUTELY NO WARRANTY. This is free software,\n'
Expand Down
29 changes: 14 additions & 15 deletions pyss3/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from datetime import datetime

from . import SS3
from .util import RecursiveDefaultDict, Print
from .util import RecursiveDefaultDict, Print, VERBOSITY

import webbrowser
import argparse
Expand Down Expand Up @@ -251,10 +251,9 @@ def __load_testset_from_files__():
r[0][0] if r[0][1] else unkwon_cat_i
for r in map(
classify,
tqdm(
fcat.readlines(),
desc=" Classifying '%s' docs" % cat
)
tqdm(fcat.readlines(),
desc=" Classifying '%s' docs" % cat,
disable=Print.is_quiet())
)
]
n_docs = len(Server.__docs__[cat]["clf_result"])
Expand All @@ -276,10 +275,9 @@ def __load_testset_from_files__():
Server.__docs__[cat]["file"] = []
Server.__docs__[cat]["clf_result"] = []

for file in tqdm(
sorted(listdir(cat_path)),
desc=" Classifying '%s' docs" % cat
):
for file in tqdm(sorted(listdir(cat_path)),
desc=" Classifying '%s' docs" % cat,
disable=Print.is_quiet()):
file_path = path.join(cat_path, file)
if path.isfile(file_path):
Server.__docs__[cat]["path"].append(file_path)
Expand Down Expand Up @@ -404,9 +402,8 @@ def start_listening(port=0):
Server.__port__ = server_socket.getsockname()[1]

Print.info(
"PySS3 server started (listening on port %d)"
%
Server.__port__
"PySS3 server started (listening on port %d)" % Server.__port__,
force_show=True
)

Print.warn(
Expand Down Expand Up @@ -465,7 +462,9 @@ def serve(
webbrowser.open("http://localhost:%d" % Server.__port__)

if quiet:
Print.quiet_begin()
Print.verbosity_region_begin(VERBOSITY.QUIET)
else:
Print.verbosity_region_begin(VERBOSITY.VERBOSE)

Print.info("waiting for requests")
print()
Expand Down Expand Up @@ -496,7 +495,7 @@ def serve(
Server.__server_socket__ = None

if quiet:
Print.quiet_end()
Print.verbosity_region_end()


if __name__ == "__main__":
Expand All @@ -517,7 +516,7 @@ def serve(
args = parser.parse_args()

if args.quiet:
Print.quiet_begin()
Print.set_verbosity(VERBOSITY.QUIET)

Print.warn(
'PySS3 Server comes with ABSOLUTELY NO WARRANTY. This is free software,'
Expand Down
Loading

0 comments on commit 216be41

Please sign in to comment.