File size: 3,626 Bytes
4943752 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
"""
Attack Logs to Visdom
========================
"""
import socket
from textattack.shared.utils import LazyLoader, html_table_from_rows
from .logger import Logger
visdom = LazyLoader("visdom", globals(), "visdom")
def port_is_open(port_num, hostname="127.0.0.1"):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((hostname, port_num))
sock.close()
if result == 0:
return True
return False
class VisdomLogger(Logger):
"""Logs attack results to Visdom."""
def __init__(self, env="main", port=8097, hostname="localhost"):
if not port_is_open(port, hostname=hostname):
raise socket.error(f"Visdom not running on {hostname}:{port}")
self.vis = visdom.Visdom(port=port, server=hostname, env=env)
self.env = env
self.port = port
self.hostname = hostname
self.windows = {}
self.sample_rows = []
def __getstate__(self):
state = {i: self.__dict__[i] for i in self.__dict__ if i != "vis"}
return state
def __setstate__(self, state):
self.__dict__ = state
self.vis = visdom.Visdom(port=self.port, server=self.hostname, env=self.env)
def log_attack_result(self, result):
text_a, text_b = result.diff_color(color_method="html")
result_str = result.goal_function_result_str(color_method="html")
self.sample_rows.append([result_str, text_a, text_b])
def log_summary_rows(self, rows, title, window_id):
self.table(rows, title=title, window_id=window_id)
def flush(self):
self.table(
self.sample_rows,
title="Sample-Level Results",
window_id="sample_level_results",
)
def log_hist(self, arr, numbins, title, window_id):
self.bar(arr, numbins=numbins, title=title, window_id=window_id)
def text(self, text_data, title=None, window_id="default"):
if window_id and window_id in self.windows:
window = self.windows[window_id]
self.vis.text(text_data, win=window)
else:
new_window = self.vis.text(text_data, opts=dict(title=title))
self.windows[window_id] = new_window
def table(self, rows, window_id=None, title=None, header=None, style=None):
"""Generates an HTML table."""
if not window_id:
window_id = title # Can provide either of these,
if not title:
title = window_id # or both.
table = html_table_from_rows(rows, title=title, header=header, style_dict=style)
self.text(table, title=title, window_id=window_id)
def bar(self, X_data, numbins=10, title=None, window_id=None):
window = None
if window_id and window_id in self.windows:
window = self.windows[window_id]
self.vis.bar(X=X_data, win=window, opts=dict(title=title, numbins=numbins))
else:
new_window = self.vis.bar(X=X_data, opts=dict(title=title, numbins=numbins))
if window_id:
self.windows[window_id] = new_window
def hist(self, X_data, numbins=10, title=None, window_id=None):
window = None
if window_id and window_id in self.windows:
window = self.windows[window_id]
self.vis.histogram(
X=X_data, win=window, opts=dict(title=title, numbins=numbins)
)
else:
new_window = self.vis.histogram(
X=X_data, opts=dict(title=title, numbins=numbins)
)
if window_id:
self.windows[window_id] = new_window
|