Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
项目经理老王
Mace
提交
657e369b
Mace
项目概览
项目经理老王
/
Mace
与 Fork 源项目一致
Fork自
Xiaomi / Mace
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Mace
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
657e369b
编写于
1月 04, 2019
作者:
李
李寅
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add MACE visualization
上级
22e40d66
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
419 addition
and
2 deletion
+419
-2
docs/development/how_to_debug.rst
docs/development/how_to_debug.rst
+2
-0
mace/core/tensor.h
mace/core/tensor.h
+4
-2
mace/python/tools/BUILD
mace/python/tools/BUILD
+1
-0
mace/python/tools/converter.py
mace/python/tools/converter.py
+8
-0
mace/python/tools/converter_tool/tensorflow_converter.py
mace/python/tools/converter_tool/tensorflow_converter.py
+1
-0
mace/python/tools/visualization/BUILD
mace/python/tools/visualization/BUILD
+14
-0
mace/python/tools/visualization/index.html
mace/python/tools/visualization/index.html
+297
-0
mace/python/tools/visualization/visualize_model.py
mace/python/tools/visualization/visualize_model.py
+92
-0
未找到文件。
docs/development/how_to_debug.rst
浏览文件 @
657e369b
...
...
@@ -79,6 +79,8 @@ Debug model conversion
After model is converted to MACE model, a literal model graph is generated in directory `mace/codegen/models/your_model`.
You can refer to it when debugging model conversion.
MACE also provides model visualization HTML generated in `builds` directory, generated after converting model.
Debug engine using log
--------------------------
...
...
mace/core/tensor.h
浏览文件 @
657e369b
...
...
@@ -289,9 +289,11 @@ class Tensor {
inline
void
Reshape
(
const
std
::
vector
<
index_t
>
&
shape
)
{
shape_
=
shape
;
if
(
has_opencl_image
())
{
MACE_CHECK
(
raw_size
()
<=
4
*
buffer_
->
size
());
MACE_CHECK
(
raw_size
()
<=
4
*
buffer_
->
size
(),
"Must satisfy: "
,
raw_size
(),
" <= "
,
4
*
buffer_
->
size
());
}
else
{
MACE_CHECK
(
raw_size
()
<=
buffer_
->
size
());
MACE_CHECK
(
raw_size
()
<=
buffer_
->
size
(),
"Must satisfy: "
,
raw_size
(),
" <= "
,
buffer_
->
size
());
}
}
...
...
mace/python/tools/BUILD
浏览文件 @
657e369b
...
...
@@ -45,6 +45,7 @@ py_binary(
deps
=
[
":converter_lib"
,
":model_saver_lib"
,
"//mace/python/tools/visualization:visualization_lib"
,
"@six_archive//:six"
,
],
)
...
...
mace/python/tools/converter.py
浏览文件 @
657e369b
...
...
@@ -25,6 +25,7 @@ from mace.python.tools import model_saver
from
mace.python.tools.converter_tool
import
base_converter
as
cvt
from
mace.python.tools.converter_tool
import
transformer
from
mace.python.tools.convert_util
import
mace_check
from
mace.python.tools.visualization
import
visualize_model
# ./bazel-bin/mace/python/tools/tf_converter --model_file quantized_test.pb \
# --output quantized_test_dsp.pb \
...
...
@@ -201,6 +202,13 @@ def main(unused_args):
option
,
output_graph_def
,
quantize_activation_info
)
output_graph_def
=
converter
.
run
()
try
:
visualizer
=
visualize_model
.
ModelVisualizer
(
FLAGS
.
model_tag
,
output_graph_def
)
visualizer
.
save_html
()
except
:
# noqa
print
(
"Failed to visualize model:"
,
sys
.
exc_info
()[
0
])
model_saver
.
save_model
(
option
,
output_graph_def
,
model_checksum
,
weight_checksum
,
FLAGS
.
template_dir
,
FLAGS
.
obfuscate
,
FLAGS
.
model_tag
,
...
...
mace/python/tools/converter_tool/tensorflow_converter.py
浏览文件 @
657e369b
...
...
@@ -272,6 +272,7 @@ class TensorflowConverter(base_converter.ConverterInterface):
print
(
"Run transform_graph: %s"
%
TFTransformGraphOptions
[
option
.
device
])
try
:
print
(
"output keys: "
,
option
.
output_nodes
.
keys
())
transformed_graph_def
=
TransformGraph
(
tf_graph_def
,
option
.
input_nodes
.
keys
(),
option
.
output_nodes
.
keys
(),
...
...
mace/python/tools/visualization/BUILD
0 → 100644
浏览文件 @
657e369b
py_library
(
name
=
"visualization_lib"
,
srcs
=
[
"visualize_model.py"
,
],
data
=
[
"index.html"
,
],
srcs_version
=
"PY2AND3"
,
visibility
=
[
"//visibility:public"
],
deps
=
[
"//mace/proto:mace_py"
,
],
)
mace/python/tools/visualization/index.html
0 → 100644
浏览文件 @
657e369b
<!DOCTYPE html>
<html
lang=
"en"
>
<style>
line
{
stroke
:
#999
;
stroke-width
:
1.5px
;
stroke
:
black
;
fill
:
transparent
;
opacity
:
0.5
;
}
ellipse
{
stroke-width
:
1.5px
;
stroke
:
black
;
opacity
:
0.5
;
}
</style>
<head>
<meta
charset=
"UTF-8"
>
<title>
MACE Model
</title>
</head>
<body>
<h1>
MACE Visualization
</h1>
<h2>
Ops
</h2>
<div
id=
"op_table"
></div>
<h2>
Tensors
</h2>
<div
id=
"tensor_table"
></div>
<h2>
Graph
</h2>
Click node to see details at bottom of this page.
<div
class=
'graph'
>
<svg
id=
'graph'
width=
'1000'
height=
'1600'
viewBox=
'0 0 1000 1600'
></svg>
</div>
<div>
<pre
id=
'info'
></pre>
</div>
</body>
<script
src=
"https://d3js.org/d3.v5.min.js"
></script>
<script>
/*
var graph = {
"nodes": [
{
"name": "A_",
"id": "A",
},
{
"name": "B_",
"id": "B",
}
],
"links": [
{
"source": "A",
"target": "B"
}
]
}
*/
var
graph
=%
s
;
function
create_table
(
divid
,
data
,
columns
)
{
var
table
=
d3
.
select
(
divid
).
append
(
"
table
"
);
var
thead
=
table
.
append
(
"
thead
"
);
var
tbody
=
table
.
append
(
"
tbody
"
);
thead
.
append
(
"
tr
"
)
.
selectAll
(
"
th
"
)
.
data
(
columns
).
enter
()
.
append
(
"
th
"
)
.
text
(
function
(
column
)
{
return
column
;
});
var
tr
=
tbody
.
selectAll
(
"
tr
"
)
.
data
(
data
)
.
enter
()
.
append
(
"
tr
"
);
var
td
=
tr
.
selectAll
(
"
td
"
)
.
data
(
function
(
row
)
{
return
columns
.
map
(
function
(
column
)
{
return
{
column
:
column
,
value
:
row
[
column
]};
});
})
.
enter
()
.
append
(
"
td
"
)
.
text
(
function
(
d
)
{
return
d
.
value
;
});
return
table
;
}
nodes
=
graph
[
"
nodes
"
];
op_data
=
[];
tensor_data
=
[];
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
var
node
=
nodes
[
i
];
if
(
node
.
node_type
===
"
op
"
)
{
var
output_shapes
=
[];
if
(
typeof
node
[
"
outputShape
"
]
!==
"
undefined
"
)
{
for
(
var
j
=
0
;
j
<
node
[
"
outputShape
"
].
length
;
j
++
)
{
var
output_shape
=
node
[
"
outputShape
"
][
j
].
dims
.
join
(
"
,
"
);
output_shapes
.
push
(
output_shape
);
}
}
var
quantize_infos
=
[];
if
(
typeof
node
[
"
quantizeInfo
"
]
!==
"
undefined
"
)
{
for
(
var
j
=
0
;
j
<
node
[
"
quantizeInfo
"
].
length
;
j
++
)
{
quantize_infos
.
push
(
"
scale=
"
+
node
[
"
quantizeInfo
"
][
j
][
"
scale
"
]
+
"
zero=
"
+
node
[
"
quantizeInfo
"
][
j
][
"
zeroPoint
"
]
+
"
min=
"
+
node
[
"
quantizeInfo
"
][
j
][
"
minval
"
]
+
"
max=
"
+
node
[
"
quantizeInfo
"
][
j
][
"
maxval
"
]);
}
}
op_data
.
push
({
"
idx
"
:
op_data
.
length
,
"
name
"
:
node
[
"
name
"
],
"
type
"
:
node
[
"
type
"
],
"
output_shape
"
:
output_shapes
.
join
(
"
;
"
),
"
quantize_info
"
:
quantize_infos
.
join
(
"
;
"
)
});
}
else
if
(
node
.
node_type
===
"
tensor
"
)
{
var
quantize_info
=
""
;
if
(
typeof
node
[
"
scale
"
]
!==
"
undefined
"
)
{
quantize_info
=
"
scale=
"
+
node
[
"
scale
"
]
+
"
zero=
"
+
node
[
"
zeroPoint
"
]
+
"
min=
"
+
node
[
"
minval
"
]
+
"
max=
"
+
node
[
"
maxval
"
];
}
tensor_data
.
push
({
"
idx
"
:
tensor_data
.
length
,
"
name
"
:
node
[
"
name
"
],
"
data_type
"
:
node
[
"
dataType
"
],
"
dims
"
:
node
[
"
dims
"
].
join
(
"
,
"
),
"
quantize_info
"
:
quantize_info
})
}
}
create_table
(
"
#op_table
"
,
op_data
,
[
"
idx
"
,
"
name
"
,
"
type
"
,
"
output_shape
"
,
"
quantize_info
"
]);
create_table
(
"
#tensor_table
"
,
tensor_data
,
[
"
idx
"
,
"
name
"
,
"
data_type
"
,
"
dims
"
,
"
quantize_info
"
]);
var
svg
=
d3
.
select
(
"
#graph
"
);
svg
.
append
(
"
svg:defs
"
).
append
(
"
svg:marker
"
)
.
attr
(
"
id
"
,
"
arrow
"
)
.
attr
(
"
viewBox
"
,
"
0 -5 10 10
"
)
.
attr
(
'
refX
'
,
30
)
.
attr
(
"
markerWidth
"
,
5
)
.
attr
(
"
markerHeight
"
,
5
)
.
attr
(
"
orient
"
,
"
auto
"
)
.
append
(
"
svg:path
"
)
.
attr
(
"
d
"
,
"
M0,-5L10,0L0,5
"
);
var
width
=
svg
.
attr
(
"
width
"
);
var
height
=
svg
.
attr
(
"
height
"
);
var
is_mouse_down
=
false
;
var
mouse_x
=
0
;
var
mouse_y
=
0
;
var
view_box_x
=
0
;
var
view_box_y
=
0
;
svg
.
on
(
"
mousedown
"
,
function
()
{
is_mouse_down
=
true
;
mouse_x
=
d3
.
mouse
(
this
)[
0
];
mouse_y
=
d3
.
mouse
(
this
)[
1
];
});
svg
.
on
(
"
mouseup
"
,
function
()
{
is_mouse_down
=
false
;
view_box_x
=
view_box_x
-
d3
.
mouse
(
this
)[
0
]
+
mouse_x
;
view_box_y
=
view_box_y
-
d3
.
mouse
(
this
)[
1
]
+
mouse_y
;
svg
.
attr
(
"
viewBox
"
,
view_box_x
+
"
"
+
view_box_y
+
"
"
+
width
+
"
"
+
height
);
});
svg
.
on
(
"
mousemove
"
,
function
()
{
if
(
is_mouse_down
)
{
view_box_x
=
view_box_x
-
d3
.
mouse
(
this
)[
0
]
+
mouse_x
;
view_box_y
=
view_box_y
-
d3
.
mouse
(
this
)[
1
]
+
mouse_y
;
svg
.
attr
(
"
viewBox
"
,
view_box_x
+
"
"
+
view_box_y
+
"
"
+
width
+
"
"
+
height
);
}
});
var
simulation
=
d3
.
forceSimulation
()
.
force
(
"
link
"
,
d3
.
forceLink
().
id
(
function
(
d
)
{
return
d
.
id
;
}).
distance
(
50
))
.
force
(
"
gravity
"
,
d3
.
forceManyBody
().
strength
(
-
50
))
.
force
(
"
center
"
,
d3
.
forceCenter
(
0.5
*
width
,
0.5
*
height
));
var
node
=
svg
.
selectAll
(
"
.nodes
"
)
.
data
(
graph
.
nodes
)
.
enter
().
append
(
"
g
"
)
.
attr
(
"
class
"
,
"
nodes
"
)
.
call
(
d3
.
drag
()
.
on
(
"
start
"
,
function
(
d
)
{
if
(
!
d3
.
event
.
active
)
simulation
.
alphaTarget
(
1.0
).
restart
();
d
.
fx
=
d
.
x
;
d
.
fy
=
d
.
y
;
})
.
on
(
"
drag
"
,
function
(
d
)
{
d
.
fx
=
d3
.
event
.
x
;
d
.
fy
=
d3
.
event
.
y
;
})
.
on
(
"
end
"
,
function
(
d
)
{
if
(
!
d3
.
event
.
active
)
simulation
.
alphaTarget
(
0
);
d
.
fx
=
d
.
fy
=
null
;
}))
.
on
(
"
click
"
,
function
(
d
)
{
d3
.
select
(
'
#info
'
).
text
(
JSON
.
stringify
(
d
,
null
,
2
))
})
function
shape_size
(
node_type
)
{
if
(
node_type
===
"
op
"
)
return
[
"
60px
"
,
"
20px
"
];
else
if
(
node_type
===
"
input
"
)
return
[
"
15px
"
,
"
15px
"
];
else
return
[
"
5px
"
,
"
5px
"
];
}
function
color
(
node_type
)
{
if
(
node_type
===
"
op
"
)
return
"
#3366cc
"
;
else
if
(
node_type
===
"
input
"
)
return
"
#ff9900
"
;
else
return
"
#dc3912
"
;
}
function
font_size
(
node_type
)
{
if
(
node_type
===
"
op
"
||
node_type
===
"
input
"
)
return
"
14px
"
;
else
return
"
8px
"
;
}
node
.
append
(
"
ellipse
"
)
.
attr
(
"
rx
"
,
function
(
d
)
{
return
shape_size
(
d
.
node_type
)[
0
];
})
.
attr
(
"
ry
"
,
function
(
d
)
{
return
shape_size
(
d
.
node_type
)[
1
];
})
.
attr
(
"
fill
"
,
function
(
d
)
{
return
color
(
d
.
node_type
);
})
node
.
append
(
"
text
"
)
.
attr
(
"
font-size
"
,
function
(
d
)
{
return
font_size
(
d
.
node_type
);
})
.
attr
(
"
dx
"
,
60
).
attr
(
"
dy
"
,
5
).
text
(
function
(
d
)
{
return
d
.
name
;
});
node
.
append
(
"
text
"
)
.
attr
(
"
font-size
"
,
function
(
d
)
{
return
font_size
(
d
.
node_type
);
})
.
attr
(
"
dx
"
,
-
25
).
attr
(
"
dy
"
,
5
).
text
(
function
(
d
)
{
if
(
d
.
node_type
===
"
op
"
)
return
d
.
type
;
else
return
""
;
}).
style
(
"
fill
"
,
"
white
"
);
var
link
=
svg
.
append
(
"
g
"
).
attr
(
"
class
"
,
"
links
"
).
selectAll
(
"
line
"
)
.
data
(
graph
.
links
).
enter
().
append
(
"
line
"
)
.
attr
(
"
marker-end
"
,
"
url(#arrow)
"
);
simulation
.
nodes
(
graph
.
nodes
).
on
(
"
tick
"
,
tick
);
simulation
.
force
(
"
link
"
).
links
(
graph
.
links
);
function
tick
()
{
link
.
attr
(
"
x1
"
,
function
(
d
)
{
return
d
.
source
.
x
;
})
.
attr
(
"
y1
"
,
function
(
d
)
{
return
d
.
source
.
y
;
})
.
attr
(
"
x2
"
,
function
(
d
)
{
return
d
.
target
.
x
;
})
.
attr
(
"
y2
"
,
function
(
d
)
{
return
d
.
target
.
y
;
});
node
.
attr
(
"
transform
"
,
function
(
d
)
{
return
"
translate(
"
+
d
.
x
+
"
,
"
+
d
.
y
+
"
)
"
;
});
}
</script>
</html>
\ No newline at end of file
mace/python/tools/visualization/visualize_model.py
0 → 100644
浏览文件 @
657e369b
import
json
import
numpy
as
np
from
google.protobuf.json_format
import
_Printer
THREASHOLD
=
16
class
NPEncoder
(
json
.
JSONEncoder
):
def
default
(
self
,
obj
):
if
isinstance
(
obj
,
np
.
integer
):
return
int
(
obj
)
elif
isinstance
(
obj
,
np
.
floating
):
return
float
(
obj
)
elif
isinstance
(
obj
,
np
.
ndarray
):
return
obj
.
tolist
()
else
:
return
super
(
MyEncoder
,
self
).
default
(
obj
)
class
ModelVisualizer
(
object
):
def
__init__
(
self
,
model_name
,
proto
):
self
.
_output_file
=
"builds/%s_index.html"
%
model_name
self
.
_proto
=
proto
def
render_html
(
self
):
json_obj
=
{
"nodes"
:
[],
"links"
:
[]
}
json_printer
=
_Printer
()
for
op
in
self
.
_proto
.
op
:
op_json
=
json_printer
.
_MessageToJsonObject
(
op
)
op_json
[
"id"
]
=
op_json
[
"name"
]
op_json
[
"node_type"
]
=
"op"
json_obj
[
"nodes"
].
append
(
op_json
)
for
tensor
in
self
.
_proto
.
tensors
:
tensor_json
=
json_printer
.
_MessageToJsonObject
(
tensor
)
tensor_json
[
"id"
]
=
tensor_json
[
"name"
]
if
"floatData"
in
tensor_json
and
\
len
(
tensor_json
[
"floatData"
])
>
THREASHOLD
:
del
tensor_json
[
"floatData"
]
if
"int32Data"
in
tensor_json
and
\
len
(
tensor_json
[
"int32Data"
])
>
THREASHOLD
:
del
tensor_json
[
"int32Data"
]
tensor_json
[
"node_type"
]
=
"tensor"
json_obj
[
"nodes"
].
append
(
tensor_json
)
node_ids
=
[
node
[
"id"
]
for
node
in
json_obj
[
"nodes"
]]
tensor_to_op
=
{}
for
op
in
self
.
_proto
.
op
:
for
tensor
in
op
.
output
:
tensor_to_op
[
tensor
]
=
op
.
name
for
op
in
json_obj
[
"nodes"
]:
if
"input"
in
op
:
for
input
in
op
[
"input"
]:
if
input
in
node_ids
and
op
[
"name"
]
in
node_ids
:
# for weights
json_obj
[
"links"
].
append
(
{
"source"
:
input
,
"target"
:
op
[
"name"
]})
elif
input
in
tensor_to_op
and
\
tensor_to_op
[
input
]
in
node_ids
:
# for intermediate tensor
json_obj
[
"links"
].
append
(
{
"source"
:
tensor_to_op
[
input
],
"target"
:
op
[
"name"
]})
else
:
# for input
json_obj
[
"nodes"
].
append
({
"id"
:
input
,
"name"
:
input
,
"node_type"
:
"input"
})
json_obj
[
"links"
].
append
(
{
"source"
:
input
,
"target"
:
op
[
"name"
]})
json_msg
=
json
.
dumps
(
json_obj
,
cls
=
NPEncoder
)
with
open
(
"mace/python/tools/visualization/index.html"
)
as
f
:
html
=
f
.
read
()
return
html
%
json_msg
def
save_html
(
self
):
html
=
self
.
render_html
()
with
open
(
self
.
_output_file
,
"wb"
)
as
f
:
f
.
write
(
html
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录