Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
7494f51d
"git@developer.sourcefind.cn:OpenDAS/torch-sparce.git" did not exist on "73146b9b76fe4dfdcab7c8b7f4c28c10756e837f"
Commit
7494f51d
authored
May 07, 2017
by
Davis King
Browse files
Added support for all the other dlib layers that make sense.
parent
99b06476
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
114 additions
and
46 deletions
+114
-46
tools/convert_dlib_nets_to_caffe/main.cpp
tools/convert_dlib_nets_to_caffe/main.cpp
+114
-46
No files found.
tools/convert_dlib_nets_to_caffe/main.cpp
View file @
7494f51d
...
@@ -14,7 +14,7 @@ using namespace dlib;
...
@@ -14,7 +14,7 @@ using namespace dlib;
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Only these computational layers have parameters
// Only these computational layers have parameters
const
std
::
set
<
string
>
comp_tags_with_params
=
{
"fc"
,
"fc_no_bias"
,
"con"
,
"
bn
_con"
,
"
bn
_fc"
,
"affine"
,
"prelu"
};
const
std
::
set
<
string
>
comp_tags_with_params
=
{
"fc"
,
"fc_no_bias"
,
"con"
,
"
affine
_con"
,
"
affine
_fc"
,
"affine"
,
"prelu"
};
struct
layer
struct
layer
{
{
...
@@ -28,6 +28,15 @@ struct layer
...
@@ -28,6 +28,15 @@ struct layer
long
skip_id
=
-
1
;
// If this isn't -1 then it means this layer draws its inputs from
long
skip_id
=
-
1
;
// If this isn't -1 then it means this layer draws its inputs from
// the most recent layer with tag_id==skip_id rather than its immediate predecessor.
// the most recent layer with tag_id==skip_id rather than its immediate predecessor.
double
attribute
(
const
string
&
key
)
const
{
auto
i
=
attributes
.
find
(
key
);
if
(
i
!=
attributes
.
end
())
return
i
->
second
;
else
throw
dlib
::
error
(
"Layer doesn't have the requested attribute '"
+
key
+
"'."
);
}
string
caffe_layer_name
()
const
string
caffe_layer_name
()
const
{
{
if
(
type
==
"input"
)
if
(
type
==
"input"
)
...
@@ -71,10 +80,10 @@ string find_layer_caffe_name (
...
@@ -71,10 +80,10 @@ string find_layer_caffe_name (
{
{
i
--
;
i
--
;
// if we hit the end of the network before we found what we were looking for
// if we hit the end of the network before we found what we were looking for
if
(
i
->
type
==
"input"
)
throw
dlib
::
error
(
"Network definition is bad, a layer wanted to skip back to a non-existing layer."
);
if
(
i
->
tag_id
==
tag_id
)
if
(
i
->
tag_id
==
tag_id
)
return
i
->
caffe_layer_name
();
return
i
->
caffe_layer_name
();
if
(
i
->
type
==
"input"
)
throw
dlib
::
error
(
"Network definition is bad, a layer wanted to skip back to a non-existing layer."
);
}
}
}
}
}
}
...
@@ -99,30 +108,30 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -99,30 +108,30 @@ void convert_dlib_xml_to_cafffe_python_code(
const
string
&
xml_filename
const
string
&
xml_filename
)
)
{
{
auto
layers
=
parse_dlib_xml
(
xml_filename
);
const
auto
layers
=
parse_dlib_xml
(
xml_filename
);
cout
<<
"import caffe "
<<
endl
;
cout
<<
"import caffe "
<<
endl
;
cout
<<
"from caffe import layers as L, params as P"
<<
endl
;
cout
<<
"from caffe import layers as L, params as P"
<<
endl
;
cout
<<
"import numpy as np"
<<
endl
;
cout
<<
"import numpy as np"
<<
endl
;
// dlib nets don't commit to a batch size, so just use
32
as the default
// dlib nets don't commit to a batch size, so just use
1
as the default
cout
<<
"batch_size =
32
;"
<<
endl
;
cout
<<
"batch_size =
1
;"
<<
endl
;
if
(
layers
.
back
().
detail_name
==
"input_rgb_image"
)
if
(
layers
.
back
().
detail_name
==
"input_rgb_image"
)
{
{
cout
<<
"input_nr =
150
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
150
here as a default."
<<
endl
;
cout
<<
"input_nr =
28
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
28
here as a default."
<<
endl
;
cout
<<
"input_nc =
150
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
150
here as a default."
<<
endl
;
cout
<<
"input_nc =
28
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
28
here as a default."
<<
endl
;
cout
<<
"input_k = 3;"
<<
endl
;
cout
<<
"input_k = 3;"
<<
endl
;
}
}
else
if
(
layers
.
back
().
detail_name
==
"input_rgb_image_sized"
)
else
if
(
layers
.
back
().
detail_name
==
"input_rgb_image_sized"
)
{
{
cout
<<
"input_nr = "
<<
layers
.
back
().
attribute
s
[
"nr"
]
<<
";"
<<
endl
;
cout
<<
"input_nr = "
<<
layers
.
back
().
attribute
(
"nr"
)
<<
";"
<<
endl
;
cout
<<
"input_nc = "
<<
layers
.
back
().
attribute
s
[
"nc"
]
<<
";"
<<
endl
;
cout
<<
"input_nc = "
<<
layers
.
back
().
attribute
(
"nc"
)
<<
";"
<<
endl
;
cout
<<
"input_k = 3;"
<<
endl
;
cout
<<
"input_k = 3;"
<<
endl
;
}
}
else
if
(
layers
.
back
().
detail_name
==
"input"
)
else
if
(
layers
.
back
().
detail_name
==
"input"
)
{
{
cout
<<
"input_nr =
150
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
150
here as a default."
<<
endl
;
cout
<<
"input_nr =
28
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
28
here as a default."
<<
endl
;
cout
<<
"input_nc =
150
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
150
here as a default."
<<
endl
;
cout
<<
"input_nc =
28
; #WARNING, the source dlib network didn't commit to a specific input size, so we put
28
here as a default."
<<
endl
;
cout
<<
"input_k = 1;"
<<
endl
;
cout
<<
"input_k = 1;"
<<
endl
;
}
}
else
else
...
@@ -131,6 +140,8 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -131,6 +140,8 @@ void convert_dlib_xml_to_cafffe_python_code(
}
}
cout
<<
"def make_netspec():"
<<
endl
;
cout
<<
"def make_netspec():"
<<
endl
;
cout
<<
" # For reference, the only
\"
documentation
\"
about caffe layer parameters seems to be this page:
\n
"
;
cout
<<
" # https://github.com/BVLC/caffe/blob/master/src/caffe/proto/caffe.proto
\n
"
<<
endl
;
cout
<<
" n = caffe.NetSpec(); "
<<
endl
;
cout
<<
" n = caffe.NetSpec(); "
<<
endl
;
cout
<<
" n.data,n.label = L.MemoryData(batch_size=batch_size, channels=input_k, height=input_nr, width=input_nc, ntop=2)"
<<
endl
;
cout
<<
" n.data,n.label = L.MemoryData(batch_size=batch_size, channels=input_k, height=input_nr, width=input_nc, ntop=2)"
<<
endl
;
// iterate the layers starting with the input layer
// iterate the layers starting with the input layer
...
@@ -144,13 +155,13 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -144,13 +155,13 @@ void convert_dlib_xml_to_cafffe_python_code(
if
(
i
->
detail_name
==
"con"
)
if
(
i
->
detail_name
==
"con"
)
{
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Convolution(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Convolution(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", num_output="
<<
i
->
attribute
s
[
"num_filters"
]
;
cout
<<
", num_output="
<<
i
->
attribute
(
"num_filters"
)
;
cout
<<
", kernel_w="
<<
i
->
attribute
s
[
"nc"
]
;
cout
<<
", kernel_w="
<<
i
->
attribute
(
"nc"
)
;
cout
<<
", kernel_h="
<<
i
->
attribute
s
[
"nr"
]
;
cout
<<
", kernel_h="
<<
i
->
attribute
(
"nr"
)
;
cout
<<
", stride_w="
<<
i
->
attribute
s
[
"stride_x"
]
;
cout
<<
", stride_w="
<<
i
->
attribute
(
"stride_x"
)
;
cout
<<
", stride_h="
<<
i
->
attribute
s
[
"stride_y"
]
;
cout
<<
", stride_h="
<<
i
->
attribute
(
"stride_y"
)
;
cout
<<
", pad_w="
<<
i
->
attribute
s
[
"padding_x"
]
;
cout
<<
", pad_w="
<<
i
->
attribute
(
"padding_x"
)
;
cout
<<
", pad_h="
<<
i
->
attribute
s
[
"padding_y"
]
;
cout
<<
", pad_h="
<<
i
->
attribute
(
"padding_y"
)
;
cout
<<
");
\n
"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"relu"
)
else
if
(
i
->
detail_name
==
"relu"
)
...
@@ -162,51 +173,91 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -162,51 +173,91 @@ void convert_dlib_xml_to_cafffe_python_code(
{
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Pooling(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Pooling(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", pool=P.Pooling.MAX"
;
cout
<<
", pool=P.Pooling.MAX"
;
cout
<<
", kernel_w="
<<
i
->
attributes
[
"nc"
];
if
(
i
->
attribute
(
"nc"
)
==
0
)
cout
<<
", kernel_h="
<<
i
->
attributes
[
"nr"
];
{
cout
<<
", stride_w="
<<
i
->
attributes
[
"stride_x"
];
cout
<<
", global_pooling=True"
;
cout
<<
", stride_h="
<<
i
->
attributes
[
"stride_y"
];
}
cout
<<
", pad_w="
<<
i
->
attributes
[
"padding_x"
];
else
cout
<<
", pad_h="
<<
i
->
attributes
[
"padding_y"
];
{
cout
<<
", kernel_w="
<<
i
->
attribute
(
"nc"
);
cout
<<
", kernel_h="
<<
i
->
attribute
(
"nr"
);
}
if
(
i
->
attribute
(
"padding_x"
)
!=
0
||
i
->
attribute
(
"padding_y"
)
!=
0
)
{
throw
dlib
::
error
(
"dlib and caffe implement pooling with non-zero padding differently, so you can't convert a "
"network with such pooling layers."
);
}
cout
<<
", stride_w="
<<
i
->
attribute
(
"stride_x"
);
cout
<<
", stride_h="
<<
i
->
attribute
(
"stride_y"
);
cout
<<
", pad_w="
<<
i
->
attribute
(
"padding_x"
);
cout
<<
", pad_h="
<<
i
->
attribute
(
"padding_y"
);
cout
<<
");
\n
"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"avg_pool"
)
else
if
(
i
->
detail_name
==
"avg_pool"
)
{
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Pooling(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Pooling(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", pool=P.Pooling.MAX"
;
cout
<<
", pool=P.Pooling.AVE"
;
cout
<<
", kernel_w="
<<
i
->
attributes
[
"nc"
];
if
(
i
->
attribute
(
"nc"
)
==
0
)
cout
<<
", kernel_h="
<<
i
->
attributes
[
"nr"
];
{
cout
<<
", stride_w="
<<
i
->
attributes
[
"stride_x"
];
cout
<<
", global_pooling=True"
;
cout
<<
", stride_h="
<<
i
->
attributes
[
"stride_y"
];
}
cout
<<
", pad_w="
<<
i
->
attributes
[
"padding_x"
];
else
cout
<<
", pad_h="
<<
i
->
attributes
[
"padding_y"
];
{
cout
<<
", kernel_w="
<<
i
->
attribute
(
"nc"
);
cout
<<
", kernel_h="
<<
i
->
attribute
(
"nr"
);
}
if
(
i
->
attribute
(
"padding_x"
)
!=
0
||
i
->
attribute
(
"padding_y"
)
!=
0
)
{
throw
dlib
::
error
(
"dlib and caffe implement pooling with non-zero padding differently, so you can't convert a "
"network with such pooling layers."
);
}
cout
<<
", stride_w="
<<
i
->
attribute
(
"stride_x"
);
cout
<<
", stride_h="
<<
i
->
attribute
(
"stride_y"
);
cout
<<
", pad_w="
<<
i
->
attribute
(
"padding_x"
);
cout
<<
", pad_h="
<<
i
->
attribute
(
"padding_y"
);
cout
<<
");
\n
"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"fc"
)
else
if
(
i
->
detail_name
==
"fc"
)
{
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.InnerProduct(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.InnerProduct(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", num_output="
<<
i
->
attribute
s
[
"num_outputs"
]
;
cout
<<
", num_output="
<<
i
->
attribute
(
"num_outputs"
)
;
cout
<<
", bias_term=True"
;
cout
<<
", bias_term=True"
;
cout
<<
");
\n
"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"fc_no_bias"
)
else
if
(
i
->
detail_name
==
"fc_no_bias"
)
{
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.InnerProduct(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.InnerProduct(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", num_output="
<<
i
->
attribute
s
[
"num_outputs"
]
;
cout
<<
", num_output="
<<
i
->
attribute
(
"num_outputs"
)
;
cout
<<
", bias_term=False"
;
cout
<<
", bias_term=False"
;
cout
<<
");
\n
"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"bn_con"
)
else
if
(
i
->
detail_name
==
"bn_con"
||
i
->
detail_name
==
"bn_fc"
)
{
{
// TODO
throw
dlib
::
error
(
"Conversion from dlib's batch norm layers to caffe's isn't supported. Instead, "
"you should put your network into 'test mode' by switching batch norm layers to affine layers."
);
}
}
else
if
(
i
->
detail_name
==
"
bn_fc
"
)
else
if
(
i
->
detail_name
==
"
affine_con
"
)
{
{
// TODO
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Scale(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", axis=1"
;
cout
<<
", bias_term=True"
;
cout
<<
");
\n
"
;
}
else
if
(
i
->
detail_name
==
"affine_fc"
)
{
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Scale(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", axis=3"
;
cout
<<
", bias_term=True"
;
cout
<<
");
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"add_prev"
)
else
if
(
i
->
detail_name
==
"add_prev"
)
{
{
// TODO
cout
<<
" n."
<<
i
->
caffe_layer_name
()
<<
" = L.Eltwise(n."
<<
find_input_layer_caffe_name
(
i
);
cout
<<
", n."
<<
find_layer_caffe_name
(
i
,
i
->
attribute
(
"tag"
));
cout
<<
", operation=P.Eltwise.SUM"
;
cout
<<
");
\n
"
;
}
}
else
else
{
{
...
@@ -215,6 +266,11 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -215,6 +266,11 @@ void convert_dlib_xml_to_cafffe_python_code(
}
}
cout
<<
" return n.to_proto();
\n\n
"
<<
endl
;
cout
<<
" return n.to_proto();
\n\n
"
<<
endl
;
// -------------------------
// -------------------------
cout
<<
"def save_as_caffe_model(def_file, weights_file):
\n
"
;
cout
<<
"def save_as_caffe_model(def_file, weights_file):
\n
"
;
cout
<<
" with open(def_file, 'w') as f: f.write(str(make_netspec()));
\n
"
;
cout
<<
" with open(def_file, 'w') as f: f.write(str(make_netspec()));
\n
"
;
cout
<<
" net = caffe.Net(def_file, caffe.TEST);
\n
"
;
cout
<<
" net = caffe.Net(def_file, caffe.TEST);
\n
"
;
...
@@ -222,6 +278,9 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -222,6 +278,9 @@ void convert_dlib_xml_to_cafffe_python_code(
cout
<<
" net.save(weights_file);
\n\n
"
;
cout
<<
" net.save(weights_file);
\n\n
"
;
// -------------------------
// -------------------------
cout
<<
"def set_network_weights(net):
\n
"
;
cout
<<
"def set_network_weights(net):
\n
"
;
cout
<<
" # populate network parameters
\n
"
;
cout
<<
" # populate network parameters
\n
"
;
...
@@ -235,7 +294,7 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -235,7 +294,7 @@ void convert_dlib_xml_to_cafffe_python_code(
if
(
i
->
detail_name
==
"con"
)
if
(
i
->
detail_name
==
"con"
)
{
{
const
long
num_filters
=
i
->
attribute
s
[
"num_filters"
]
;
const
long
num_filters
=
i
->
attribute
(
"num_filters"
)
;
matrix
<
double
>
weights
=
trans
(
rowm
(
i
->
params
,
range
(
0
,
i
->
params
.
size
()
-
num_filters
-
1
)));
matrix
<
double
>
weights
=
trans
(
rowm
(
i
->
params
,
range
(
0
,
i
->
params
.
size
()
-
num_filters
-
1
)));
matrix
<
double
>
biases
=
trans
(
rowm
(
i
->
params
,
range
(
i
->
params
.
size
()
-
num_filters
,
i
->
params
.
size
()
-
1
)));
matrix
<
double
>
biases
=
trans
(
rowm
(
i
->
params
,
range
(
i
->
params
.
size
()
-
num_filters
,
i
->
params
.
size
()
-
1
)));
...
@@ -273,13 +332,21 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -273,13 +332,21 @@ void convert_dlib_xml_to_cafffe_python_code(
cout
<<
" p.shape = net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data.shape;
\n
"
;
cout
<<
" p.shape = net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data.shape;
\n
"
;
cout
<<
" net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data[:] = p;
\n
"
;
cout
<<
" net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data[:] = p;
\n
"
;
}
}
else
if
(
i
->
detail_name
==
"
bn_con
"
)
else
if
(
i
->
detail_name
==
"
affine_con"
||
i
->
detail_name
==
"affine_fc
"
)
{
{
// TODO
const
long
dims
=
i
->
params
.
size
()
/
2
;
}
matrix
<
double
>
gamma
=
trans
(
rowm
(
i
->
params
,
range
(
0
,
dims
-
1
)));
else
if
(
i
->
detail_name
==
"bn_fc"
)
matrix
<
double
>
beta
=
trans
(
rowm
(
i
->
params
,
range
(
dims
,
2
*
dims
-
1
)));
{
// TODO
// set gamma weights
cout
<<
" p = "
;
print_as_np_array
(
cout
,
gamma
);
cout
<<
";
\n
"
;
cout
<<
" p.shape = net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data.shape;
\n
"
;
cout
<<
" net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][0].data[:] = p;
\n
"
;
// set beta weights
cout
<<
" p = "
;
print_as_np_array
(
cout
,
beta
);
cout
<<
";
\n
"
;
cout
<<
" p.shape = net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][1].data.shape;
\n
"
;
cout
<<
" net.params['"
<<
i
->
caffe_layer_name
()
<<
"'][1].data[:] = p;
\n
"
;
}
}
}
}
...
@@ -289,6 +356,7 @@ void convert_dlib_xml_to_cafffe_python_code(
...
@@ -289,6 +356,7 @@ void convert_dlib_xml_to_cafffe_python_code(
int
main
(
int
argc
,
char
**
argv
)
try
int
main
(
int
argc
,
char
**
argv
)
try
{
{
cout
.
precision
(
9
);
// TODO, write out to multiple files or just process one file at a time.
// TODO, write out to multiple files or just process one file at a time.
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
convert_dlib_xml_to_cafffe_python_code
(
argv
[
i
]);
convert_dlib_xml_to_cafffe_python_code
(
argv
[
i
]);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment