提交 5d9dbe1e 编写于 作者: Q qiaolongfei

Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into...

Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into add-program-cache-for-executor
if(NOT DEFINED SPHINX_THEME)
set(SPHINX_THEME default)
endif()
if(NOT DEFINED SPHINX_THEME_DIR)
set(SPHINX_THEME_DIR)
endif()
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/_doctrees")
# HTML output director
set(SPHINX_HTML_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/html")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/templates/conf.py.en.in"
"${BINARY_BUILD_DIR_EN}/conf.py"
@ONLY)
sphinx_add_target(paddle_docs
html
${BINARY_BUILD_DIR_EN}
${SPHINX_CACHE_DIR_EN}
${CMAKE_CURRENT_SOURCE_DIR}
${SPHINX_HTML_DIR_EN})
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/_doctrees")
# HTML output directory
set(SPHINX_HTML_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/html")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/templates/conf.py.cn.in"
"${BINARY_BUILD_DIR_CN}/conf.py"
@ONLY)
sphinx_add_target(paddle_docs_cn
html
${BINARY_BUILD_DIR_CN}
${SPHINX_CACHE_DIR_CN}
${CMAKE_CURRENT_SOURCE_DIR}
${SPHINX_HTML_DIR_CN})
add_subdirectory(api) add_subdirectory(api)
add_subdirectory(v2)
../../CONTRIBUTING.md
\ No newline at end of file
...@@ -21,10 +21,11 @@ import paddle.v2 ...@@ -21,10 +21,11 @@ import paddle.v2
MarkdownParser = parser.CommonMarkParser MarkdownParser = parser.CommonMarkParser
AutoStructify = transform.AutoStructify AutoStructify = transform.AutoStructify
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
templates_path = ["@PADDLE_SOURCE_DIR@/doc_theme/templates"] templates_path = ["@PADDLE_SOURCE_DIR@/doc/templates"]
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
...@@ -120,7 +121,7 @@ html_theme = 'sphinx_rtd_theme' ...@@ -120,7 +121,7 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['@PADDLE_SOURCE_DIR@/doc_theme/static'] #html_static_path = []
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = project + 'doc' htmlhelp_basename = project + 'doc'
......
...@@ -22,10 +22,11 @@ import paddle.v2 ...@@ -22,10 +22,11 @@ import paddle.v2
MarkdownParser = parser.CommonMarkParser MarkdownParser = parser.CommonMarkParser
AutoStructify = transform.AutoStructify AutoStructify = transform.AutoStructify
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
templates_path = ["@PADDLE_SOURCE_DIR@/doc_theme/templates"] templates_path = ["@PADDLE_SOURCE_DIR@/doc/templates"]
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
...@@ -120,7 +121,7 @@ html_theme = 'sphinx_rtd_theme' ...@@ -120,7 +121,7 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['@PADDLE_SOURCE_DIR@/doc_theme/static'] #html_static_path = []
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = project + 'doc' htmlhelp_basename = project + 'doc'
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
{# Import the theme's layout. #} {# Import the theme's layout. #}
{% extends "!layout.html" %} {% extends "!layout.html" %}
{# SIDE NAV, TOGGLES ON MOBILE #}
{% block menu %}
<nav class="doc-menu-vertical" role="navigation">
{% set toctree = toctree(maxdepth=-1, collapse=False,titles_only=True, includehidden=True) %}
{{ toctree }}
</nav>
{% endblock %}
{%- block extrahead %} {%- block extrahead %}
<script> <script>
......
if(NOT DEFINED SPHINX_THEME)
set(SPHINX_THEME default)
endif()
if(NOT DEFINED SPHINX_THEME_DIR)
set(SPHINX_THEME_DIR)
endif()
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/_doctrees")
# HTML output director
set(SPHINX_HTML_DIR_EN "${CMAKE_CURRENT_BINARY_DIR}/en/html")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/../templates/conf.py.en.in"
"${BINARY_BUILD_DIR_EN}/conf.py"
@ONLY)
sphinx_add_target(paddle_docs
html
${BINARY_BUILD_DIR_EN}
${SPHINX_CACHE_DIR_EN}
${CMAKE_CURRENT_SOURCE_DIR}
${SPHINX_HTML_DIR_EN})
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/_doctrees")
# HTML output directory
set(SPHINX_HTML_DIR_CN "${CMAKE_CURRENT_BINARY_DIR}/cn/html")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/../templates/conf.py.cn.in"
"${BINARY_BUILD_DIR_CN}/conf.py"
@ONLY)
sphinx_add_target(paddle_docs_cn
html
${BINARY_BUILD_DIR_CN}
${SPHINX_CACHE_DIR_CN}
${CMAKE_CURRENT_SOURCE_DIR}
${SPHINX_HTML_DIR_CN})
../../../CONTRIBUTING.md
\ No newline at end of file
...@@ -6,3 +6,4 @@ ...@@ -6,3 +6,4 @@
contribute_to_paddle_cn.md contribute_to_paddle_cn.md
write_docs_cn.rst write_docs_cn.rst
new_layer_cn.rst
...@@ -6,3 +6,4 @@ Development ...@@ -6,3 +6,4 @@ Development
contribute_to_paddle_en.md contribute_to_paddle_en.md
write_docs_en.rst write_docs_en.rst
new_layer_en.rst
================ ==================
实现新的网络层 如何实现新的网络层
================ ==================
这份教程展示了如何在PaddlePaddle中实现一个自定义的网络层。在这里我们使用全连接层作为例子来展示实现新网络层所需要的四个步骤。 这份教程展示了如何在PaddlePaddle中实现一个自定义的网络层。在这里我们使用全连接层作为例子来展示实现新网络层所需要的四个步骤。
......
...@@ -6,5 +6,6 @@ HOW TO ...@@ -6,5 +6,6 @@ HOW TO
cmd_parameter/index_en.rst cmd_parameter/index_en.rst
cluster/index_en.rst cluster/index_en.rst
capi/index_en.rst
rnn/index_en.rst rnn/index_en.rst
optimization/gpu_profiling_en.rst optimization/gpu_profiling_en.rst
...@@ -55,7 +55,7 @@ above profilers. ...@@ -55,7 +55,7 @@ above profilers.
:code:`paddle/math/test` 目录中的 :code:`test_GpuProfiler` 就是用于展示上述分析工具的用法。 :code:`paddle/math/test` 目录中的 :code:`test_GpuProfiler` 就是用于展示上述分析工具的用法。
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:linenos: :linenos:
...@@ -83,7 +83,7 @@ program crashes when CPU version of PaddlePaddle invokes them. ...@@ -83,7 +83,7 @@ program crashes when CPU version of PaddlePaddle invokes them.
1. 加入 :code:`REGISTER_TIMER_INFO` 和 :code:`printAllStatus` 函数(如高亮部分)。 1. 加入 :code:`REGISTER_TIMER_INFO` 和 :code:`printAllStatus` 函数(如高亮部分)。
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:emphasize-lines: 8-12,14 :emphasize-lines: 8-12,14
...@@ -130,7 +130,7 @@ nvprof 工具 ...@@ -130,7 +130,7 @@ nvprof 工具
1. 将 :code:`REGISTER_GPU_PROFILER` 函数加到代码中(参考强调部分)。 1. 将 :code:`REGISTER_GPU_PROFILER` 函数加到代码中(参考强调部分)。
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:emphasize-lines: 6-7 :emphasize-lines: 6-7
......
...@@ -54,7 +54,7 @@ In this tutorial, we will focus on nvprof and nvvp. ...@@ -54,7 +54,7 @@ In this tutorial, we will focus on nvprof and nvvp.
:code:`test_GpuProfiler` from :code:`paddle/math/tests` directory will be used to evaluate :code:`test_GpuProfiler` from :code:`paddle/math/tests` directory will be used to evaluate
above profilers. above profilers.
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:linenos: :linenos:
...@@ -80,7 +80,7 @@ As a simple example, consider the following: ...@@ -80,7 +80,7 @@ As a simple example, consider the following:
1. Add :code:`REGISTER_TIMER_INFO` and :code:`printAllStatus` functions (see the emphasize-lines). 1. Add :code:`REGISTER_TIMER_INFO` and :code:`printAllStatus` functions (see the emphasize-lines).
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:emphasize-lines: 8-12,14 :emphasize-lines: 8-12,14
...@@ -127,7 +127,7 @@ To use this command line profiler **nvprof**, you can simply issue the following ...@@ -127,7 +127,7 @@ To use this command line profiler **nvprof**, you can simply issue the following
1. Add :code:`REGISTER_GPU_PROFILER` function (see the emphasize-lines). 1. Add :code:`REGISTER_GPU_PROFILER` function (see the emphasize-lines).
.. literalinclude:: ../../../paddle/math/tests/test_GpuProfiler.cpp .. literalinclude:: ../../../../paddle/math/tests/test_GpuProfiler.cpp
:language: c++ :language: c++
:lines: 137-151 :lines: 137-151
:emphasize-lines: 6-7 :emphasize-lines: 6-7
......
* {
font-family:"Roboto","Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
}
body {
padding-top: 80px;
background-image: none !important;
font-family: Roboto;
}
a, a:focus, a:hover, a:visited {
color: #597cf1;
}
.site-header {
position: fixed;
top: 0;
width: 100%;
left: 0;
z-index: 99;
background: #333;
height: 80px;
display: -webkit-flex;
display: -ms-flex;
display: -o-flex;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
box-shadow: #ccc 0 3px 3px;
}
.site-header > div {
height: 80px;
display: inline-block;
background-color: #2f323a;
padding: 0 30px;
}
.site-header .site-logo {
line-height: 80px;
width: 290px;
flex: 0 1 290px;
}
.site-header .site-logo > a {
display: inline-block;
width: 230px;
}
.site-header .site-nav-links {
flex: 0 1 100%;
}
.site-header .site-nav-links .site-menu {
height: 30px;
line-height: 30px;
font-size: 12px;
background: -webkit-linear-gradient(#282b33, #2f323a);
background: -o-linear-gradient(#282b33, #2f323a);
background: -moz-linear-gradient(#282b33, #2f323a);
background: linear-gradient(to left, #282b33, #2f323a);
margin-right: -30px;
padding-right: 30px;
}
.site-header .site-nav-links .site-menu .site-page-links {
display: inline-block;
float: right;
margin-right: 20px;
}
.site-header .site-nav-links .site-menu .site-page-links> li {
display: inline-block;
float: left;
}
.site-header .site-nav-links .site-menu .site-page-links > li > a {
color: #a7adbd;
display: inline-block;
height: 30px;
padding: 0 20px;
font-size: 12px;
}
.site-header .site-nav-links .site-menu .site-page-links > li:hover > a,
.site-header .site-nav-links .site-menu .site-page-links > li.active > a {
background-color: #2f323a;
color: #bcc1d0;
}
.site-header .site-nav-links .site-menu .site-page-links > li.active > a {
font-weight: bold;
}
.site-header .site-nav-links .site-menu .fork-on-github {
color: #597cf1;
line-height: 30px;
display: inline-block;
padding: 0 0 0 20px;
float: right;
position: relative;
}
.site-header .site-nav-links .site-menu .fork-on-github .fa {
margin-right: 5px;
font-size: 16px;
vertical-align: middle;
}
.site-header .site-nav-links .site-menu .language-switcher {
height: 30px;
display: inline-block;
float: right;
line-height: 30px;
padding: 0 20px;
position: relative;
}
.site-header .site-nav-links .site-menu .language-switcher > a {
color: #a7adbd;
}
.site-header .site-nav-links .site-menu .language-switcher.open > a {
background-color: #24272f;
color: #bcc1d0;
}
.site-header .site-nav-links .site-menu .language-switcher .fa {
margin-left: 5px;
}
.site-header .site-nav-links .site-menu .language-switcher .fa-angle-down {
display: inline;
}
.site-header .site-nav-links .site-menu .language-switcher.open .fa-angle-down {
display: none;
}
.site-header .site-nav-links .site-menu .language-switcher .fa-angle-up {
display: none;
}
.site-header .site-nav-links .site-menu .language-switcher.open .fa-angle-up {
display: inline;
}
.site-header .site-nav-links .site-menu .fork-on-github:before,
.site-header .site-nav-links .site-menu .language-switcher:before {
width: 1px;
height: 12px;
top: 9px;
background-color: #3a3d47;
left: 0;
display: inline-block;
position: absolute;
content: "";
}
.site-header .site-nav-links .site-menu .language-switcher .dropdown-menu {
display: none;
position: absolute;
box-shadow: #ccc 0 0 5px;
background-color: #fff;
width: 100%;
left: 0;
top: 30px;
}
.site-header .site-nav-links .site-menu .language-switcher .dropdown-menu > li {
line-height: 30px;
padding: 0 20px;
}
.site-header .site-nav-links .site-menu .language-switcher .dropdown-menu > li:hover {
background-color: #f7f8fe;
}
.site-header .site-nav-links .site-menu .language-switcher .dropdown-menu > li + li {
border-top: 1px solid #dedfe5;
}
.site-header .site-nav-links .site-menu .language-switcher .dropdown-menu > li > a {
color: #2f323a;
}
.site-header .site-nav-links .site-menu .language-switcher.open .dropdown-menu {
display: inline-block;
}
.site-header .site-nav-links .doc-module {
display: block;
height: 50px;
line-height: 50px;
}
.site-header .site-nav-links .doc-module > ul > li {
display: inline-block;
float: left;
}
.site-header .site-nav-links .doc-module > ul > li > a {
color: #c9cbd0;
font-size: 14px;
display: inline-block;
height: 50px;
line-height: 50px;
border-bottom: 2px solid transparent;
padding: 0 20px;
}
.site-header .site-nav-links .doc-module > ul > li:hover > a {
color: #fff;
}
.site-header .site-nav-links .doc-module > ul > li.current > a {
border-bottom-color: #fff;
color: #fff;
}
.site-header .site-nav-links .doc-module [role="search"]{
float: right;
}
.site-header .site-nav-links .doc-module [role="search"] input {
background-color: #3a3d47;
border-radius: 15px;
color: #a7adbd;
border: 1px solid transparent;
padding: 6px 15px;
width: 180px;
box-shadow: none;
transition: all .2s;
-webkit-transition: all .2s;
-moz-transition: all .2s;
-o-transition: all .2s;
background-repeat: no-repeat;
background-position: 145px center;
background-image: url("data:image/png;base64,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");
}
.site-header .site-nav-links .doc-module [role="search"] input:focus {
width: 300px;
}
.site-header .site-nav-links .doc-module [role="search"] input:focus {
background-position: 265px center;
}
.site-header .site-nav-links .doc-module [role="search"] input:hover,
.site-header .site-nav-links .doc-module [role="search"] input:focus {
color: #fff;
border-color: #597cf1;
background-image: url("data:image/png;base64,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");
}
.doc-menu-vertical {
display: inline-block;
float: left;
width: 240px;
height: 100%;
background-color: #ecedee;
position: absolute;
left: 0;
top: 0;
overflow: hidden;
padding: 0;
border-right: 1px solid #dddfe3;
}
.doc-menu-vertical > ul {
display: none;
}
.doc-menu-vertical > ul.current{
display: block;
}
.doc-menu-vertical > ul.current > li.toctree-l1 {
display: none;
}
.doc-menu-vertical > ul.current > li.toctree-l1.current {
display: block;
}
.doc-menu-vertical > ul.current > li.toctree-l1.current > a {
display: none;
}
.doc-menu-vertical .toctree-l2 a {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding-right: 30px;
}
.doc-menu-vertical .toctree-l2 > a {
font-size: 14px;
color: #2f323a;
padding-left: 30px;
line-height: 50px;
display: block;
font-weight: bold;
border-bottom: 1px solid #dddfe3;
}
.doc-menu-vertical .toctree-l2.has-child > a:after {
font-family: "FontAwesome";
display: inline-block;
font-style: normal;
font-weight: normal;
text-decoration: inherit;
content: "";
float: right;
line-height: 50px;
color: #a7adbd;
position: absolute;
right: 15px;
}
.doc-menu-vertical .toctree-l2.has-child.current > a:after {
content: "";
}
.doc-menu-vertical .toctree-l2 > a + ul{
background-color: #e4e6e9;
height: 0;
overflow: hidden;
}
.doc-menu-vertical .toctree-l2.current > a + ul {
border-bottom: 1px solid #dddfe3;
height: auto;
}
.doc-menu-vertical .toctree-l2 li.active > a {
background-color: #597cf1;
color: #fff;
}
.doc-menu-vertical .toctree-l3 > a {
font-size: 12px;
color: #2f323a;
padding-left: 30px;
line-height: 40px;
display: block;
}
.doc-menu-vertical .toctree-l4 > a {
font-size: 12px;
color: #64697b;
padding-left: 50px;
line-height: 30px;
display: block;
}
.doc-menu-vertical .toctree-l5 > a {
font-size: 14px;
color: #ccc;
padding-left: 40px;
display: block;
}
.local-toc {
position: absolute;
height: 100%;
background-color: #f6f7f8;
top: 0;
left: 240px;
padding: 0;
z-index: 9;
}
.local-toc:after {
content: "";
position: absolute;
height: 100%;
width: 1px;
display: inline-block;
right: 0;
background-color: #dddfe3;
top: 0;
z-index: -1;
}
.local-toc:hover a {
width: auto;
}
.local-toc > ul > li a {
position: relative;
font-size: 12px;
overflow: hidden;
display: none;
}
.local-toc > ul > li > ul > li a {
display: block;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
padding-right: 20px;
width: 50px;
}
.local-toc > ul > li > ul > li > ul > li > ul a {
display: none;
}
.local-toc > ul > li > ul li > a:after {
content: "";
display: inline-block;
width: 1px;
height: 100%;
background-color: transparent;
position: absolute;
right: 0;
top: 0;
}
.local-toc > ul > li > ul li a:hover{
background-color: #e6eaf7 !important;
}
.local-toc > ul > li > ul li a:hover:after {
background-color: #e6eaf7 !important;
}
.local-toc > ul > li > ul li.active > a {
color: #ff9711;
background-color: #fff;
border-top: 1px solid #dddfe3;
border-bottom: 1px solid #dddfe3;
}
.local-toc > ul > li > ul li.active > a:before {
background-color: #ff9711;
width: 10px;
height: 10px;
margin: 15px 20px;
border-radius: 5px;
}
.local-toc > ul > li > ul li.active > a:after {
background-color: #fff;
}
.local-toc > ul > li > ul > li {
position: relative;
line-height: 40px;
white-space: nowrap;
}
.local-toc > ul > li > ul > li > a {
color: #64697b;
}
.local-toc > ul > li > ul > li > a + ul {
display: none;
}
.local-toc > ul > li > ul > li > a:before {
display: inline-block;
content: "";
width: 6px;
height: 6px;
background-color: #ccc;
border-radius: 3px;
margin: 17px 22px;
float: left;
}
.local-toc > ul > li > ul > li > ul > li > a {
color: #a7adbd;
}
.local-toc > ul > li > ul > li > ul > li > a:before {
display: inline-block;
content: "";
width: 6px;
height: 6px;
background-color: #ccc;
border-radius: 3px;
margin: 17px 22px;
float: left;
}
.main-content-wrap {
position: absolute;
width: 100%;
top: 80px;
bottom: 0;
overflow: auto;
background-color: #f6f7f8;
}
.doc-content-wrap {
margin-left: 290px;
height: 100%;
position: relative;
padding-top: 60px;
background-color: #fff;
}
.doc-content-wrap > div[role='navigation'] {
position: absolute;
top: 0;
width: 100%;
left: 0;
padding: 0 30px;
height: 60px;
}
.wy-breadcrumbs {
line-height: 50px;
height: 60px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA4ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjMjhmMGQ3ZC0wODU3LTQ0ZTctOGRhZi00NGU3OTc1ZmM2MzkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzRBN0NEODRBRTM2MTFFNjlGMDI4RUM3M0VDQzY4NTkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzRBN0NEODNBRTM2MTFFNjlGMDI4RUM3M0VDQzY4NTkiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozNWQwMzI1ZC01ZDAyLTQ1YTYtODUxOS1lNWUzNjU5NGFhMzAiIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDozZGVmZmY0OS1mNjA4LTExNzktYTRlZC1kZjJiNGY3N2YwNzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7FGmP1AAAAKUlEQVR42mK4/+DpfwY9Q0tBJgYGhv8g4h8uFoKLEGOAc9FYSARAgAEAUgMQYBNmQ7sAAAAASUVORK5CYII=");
background-repeat: repeat no-repeat;
background-position: center 50px;
}
.wy-breadcrumbs > li {
color: #ccc;
}
.wy-breadcrumbs > li a {
color: #ff9711;
padding: 0;
}
.wy-breadcrumbs > li:first-child a {
color: #597cf1;
}
.wy-nav-content{
max-width: none;
overflow: auto;
position: relative;
padding: 30px;
background-color: #fff;
}
.wy-nav-content h1 {
font-size: 24px;
color: #2f323a;
margin-bottom: 30px;
}
.wy-nav-content h2 {
font-size: 20px;
color: #2f323a;
margin-bottom: 30px;
}
.wy-nav-content h3 {
font-size: 18px;
color: #2f323a;
margin-bottom: 30px;
}
.wy-nav-content h4 {
font-size: 16px;
color: #2f323a;
margin-bottom: 30px;
}
.wy-nav-content p + h1,
.wy-nav-content p + h2,
.wy-nav-content p + h3,
.wy-nav-content p + h4 {
margin-top: 20px;
}
.wy-nav-content p{
color: #2f323a;
margin-bottom: 20px;
font-size: 14px;
}
#search-results h2 {
font-size: 24px;
margin: 20px 0 10px 0;
}
#search-results p {
color: #a7adbd;
}
#search-results ul.search > li {
border-bottom: none;
}
#search-results ul.search > li > a {
color: #597cf1;
}
.rst-content .highlighted{
background-color: transparent;
color: #ff9711;
padding: 0;
}
$(document).ready(function(){
$('.local-toc').on('click' ,'a.reference.internal', function (){
$('.local-toc li.active').removeClass('active');
$(this).parent('li').addClass('active');
});
if ($('.local-toc a:visible').length) {
$('.local-toc > ul').addClass('nav nav-stacked');
$('#doc-content').scrollspy({
target: '.local-toc'
});
$('.local-toc').perfectScrollbar();
} else {
$('.doc-content-wrap').css('margin-left', '-=50px');
$('.local-toc').remove();
}
if (!$('.doc-menu-vertical > ul > li.current > ul').length) {
$('.doc-content-wrap').css('margin-left', '-=240px');
$('.doc-menu-vertical').remove();
$('.local-toc').css('left', '0');
}
$('.doc-menu-vertical .toctree-l2').each(function (i, e){
$(e).toggleClass('has-child', !!$(e).find('ul').length);
});
$('.doc-menu-vertical').find('li.current').last().addClass('active');
$('.doc-menu-vertical').perfectScrollbar();
});
{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #}
{% if page_source_suffix %}
{% set suffix = page_source_suffix %}
{% else %}
{% set suffix = source_suffix %}
{% endif %}
{% if meta is defined and 'github_url' in meta %}
{% set display_github = True %}
{% endif %}
{% if meta is defined and 'bitbucket_url' in meta %}
{% set display_bitbucket = True %}
{% endif %}
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
{% for doc in parents %}
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> > </li>
{% endfor %}
<li>{{ title }}</li>
</ul>
</div>
{# TEMPLATE VAR SETTINGS #}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
{{ metatags }}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{% endblock %}
{# FAVICON #}
{% if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{% endif %}
{# CSS #}
{# OPENSEARCH #}
{% if not embedded %}
{% if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{% endif %}
{% endif %}
{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
{% endif %}
{% for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{% for cssfile in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}"
href="{{ pathto('about') }}"/>
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}"
href="{{ pathto('genindex') }}"/>
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
{%- endif %}
{%- endblock %}
{%- block extrahead %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/css/perfect-scrollbar.min.css" type="text/css" />
<link rel="stylesheet" href="{{pathto('_static/css/override.css', 1)}}" type="text/css" />
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?b9a314ab40d04d805655aab1deee08ba";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
{% endblock %}
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="{{ pathto('_static/js/modernizr.min.js', 1) }}"></script>
</head>
<body class="wy-body-for-nav" role="document">
{% block extrabody %}
<header class="site-header">
<div class="site-logo">
<a href="/"><img src="{{pathto('_static/images/PP_w.png', 1)}}"></a>
</div>
<div class="site-nav-links">
<div class="site-menu">
<a class="fork-on-github" href="https://github.com/PaddlePaddle/Paddle" target="_blank"><i class="fa fa-github"></i>Fork me on Github</a>
<div class="language-switcher dropdown">
<a type="button" data-toggle="dropdown">
<span>English</span>
<i class="fa fa-angle-up"></i>
<i class="fa fa-angle-down"></i>
</a>
<ul class="dropdown-menu">
<li><a href="/doc_cn">中文</a></li>
<li><a href="/doc">English</a></li>
</ul>
</div>
<ul class="site-page-links">
<li><a href="/">Home</a></li>
</ul>
</div>
<div class="doc-module">
{%set modules = toctree(maxdepth=0, collapse=False, titles_only=True)%}
{{modules}}
{% include "searchbox.html" %}
</div>
</div>
</header>
{% endblock %}
<div class="main-content-wrap">
{# SIDE NAV, TOGGLES ON MOBILE #}
<nav class="doc-menu-vertical" role="navigation">
{% block menu %}
{% set toctree = toctree(maxdepth=-1, collapse=False,titles_only=True, includehidden=True) %}
{{ toctree }}
{% endblock %}
</nav>
{% if False %}
<nav class="local-toc">{{ toc }}</nav>
{% endif %}
<section class="doc-content-wrap">
{% include "breadcrumbs.html" %}
{# PAGE CONTENT #}
<div class="wy-nav-content" id="doc-content">
<div class="rst-content">
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
{% block body %}{% endblock %}
</div>
</div>
{% include "footer.html" %}
</div>
</div>
</section>
</div>
{% include "versions.html" %}
{% if not embedded %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'{{ url_root }}',
VERSION:'{{ release|e }}',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: ".txt",
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{% endif %}
{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{% endif %}
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/js/perfect-scrollbar.jquery.min.js"></script>
<script src="{{ pathto('_static/js/paddle_doc_init.js', 1) }}"></script>
{%- block footer %} {% endblock %}
</body>
</html>
{#
basic/search.html
~~~~~~~~~~~~~~~~~
Template for the search page.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block footer %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
jQuery('.doc-content-wrap > div[role="navigation"]').remove();
jQuery('.doc-content-wrap').css('padding-top', 0);
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script type="text/javascript" id="searchindexloader"></script>
{{ super() }}
{% endblock %}
{% block body %}
<noscript>
<div id="fallback" class="admonition warning">
<p class="last">
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
</p>
</div>
</noscript>
{% if search_performed %}
<h2>{{ _('Search Results') }}</h2>
{% if not search_results %}
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
{% endif %}
{% endif %}
<div id="search-results">
{% if search_results %}
<ul>
{% for href, caption, context in search_results %}
<li>
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
<p class="context">{{ context|e }}</p>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock %}
...@@ -47,11 +47,10 @@ class DetectionMAPOp : public framework::OperatorWithKernel { ...@@ -47,11 +47,10 @@ class DetectionMAPOp : public framework::OperatorWithKernel {
PADDLE_ENFORCE_EQ(det_dims[1], 6UL, PADDLE_ENFORCE_EQ(det_dims[1], 6UL,
"The shape is of Input(DetectRes) [N, 6]."); "The shape is of Input(DetectRes) [N, 6].");
auto label_dims = ctx->GetInputDim("Label"); auto label_dims = ctx->GetInputDim("Label");
PADDLE_ENFORCE_EQ(label_dims.size(), 2UL, PADDLE_ENFORCE_EQ(label_dims.size(), 2,
"The rank of Input(Label) must be 2, " "The rank of Input(Label) must be 2, "
"the shape is [N, 6]."); "the shape is [N, 6].");
PADDLE_ENFORCE_EQ(label_dims[1], 6UL, PADDLE_ENFORCE_EQ(label_dims[1], 6, "The shape is of Input(Label) [N, 6].");
"The shape is of Input(Label) [N, 6].");
if (ctx->HasInput("PosCount")) { if (ctx->HasInput("PosCount")) {
PADDLE_ENFORCE(ctx->HasInput("TruePos"), PADDLE_ENFORCE(ctx->HasInput("TruePos"),
...@@ -96,6 +95,10 @@ class DetectionMAPOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -96,6 +95,10 @@ class DetectionMAPOpMaker : public framework::OpProtoAndCheckerMaker {
"instance, the offsets in first dimension are called LoD, " "instance, the offsets in first dimension are called LoD, "
"the number of offset is N + 1, if LoD[i + 1] - LoD[i] == 0, " "the number of offset is N + 1, if LoD[i + 1] - LoD[i] == 0, "
"means there is no ground-truth data."); "means there is no ground-truth data.");
AddInput("HasState",
"(Tensor<int>) A tensor with shape [1], 0 means ignoring input "
"states, which including PosCount, TruePos, FalsePos.")
.AsDispensable();
AddInput("PosCount", AddInput("PosCount",
"(Tensor) A tensor with shape [Ncls, 1], store the " "(Tensor) A tensor with shape [Ncls, 1], store the "
"input positive example count of each class, Ncls is the count of " "input positive example count of each class, Ncls is the count of "
...@@ -145,7 +148,7 @@ class DetectionMAPOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -145,7 +148,7 @@ class DetectionMAPOpMaker : public framework::OpProtoAndCheckerMaker {
"(float) " "(float) "
"The lower bound jaccard overlap threshold of detection output and " "The lower bound jaccard overlap threshold of detection output and "
"ground-truth data.") "ground-truth data.")
.SetDefault(.3f); .SetDefault(.5f);
AddAttr<bool>("evaluate_difficult", AddAttr<bool>("evaluate_difficult",
"(bool, default true) " "(bool, default true) "
"Switch to control whether the difficult data is evaluated.") "Switch to control whether the difficult data is evaluated.")
......
...@@ -87,7 +87,13 @@ class DetectionMAPOpKernel : public framework::OpKernel<T> { ...@@ -87,7 +87,13 @@ class DetectionMAPOpKernel : public framework::OpKernel<T> {
std::map<int, std::vector<std::pair<T, int>>> true_pos; std::map<int, std::vector<std::pair<T, int>>> true_pos;
std::map<int, std::vector<std::pair<T, int>>> false_pos; std::map<int, std::vector<std::pair<T, int>>> false_pos;
if (in_pos_count != nullptr) { auto* has_state = ctx.Input<framework::LoDTensor>("HasState");
int state = 0;
if (has_state) {
state = has_state->data<int>()[0];
}
if (in_pos_count != nullptr && state) {
GetInputPos(*in_pos_count, *in_true_pos, *in_false_pos, label_pos_count, GetInputPos(*in_pos_count, *in_true_pos, *in_false_pos, label_pos_count,
true_pos, false_pos); true_pos, false_pos);
} }
...@@ -202,6 +208,7 @@ class DetectionMAPOpKernel : public framework::OpKernel<T> { ...@@ -202,6 +208,7 @@ class DetectionMAPOpKernel : public framework::OpKernel<T> {
int* pos_count_data = output_pos_count.mutable_data<int>( int* pos_count_data = output_pos_count.mutable_data<int>(
framework::make_ddim({max_class_id + 1, 1}), ctx.GetPlace()); framework::make_ddim({max_class_id + 1, 1}), ctx.GetPlace());
T* true_pos_data = output_true_pos.mutable_data<T>( T* true_pos_data = output_true_pos.mutable_data<T>(
framework::make_ddim({true_pos_count, 2}), ctx.GetPlace()); framework::make_ddim({true_pos_count, 2}), ctx.GetPlace());
T* false_pos_data = output_false_pos.mutable_data<T>( T* false_pos_data = output_false_pos.mutable_data<T>(
......
...@@ -12,8 +12,8 @@ make -j `nproc` copy_paddle_pybind ...@@ -12,8 +12,8 @@ make -j `nproc` copy_paddle_pybind
make -j `nproc` paddle_docs paddle_docs_cn paddle_api_docs make -j `nproc` paddle_docs paddle_docs_cn paddle_api_docs
# check websites for broken links # check websites for broken links
linkchecker doc/en/html/index.html linkchecker doc/v2/en/html/index.html
linkchecker doc/cn/html/index.html linkchecker doc/v2/cn/html/index.html
linkchecker doc/api/en/html/index.html linkchecker doc/api/en/html/index.html
# Parse Github URL # Parse Github URL
...@@ -55,8 +55,8 @@ function deploy_docs() { ...@@ -55,8 +55,8 @@ function deploy_docs() {
set +e set +e
rm -rf ${DIR}/doc ${DIR}/doc_cn ${DIR}/api_doc rm -rf ${DIR}/doc ${DIR}/doc_cn ${DIR}/api_doc
set -e set -e
cp -r ../doc/cn/html ${DIR}/doc_cn cp -r ../doc/v2/cn/html ${DIR}/doc_cn
cp -r ../doc/en/html ${DIR}/doc cp -r ../doc/v2/en/html ${DIR}/doc
cp -r ../doc/api/en/html ${DIR}/api_doc cp -r ../doc/api/en/html ${DIR}/api_doc
git add . git add .
} }
......
...@@ -26,7 +26,6 @@ import initializer ...@@ -26,7 +26,6 @@ import initializer
import layers import layers
import nets import nets
import optimizer import optimizer
import learning_rate_decay
import backward import backward
import regularizer import regularizer
from param_attr import ParamAttr, WeightNormParamAttr from param_attr import ParamAttr, WeightNormParamAttr
......
...@@ -18,11 +18,13 @@ import layers ...@@ -18,11 +18,13 @@ import layers
from framework import Program, Variable, program_guard from framework import Program, Variable, program_guard
import unique_name import unique_name
from layer_helper import LayerHelper from layer_helper import LayerHelper
from initializer import Constant
__all__ = [ __all__ = [
'Accuracy', 'Accuracy',
'ChunkEvaluator', 'ChunkEvaluator',
'EditDistance', 'EditDistance',
'DetectionMAP',
] ]
...@@ -285,3 +287,120 @@ class EditDistance(Evaluator): ...@@ -285,3 +287,120 @@ class EditDistance(Evaluator):
result = executor.run( result = executor.run(
eval_program, fetch_list=[avg_distance, avg_instance_error]) eval_program, fetch_list=[avg_distance, avg_instance_error])
return np.array(result[0]), np.array(result[1]) return np.array(result[0]), np.array(result[1])
class DetectionMAP(Evaluator):
"""
Calculate the detection mean average precision (mAP).
TODO (Dang Qingqing): update the following doc.
The general steps are as follows:
1. calculate the true positive and false positive according to the input
of detection and labels.
2. calculate mAP value, support two versions: '11 point' and 'integral'.
Please get more information from the following articles:
https://sanchom.wordpress.com/tag/average-precision/
https://arxiv.org/abs/1512.02325
Args:
input (Variable): The detection results, which is a LoDTensor with shape
[M, 6]. The layout is [label, confidence, xmin, ymin, xmax, ymax].
gt_label (Variable): The ground truth label index, which is a LoDTensor
with shape [N, 1].
gt_difficult (Variable): Whether this ground truth is a difficult
bounding box (bbox), which is a LoDTensor [N, 1].
gt_box (Variable): The ground truth bounding box (bbox), which is a
LoDTensor with shape [N, 6]. The layout is [xmin, ymin, xmax, ymax].
overlap_threshold (float): The threshold for deciding true/false
positive, 0.5 by defalut.
evaluate_difficult (bool): Whether to consider difficult ground truth
for evaluation, True by defalut.
ap_version (string): The average precision calculation ways, it must be
'integral' or '11point'. Please check
https://sanchom.wordpress.com/tag/average-precision/ for details.
- 11point: the 11-point interpolated average precision.
- integral: the natural integral of the precision-recall curve.
Example:
exe = fluid.executor(place)
map_evaluator = fluid.Evaluator.DetectionMAP(input,
gt_label, gt_difficult, gt_box)
cur_map, accum_map = map_evaluator.get_map_var()
fetch = [cost, cur_map, accum_map]
for epoch in PASS_NUM:
map_evaluator.reset(exe)
for data in batches:
loss, cur_map_v, accum_map_v = exe.run(fetch_list=fetch)
In the above example:
'cur_map_v' is the mAP of current mini-batch.
'accum_map_v' is the accumulative mAP of one pass.
"""
def __init__(self,
input,
gt_label,
gt_box,
gt_difficult,
overlap_threshold=0.5,
evaluate_difficult=True,
ap_version='integral'):
super(DetectionMAP, self).__init__("map_eval")
gt_label = layers.cast(x=gt_label, dtype=gt_box.dtype)
gt_difficult = layers.cast(x=gt_difficult, dtype=gt_box.dtype)
label = layers.concat([gt_label, gt_difficult, gt_box], axis=1)
# calculate mean average precision (mAP) of current mini-batch
map = layers.detection_map(
input,
label,
overlap_threshold=overlap_threshold,
evaluate_difficult=evaluate_difficult,
ap_version=ap_version)
self.create_state(dtype='int32', shape=None, suffix='accum_pos_count')
self.create_state(dtype='float32', shape=None, suffix='accum_true_pos')
self.create_state(dtype='float32', shape=None, suffix='accum_false_pos')
self.has_state = None
var = self.helper.create_variable(
persistable=True, dtype='int32', shape=[1])
self.helper.set_variable_initializer(
var, initializer=Constant(value=int(0)))
self.has_state = var
# calculate accumulative mAP
accum_map = layers.detection_map(
input,
label,
overlap_threshold=overlap_threshold,
evaluate_difficult=evaluate_difficult,
has_state=self.has_state,
input_states=self.states,
out_states=self.states,
ap_version=ap_version)
layers.fill_constant(
shape=self.has_state.shape,
value=1,
dtype=self.has_state.dtype,
out=self.has_state)
self.cur_map = map
self.accum_map = accum_map
def get_map_var(self):
return self.cur_map, self.accum_map
def reset(self, executor, reset_program=None):
if reset_program is None:
reset_program = Program()
with program_guard(main_program=reset_program):
var = _clone_var_(reset_program.current_block(), self.has_state)
layers.fill_constant(
shape=var.shape, value=0, dtype=var.dtype, out=var)
executor.run(reset_program)
...@@ -28,6 +28,7 @@ import math_op_patch ...@@ -28,6 +28,7 @@ import math_op_patch
from math_op_patch import * from math_op_patch import *
import detection import detection
from detection import * from detection import *
from learning_rate_scheduler import *
__all__ = [] __all__ = []
__all__ += math_op_patch.__all__ __all__ += math_op_patch.__all__
...@@ -38,3 +39,4 @@ __all__ += control_flow.__all__ ...@@ -38,3 +39,4 @@ __all__ += control_flow.__all__
__all__ += ops.__all__ __all__ += ops.__all__
__all__ += device.__all__ __all__ += device.__all__
__all__ += detection.__all__ __all__ += detection.__all__
__all__ += learning_rate_scheduler.__all__
...@@ -151,23 +151,34 @@ def detection_output(loc, ...@@ -151,23 +151,34 @@ def detection_output(loc,
@autodoc() @autodoc()
def detection_map(detect_res, def detection_map(detect_res,
label, label,
pos_count=None,
true_pos=None,
false_pos=None,
overlap_threshold=0.3, overlap_threshold=0.3,
evaluate_difficult=True, evaluate_difficult=True,
ap_type='integral'): has_state=None,
input_states=None,
out_states=None,
ap_version='integral'):
helper = LayerHelper("detection_map", **locals()) helper = LayerHelper("detection_map", **locals())
map_out = helper.create_tmp_variable(dtype='float32') def __create_var(type):
accum_pos_count_out = helper.create_tmp_variable(dtype='int32') return helper.create_tmp_variable(dtype=type)
accum_true_pos_out = helper.create_tmp_variable(dtype='float32')
accum_false_pos_out = helper.create_tmp_variable(dtype='float32') map_out = __create_var('float32')
accum_pos_count_out = out_states[0] if out_states else __create_var('int32')
accum_true_pos_out = out_states[1] if out_states else __create_var(
'float32')
accum_false_pos_out = out_states[2] if out_states else __create_var(
'float32')
pos_count = input_states[0] if input_states else None
true_pos = input_states[1] if input_states else None
false_pos = input_states[2] if input_states else None
helper.append_op( helper.append_op(
type="detection_map", type="detection_map",
inputs={ inputs={
'Label': label, 'Label': label,
'DetectRes': detect_res, 'DetectRes': detect_res,
'HasState': has_state,
'PosCount': pos_count, 'PosCount': pos_count,
'TruePos': true_pos, 'TruePos': true_pos,
'FalsePos': false_pos 'FalsePos': false_pos
...@@ -181,9 +192,9 @@ def detection_map(detect_res, ...@@ -181,9 +192,9 @@ def detection_map(detect_res,
attrs={ attrs={
'overlap_threshold': overlap_threshold, 'overlap_threshold': overlap_threshold,
'evaluate_difficult': evaluate_difficult, 'evaluate_difficult': evaluate_difficult,
'ap_type': ap_type 'ap_type': ap_version
}) })
return map_out, accum_pos_count_out, accum_true_pos_out, accum_false_pos_out return map_out
def bipartite_match(dist_matrix, def bipartite_match(dist_matrix,
......
...@@ -12,8 +12,11 @@ ...@@ -12,8 +12,11 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import layers import control_flow
from initializer import init_on_cpu import nn
import ops
import tensor
from ..initializer import init_on_cpu
__all__ = [ __all__ = [
'exponential_decay', 'natural_exp_decay', 'inverse_time_decay', 'exponential_decay', 'natural_exp_decay', 'inverse_time_decay',
...@@ -31,9 +34,9 @@ strategy according to this module. ...@@ -31,9 +34,9 @@ strategy according to this module.
def _decay_step_counter(): def _decay_step_counter():
# the first global step is zero in learning rate decay # the first global step is zero in learning rate decay
global_step = layers.autoincreased_step_counter( global_step = nn.autoincreased_step_counter(
counter_name='@LR_DECAY_COUNTER@', begin=0, step=1) counter_name='@LR_DECAY_COUNTER@', begin=0, step=1)
global_step = layers.cast(global_step, 'float32') global_step = tensor.cast(global_step, 'float32')
return global_step return global_step
...@@ -60,7 +63,7 @@ def exponential_decay(learning_rate, decay_steps, decay_rate, staircase=False): ...@@ -60,7 +63,7 @@ def exponential_decay(learning_rate, decay_steps, decay_rate, staircase=False):
# update learning_rate # update learning_rate
div_res = global_step / decay_steps div_res = global_step / decay_steps
if staircase: if staircase:
div_res = layers.floor(x=div_res) div_res = ops.floor(div_res)
decayed_lr = learning_rate * (decay_rate**div_res) decayed_lr = learning_rate * (decay_rate**div_res)
return decayed_lr return decayed_lr
...@@ -89,8 +92,8 @@ def natural_exp_decay(learning_rate, decay_steps, decay_rate, staircase=False): ...@@ -89,8 +92,8 @@ def natural_exp_decay(learning_rate, decay_steps, decay_rate, staircase=False):
with init_on_cpu(): with init_on_cpu():
div_res = global_step / decay_steps div_res = global_step / decay_steps
if staircase: if staircase:
div_res = layers.floor(x=div_res) div_res = ops.floor(div_res)
decayed_lr = learning_rate * layers.exp(x=(-1 * decay_rate * div_res)) decayed_lr = learning_rate * ops.exp(-1 * decay_rate * div_res)
return decayed_lr return decayed_lr
...@@ -118,7 +121,7 @@ def inverse_time_decay(learning_rate, decay_steps, decay_rate, staircase=False): ...@@ -118,7 +121,7 @@ def inverse_time_decay(learning_rate, decay_steps, decay_rate, staircase=False):
with init_on_cpu(): with init_on_cpu():
div_res = global_step / decay_steps div_res = global_step / decay_steps
if staircase: if staircase:
div_res = layers.floor(x=div_res) div_res = ops.floor(div_res)
decayed_lr = learning_rate / (1 + decay_rate * div_res) decayed_lr = learning_rate / (1 + decay_rate * div_res)
...@@ -154,21 +157,20 @@ def polynomial_decay(learning_rate, ...@@ -154,21 +157,20 @@ def polynomial_decay(learning_rate,
with init_on_cpu(): with init_on_cpu():
if cycle: if cycle:
div_res = layers.ceil(x=(global_step / decay_steps)) div_res = ops.ceil(global_step / decay_steps)
zero_var = layers.fill_constant( zero_var = tensor.fill_constant(
shape=[1], dtype='float32', value=0.0) shape=[1], dtype='float32', value=0.0)
one_var = layers.fill_constant( one_var = tensor.fill_constant(
shape=[1], dtype='float32', value=1.0) shape=[1], dtype='float32', value=1.0)
with layers.Switch() as switch: with control_flow.Switch() as switch:
with switch.case(global_step == zero_var): with switch.case(global_step == zero_var):
layers.assign(input=one_var, output=div_res) tensor.assign(input=one_var, output=div_res)
decay_steps = decay_steps * div_res decay_steps = decay_steps * div_res
else: else:
decay_steps_var = layers.fill_constant( decay_steps_var = tensor.fill_constant(
shape=[1], dtype='float32', value=float(decay_steps)) shape=[1], dtype='float32', value=float(decay_steps))
global_step = layers.elementwise_min( global_step = ops.elementwise_min(x=global_step, y=decay_steps_var)
x=global_step, y=decay_steps_var)
decayed_lr = (learning_rate - end_learning_rate) * \ decayed_lr = (learning_rate - end_learning_rate) * \
((1 - global_step / decay_steps) ** power) + end_learning_rate ((1 - global_step / decay_steps) ** power) + end_learning_rate
...@@ -195,26 +197,26 @@ def piecewise_decay(boundaries, values): ...@@ -195,26 +197,26 @@ def piecewise_decay(boundaries, values):
global_step = _decay_step_counter() global_step = _decay_step_counter()
with init_on_cpu(): with init_on_cpu():
lr = layers.create_global_var( lr = tensor.create_global_var(
shape=[1], shape=[1],
value=0.0, value=0.0,
dtype='float32', dtype='float32',
persistable=True, persistable=True,
name="learning_rate") name="learning_rate")
with layers.Switch() as switch: with control_flow.Switch() as switch:
for i in range(len(boundaries)): for i in range(len(boundaries)):
boundary_val = layers.fill_constant( boundary_val = tensor.fill_constant(
shape=[1], dtype='float32', value=float(boundaries[i])) shape=[1], dtype='float32', value=float(boundaries[i]))
value_var = layers.fill_constant( value_var = tensor.fill_constant(
shape=[1], dtype='float32', value=float(values[i])) shape=[1], dtype='float32', value=float(values[i]))
with switch.case(global_step < boundary_val): with switch.case(global_step < boundary_val):
layers.assign(value_var, lr) tensor.assign(value_var, lr)
last_value_var = layers.fill_constant( last_value_var = tensor.fill_constant(
shape=[1], shape=[1],
dtype='float32', dtype='float32',
value=float(values[len(values) - 1])) value=float(values[len(values) - 1]))
with switch.default(): with switch.default():
layers.assign(last_value_var, lr) tensor.assign(last_value_var, lr)
return lr return lr
...@@ -170,7 +170,7 @@ def train(use_cuda, save_dirname=None, is_local=True): ...@@ -170,7 +170,7 @@ def train(use_cuda, save_dirname=None, is_local=True):
# TODO(qiao) # TODO(qiao)
# check other optimizers and check why out will be NAN # check other optimizers and check why out will be NAN
sgd_optimizer = fluid.optimizer.SGD( sgd_optimizer = fluid.optimizer.SGD(
learning_rate=fluid.learning_rate_decay.exponential_decay( learning_rate=fluid.layers.exponential_decay(
learning_rate=0.0001, learning_rate=0.0001,
decay_steps=100000, decay_steps=100000,
decay_rate=0.5, decay_rate=0.5,
......
...@@ -274,7 +274,7 @@ def main(word_dict, net_method, use_cuda, parallel=False, save_dirname=None): ...@@ -274,7 +274,7 @@ def main(word_dict, net_method, use_cuda, parallel=False, save_dirname=None):
use_cuda, use_cuda,
parallel=parallel, parallel=parallel,
save_dirname=save_dirname) save_dirname=save_dirname)
infer(use_cuda, save_dirname) infer(word_dict, use_cuda, save_dirname)
class TestUnderstandSentiment(unittest.TestCase): class TestUnderstandSentiment(unittest.TestCase):
......
...@@ -31,7 +31,7 @@ use_nccl = False ...@@ -31,7 +31,7 @@ use_nccl = False
place = fluid.CPUPlace() place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda(): if fluid.core.is_compiled_with_cuda():
device_type = 'CUDA' device_type = 'CUDA'
use_nccl = True use_nccl = False
place = fluid.CUDAPlace(0) place = fluid.CUDAPlace(0)
places = fluid.layers.get_places(device_count=0, device_type=device_type) places = fluid.layers.get_places(device_count=0, device_type=device_type)
......
...@@ -158,26 +158,9 @@ class TestDetectionMAP(unittest.TestCase): ...@@ -158,26 +158,9 @@ class TestDetectionMAP(unittest.TestCase):
append_batch_size=False, append_batch_size=False,
dtype='float32') dtype='float32')
map_out, accum_pos_count_out, accum_true_pos_out, accum_false_pos_out = layers.detection_map( map_out = layers.detection_map(detect_res=detect_res, label=label)
detect_res=detect_res, label=label)
self.assertIsNotNone(map_out) self.assertIsNotNone(map_out)
self.assertIsNotNone(accum_pos_count_out)
self.assertIsNotNone(accum_true_pos_out)
self.assertIsNotNone(accum_false_pos_out)
self.assertEqual(map_out.shape, (1, )) self.assertEqual(map_out.shape, (1, ))
map_out, accum_pos_count_out2, accum_true_pos_out2, accum_false_pos_out2 = layers.detection_map(
detect_res=detect_res, label=label)
self.assertIsNotNone(map_out)
self.assertIsNotNone(accum_pos_count_out2)
self.assertIsNotNone(accum_true_pos_out2)
self.assertIsNotNone(accum_false_pos_out2)
self.assertEqual(map_out.shape, (1, ))
self.assertEqual(accum_pos_count_out.shape,
accum_pos_count_out2.shape)
self.assertEqual(accum_true_pos_out.shape,
accum_true_pos_out2.shape)
self.assertEqual(accum_false_pos_out.shape,
accum_false_pos_out2.shape)
print(str(program)) print(str(program))
......
...@@ -34,10 +34,12 @@ class TestDetectionMAPOp(OpTest): ...@@ -34,10 +34,12 @@ class TestDetectionMAPOp(OpTest):
'int32') 'int32')
self.true_pos = np.array(self.true_pos).astype('float32') self.true_pos = np.array(self.true_pos).astype('float32')
self.false_pos = np.array(self.false_pos).astype('float32') self.false_pos = np.array(self.false_pos).astype('float32')
self.has_state = np.array([1]).astype('int32')
self.inputs = { self.inputs = {
'Label': (self.label, self.label_lod), 'Label': (self.label, self.label_lod),
'DetectRes': (self.detect, self.detect_lod), 'DetectRes': (self.detect, self.detect_lod),
'HasState': self.has_state,
'PosCount': self.class_pos_count, 'PosCount': self.class_pos_count,
'TruePos': (self.true_pos, self.true_pos_lod), 'TruePos': (self.true_pos, self.true_pos_lod),
'FalsePos': (self.false_pos, self.false_pos_lod) 'FalsePos': (self.false_pos, self.false_pos_lod)
......
...@@ -17,8 +17,8 @@ import math ...@@ -17,8 +17,8 @@ import math
import unittest import unittest
import paddle.fluid as fluid import paddle.fluid as fluid
import paddle.fluid.layers as layers
import paddle.fluid.framework as framework import paddle.fluid.framework as framework
import paddle.fluid.learning_rate_decay as lr_decay
def exponential_decay(learning_rate, def exponential_decay(learning_rate,
...@@ -111,27 +111,24 @@ class TestLearningRateDecay(unittest.TestCase): ...@@ -111,27 +111,24 @@ class TestLearningRateDecay(unittest.TestCase):
common_kwargs_false["staircase"] = False common_kwargs_false["staircase"] = False
decay_fns = [ decay_fns = [
(exponential_decay, lr_decay.exponential_decay, common_kwargs_true), (exponential_decay, layers.exponential_decay, common_kwargs_true),
(exponential_decay, lr_decay.exponential_decay, (exponential_decay, layers.exponential_decay, common_kwargs_false),
(natural_exp_decay, layers.natural_exp_decay, common_kwargs_true),
(natural_exp_decay, layers.natural_exp_decay, common_kwargs_false),
(inverse_time_decay, layers.inverse_time_decay, common_kwargs_true),
(inverse_time_decay, layers.inverse_time_decay,
common_kwargs_false), common_kwargs_false),
(natural_exp_decay, lr_decay.natural_exp_decay, common_kwargs_true), (polynomial_decay, layers.polynomial_decay, {
(natural_exp_decay, lr_decay.natural_exp_decay,
common_kwargs_false),
(inverse_time_decay, lr_decay.inverse_time_decay,
common_kwargs_true),
(inverse_time_decay, lr_decay.inverse_time_decay,
common_kwargs_false),
(polynomial_decay, lr_decay.polynomial_decay, {
"learning_rate": 1.0, "learning_rate": 1.0,
"decay_steps": 5, "decay_steps": 5,
"cycle": True "cycle": True
}), }),
(polynomial_decay, lr_decay.polynomial_decay, { (polynomial_decay, layers.polynomial_decay, {
"learning_rate": 1.0, "learning_rate": 1.0,
"decay_steps": 5, "decay_steps": 5,
"cycle": False "cycle": False
}), }),
(piecewise_decay, lr_decay.piecewise_decay, { (piecewise_decay, layers.piecewise_decay, {
"boundaries": [3, 6, 9], "boundaries": [3, 6, 9],
"values": [0.1, 0.2, 0.3, 0.4] "values": [0.1, 0.2, 0.3, 0.4]
}), }),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册