@@ -17,6 +17,7 @@ | |||
""" | |||
import re | |||
import time | |||
import urllib.parse | |||
from pathlib import Path | |||
from django.http import HttpResponseNotAllowed, HttpResponseBadRequest, \ | |||
JsonResponse, HttpResponse | |||
@@ -228,9 +229,17 @@ def response_wrapper(fn): | |||
}) | |||
return res | |||
except Exception as e: | |||
_tb = e.__traceback__ | |||
_str_tb = "" | |||
while _tb: | |||
_st = "in {}, at line {} \n".format(_tb.tb_frame.f_globals["__file__"], | |||
_tb.tb_lineno) | |||
_str_tb += _st | |||
_tb = _tb.tb_next | |||
msg = "{}: Trace: {}".format(str(e), _str_tb) | |||
return JsonResponse({ | |||
'code': 500, | |||
'msg': str(e), | |||
'msg': msg, | |||
'data': "" | |||
}) | |||
@@ -256,5 +265,9 @@ def get_api_params(request, params): | |||
params_key = res.keys() | |||
if 'uid' in params_key and 'trainJobName' in params_key: | |||
res['uid'] = res['uid'] + '_' + res['trainJobName'] | |||
return res.values() | |||
ret = list(res.values()) | |||
for i, r in enumerate(ret): | |||
ret[i] = urllib.parse.unquote(r) | |||
if '%' in ret[i]: | |||
ret[i] = urllib.parse.unquote(ret[i]) | |||
return ret |
@@ -287,11 +287,11 @@ class Proxy: | |||
def _get_links(self): | |||
links = defaultdict(list) | |||
for node in self._nodes: | |||
to_name_without = get_source_name(node.name) | |||
from_names = node.input | |||
to_name_without = get_source_name(node["name"]) | |||
from_names = node["inputs"] | |||
if from_names: | |||
for from_name in from_names: | |||
name = node.name | |||
name = node["name"] | |||
from_name_without_ = get_source_name(from_name) | |||
if "^" in from_name: | |||
name = "^" + name | |||
@@ -304,8 +304,8 @@ class Proxy: | |||
def _set_graph(self): | |||
G = Graph() | |||
for node in self._nodes: | |||
tmp_node = Node(node.name, node.op) | |||
links = self._links[node.name] | |||
tmp_node = Node(node["name"], node["op"]) | |||
links = self._links[node["name"]] | |||
if links: | |||
for f, t in links: | |||
f_without = get_source_name(f) | |||
@@ -313,7 +313,7 @@ class Proxy: | |||
tmp_node.add_output(t) | |||
else: | |||
tmp_node.add_input(f) | |||
tmp_node.set_attr(node.attr) | |||
tmp_node.set_attr(node["attrs"]) | |||
G.add_node(tmp_node) | |||
return G | |||
@@ -183,34 +183,8 @@ def edge_deal(node, edges_info, edges_info_num, edges_info_list, edges_control_i | |||
edge_id = i + "__" + j | |||
if sign == 0: | |||
edges_info_temp[edge_id] = output_shapes[0] | |||
# 若该边存在多条,则以;的形式对边信息进行划分 | |||
# 其中若边信息为空,则以()替代 | |||
# if edge_id not in edges_info.keys(): | |||
# edges_info[edge_id] = output_shapes[0] | |||
# edges_info_num[edge_id] = 1 | |||
# else: | |||
# if edges_info[edge_id] == '': | |||
# edges_info[edge_id] = '()' | |||
# if output_shapes[0] == '': | |||
# edges_info[edge_id] = edges_info[edge_id] + ';' + '()' | |||
# else: | |||
# edges_info[edge_id] = edges_info[edge_id] + ';' + output_shapes[0] | |||
# edges_info_num[edge_id] += 1 | |||
else: | |||
edges_info_temp[edge_id] = cur2targets_edge_info[k] | |||
# 若该边存在多条,则以;的形式对边信息进行划分 | |||
# 其中若边信息为空,则以()替代 | |||
# if edge_id not in edges_info.keys(): | |||
# edges_info[edge_id] = cur2targets_edge_info[k] | |||
# edges_info_num[edge_id] = 1 | |||
# else: | |||
# if edges_info[edge_id] == '': | |||
# edges_info[edge_id] = '()' | |||
# if cur2targets_edge_info[k] == '': | |||
# edges_info[edge_id] = edges_info[edge_id] + ';' + '()' | |||
# else: | |||
# edges_info[edge_id] = edges_info[edge_id] + ';' + cur2targets_edge_info[k] | |||
# edges_info_num[edge_id] += 1 | |||
# 构造和存储每条边的控制信息 | |||
# 若对于一条边既存在实边也存在控制边,则绘制为实边 | |||
@@ -342,24 +316,7 @@ def data_build(tree, graph, data, level, curr_path=None): | |||
if (key != "_output_shapes") & (key != "shape"): | |||
node_attr[key] = str(node_info.attr[key]).replace('\n', '') | |||
elif key == "shape": | |||
# shape处理成{1,1,1}形式的字符串 | |||
# 每个shape都是一个protobuf,通过.来获取子层结构 | |||
raw_dim = node_info.attr[key].shape.dim | |||
raw_dim_length = len(raw_dim) | |||
new_dim = "" | |||
for j, dim in enumerate(raw_dim): | |||
str_dim = "" | |||
if dim.size == -1: | |||
str_dim = "?" | |||
else: | |||
str_dim = str(dim.size) | |||
if j == 0: | |||
new_dim = '{' + str_dim | |||
else: | |||
new_dim += ',' + str_dim | |||
if j == raw_dim_length - 1: | |||
new_dim += '}' | |||
node_attr[key] = new_dim | |||
node_attr[key] = node_info.attr[key] | |||
elif key == "_output_shapes": | |||
# 在_output_shapes中用一个list存储当前节点到其他节点边的维度信息,每一个是一个shape | |||
shape_list = node_info.attr[key].list.shape | |||
@@ -488,6 +445,3 @@ def get_data(graph): | |||
# TODO | |||
# 放回data | |||
return data | |||
# f = open('data_v1.txt', 'w') | |||
# f.write(str(data)) | |||
# f.close() |
@@ -18,8 +18,7 @@ | |||
import json | |||
from utils.cache_io import CacheIO | |||
from utils.path_utils import get_file_path | |||
from .graph_read import get_data as graph_get_data | |||
from .s_graph_read import get_s_graph_data | |||
from .s_graph_read import get_s_graph_data, get_c_graph_data | |||
from .graph import graph_op | |||
from backend.api.utils import get_api_params | |||
@@ -28,8 +27,8 @@ def graph_provider(file_path): | |||
res = CacheIO(file_path).get_cache() | |||
if res: | |||
return { | |||
'net': get_s_graph_data(res) if isinstance(res, str) | |||
else graph_get_data(res), | |||
'net': get_s_graph_data(res) if "s_graph" in str(file_path) | |||
else get_c_graph_data(res), | |||
'operator': graph_op | |||
} | |||
else: | |||
@@ -18,18 +18,36 @@ | |||
import json | |||
from backend.component.Graph.parse_json import Proxy_json | |||
from backend.component.Graph.graph import Node | |||
from backend.component.Graph.graph_read import get_data | |||
# Base_RATE = 16 | |||
# nodes保留每个节点的单独信息,以节点全称为key进行索引 | |||
nodes = {} | |||
# edges_info保留每条线的维度信息,以起始节点+‘_’+目标节点为key进行索引 | |||
edges_info = {} | |||
class Graph: | |||
def __init__(self): | |||
self.nodes = [] | |||
@property | |||
def node(self): | |||
return self.nodes | |||
def add_node(self, node): | |||
node["name"] = node["uid"].replace("-", "/") | |||
for i in range(len(node["inputs"])): | |||
node["inputs"][i] = node["inputs"][i].replace("-", "/") | |||
self.nodes.append(node) | |||
# 同根同支,以短边的尽头为分叉点 | |||
# 同根不同支, | |||
# 不同根 | |||
def diff_index_find(small_len, node_edge_list, target_edge_list, same_root, same_branch): | |||
def diff_index_find(small_len, node_edge_list, target_edge_list, same_root, | |||
same_branch): | |||
# 遍历寻找分叉点 | |||
for i in range(small_len): | |||
@@ -101,7 +119,8 @@ def edge_deal(node): | |||
unique_sign = False | |||
duplication_sign = False | |||
if "_output_shapes" in nodes[target]["attrs"]: | |||
target_output_shapes = nodes[target]["attrs"]["_output_shapes"] | |||
target_output_shapes = nodes[target]["attrs"][ | |||
"_output_shapes"] | |||
else: | |||
target_output_shapes = [""] | |||
# 若有匹配 | |||
@@ -111,11 +130,13 @@ def edge_deal(node): | |||
if duplication_sign: | |||
break | |||
for target_output_shape in target_output_shapes: | |||
if (output_shape == target_output_shape) & (unique_sign is False): | |||
if (output_shape == target_output_shape) & ( | |||
unique_sign is False): | |||
unique_sign = True | |||
cur2targets_edge_info[i] = output_shape | |||
break | |||
elif (output_shape == target_output_shape) & (unique_sign is True): | |||
elif (output_shape == target_output_shape) & ( | |||
unique_sign is True): | |||
duplication_sign = True | |||
cur2targets_edge_info[i] = "{?}" | |||
# candidate_list.append(target) | |||
@@ -144,9 +165,13 @@ def edge_deal(node): | |||
# 寻找分叉点 | |||
if node_edge_len < target_edge_len: | |||
diff_index = diff_index_find(node_edge_len, node_edge_list, target_edge_list, same_root, same_branch) | |||
diff_index = diff_index_find(node_edge_len, node_edge_list, | |||
target_edge_list, same_root, | |||
same_branch) | |||
else: | |||
diff_index = diff_index_find(target_edge_len, node_edge_list, target_edge_list, same_root, same_branch) | |||
diff_index = diff_index_find(target_edge_len, node_edge_list, | |||
target_edge_list, same_root, | |||
same_branch) | |||
# 构边与插入 | |||
# 同支情况下由于展开父节点消失,故不进行边的构建 | |||
@@ -176,7 +201,7 @@ def edge_deal(node): | |||
# layer 节点当前所在的层级 | |||
# targets 目标节点 | |||
# attrs 属性 | |||
def data_build(tree, graph, data, level, curr_path=None): | |||
def data_build(tree, graph, data, level, curr_path=None, Graph_=None): | |||
# parent用于存储父节点名称 | |||
# curr_path用于存储当前路径,主要用于虚节点的构造上 | |||
parent = curr_path | |||
@@ -272,7 +297,9 @@ def data_build(tree, graph, data, level, curr_path=None): | |||
node["op"] = node_info.op | |||
node["layer"] = level + 1 | |||
node["attrs"] = node_attr | |||
node["inputs"] = node_info.input | |||
Graph_.add_node(node) | |||
# print(node_info) | |||
node2nodes = node.copy() | |||
# nodes中node的边不重复,且仅含当前节点的信息,构建时为空,在处理后添加 | |||
node2nodes["targets"] = set() | |||
@@ -282,10 +309,12 @@ def data_build(tree, graph, data, level, curr_path=None): | |||
node["sub_net"] = [] | |||
if level == 0: | |||
data.append(node) | |||
data_build(tree.child[node_name], graph, data[i], level + 1, curr_path) | |||
data_build(tree.child[node_name], graph, data[i], | |||
level + 1, curr_path) | |||
else: | |||
data["sub_net"].append(node) | |||
data_build(tree.child[node_name], graph, data["sub_net"][i], level + 1, curr_path) | |||
data_build(tree.child[node_name], graph, | |||
data["sub_net"][i], level + 1, curr_path) | |||
def data_search(data, level=1, build=True): | |||
@@ -329,10 +358,11 @@ def data_search(data, level=1, build=True): | |||
data_search(sub_data, level + 1, build) | |||
def get_s_graph_data(s_data): | |||
def preprocess(s_data): | |||
s_data = s_data.replace('\n', '') | |||
data = json.loads(s_data) | |||
res = [] | |||
g = Graph() | |||
for d in data: | |||
proxy = Proxy_json(d) | |||
tree = proxy.tree | |||
@@ -340,12 +370,22 @@ def get_s_graph_data(s_data): | |||
_data = [] | |||
level = 0 | |||
graph = proxy.graph | |||
data_build(tree, graph, _data, level) | |||
data_build(tree, graph, _data, level, Graph_=g) | |||
# 边的重新构造,存入nodes中 | |||
data_search(_data, build=True) | |||
# 从nodes中取出边,赋值回data中 | |||
data_search(_data, build=False) | |||
if _data: | |||
res.append(_data) | |||
return [res, g] | |||
def get_s_graph_data(s_data): | |||
res, g = preprocess(s_data) | |||
return res | |||
def get_c_graph_data(c_data): | |||
res, g = preprocess(c_data) | |||
res = get_data(g) | |||
return res |
@@ -50,7 +50,8 @@ class projector_reduction: | |||
raise ValueError('The dimension of the tsne method must be 2 or 3') | |||
_data = np.array(self.data) | |||
seed = np.random.RandomState(0) | |||
data = bh_sne(_data, pca_d=True, d=self.dimension, perplexity=30, random_state=seed) | |||
perplexity = _data.shape[0]//4 if _data.shape[0]-1 < 3*30 else 30 | |||
data = bh_sne(_data, pca_d=True, d=self.dimension, perplexity=perplexity, random_state=seed) | |||
return data.tolist() | |||
@@ -17,6 +17,7 @@ | |||
""" | |||
import threading | |||
import time | |||
import json | |||
from io import BytesIO | |||
from pathlib import Path | |||
from tbparser import SummaryReader | |||
@@ -168,12 +169,46 @@ class Trace_Thread(threading.Thread): | |||
self.set_redis_key(type="embedding", tag="sample_" + items.tag, | |||
file_path=file_path) | |||
def filter_graph(self, file): | |||
variable_names = {} | |||
graph = json.loads(file) | |||
for sub_graph in graph: | |||
cfg = sub_graph["config"] | |||
# 拷贝一份,用于循环 | |||
cfg_copy = cfg["layers"].copy() | |||
for layer in cfg_copy: | |||
if layer["class_name"] == "variable": | |||
_name = layer["name"] | |||
variable_names[_name] = layer | |||
cfg["layers"].remove(layer) | |||
# 第二遍循环,删除`variable_names`出现在`inbound_nodes`中的名字 | |||
for sub_graph in graph: | |||
cfg = sub_graph["config"] | |||
for layer in cfg["layers"]: | |||
in_nodes = layer["inbound_nodes"] | |||
in_nodes_copy = in_nodes.copy() | |||
for node in in_nodes_copy: | |||
# 在里面则删除 | |||
if node in variable_names.keys(): | |||
in_nodes.remove(node) | |||
graph_str = json.dumps(graph) | |||
return graph_str | |||
def load_model_file(self, file): | |||
with open(file, "r") as f: | |||
_content = f.read() | |||
file_path = path_parser(self.cache_path, self.runname, | |||
type="graph", | |||
tag="s_graph") | |||
CacheIO(file_path).set_cache(data=_content) | |||
# 结构图内容 | |||
_cg_content = f.read() | |||
_sg_content = self.filter_graph(_cg_content) | |||
# caclulate_graph.json | |||
sg_file_path = path_parser(self.cache_path, self.runname, | |||
type="graph", | |||
tag="s_graph") | |||
cg_file_path = path_parser(self.cache_path, self.runname, | |||
type="graph", | |||
tag="c_graph") | |||
CacheIO(sg_file_path).set_cache(data=_sg_content) | |||
CacheIO(cg_file_path).set_cache(data=_cg_content) | |||
self.set_redis_key(type="graph", tag="s_graph", | |||
file_path=file_path) | |||
file_path=sg_file_path) | |||
self.set_redis_key(type="graph", tag="c_graph", | |||
file_path=cg_file_path) |
@@ -36,11 +36,12 @@ def id2logdir(uid, trainJobName): | |||
def get_file_path(uid, run, type, tag): | |||
_key = uid + '_' + run + '_' + type + '_' + tag | |||
try: | |||
_path = Path(RedisInstance.get(_key)) | |||
_res = RedisInstance.get(_key) | |||
_path = Path(_res) | |||
except TypeError: | |||
raise OSError('Redis key {} not found according to request ' | |||
'parameters, please check the parameters' | |||
.format(_key)) | |||
'parameters, please check the parameters\n _path={}' | |||
.format(_key, _res)) | |||
return _path | |||