Merge branch 'master' into fmegen/aarch64/mpi

# Conflicts:
#	Source/1BitSGD
#	Source/Common/Include/MPIWrapper.h
#	Source/Common/MPIWrapper.cpp
#	configure
This commit is contained in:
Friedel van Megen 2016-10-31 16:08:02 +01:00
Родитель 3d4723ca04 4b2a7b8e5a
Коммит 82ec273df3
424 изменённых файлов: 36977 добавлений и 12675 удалений

24
.gitattributes поставляемый
Просмотреть файл

@ -1,6 +1,3 @@
Dockerfile-CPU text
Dockerfile-GPU text
*.ini text
*.simple text
*.counts text
@ -24,11 +21,14 @@ Dockerfile-GPU text
*.html text
*.lyx text
*.bib text
.gitkeep text
KaldiReaderReadme text
Readme text
*.bat text
*.cmd text
*.py text
*.ipynb text
*.pl text
*.ps1 text
*.ps text
@ -53,6 +53,7 @@ Tests/UnitTests/ReaderTests/Data/CNTKTextFormatReader/invalid_inputs.txt eol=lf
Makefile text
*.sln text
*.pyproj text
*.vcxproj text
*.vcxproj.filters text
*.vssettings text
@ -65,10 +66,12 @@ Makefile text
*.cc text
*.cu text
*.cuh text
*.proto text
*.cs text
*.yml text
*.yml.bak text
*.config text
*.cntk text
@ -83,7 +86,7 @@ Makefile text
*.log text
Dockerfile. text
Dockerfile* text
# Speech data
mean.363 text
@ -117,14 +120,21 @@ TIMIT*.tfsa text
TIMIT*.transitions text
Examples/Text/ATIS/Data/ATIS.* text
Examples/Text/ATIS/*.wl text
Examples/SequenceToSequence/CMUDict/Data/cmudict-0.7b* text
# Binary extensions:
*.vsdm binary
*.ark binary
*.chunk binary
*.cmf binary
*.docx binary
*.jpg binary
*.pdf binary
*.png binary
*.docx binary
*.chunk binary
*.pptx binary
*.snk binary
*.vsdm binary
*.zip binary
*.dnn binary
Examples/Image/Detection/FastRCNN/fastRCNN/*/*.pyd binary

15
.gitignore поставляемый
Просмотреть файл

@ -23,6 +23,11 @@ build/
.run-*
lib/
bin/
Examples/Image/DataSets/Pascal/VOC*
Examples/Image/DataSets/Pascal/selective_search_data*
Examples/Image/Detection/FastRCNN/proc/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
@ -196,6 +201,8 @@ Tests/EndToEndTests/UnitTests/MathTests/MCPU.txt
Tests/EndToEndTests/UnitTests/MathTests/MGPU.txt
Tests/EndToEndTests/UnitTests/MathTests/MS.txt
Tests/Install/linux/BinaryDrops.tar.gz
Dependencies/CNTKCustomMKL/Publish
Dependencies/CNTKCustomMKL/CNTKCustomMKL-Linux-*.tgz
Dependencies/CNTKCustomMKL/CNTKCustomMKL-Windows-*.zip
@ -208,3 +215,11 @@ bindings/python/cntk/libs/
bindings/python/cntk/cntk_py_wrap.cpp
bindings/python/cntk/cntk_py_wrap.h
bindings/python/dist/
# Auto-generated sources from CNTK.proto
Source/CNTKv2LibraryDll/proto/CNTK.pb.cc
Source/CNTKv2LibraryDll/proto/CNTK.pb.h
bindings/python/cntk/c_plus_c.mod
bindings/python/cntk/i_plus_c_0.mod
bindings/python/cntk/i_plus_i_0.mod

Просмотреть файл

@ -20,6 +20,9 @@
<CpuOnlyBuild>true</CpuOnlyBuild>
<CpuOnlyBuild Condition="$(GpuBuild)">false</CpuOnlyBuild>
<NoOptBuild>false</NoOptBuild>
<NoOptBuild Condition="$(Configuration.Contains('NoOpt'))">true</NoOptBuild>
<NvmlInclude>"c:\Program Files\NVIDIA Corporation\GDK\gdk_win7_amd64_release\nvml\include"</NvmlInclude>
<NvmlLibPath>"c:\Program Files\NVIDIA Corporation\GDK\gdk_win7_amd64_release\nvml\lib"</NvmlLibPath>
@ -30,8 +33,11 @@
<HasOpenCv>false</HasOpenCv>
<HasOpenCv Condition="Exists('$(OPENCV_PATH)') Or Exists('$(OPENCV_PATH_V31)')">true</HasOpenCv>
<HasBoost>false</HasBoost>
<HasProtobuf>false</HasProtobuf>
<HasProtobuf Condition="Exists('$(PROTOBUF_PATH)')">true</HasProtobuf>
<HasBoost>false</HasBoost>
<HasBoost Condition="Exists('$(BOOST_INCLUDE_PATH)') And Exists('$(BOOST_LIB_PATH)')">true</HasBoost>
<UseZip>false</UseZip>
@ -88,6 +94,13 @@
<OpenCvBinPath>$(OpenCvPath)\x64\vc12\bin</OpenCvBinPath>
</PropertyGroup>
<PropertyGroup Condition="$(HasProtobuf)">
<ProtobufInclude>$(PROTOBUF_PATH)\include;</ProtobufInclude>
<ProtobufLibPath>$(PROTOBUF_PATH)\lib;</ProtobufLibPath>
<ProtobufLib Condition="$(ReleaseBuild)">libprotobuf.lib</ProtobufLib>
<ProtobufLib Condition="$(DebugBuild)">libprotobufd.lib</ProtobufLib>
</PropertyGroup>
<PropertyGroup Condition="'$(CudaVersion)' == '8.0'">
<CudaPath>$(CUDA_PATH_V8_0)</CudaPath>
<CudaRuntimeDll>cudart64_80.dll</CudaRuntimeDll>
@ -151,7 +164,7 @@
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(ConfigurationType)' == 'StaticLibrary' And $(ReleaseBuild)">
<ItemDefinitionGroup Condition="'$(ConfigurationType)' == 'StaticLibrary' And $(ReleaseBuild) And !$(NoOptBuild)">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -166,4 +179,15 @@
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="$(NoOptBuild)">
<ClCompile>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
</ClCompile>
<Link>
<OptimizeReferences>false</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
</Project>

326
CNTK.sln
Просмотреть файл

@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CNTK", "Source\CNTK\CNTK.vc
{EB2BE26F-6BD4-4274-971F-86D080779DD1} = {EB2BE26F-6BD4-4274-971F-86D080779DD1}
{F0A9637C-20DA-42F0-83D4-23B4704DE602} = {F0A9637C-20DA-42F0-83D4-23B4704DE602}
{EAD17188-072C-4726-B840-A769C36DAD1B} = {EAD17188-072C-4726-B840-A769C36DAD1B}
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937} = {DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}
EndProjectSection
EndProject
@ -278,6 +279,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MathTests", "Tests\UnitTest
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActionsLib", "Source\ActionsLib\ActionsLib.vcxproj", "{EB2BE26F-6BD4-4274-971F-86D080779DD1}"
ProjectSection(ProjectDependencies) = postProject
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SequenceTraining", "SequenceTraining", "{BB8B9FC5-C4B3-477F-80E2-665DC8E431BD}"
ProjectSection(SolutionItems) = preProject
@ -455,11 +459,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MNIST", "MNIST", "{FA33A61E
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Miscellaneous", "Miscellaneous", "{F99E1E80-50D8-421C-AD94-8ED0DF08C355}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalFiles", "AdditionalFiles", "{ED57E827-B28F-4BEE-BFB7-398EF8D83357}"
ProjectSection(SolutionItems) = preProject
Examples\Image\MNIST\AdditionalFiles\mnist_convert.py = Examples\Image\MNIST\AdditionalFiles\mnist_convert.py
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{6E5A252C-ACCE-42E0-9819-FF4DEF6D739E}"
ProjectSection(SolutionItems) = preProject
Examples\Image\MNIST\Config\01_OneHidden.ndl = Examples\Image\MNIST\Config\01_OneHidden.ndl
@ -486,10 +485,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CIFAR-10", "CIFAR-10", "{77
Examples\Image\Miscellaneous\CIFAR-10\04_ResNet_56_ndl_deprecated.cntk = Examples\Image\Miscellaneous\CIFAR-10\04_ResNet_56_ndl_deprecated.cntk
Examples\Image\Miscellaneous\CIFAR-10\16to32.txt = Examples\Image\Miscellaneous\CIFAR-10\16to32.txt
Examples\Image\Miscellaneous\CIFAR-10\32to64.txt = Examples\Image\Miscellaneous\CIFAR-10\32to64.txt
Examples\Image\Miscellaneous\CIFAR-10\CifarConverter.py = Examples\Image\Miscellaneous\CIFAR-10\CifarConverter.py
Examples\Image\Miscellaneous\CIFAR-10\CifarConverter_py3.py = Examples\Image\Miscellaneous\CIFAR-10\CifarConverter_py3.py
Examples\Image\Miscellaneous\CIFAR-10\CifarDownload.py = Examples\Image\Miscellaneous\CIFAR-10\CifarDownload.py
Examples\Image\Miscellaneous\CIFAR-10\CifarDownload_py3.py = Examples\Image\Miscellaneous\CIFAR-10\CifarDownload_py3.py
Examples\Image\Miscellaneous\CIFAR-10\labelsmap.txt = Examples\Image\Miscellaneous\CIFAR-10\labelsmap.txt
Examples\Image\Miscellaneous\CIFAR-10\Macros.ndl = Examples\Image\Miscellaneous\CIFAR-10\Macros.ndl
Examples\Image\Miscellaneous\CIFAR-10\readme.txt = Examples\Image\Miscellaneous\CIFAR-10\readme.txt
@ -1123,7 +1118,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CNTKv2LibraryDll", "Source\
{86883653-8A61-4038-81A0-2379FAE4200A} = {86883653-8A61-4038-81A0-2379FAE4200A}
{F0A9637C-20DA-42F0-83D4-23B4704DE602} = {F0A9637C-20DA-42F0-83D4-23B4704DE602}
{EAD17188-072C-4726-B840-A769C36DAD1B} = {EAD17188-072C-4726-B840-A769C36DAD1B}
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937} = {DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V2LibraryTests", "Tests\UnitTests\V2LibraryTests\V2LibraryTests.vcxproj", "{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}"
@ -1152,56 +1146,52 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tutorials", "Tutorials", "{
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ImageHandsOn", "ImageHandsOn", "{2230BF3D-4317-4A3F-A743-DDD6160503F8}"
ProjectSection(SolutionItems) = preProject
Tutorials\ImageHandsOn\ImageHandsOn.cntk = Tutorials\ImageHandsOn\ImageHandsOn.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn.cntk
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SLUHandsOn", "SLUHandsOn", "{CC143D08-567D-4DAC-9E14-264749C19039}"
ProjectSection(SolutionItems) = preProject
Tutorials\SLUHandsOn\SLUHandsOn.cntk = Tutorials\SLUHandsOn\SLUHandsOn.cntk
Examples\Tutorials\SLUHandsOn\SLUHandsOn.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn.cntk
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pretrained Models", "Pretrained Models", "{0ED2EE97-0A26-4865-871F-11033867BA34}"
ProjectSection(SolutionItems) = preProject
Tutorials\ImageHandsOn\cifar10.pretrained.cmf = Tutorials\ImageHandsOn\cifar10.pretrained.cmf
Tutorials\ImageHandsOn\cifar10.ResNet.cmf = Tutorials\ImageHandsOn\cifar10.ResNet.cmf
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solutions", "Solutions", "{A2A4893C-0D5B-42E2-BFAD-C123AE7FDAFD}"
ProjectSection(SolutionItems) = preProject
Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk
Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{8CFBD0DB-5F16-48E6-984C-4401317FA10E}"
ProjectSection(SolutionItems) = preProject
Tutorials\SLUHandsOn\atis.test.ctf = Tutorials\SLUHandsOn\atis.test.ctf
Tutorials\SLUHandsOn\atis.train.ctf = Tutorials\SLUHandsOn\atis.train.ctf
Examples\Tutorials\SLUHandsOn\atis.test.ctf = Examples\Tutorials\SLUHandsOn\atis.test.ctf
Examples\Tutorials\SLUHandsOn\atis.train.ctf = Examples\Tutorials\SLUHandsOn\atis.train.ctf
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solutions", "Solutions", "{BD7FF8C0-EC3A-49CD-9D81-4A8A29B8AD8E}"
ProjectSection(SolutionItems) = preProject
Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk
Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk
Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk
Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pretrained Models", "Pretrained Models", "{4727594B-A052-4834-B0E8-57DBB9ADEF13}"
ProjectSection(SolutionItems) = preProject
Tutorials\SLUHandsOn\slu.forward.backward.cmf = Tutorials\SLUHandsOn\slu.forward.backward.cmf
Tutorials\SLUHandsOn\slu.forward.cmf = Tutorials\SLUHandsOn\slu.forward.cmf
Tutorials\SLUHandsOn\slu.forward.lookahead.cmf = Tutorials\SLUHandsOn\slu.forward.lookahead.cmf
Tutorials\SLUHandsOn\slu.forward.nobn.cmf = Tutorials\SLUHandsOn\slu.forward.nobn.cmf
Examples\Tutorials\SLUHandsOn\slu.forward.backward.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.backward.cmf
Examples\Tutorials\SLUHandsOn\slu.forward.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.cmf
Examples\Tutorials\SLUHandsOn\slu.forward.lookahead.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.lookahead.cmf
Examples\Tutorials\SLUHandsOn\slu.forward.nobn.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.nobn.cmf
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{4A59163B-1EDE-4439-9E7D-40A30B82A3A0}"
ProjectSection(SolutionItems) = preProject
Tutorials\ImageHandsOn\CifarConverter.py = Tutorials\ImageHandsOn\CifarConverter.py
Examples\Tutorials\ImageHandsOn\CifarConverter.py = Examples\Tutorials\ImageHandsOn\CifarConverter.py
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TIMIT", "TIMIT", "{B586AA4C-0BB9-4629-9EDA-25FF2618AC9F}"
@ -1261,6 +1251,40 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSEvalClientTest", "Tests\E
EndProject
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "CNTKv2", "bindings\python\examples\CNTKv2.pyproj", "{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IRMetric", "IRMetric", "{E844AB9A-A48F-4A99-9625-F528C5C46D83}"
ProjectSection(SolutionItems) = preProject
Tests\EndToEndTests\Text\IRMetric\baseline.linux.txt = Tests\EndToEndTests\Text\IRMetric\baseline.linux.txt
Tests\EndToEndTests\Text\IRMetric\baseline.windows.txt = Tests\EndToEndTests\Text\IRMetric\baseline.windows.txt
Tests\EndToEndTests\Text\IRMetric\ir.cntk = Tests\EndToEndTests\Text\IRMetric\ir.cntk
Tests\EndToEndTests\Text\IRMetric\run-test = Tests\EndToEndTests\Text\IRMetric\run-test
Tests\EndToEndTests\Text\IRMetric\testcases.yml = Tests\EndToEndTests\Text\IRMetric\testcases.yml
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PythonBindings", "bindings\python\PythonBindings.vcxproj", "{CD721536-CFD3-413E-A3D7-FB0FAF989635}"
ProjectSection(ProjectDependencies) = postProject
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB} = {9BD0A711-0BBD-45B6-B81C-053F03C26CFB}
{33D2FD22-DEF2-4507-A58A-368F641AEBE5} = {33D2FD22-DEF2-4507-A58A-368F641AEBE5}
{D667AF32-028A-4A5D-BE19-F46776F0F6B2} = {D667AF32-028A-4A5D-BE19-F46776F0F6B2}
{7B7A563D-AA8E-4660-A805-D50235A02120} = {7B7A563D-AA8E-4660-A805-D50235A02120}
{9A2F2441-5972-4EA8-9215-4119FCE0FB68} = {9A2F2441-5972-4EA8-9215-4119FCE0FB68}
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5} = {60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}
{91973E60-A7BE-4C86-8FDB-59C88A0B3715} = {91973E60-A7BE-4C86-8FDB-59C88A0B3715}
{014DA766-B37B-4581-BC26-963EA5507931} = {014DA766-B37B-4581-BC26-963EA5507931}
{CE429AA2-3778-4619-8FD1-49BA3B81197B} = {CE429AA2-3778-4619-8FD1-49BA3B81197B}
{EF766CAE-9CB1-494C-9153-0030631A6340} = {EF766CAE-9CB1-494C-9153-0030631A6340}
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6} = {62836DC1-DF77-4B98-BF2D-45C943B7DDC6}
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
{482999D1-B7E2-466E-9F8D-2119F93EAFD9} = {482999D1-B7E2-466E-9F8D-2119F93EAFD9}
{1D5787D4-52E4-45DB-951B-82F220EE0C6A} = {1D5787D4-52E4-45DB-951B-82F220EE0C6A}
{7B7A51ED-AA8E-4660-A805-D50235A02120} = {7B7A51ED-AA8E-4660-A805-D50235A02120}
{E6646FFE-3588-4276-8A15-8D65C22711C1} = {E6646FFE-3588-4276-8A15-8D65C22711C1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V2LibraryDistributionTests", "Tests\UnitTests\V2LibraryDistributionTests\V2LibraryDistributionTests.vcxproj", "{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}"
ProjectSection(ProjectDependencies) = postProject
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_CpuOnly|Any CPU = Debug_CpuOnly|Any CPU
@ -1272,6 +1296,9 @@ Global
Release_CpuOnly|Any CPU = Release_CpuOnly|Any CPU
Release_CpuOnly|Mixed Platforms = Release_CpuOnly|Mixed Platforms
Release_CpuOnly|x64 = Release_CpuOnly|x64
Release_NoOpt|Any CPU = Release_NoOpt|Any CPU
Release_NoOpt|Mixed Platforms = Release_NoOpt|Mixed Platforms
Release_NoOpt|x64 = Release_NoOpt|x64
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x64 = Release|x64
@ -1292,6 +1319,11 @@ Global
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Any CPU.ActiveCfg = Release|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Mixed Platforms.ActiveCfg = Release|x64
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1312,6 +1344,11 @@ Global
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Any CPU.ActiveCfg = Release|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Mixed Platforms.ActiveCfg = Release|x64
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1332,6 +1369,11 @@ Global
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Any CPU.ActiveCfg = Release|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Mixed Platforms.ActiveCfg = Release|x64
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1352,6 +1394,11 @@ Global
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Any CPU.ActiveCfg = Release|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Mixed Platforms.ActiveCfg = Release|x64
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1372,6 +1419,11 @@ Global
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Any CPU.ActiveCfg = Release|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Mixed Platforms.ActiveCfg = Release|x64
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1392,6 +1444,11 @@ Global
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Any CPU.ActiveCfg = Release|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Mixed Platforms.ActiveCfg = Release|x64
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1412,6 +1469,11 @@ Global
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Any CPU.ActiveCfg = Release|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Mixed Platforms.ActiveCfg = Release|x64
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1432,6 +1494,11 @@ Global
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Any CPU.ActiveCfg = Release|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Mixed Platforms.ActiveCfg = Release|x64
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1452,6 +1519,11 @@ Global
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Any CPU.ActiveCfg = Release|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Mixed Platforms.ActiveCfg = Release|x64
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1470,6 +1542,11 @@ Global
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|Mixed Platforms.Build.0 = Release|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|x64.ActiveCfg = Release|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Any CPU.ActiveCfg = Release|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Mixed Platforms.ActiveCfg = Release|x64
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1490,6 +1567,11 @@ Global
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Any CPU.ActiveCfg = Release|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Mixed Platforms.ActiveCfg = Release|x64
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1510,6 +1592,11 @@ Global
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Any CPU.ActiveCfg = Release|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Mixed Platforms.ActiveCfg = Release|x64
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1530,6 +1617,11 @@ Global
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Any CPU.ActiveCfg = Release|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Mixed Platforms.ActiveCfg = Release|x64
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1550,6 +1642,11 @@ Global
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Any CPU.ActiveCfg = Release|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Mixed Platforms.ActiveCfg = Release|x64
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1570,6 +1667,11 @@ Global
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Any CPU.ActiveCfg = Release|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Mixed Platforms.ActiveCfg = Release|x64
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1590,6 +1692,11 @@ Global
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Any CPU.ActiveCfg = Release|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Mixed Platforms.ActiveCfg = Release|x64
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1610,6 +1717,11 @@ Global
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Any CPU.ActiveCfg = Release|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Mixed Platforms.ActiveCfg = Release|x64
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1630,6 +1742,11 @@ Global
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Any CPU.ActiveCfg = Release|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Mixed Platforms.ActiveCfg = Release|x64
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1650,6 +1767,11 @@ Global
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Any CPU.ActiveCfg = Release|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Mixed Platforms.ActiveCfg = Release|x64
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1670,6 +1792,11 @@ Global
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Any CPU.ActiveCfg = Release|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Mixed Platforms.ActiveCfg = Release|x64
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1690,6 +1817,11 @@ Global
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Any CPU.ActiveCfg = Release|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Mixed Platforms.ActiveCfg = Release|x64
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1710,6 +1842,11 @@ Global
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Any CPU.ActiveCfg = Release|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Mixed Platforms.ActiveCfg = Release|x64
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1730,6 +1867,11 @@ Global
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Any CPU.ActiveCfg = Release|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.ActiveCfg = Release|x64
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1750,6 +1892,11 @@ Global
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Any CPU.ActiveCfg = Release|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Mixed Platforms.ActiveCfg = Release|x64
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1770,6 +1917,11 @@ Global
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Any CPU.ActiveCfg = Release|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Mixed Platforms.ActiveCfg = Release|x64
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1790,6 +1942,11 @@ Global
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Any CPU.ActiveCfg = Release|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Mixed Platforms.ActiveCfg = Release|x64
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1810,6 +1967,11 @@ Global
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Any CPU.ActiveCfg = Release|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.ActiveCfg = Release|x64
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1830,6 +1992,11 @@ Global
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Any CPU.ActiveCfg = Release|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Mixed Platforms.ActiveCfg = Release|x64
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1850,6 +2017,11 @@ Global
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Any CPU.ActiveCfg = Release|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Mixed Platforms.ActiveCfg = Release|x64
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1870,6 +2042,11 @@ Global
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Any CPU.ActiveCfg = Release|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Mixed Platforms.ActiveCfg = Release|x64
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1890,6 +2067,11 @@ Global
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Any CPU.ActiveCfg = Release|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.ActiveCfg = Release|x64
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1910,6 +2092,11 @@ Global
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Any CPU.ActiveCfg = Release|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Mixed Platforms.ActiveCfg = Release|x64
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1930,6 +2117,11 @@ Global
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Any CPU.ActiveCfg = Release|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Mixed Platforms.ActiveCfg = Release|x64
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1950,6 +2142,11 @@ Global
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Any CPU.ActiveCfg = Release|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Mixed Platforms.ActiveCfg = Release|x64
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1970,6 +2167,11 @@ Global
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Any CPU.ActiveCfg = Release|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Mixed Platforms.ActiveCfg = Release|x64
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Mixed Platforms.Build.0 = Release|x64
@ -1984,9 +2186,60 @@ Global
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|Any CPU.ActiveCfg = Release|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|x64.ActiveCfg = Release|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|x64.ActiveCfg = Release|Any CPU
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Any CPU.ActiveCfg = Debug_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Mixed Platforms.ActiveCfg = Debug_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Mixed Platforms.Build.0 = Debug_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|x64.ActiveCfg = Debug_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|x64.Build.0 = Debug_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Any CPU.ActiveCfg = Debug|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Mixed Platforms.Build.0 = Debug|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|x64.ActiveCfg = Debug|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|x64.Build.0 = Debug|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Any CPU.ActiveCfg = Release_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Any CPU.ActiveCfg = Release|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Mixed Platforms.ActiveCfg = Release|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Mixed Platforms.Build.0 = Release|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|x64.ActiveCfg = Release|x64
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|x64.Build.0 = Release|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Any CPU.ActiveCfg = Debug_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Mixed Platforms.ActiveCfg = Debug_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Mixed Platforms.Build.0 = Debug_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|x64.ActiveCfg = Debug_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|x64.Build.0 = Debug_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Any CPU.ActiveCfg = Debug|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Mixed Platforms.Build.0 = Debug|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|x64.ActiveCfg = Debug|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|x64.Build.0 = Debug|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Any CPU.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Any CPU.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.ActiveCfg = Release_CpuOnly|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Any CPU.ActiveCfg = Release|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.ActiveCfg = Release|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.Build.0 = Release|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|x64.ActiveCfg = Release|x64
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2051,7 +2304,6 @@ Global
{2A1F0FB0-2304-4F35-87B3-66230C6E58F0} = {811924DE-2F12-4EA0-BE58-E57BEF3B74D1}
{FA33A61E-95C7-4049-8111-22058CE361A3} = {9BDFA4BE-790E-408F-915B-5979BB5078C6}
{F99E1E80-50D8-421C-AD94-8ED0DF08C355} = {9BDFA4BE-790E-408F-915B-5979BB5078C6}
{ED57E827-B28F-4BEE-BFB7-398EF8D83357} = {FA33A61E-95C7-4049-8111-22058CE361A3}
{6E5A252C-ACCE-42E0-9819-FF4DEF6D739E} = {FA33A61E-95C7-4049-8111-22058CE361A3}
{77125562-3BF2-45D2-9B73-72CA8E03C78C} = {F99E1E80-50D8-421C-AD94-8ED0DF08C355}
{EF710C5A-E616-442A-889D-C997D39AF2E1} = {F99E1E80-50D8-421C-AD94-8ED0DF08C355}
@ -2143,6 +2395,7 @@ Global
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
{9F999212-AFC5-4EAC-AA78-F7247D46C456} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
{8BE0642A-A3AA-4A64-95D0-C78FB285B2A4} = {47755F2E-D674-4175-9E38-8EA053455072}
{2230BF3D-4317-4A3F-A743-DDD6160503F8} = {8BE0642A-A3AA-4A64-95D0-C78FB285B2A4}
{CC143D08-567D-4DAC-9E14-264749C19039} = {8BE0642A-A3AA-4A64-95D0-C78FB285B2A4}
{0ED2EE97-0A26-4865-871F-11033867BA34} = {2230BF3D-4317-4A3F-A743-DDD6160503F8}
@ -2161,5 +2414,8 @@ Global
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E} = {05E45AF7-C069-4057-BC16-0A532D068CE4}
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF} = {05E45AF7-C069-4057-BC16-0A532D068CE4}
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74} = {47755F2E-D674-4175-9E38-8EA053455072}
{E844AB9A-A48F-4A99-9625-F528C5C46D83} = {8656B71D-E24C-4AC2-8BE4-C07B415A3E15}
{CD721536-CFD3-413E-A3D7-FB0FAF989635} = {DD043083-71A4-409A-AA91-F9C548DCF7EC}
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
EndGlobalSection
EndGlobal

312
Dependencies/CNTKCustomMKL/build-windows.cmd поставляемый
Просмотреть файл

@ -1,156 +1,156 @@
@echo off
REM
REM Copyright (c) Microsoft. All rights reserved.
REM
REM Licensed under the MIT license. See LICENSE.md file in the project root
REM for full license information.
REM ==============================================================================
REM
echo.
echo This batch file will build a custom MKL dynamic link library for usage by CNTK.
echo.
echo Requirements:
echo - Intel MKL SDK installed on the machine
echo - MKLROOT environment variable is set to the MKL directory inside the Intel MKL SDK
echo - Visual Studio 2013 installed and included in the path
echo.
setlocal enableextensions enabledelayedexpansion
pushd "%~dp0"
if errorlevel 1 (
echo Could not change directory to script location.
exit /b 1
)
if not defined MKLROOT (
echo Error: Environment variable MKLROOT is undefined.
exit /b 1
)
if not exist "%MKLROOT%" (
echo Error: Directory doesn't exist: "%MKLROOT%".
exit /b 1
)
set MKLBUILDERROOT=%MKLROOT%\tools\builder
if not exist "%MKLBUILDERROOT%" (
echo Error: Directory doesn't exist: "%MKLBUILDERROOT%".
exit /b 1
)
where /q nmake.exe
if errorlevel 1 (
echo Error: NMAKE.EXE not in path.
exit /b 1
)
where /q link.exe
if errorlevel 1 (
echo Error: LINK.EXE not in path.
exit /b 1
)
set /p CNTKCUSTOMMKLVERSION=<version.txt
if not defined CNTKCUSTOMMKLVERSION (
echo Cannot determine CNTK custom MKL version.
exit /b 1
)
if exist lib rmdir /s /q lib
if errorlevel 1 exit /b 1
if exist Publish rmdir /s /q Publish
if errorlevel 1 exit /b 1
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64
echo.
echo Copying "%MKLBUILDERROOT%\lib".
xcopy /s /e /y /i "%MKLBUILDERROOT%\lib" lib
if errorlevel 1 (
exit /b 1
)
echo.
echo Compiling and copying libraries.
for %%t in (
parallel
sequential
) do (
set TFIRSTCHAR=%%t
set TFIRSTCHAR=!TFIRSTCHAR:~0,1!
set LIBBASENAME=mkl_cntk_!TFIRSTCHAR!
echo.
echo Calling NMAKE libintel64 export=functions.txt threading=%%t name=!LIBBASENAME! MKLROOT="%MKLROOT%".
NMAKE /f "%MKLBUILDERROOT%\makefile" ^
libintel64 ^
export=functions.txt ^
threading=%%t ^
name=!LIBBASENAME! ^
MKLROOT="%MKLROOT%"
if errorlevel 1 (
echo Error: NMAKE.exe for threading=%%t failed.
exit /b 1
)
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
move !LIBBASENAME!.dll Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
move !LIBBASENAME!.lib Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
del !LIBBASENAME!*
if errorlevel 1 exit /b 1
@REM TODO manifest?
)
echo.
echo Copying libiomp5md.dll.
copy "%MKLROOT%\..\redist\intel64_win\compiler\libiomp5md.dll" Publish\%CNTKCUSTOMMKLVERSION%\x64\parallel
if errorlevel 1 (
exit /b 1
)
echo.
echo Removing LIB directory.
rmdir /s /q lib
if errorlevel 1 exit /b 1
echo.
echo Copying include files to Publish\%CNTKCUSTOMMKLVERSION%\include.
mkdir Publish\%CNTKCUSTOMMKLVERSION%\include
for /f %%h in (headers.txt) do (
copy "%MKLROOT%\include\%%h" Publish\%CNTKCUSTOMMKLVERSION%\include
if errorlevel 1 (
echo Failed to copy "%MKLROOT%\include\%%h".
exit /b 1
)
)
copy README-for-redistributable.txt Publish\%CNTKCUSTOMMKLVERSION%\README.txt
if errorlevel 1 (
echo Failed to copy README.
exit /b 1
)
copy ..\..\LICENSE.md Publish\%CNTKCUSTOMMKLVERSION%
if errorlevel 1 (
echo Failed to copy LICENSE.md.
exit /b 1
)
popd
@echo off
REM
REM Copyright (c) Microsoft. All rights reserved.
REM
REM Licensed under the MIT license. See LICENSE.md file in the project root
REM for full license information.
REM ==============================================================================
REM
echo.
echo This batch file will build a custom MKL dynamic link library for usage by CNTK.
echo.
echo Requirements:
echo - Intel MKL SDK installed on the machine
echo - MKLROOT environment variable is set to the MKL directory inside the Intel MKL SDK
echo - Visual Studio 2013 installed and included in the path
echo.
setlocal enableextensions enabledelayedexpansion
pushd "%~dp0"
if errorlevel 1 (
echo Could not change directory to script location.
exit /b 1
)
if not defined MKLROOT (
echo Error: Environment variable MKLROOT is undefined.
exit /b 1
)
if not exist "%MKLROOT%" (
echo Error: Directory doesn't exist: "%MKLROOT%".
exit /b 1
)
set MKLBUILDERROOT=%MKLROOT%\tools\builder
if not exist "%MKLBUILDERROOT%" (
echo Error: Directory doesn't exist: "%MKLBUILDERROOT%".
exit /b 1
)
where /q nmake.exe
if errorlevel 1 (
echo Error: NMAKE.EXE not in path.
exit /b 1
)
where /q link.exe
if errorlevel 1 (
echo Error: LINK.EXE not in path.
exit /b 1
)
set /p CNTKCUSTOMMKLVERSION=<version.txt
if not defined CNTKCUSTOMMKLVERSION (
echo Cannot determine CNTK custom MKL version.
exit /b 1
)
if exist lib rmdir /s /q lib
if errorlevel 1 exit /b 1
if exist Publish rmdir /s /q Publish
if errorlevel 1 exit /b 1
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64
echo.
echo Copying "%MKLBUILDERROOT%\lib".
xcopy /s /e /y /i "%MKLBUILDERROOT%\lib" lib
if errorlevel 1 (
exit /b 1
)
echo.
echo Compiling and copying libraries.
for %%t in (
parallel
sequential
) do (
set TFIRSTCHAR=%%t
set TFIRSTCHAR=!TFIRSTCHAR:~0,1!
set LIBBASENAME=mkl_cntk_!TFIRSTCHAR!
echo.
echo Calling NMAKE libintel64 export=functions.txt threading=%%t name=!LIBBASENAME! MKLROOT="%MKLROOT%".
NMAKE /f "%MKLBUILDERROOT%\makefile" ^
libintel64 ^
export=functions.txt ^
threading=%%t ^
name=!LIBBASENAME! ^
MKLROOT="%MKLROOT%"
if errorlevel 1 (
echo Error: NMAKE.exe for threading=%%t failed.
exit /b 1
)
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
move !LIBBASENAME!.dll Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
move !LIBBASENAME!.lib Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
if errorlevel 1 exit /b 1
del !LIBBASENAME!*
if errorlevel 1 exit /b 1
@REM TODO manifest?
)
echo.
echo Copying libiomp5md.dll.
copy "%MKLROOT%\..\redist\intel64_win\compiler\libiomp5md.dll" Publish\%CNTKCUSTOMMKLVERSION%\x64\parallel
if errorlevel 1 (
exit /b 1
)
echo.
echo Removing LIB directory.
rmdir /s /q lib
if errorlevel 1 exit /b 1
echo.
echo Copying include files to Publish\%CNTKCUSTOMMKLVERSION%\include.
mkdir Publish\%CNTKCUSTOMMKLVERSION%\include
for /f %%h in (headers.txt) do (
copy "%MKLROOT%\include\%%h" Publish\%CNTKCUSTOMMKLVERSION%\include
if errorlevel 1 (
echo Failed to copy "%MKLROOT%\include\%%h".
exit /b 1
)
)
copy README-for-redistributable.txt Publish\%CNTKCUSTOMMKLVERSION%\README.txt
if errorlevel 1 (
echo Failed to copy README.
exit /b 1
)
copy ..\..\LICENSE.md Publish\%CNTKCUSTOMMKLVERSION%
if errorlevel 1 (
echo Failed to copy LICENSE.md.
exit /b 1
)
popd

Просмотреть файл

@ -0,0 +1,27 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//
// CPPEvalV2Client.cpp : Sample application shows how to evaluate a model using CNTK V2 API.
//
#include <stdio.h>
// define GPU_AVAILABLE, if you want to run evaluation on a GPU device. You also need CNTK GPU binaries.
// undefine GPU_AVAILABLE, if you want to run evaluation on a CPU device.
// #define GPU_AVAILABLE
void MultiThreadsEvaluation(bool);
int main()
{
#ifdef GPU_AVAILABLE
fprintf(stderr, "\n##### Run eval on GPU device. #####\n");
MultiThreadsEvaluation(true);
#else
fprintf(stderr, "\n##### Run eval on CPU device. #####\n");
MultiThreadsEvaluation(false);
#endif
}

Просмотреть файл

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CPPEvalV2Client.cpp" />
<ClCompile Include="EvalMultithreads.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D771A06D-CC25-4582-B5CD-D2A4782BB005}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>CPPEvalV2Client</RootNamespace>
<ProjectName>CPPEvalV2Client</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>$(SolutionDir)..\..\$(Platform)\$(ProjectName).$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>WIN32;_CONSOLE;UNICODE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\Include</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<FloatingPointModel>Fast</FloatingPointModel>
<OpenMPSupport>true</OpenMPSupport>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalLibraryDirectories>$(SolutionDir)\..\..\cntk</AdditionalLibraryDirectories>
<AdditionalDependencies>CNTKLibrary-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CPPEvalV2Client.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="EvalMultithreads.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

Просмотреть файл

@ -95,7 +95,7 @@ void MultiThreadsEvaluationWithClone(const DeviceDescriptor& device, const int t
}
auto outputTimesParam = Parameter(NDArrayView::RandomUniform<float>({numOutputClasses, hiddenLayersDim}, -0.5, 0.5, 1, device));
auto classifierFunc = Times(outputTimesParam, classifierRoot, 1, L"classifierOutput");
auto classifierFunc = Times(outputTimesParam, classifierRoot, L"classifierOutput");
// Now test the structure
if (classifierFunc->Parameters().size() != ((numHiddenLayers * 2) + 1))
@ -128,11 +128,14 @@ void MultiThreadsEvaluationWithClone(const DeviceDescriptor& device, const int t
/// It first loads a model, then spawns multi threads. Each thread uses Clone() to create a new
/// instance of function and then use this instance to do evaluation.
/// All cloned functions share the same parameters.
/// Note: It uses the model trained by Examples\Image\GettingStarted\01_OneHidden.cntk as example. Instructions
/// to train the model is described in Examples\Image\GettingStarted\README.md.
/// The pre-trained model file 01_OneHidden needs to be in the current directory.
/// </description>
void MultiThreadsEvaluationWithLoadModel(const DeviceDescriptor& device, const int threadCount)
{
// The model file will be trained and copied to the current runtime directory first.
auto modelFuncPtr = CNTK::LoadLegacyModel(DataType::Float, L"01_OneHidden", device);
auto modelFuncPtr = CNTK::Function::LoadModel(DataType::Float, L"01_OneHidden", device);
OutputFunctionInfo(modelFuncPtr);
@ -287,13 +290,13 @@ inline FunctionPtr SetupFullyConnectedDNNLayer(Variable input, size_t outputDim,
void OutputFunctionInfo(FunctionPtr func)
{
auto inputVariables = func->Arguments();
fprintf(stderr, "Function %S: Input Variables (count=%lu)\n", func->Name().c_str(), inputVariables.size());
fprintf(stderr, "Function '%S': Input Variables (count=%lu)\n", func->Name().c_str(), inputVariables.size());
for_each(inputVariables.begin(), inputVariables.end(), [](const Variable v) {
fprintf(stderr, " name=%S, kind=%d\n", v.Name().c_str(), static_cast<int>(v.Kind()));
});
auto outputVariables = func->Outputs();
fprintf(stderr, "Function %S: Output Variables (count=%lu)\n", func->Name().c_str(), outputVariables.size());
fprintf(stderr, "Function '%S': Output Variables (count=%lu)\n", func->Name().c_str(), outputVariables.size());
for_each(outputVariables.begin(), outputVariables.end(), [](const Variable v) {
fprintf(stderr, " name=%S, kind=%d\n", v.Name().c_str(), static_cast<int>(v.Kind()));
});
@ -454,46 +457,37 @@ void RunEvaluationOneHidden(FunctionPtr evalFunc, const DeviceDescriptor& device
void MultiThreadsEvaluation(bool isGPUAvailable)
{
#ifndef CPUONLY
if (isGPUAvailable)
{
fprintf(stderr, "Run evaluation on GPU device using GPU build.\n");
}
else
{
fprintf(stderr, "Run evaluation on CPU device using GPU build.\n");
}
#else
fprintf(stderr, "Run evaluation using CPU-only build.\n");
#endif
// The number of threads running evaluation in parallel.
const int numOfThreads = 2;
fprintf(stderr, "\n##### Run evaluation on %s device with %d parallel evaluation thread(s). #####\n", isGPUAvailable ? "GPU" : "CPU", numOfThreads);
// Test multi-threads evaluation with new function
fprintf(stderr, "Test multi-threaded evaluation with new function on CPU.\n");
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::CPUDevice(), 2);
fprintf(stderr, "\n##### Run evaluation using new function on CPU. #####\n");
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::CPUDevice(), numOfThreads);
if (isGPUAvailable)
{
fprintf(stderr, "Test multi-threaded evaluation with new function on GPU\n");
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::GPUDevice(0), 2);
fprintf(stderr, "\n##### Run evaluation using new function on GPU. #####\n");;
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::GPUDevice(0), numOfThreads);
}
// Test multi-threads evaluation using clone.
fprintf(stderr, "Test multi-threaded evaluation using clone on CPU.\n");
MultiThreadsEvaluationWithClone(DeviceDescriptor::CPUDevice(), 2);
fprintf(stderr, "\n##### Run evaluation using clone function on CPU. #####\n");
MultiThreadsEvaluationWithClone(DeviceDescriptor::CPUDevice(), numOfThreads);
if (isGPUAvailable)
{
fprintf(stderr, "Test multi-threaded evaluation using clone on GPU.\n");
MultiThreadsEvaluationWithClone(DeviceDescriptor::GPUDevice(0), 2);
fprintf(stderr, "\n##### Run evaluation using clone function on GPU. #####\n");
MultiThreadsEvaluationWithClone(DeviceDescriptor::GPUDevice(0), numOfThreads);
}
// test multi-threads evaluation with loading existing models
fprintf(stderr, "Test multi-threaded evaluation with loading existing models on CPU.\n");
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::CPUDevice(), 2);
fprintf(stderr, "\n##### Run evaluation using pre-trained model on CPU. #####\n");
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::CPUDevice(), numOfThreads);
if (isGPUAvailable)
{
fprintf(stderr, "Test multi-threaded evaluation with loading existing models on GPU.\n");
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::GPUDevice(0), 2);
fprintf(stderr, "\n##### Run evaluation using pre-trained model on GPU. #####\n");
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::GPUDevice(0), numOfThreads);
}
fflush(stderr);
}

Просмотреть файл

@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPEvalClient", "CPPEvalCli
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSEvalClient", "CSEvalClient\CSEvalClient.csproj", "{92CCF4B9-BFED-4914-901A-CF1327B1A02D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPEvalV2Client", "CPPEvalV2Client\CPPEvalV2Client.vcxproj", "{D771A06D-CC25-4582-B5CD-D2A4782BB005}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -20,6 +22,9 @@ Global
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Debug|x64.Build.0 = Debug|x64
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Release|x64.ActiveCfg = Release|x64
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Release|x64.Build.0 = Release|x64
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Debug|x64.ActiveCfg = Release|x64
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Release|x64.ActiveCfg = Release|x64
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -1,7 +0,0 @@
m1=LoadModel($CurModel$, format=cntk)
SetDefaultModel(m1)
# Add top-5 error prediction node.
ErrTop5 = ClassificationError(labels, OutputNodes.z, Const(5), tag = Eval)
SaveModel(m1, $NewModel$, format=cntk)

Просмотреть файл

@ -73,8 +73,8 @@ ResNetBottleneckInc {outChannels, interOutChannels, stride1x1, stride3x3, bnTime
ConvBNLayer {outChannels, (1:1), (1:1), bnTimeConst}) (x)
# Shortcut
stride = stride1x1.*stride3x3
s = ConvBNReLULayer {outChannels, (1:1), stride, bnTimeConst} (x)
stride[i:0..Length(stride1x1)-1] = stride1x1[i] * stride3x3[i]
s = ConvBNLayer {outChannels, (1:1), stride, bnTimeConst} (x)
p = Plus(b, s)
r = ReLU(p)

Просмотреть файл

@ -1,145 +0,0 @@
Conv(W, inp, outMap, kW, kH, hStride, vStride)
[
c = Convolution(W, inp, kW, kH, outMap, hStride, vStride, zeroPadding = true, imageLayout = "cudnn")
]
BN(inp, mapCount, bValue, scValue, bnTimeConst)
[
b = Parameter(mapCount, 1, init = fixedValue, value = bValue)
sc = Parameter(mapCount, 1, init = fixedValue, value = scValue)
m = Parameter(mapCount, 1, init = fixedValue, value = 0, learningRateMultiplier = 0)
v = Parameter(mapCount, 1, init = fixedValue, value = 0, learningRateMultiplier = 0)
y = BatchNormalization(inp, sc, b, m, v, spatial = true, normalizationTimeConstant = bnTimeConst, epsilon = 0.000000001, imageLayout = "cudnn", engine = "cudnn")
]
ConvBNLayerW(W, inp, outMap, kW, kH, hStride, vStride, bValue, scValue, bnTimeConst)
[
c = Conv(W, inp, outMap, kW, kH, hStride, vStride)
y = BN(c, outMap, bValue, scValue, bnTimeConst)
]
ConvBNLayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
[
W = Parameter(outMap, inWCount, init = Gaussian, initValueScale = wScale)
c = Conv(W, inp, outMap, kW, kH, hStride, vStride)
y = BN(c, outMap, bValue, scValue, bnTimeConst)
]
ConvBNReLULayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
[
c = ConvBNLayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
y = RectifiedLinear(c)
]
Conv1x1(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
[
W = Parameter(outMap, inMap, init = Gaussian, initValueScale = wScale)
c = Convolution(W, inp, 1, 1, outMap, hStride, vStride, zeroPadding = false, imageLayout = "cudnn")
y = BN(c, outMap, bValue, scValue, bnTimeConst)
]
Conv1x1ReLU(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
[
c = Conv1x1(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
y = RectifiedLinear(c)
]
# Standard building block for ResNet with identity shortcut (option A).
ResNetNode2A(inp, outMap, inWCount, kW, kH, wScale, bValue, scValue)
[
# First convolution layer.
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
# Second convolution layer, no ReLU.
c2 = ConvBNLayer(c1, outMap, inWCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
# Identity shortcut.
p = Plus(c2, inp)
y = RectifiedLinear(p)
]
# Standard building block for ResNet with padding (option A).
ResNetNode2AInc(inp, outMap, inWCount, wCount, kW, kH, wScale, bValue, scValue, bnTimeConst, Wproj)
[
# First convolution layer.
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, 2, 2, wScale, bValue, scValue, bnTimeConst)
# Second convolution layer, no ReLU.
c2 = ConvBNLayer(c1, outMap, wCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
# Projection convolution layer.
c_proj = ConvBNLayerW(Wproj, inp, outMap, 1, 1, 2, 2, bValue, scValue, bnTimeConst)
p = Plus(c2, c_proj)
y2 = RectifiedLinear(p)
]
# Standard building block for ResNet with padding (option B).
ResNetNode2BInc(inp, outMap, inMap, inWCount, wCount, kW, kH, wScale, bValue, scValue, bnTimeConst, stride1x1, stride3x3)
[
# First convolution layer.
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, stride1x1, stride1x1, wScale, bValue, scValue, bnTimeConst)
# Second convolution layer, no ReLU.
c2 = ConvBNLayer(c1, outMap, wCount, kW, kH, stride3x3, stride3x3, wScale, bValue, scValue, bnTimeConst)
# Projection convolution layer.
c_proj = Conv1x1(inp, outMap, inMap, 2, 2, wScale, bValue, scValue, bnTimeConst)
p = Plus(c2, c_proj)
y2 = RectifiedLinear(p)
]
# Bottleneck building block for ResNet.
ResNetNode3A(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst)
[
# 1x1 reducing convolution.
c1 = Conv1x1ReLU(inp, convMap, inMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
# 3x3 convolution.
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, 1, 1, wScale, bValue, scValue, bnTimeConst)
# 1x1 expanding convolution, no ReLU.
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
p = Plus(c3, inp)
y = RectifiedLinear(p)
]
ResNetNode3AInc(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst, wProj, projStride)
[
# 1x1 reducing convolution.
c1 = Conv1x1ReLU(inp, convMap, inMap, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
# 3x3 convolution.
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, 1, 1, wScale, bValue, scValue, bnTimeConst)
# 1x1 expanding convolution, no ReLU.
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
# Input-to-output mapping convolution.
c_proj = ConvBNLayerW(wProj, inp, outMap, 1, 1, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
p = Plus(c3, c_proj)
y = RectifiedLinear(p)
]
ResNetNode3BInc(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst, projStride, stride1x1, stride3x3)
[
# 1x1 reducing convolution.
c1 = Conv1x1ReLU(inp, convMap, inMap, stride1x1, stride1x1, wScale, bValue, scValue, bnTimeConst)
# 3x3 convolution.
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, stride3x3, stride3x3, wScale, bValue, scValue, bnTimeConst)
# 1x1 expanding convolution, no ReLU.
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
# Input-to-output mapping convolution.
c_proj = Conv1x1(inp, outMap, inMap, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
p = Plus(c3, c_proj)
y = RectifiedLinear(p)
]
DnnLayer(hiddenDim, labelDim, x, wScale, bValue)
[
W = Parameter(labelDim, hiddenDim, init = Gaussian, initValueScale = wScale)
b = Parameter(labelDim, init = fixedValue, value = bValue)
t = Times(W, x)
z = Plus(t, b)
]
MaxNDPooling(inp, kW, kH, hStride, vStride)
[
p = Pooling(inp, "max", {kW, kH, 1}, stride = {hStride, vStride, 1}, autoPadding = {true, true, false}, imageLayout = "cudnn")
]

Просмотреть файл

@ -1,12 +0,0 @@
import sys
import numpy as np
def writeConvWeights(fname, cmapIn, cmapOut):
w = np.eye(cmapOut, cmapIn)
np.savetxt(fname, w, fmt = '%d', delimiter = ' ')
if __name__ == "__main__":
cmapIn = int(sys.argv[1])
cmapOut = int(sys.argv[2])
fname = sys.argv[3]
writeConvWeights(fname, cmapIn, cmapOut)

Просмотреть файл

@ -1,5 +1,7 @@
# CNTK Examples: Image/Classification/ResNet
The recipes above are in BrainScript. [For Python click here](https://github.com/Microsoft/CNTK/blob/v2.0.beta1.0/bindings/python/tutorials/CNTK_201A_CIFAR-10_DataLoader.ipynb).
## Overview
|Data: |The CIFAR-10 dataset (http://www.cs.toronto.edu/~kriz/cifar.html) and the ILSVRC2012 dataset (http://www.image-net.org/challenges/LSVRC/2012/) for image classification.
@ -12,7 +14,7 @@
## Running the example
### Getting the data
We use the CIFAR-10 and ILSVRC2012 datasets to demonstrate how to train a deep convolutional residual network (ResNet). ResNet was invented by Researchers at [Microsoft Research](https://www.microsoft.com/en-us/research/), and it won first place in both [ILSVRC](http://www.image-net.org/challenges/LSVRC/) and [MS COCO](http://mscoco.org/) competitions in the year of 2015.
We use the CIFAR-10 and ILSVRC2012 datasets to demonstrate how to train a deep convolutional residual network (ResNet). ResNet was invented by Researchers at [Microsoft Research](https://www.microsoft.com/en-us/research/), and it won first place in both [ILSVRC](http://www.image-net.org/challenges/LSVRC/) and [MS COCO](http://mscoco.org/) competitions in the year of 2015. The original implementation of ResNet was on Caffe (https://github.com/KaimingHe/deep-residual-networks).
CIFAR-10 and ILSVRC2012 datasets are not included in the CNTK distribution. The CIFAR-10 datasets can be downloaded and converted by following the instructions in [DataSets/CIFAR-10](../../DataSets/CIFAR-10). We recommend you to keep the downloaded data in the respective folder while downloading, as the configuration files in this folder assumes that by default. For ILSVRC2012 datasets, you may obtain it through http://image-net.org.
@ -39,16 +41,22 @@ In this example we increase the depth of the ResNet to 110 layers. That is, we s
The network achieves an error rate of about `6.2-6.5%`.
### ImageNet
### ResNet50_ImageNet1K.cntk
The BrainScript configuration files for ImageNet will be available soon. For now only a few deprecated ndl files are available here. The following table contains results as well as links to pre-trained models that can be used in various applications.
This is an example using a 50-layer ResNet to train on ILSVRC2012 datasets. Compared with the CIFAR-10 examples, we introduced bottleneck blocks to reduce the amount of computation by replacing the two `3x3` convolutions by a `1x1` convolution, bottlenecked to 1/4 of feature maps, followed by a `3x3` convolution, and then a `1x1` convolution again, with the same number feature maps as input.
| Network | Top-1 error | Top-5 error | Model
| ------------- | ----------- | ----------- | ----------
| ResNet-18 | 29.57 | 10.41 | [Download](https://www.cntk.ai/resnet/ResNet_18.model)
| ResNet-34 | 27.31 | 8.97 | [Download](https://www.cntk.ai/resnet/ResNet_34.model)
| ResNet-50 | 24.56 | 7.47 |
| ResNet-152 | 22.57 | 6.44 | [Download](https://www.cntk.ai/resnet/ResNet_152.model)
Run the example from the current folder using:
## Notes
This work is an implementation of ResNets in CNTK. If you are interested in the original implementation of ResNet, follow [this link](https://github.com/KaimingHe/deep-residual-networks).
`cntk configFile=ResNet50_ImageNet1K.cntk`
### ResNet101_ImageNet1K.cntk
Increase the depth of the ResNet to 101 layers:
`cntk configFile=ResNet101_ImageNet1K.cntk`
### ResNet152_ImageNet1K.cntk
Further increase the depth of the ResNet to 152 layers:
`cntk configFile=ResNet152_ImageNet1K.cntk`

Просмотреть файл

@ -0,0 +1,191 @@
# Node: ResNet-50 with ImageNet -- 101 layers bottleneck ResNet for image classification
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
command = TrainNetwork:BNStatistics:Eval
precision = "float"; traceLevel = 1 ; deviceId = "auto"
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
outputDir = "$rootDir$/Output" ;
modelPath = "$outputDir$/Models/ResNet_101"
stderr = "$outputDir$/ResNet_101_BS_out"
parallelTrain = true
TrainNetwork = {
action = "train"
BrainScriptNetworkBuilder = {
include "$configDir$/Macros.bs"
imageShape = 224:224:3 # image dimensions
labelDim = 1000 # number of distinct labels
cMap = 64:128:256:512:1024:2048
numLayers = 2:3:22:2
bnTimeConst = 0
# stride in BottleneckInc
stride1x1 = (2:2)
stride3x3 = (1:1)
model = Sequential(
# conv1 and max pooling
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
# conv2_x
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
# conv3_x
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
# conv4_x
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
# conv5_x
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
# avg pooling
AveragePoolingLayer {(7: 7), stride = 1} :
# FC
LinearLayer {labelDim, init= 'uniform'}
)
# inputs
features = Input {imageShape}
labels = Input {labelDim}
# apply model to features
ol = model (features)
# loss and error computation
ce = CrossEntropyWithSoftmax (labels, ol)
errs = ClassificationError (labels, ol)
top5Errs = ClassificationError (labels, ol, topN = 5)
# declare special nodes
featureNodes = (features)
labelNodes = (labels)
criterionNodes = (ce)
evaluationNodes = (errs) # top5Errs only used in Eval
outputNodes = (ol)
}
SGD = {
epochSize = 0
minibatchSize = 256
maxEpochs = 120
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
momentumPerMB = 0.9
gradUpdateType = "None"
L2RegWeight = 0.0001
dropoutRate = 0
numMBsToShowResult = 500
disableRegInBatchNormalization = true
ParallelTrain = {
parallelizationMethod = "DataParallelSGD"
distributedMBReading = true
parallelizationStartEpoch = 1
DataParallelSGD = {
gradientBits = 32
}
}
}
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
jitterType = "UniRatio"
cropRatio = 0.46666:0.875
hflip = true
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
cvReader = {
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
BNStatistics = {
action = "bnstat"
modelPath = "$modelPath$"
minibatchSize = 256
itersPerNode = 30
enableDistributedMBReading = true
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
hflip = true
cropRatio = 0.46666:0.875
jitterType = "UniRatio"
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
Eval = {
action = "test"
modelPath = "$modelPath$.PBN"
minibatchSize = 200
evalNodeNames = errs:top5Errs
reader={
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}

Просмотреть файл

@ -0,0 +1,191 @@
# Node: ResNet-50 with ImageNet -- 152 layers bottleneck ResNet for image classification
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
command = TrainNetwork:BNStatistics:Eval
precision = "float"; traceLevel = 1 ; deviceId = "auto"
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
outputDir = "$rootDir$/Output" ;
modelPath = "$outputDir$/Models/ResNet_152"
stderr = "$outputDir$/ResNet_152_BS_out"
parallelTrain = true
TrainNetwork = {
action = "train"
BrainScriptNetworkBuilder = {
include "$configDir$/Macros.bs"
imageShape = 224:224:3 # image dimensions
labelDim = 1000 # number of distinct labels
cMap = 64:128:256:512:1024:2048
numLayers = 2:7:35:2
bnTimeConst = 0
# stride in BottleneckInc
stride1x1 = (2:2)
stride3x3 = (1:1)
model = Sequential(
# conv1 and max pooling
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
# conv2_x
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
# conv3_x
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
# conv4_x
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
# conv5_x
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
# avg pooling
AveragePoolingLayer {(7: 7), stride = 1} :
# FC
LinearLayer {labelDim, init= 'uniform'}
)
# inputs
features = Input {imageShape}
labels = Input {labelDim}
# apply model to features
ol = model (features)
# loss and error computation
ce = CrossEntropyWithSoftmax (labels, ol)
errs = ClassificationError (labels, ol)
top5Errs = ClassificationError (labels, ol, topN = 5)
# declare special nodes
featureNodes = (features)
labelNodes = (labels)
criterionNodes = (ce)
evaluationNodes = (errs) # top5Errs only used in Eval
outputNodes = (ol)
}
SGD = {
epochSize = 0
minibatchSize = 256
maxEpochs = 120
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
momentumPerMB = 0.9
gradUpdateType = "None"
L2RegWeight = 0.0001
dropoutRate = 0
numMBsToShowResult = 500
disableRegInBatchNormalization = true
ParallelTrain = {
parallelizationMethod = "DataParallelSGD"
distributedMBReading = true
parallelizationStartEpoch = 1
DataParallelSGD = {
gradientBits = 32
}
}
}
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
jitterType = "UniRatio"
cropRatio = 0.46666:0.875
hflip = true
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
cvReader = {
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
BNStatistics = {
action = "bnstat"
modelPath = "$modelPath$"
minibatchSize = 256
itersPerNode = 30
enableDistributedMBReading = true
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
hflip = true
cropRatio = 0.46666:0.875
jitterType = "UniRatio"
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
Eval = {
action = "test"
modelPath = "$modelPath$.PBN"
minibatchSize = 200
evalNodeNames = errs:top5Errs
reader={
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}

Просмотреть файл

@ -0,0 +1,192 @@
# Node: ResNet-50 with ImageNet -- 50 layers bottleneck ResNet for image classification
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
command = TrainNetwork:BNStatistics:Eval
precision = "float"; traceLevel = 1 ; deviceId = "auto"
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
outputDir = "$rootDir$/Output" ;
modelPath = "$outputDir$/Models/ResNet_50"
stderr = "$outputDir$/ResNet_50_BS_out"
parallelTrain = true
TrainNetwork = {
action = "train"
BrainScriptNetworkBuilder = {
include "$configDir$/Macros.bs"
imageShape = 224:224:3 # image dimensions
labelDim = 1000 # number of distinct labels
cMap = 64:128:256:512:1024:2048
numLayers = 2:3:5:2
bnTimeConst = 0
# stride in BottleneckInc
stride1x1 = (2:2)
stride3x3 = (1:1)
model = Sequential(
# conv1 and max pooling
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
# conv2_x
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
# conv3_x
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
# conv4_x
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
# conv5_x
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
# avg pooling
AveragePoolingLayer {(7: 7), stride = 1} :
# FC
LinearLayer {labelDim, init = 'uniform'}
)
# inputs
features = Input {imageShape}
labels = Input {labelDim}
# apply model to features
z = model (features)
# loss and error computation
ce = CrossEntropyWithSoftmax (labels, z)
errs = ClassificationError (labels, z)
top5Errs = ClassificationError (labels, z, topN = 5)
# declare special nodes
featureNodes = (features)
labelNodes = (labels)
criterionNodes = (ce)
evaluationNodes = (errs) # top5Errs only used in Eval
outputNodes = (z)
}
SGD = {
epochSize = 0
minibatchSize = 256
maxEpochs = 120
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
momentumPerMB = 0.9
gradUpdateType = "None"
L2RegWeight = 0.0001
dropoutRate = 0
numMBsToShowResult = 500
disableRegInBatchNormalization = true
ParallelTrain = {
parallelizationMethod = "DataParallelSGD"
distributedMBReading = true
parallelizationStartEpoch = 1
DataParallelSGD = {
gradientBits = 32
}
}
}
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
jitterType = "UniRatio"
cropRatio = 0.46666:0.875
hflip = true
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
cvReader = {
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
# Re-statistics the mean and variance of batch normalization layers while other parameters frozen after training
# more details: https://github.com/Microsoft/CNTK/wiki/Post-Batch-Normalization-Statistics#post-batch-normalization-statistics
BNStatistics = {
action = "bnstat"
modelPath = "$modelPath$"
minibatchSize = 256
itersPerNode = 30
enableDistributedMBReading = true
reader = {
readerType = "ImageReader"
file = "$DataDir$/train_map.txt"
randomize = "Auto"
features = {
width = 224
height = 224
channels = 3
cropType = "Random"
hflip = true
cropRatio = 0.46666:0.875
jitterType = "UniRatio"
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}
Eval = {
action = "test"
modelPath = "$modelPath$.PBN"
minibatchSize = 200
evalNodeNames = errs:top5Errs
reader={
readerType = "ImageReader"
file = "$DataDir$/val_map.txt"
randomize = "None"
features = {
width = 224
height = 224
channels = 3
cropType = "Center"
cropRatio = 0.875
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
}
labels = {
labelDim = 1000
}
}
}

Просмотреть файл

@ -1,116 +0,0 @@
load=ndlMacros
run=DNN
ndlMacros = [
ImageW = 224
ImageH = 224
ImageC = 3
LabelDim = 1000
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
labels = Input(LabelDim, tag = label)
# Kernels width and height.
kW = 3
kH = 3
# Kernel stride.
hs = 1
vs = 1
# Initial parameter values.
convWScale = 7.07
convBValue = 0
fcWScale = 2.26
fcBValue = 0
scValue = 1
# Batch normalization time constant.
bnTimeConst = 4096
]
DNN=[
cMap1 = 64
cMap2 = 128
cMap3 = 256
cMap4 = 512
cMap5 = 1024
cMap6 = 2048
conv1WScale = 0.6
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
# Max pooling
pool1W = 3
pool1H = 3
pool1hs = 2
pool1vs = 2
pool1 = MaxPooling(conv1, pool1W, pool1H, pool1hs, pool1vs, imageLayout = "cudnn")
rn1_1 = ResNetNode3BInc(pool1, cMap1, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst, 1, 1, 1)
rn1_2 = ResNetNode3A(rn1_1, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
rn1_3 = ResNetNode3A(rn1_2, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
rn2_1 = ResNetNode3BInc(rn1_3, cMap3, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn2_2 = ResNetNode3A(rn2_1, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_3 = ResNetNode3A(rn2_2, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_4 = ResNetNode3A(rn2_3, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_5 = ResNetNode3A(rn2_4, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_6 = ResNetNode3A(rn2_5, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_7 = ResNetNode3A(rn2_6, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_8 = ResNetNode3A(rn2_7, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn3_1 = ResNetNode3BInc(rn2_8, cMap4, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn3_2 = ResNetNode3A(rn3_1, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_3 = ResNetNode3A(rn3_2, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_4 = ResNetNode3A(rn3_3, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_5 = ResNetNode3A(rn3_4, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_6 = ResNetNode3A(rn3_5, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_7 = ResNetNode3A(rn3_6, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_8 = ResNetNode3A(rn3_7, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_9 = ResNetNode3A(rn3_8, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_10= ResNetNode3A(rn3_9, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_11= ResNetNode3A(rn3_10, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_12= ResNetNode3A(rn3_11, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_13= ResNetNode3A(rn3_12, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_14= ResNetNode3A(rn3_13, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_15= ResNetNode3A(rn3_14, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_16= ResNetNode3A(rn3_15, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_17= ResNetNode3A(rn3_16, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_18= ResNetNode3A(rn3_17, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_19= ResNetNode3A(rn3_18, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_20= ResNetNode3A(rn3_19, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_21= ResNetNode3A(rn3_20, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_22= ResNetNode3A(rn3_21, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_23= ResNetNode3A(rn3_22, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_24= ResNetNode3A(rn3_23, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_25= ResNetNode3A(rn3_24, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_26= ResNetNode3A(rn3_25, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_27= ResNetNode3A(rn3_26, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_28= ResNetNode3A(rn3_27, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_29= ResNetNode3A(rn3_28, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_30= ResNetNode3A(rn3_29, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_31= ResNetNode3A(rn3_30, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_32= ResNetNode3A(rn3_31, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_33= ResNetNode3A(rn3_32, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_34= ResNetNode3A(rn3_33, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_35= ResNetNode3A(rn3_34, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_36= ResNetNode3A(rn3_35, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn4_1 = ResNetNode3BInc(rn3_36, cMap5, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn4_2 = ResNetNode3A(rn4_1, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
rn4_3 = ResNetNode3A(rn4_2, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
# Global average pooling
pool2W = 7
pool2H = 7
pool2hs = 1
pool2vs = 1
pool2 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
ol = DnnLayer(cMap6, labelDim, pool2, fcWScale, fcBValue)
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
Err = ClassificationError(labels, ol, tag = Eval)
OutputNodes = ol
]

Просмотреть файл

@ -1,136 +0,0 @@
# Note: This sample uses the deprecated NdlNetworkBuilder.
# An updated version using BrainScript is coming soon.
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
#
RootDir = "."
ConfigDir = "$RootDir$"
DataDir = "$RootDir$"
OutputDir = "$RootDir$/Output"
ModelDir = "$OutputDir$/Models"
ndlMacros="$ConfigDir$/Macros.ndl"
precision="float"
deviceId="Auto"
command=Train:CreateEval:Test
parallelTrain="false"
stderr="$OutputDir$/ResNet_152"
traceLevel=1
numMBsToShowResult=500
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
stride1x1=1
stride3x3=2
Train=[
action="train"
modelPath="$ModelDir$/ResNet_152"
NDLNetworkBuilder=[
networkDescription="$ConfigDir$/ResNet_152.ndl"
]
SGD=[
epochSize=0
minibatchSize=256
# Note that learning rates are 10x more than in the paper due to a different
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
momentumPerMB=0.9
maxEpochs=125
gradUpdateType="None"
L2RegWeight=0.0001
dropoutRate=0
ParallelTrain=[
parallelizationMethod="DataParallelSGD"
distributedMBReading="true"
parallelizationStartEpoch=1
DataParallelSGD=[
gradientBits=32
]
]
]
reader=[
readerType="ImageReader"
# Map file which maps images to labels using the following format:
# <full path to image><tab><numerical label (0-based class id)>
# Example:
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
file="$DataDir$/train_map.txt"
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
randomize="Auto"
features=[
# Below are the required parameters.
width=224
height=224
channels=3
# Below are the optional parameters.
# Possible values: Center, Random. Default: Center
cropType="Random"
# Horizontal random flip, will be enabled by default if cropType=Random
#hflip="true"
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
cropRatio=0.46666:0.875
# Crop scale ratio jitter type.
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
jitterType="UniRatio"
# Interpolation to use when scaling image to width x height size.
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
interpolations="cubic"
# Aspect ratio jitter radius. Default is 0 (disabled).
aspectRatioRadius=0:0.2
# Brightness, contrast and color jittering. Default is 0 (disabled).
# Using 0 in the first epoch so the network can process original images.
brightnessRadius=0:0.2
contrastRadius=0:0.2
saturationRadius=0:0.4
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
# StdDev for intensity jittering. Start from the second epoch.
intensityStdDev=0:0.1
# Mean subtraction: enabled if file is specified.
# The file stores mean values for each pixel in OpenCV matrix XML format.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]
CreateEval=[
action="edit"
CurModel="$ModelDir$/ResNet_152"
NewModel="$ModelDir$/ResNet_152.Eval"
editPath="$ConfigDir$/CreateEvalModel.mel"
]
Test=[
action="test"
modelPath="$ModelDir$/ResNet_152.Eval"
# Set minibatch size for testing.
minibatchSize=32
reader=[
readerType="ImageReader"
file="$DataDir$/val_map.txt"
randomize="None"
features=[
width=224
height=224
channels=3
cropType="Center"
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]

Просмотреть файл

@ -1,72 +0,0 @@
load=ndlMacros
run=DNN
ndlMacros = [
ImageW = 224
ImageH = 224
ImageC = 3
LabelDim = 1000
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
labels = Input(LabelDim, tag = label)
# Kernels width and height.
kW = 3
kH = 3
# Kernel stride.
hs = 1
vs = 1
# Initial parameter values.
convWScale = 7.07
convBValue = 0
fcWScale = 1.13
fcBValue = 0
scValue = 1
# Batch normalization time constant.
bnTimeConst = 32768
]
DNN=[
conv1WScale = 0.6
cMap1 = 64
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
# Max pooling
pool1W = 3
pool1H = 3
pool1hs = 2
pool1vs = 2
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
rn1_1 = ResNetNode2A(pool1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn1_2 = ResNetNode2A(rn1_1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap2 = 128
rn2_1 = ResNetNode2BInc(rn1_2, cMap2, cMap1, 576, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn2_2 = ResNetNode2A(rn2_1, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap3 = 256
rn3_1 = ResNetNode2BInc(rn2_2, cMap3, cMap2, 1152, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn3_2 = ResNetNode2A(rn3_1, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap4 = 512
rn4_1 = ResNetNode2BInc(rn3_2, cMap4, cMap3, 2304, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn4_2 = ResNetNode2A(rn4_1, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn4_3 = ResNetNode2A(rn4_2, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
# Global average pooling
pool2W = 7
pool2H = 7
pool2hs = 1
pool2vs = 1
pool5 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
ol = DnnLayer(cMap4, labelDim, pool5, fcWScale, fcBValue)
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
Err = ClassificationError(labels, ol, tag = Eval)
OutputNodes = ol
]

Просмотреть файл

@ -1,136 +0,0 @@
# Note: This sample uses the deprecated NdlNetworkBuilder.
# An updated version using BrainScript is coming soon.
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
#
RootDir = "."
ConfigDir = "$RootDir$"
DataDir = "$RootDir$"
OutputDir = "$RootDir$/Output"
ModelDir = "$OutputDir$/Models"
ndlMacros="$ConfigDir$/Macros.ndl"
precision="float"
deviceId="Auto"
command=Train:CreateEval:Test
parallelTrain="false"
stderr="$OutputDir$/ResNet_18"
traceLevel=1
numMBsToShowResult=500
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
stride1x1=1
stride3x3=2
Train=[
action="train"
modelPath="$ModelDir$/ResNet_18"
NDLNetworkBuilder=[
networkDescription="$ConfigDir$/ResNet_18.ndl"
]
SGD=[
epochSize=0
minibatchSize=256
# Note that learning rates are 10x more than in the paper due to a different
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
momentumPerMB=0.9
maxEpochs=125
gradUpdateType="None"
L2RegWeight=0.0001
dropoutRate=0
ParallelTrain=[
parallelizationMethod="DataParallelSGD"
distributedMBReading="true"
parallelizationStartEpoch=1
DataParallelSGD=[
gradientBits=32
]
]
]
reader=[
readerType="ImageReader"
# Map file which maps images to labels using the following format:
# <full path to image><tab><numerical label (0-based class id)>
# Example:
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
file="$DataDir$/train_map.txt"
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
randomize="Auto"
features=[
# Below are the required parameters.
width=224
height=224
channels=3
# Below are the optional parameters.
# Possible values: Center, Random, MultiView10. Default: Center
cropType="Random"
# Horizontal random flip, will be enabled by default if cropType=Random
#hflip="true"
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
cropRatio=0.46666:0.875
# Crop scale ratio jitter type.
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
jitterType="UniRatio"
# Interpolation to use when scaling image to width x height size.
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
interpolations="cubic"
# Aspect ratio jitter radius. Default is 0 (disabled).
aspectRatioRadius=0:0.2
# Brightness, contrast and color jittering. Default is 0 (disabled).
# Using 0 in the first epoch so the network can process original images.
brightnessRadius=0:0.2
contrastRadius=0:0.2
saturationRadius=0:0.4
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
# StdDev for intensity jittering. Start from the second epoch.
intensityStdDev=0:0.1
# Mean subtraction: enabled if file is specified.
# The file stores mean values for each pixel in OpenCV matrix XML format.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]
CreateEval=[
action="edit"
CurModel="$ModelDir$/ResNet_18"
NewModel="$ModelDir$/ResNet_18.Eval"
editPath="$ConfigDir$/CreateEvalModel.mel"
]
Test=[
action="test"
modelPath="$ModelDir$/ResNet_18.Eval"
# Set minibatch size for testing.
minibatchSize=64
reader=[
readerType="ImageReader"
file="$DataDir$/val_map.txt"
randomize="None"
features=[
width=224
height=224
channels=3
cropType="Center" # Use MultiView10 to enable 10-view testing.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]

Просмотреть файл

@ -1,79 +0,0 @@
load=ndlMacros
run=DNN
ndlMacros = [
ImageW = 224
ImageH = 224
ImageC = 3
LabelDim = 1000
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
labels = Input(LabelDim, tag = label)
# Kernels width and height.
kW = 3
kH = 3
# Kernel stride.
hs = 1
vs = 1
# Initial parameter values.
convWScale = 7.07
convBValue = 0
fcWScale = 1.13
fcBValue = 0
scValue = 1
# Batch normalization time constant.
bnTimeConst = 4096
]
DNN=[
conv1WScale = 0.6
cMap1 = 64
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
# Max pooling
pool1W = 3
pool1H = 3
pool1hs = 2
pool1vs = 2
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
rn1_1 = ResNetNode2A(pool1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn1_2 = ResNetNode2A(rn1_1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn1_3 = ResNetNode2A(rn1_2, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap2 = 128
rn2_1 = ResNetNode2BInc(rn1_3, cMap2, cMap1, 576, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn2_2 = ResNetNode2A(rn2_1, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn2_3 = ResNetNode2A(rn2_2, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn2_4 = ResNetNode2A(rn2_3, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap3 = 256
rn3_1 = ResNetNode2BInc(rn2_4, cMap3, cMap2, 1152, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn3_2 = ResNetNode2A(rn3_1, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn3_3 = ResNetNode2A(rn3_2, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn3_4 = ResNetNode2A(rn3_3, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn3_5 = ResNetNode2A(rn3_4, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn3_6 = ResNetNode2A(rn3_5, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
cMap4 = 512
rn4_1 = ResNetNode2BInc(rn3_6, cMap4, cMap3, 2304, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
rn4_2 = ResNetNode2A(rn4_1, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
rn4_3 = ResNetNode2A(rn4_2, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
# Global average pooling
pool2W = 7
pool2H = 7
pool2hs = 1
pool2vs = 1
pool5 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
ol = DnnLayer(cMap4, labelDim, pool5, fcWScale, fcBValue)
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
Err = ClassificationError(labels, ol, tag = Eval)
OutputNodes = ol
]

Просмотреть файл

@ -1,136 +0,0 @@
# Note: This sample uses the deprecated NdlNetworkBuilder.
# An updated version using BrainScript is coming soon.
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
#
RootDir = "."
ConfigDir = "$RootDir$"
DataDir = "$RootDir$"
OutputDir = "$RootDir$/Output"
ModelDir = "$OutputDir$/Models"
ndlMacros="$ConfigDir$/Macros.ndl"
precision="float"
deviceId="Auto"
command=Train:CreateEval:Test
parallelTrain="false"
stderr="$OutputDir$/ResNet_34"
traceLevel=1
numMBsToShowResult=500
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
stride1x1=1
stride3x3=2
Train=[
action="train"
modelPath="$ModelDir$/ResNet_34"
NDLNetworkBuilder=[
networkDescription="$ConfigDir$/ResNet_34.ndl"
]
SGD=[
epochSize=0
minibatchSize=256
# Note that learning rates are 10x more than in the paper due to a different
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
momentumPerMB=0.9
maxEpochs=125
gradUpdateType="None"
L2RegWeight=0.0001
dropoutRate=0
ParallelTrain=[
parallelizationMethod="DataParallelSGD"
distributedMBReading="true"
parallelizationStartEpoch=1
DataParallelSGD=[
gradientBits=32
]
]
]
reader=[
readerType="ImageReader"
# Map file which maps images to labels using the following format:
# <full path to image><tab><numerical label (0-based class id)>
# Example:
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
file="$DataDir$/train_map.txt"
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
randomize="Auto"
features=[
# Below are the required parameters.
width=224
height=224
channels=3
# Below are the optional parameters.
# Possible values: Center, Random, MultiView10. Default: Center
cropType="Random"
# Horizontal random flip, will be enabled by default if cropType=Random
#hflip="true"
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
cropRatio=0.46666:0.875
# Crop scale ratio jitter type.
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
jitterType="UniRatio"
# Interpolation to use when scaling image to width x height size.
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
interpolations="cubic"
# Aspect ratio jitter radius. Default is 0 (disabled).
aspectRatioRadius=0:0.2
# Brightness, contrast and color jittering. Default is 0 (disabled).
# Using 0 in the first epoch so the network can process original images.
brightnessRadius=0:0.2
contrastRadius=0:0.2
saturationRadius=0:0.4
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
# StdDev for intensity jittering. Start from the second epoch.
intensityStdDev=0:0.1
# Mean subtraction: enabled if file is specified.
# The file stores mean values for each pixel in OpenCV matrix XML format.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]
CreateEval=[
action="edit"
CurModel="$ModelDir$/ResNet_34"
NewModel="$ModelDir$/ResNet_34.Eval"
editPath="$ConfigDir$/CreateEvalModel.mel"
]
Test=[
action="test"
modelPath="$ModelDir$/ResNet_34.Eval"
# Set minibatch size for testing.
minibatchSize=64
reader=[
readerType="ImageReader"
file="$DataDir$/val_map.txt"
randomize="None"
features=[
width=224
height=224
channels=3
cropType="Center" # Use MultiView10 to enable 10-view testing.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]

Просмотреть файл

@ -1,82 +0,0 @@
load=ndlMacros
run=DNN
ndlMacros = [
ImageW = 224
ImageH = 224
ImageC = 3
LabelDim = 1000
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
labels = Input(LabelDim, tag = label)
# Kernels width and height.
kW = 3
kH = 3
# Kernel stride.
hs = 1
vs = 1
# Initial parameter values.
convWScale = 7.07
convBValue = 0
fcWScale = 2.26
fcBValue = 0
scValue = 1
# Batch normalization time constant.
bnTimeConst = 0
]
DNN=[
cMap1 = 64
cMap2 = 128
cMap3 = 256
cMap4 = 512
cMap5 = 1024
cMap6 = 2048
conv1WScale = 0.6
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
# Max pooling
pool1W = 3
pool1H = 3
pool1hs = 2
pool1vs = 2
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
rn1_1 = ResNetNode3BInc(pool1, cMap1, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst, 1, 1, 1)
rn1_2 = ResNetNode3A(rn1_1, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
rn1_3 = ResNetNode3A(rn1_2, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
rn2_1 = ResNetNode3BInc(rn1_3, cMap3, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn2_2 = ResNetNode3A(rn2_1, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_3 = ResNetNode3A(rn2_2, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn2_4 = ResNetNode3A(rn2_3, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
rn3_1 = ResNetNode3BInc(rn2_4, cMap4, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn3_2 = ResNetNode3A(rn3_1, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_3 = ResNetNode3A(rn3_2, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_4 = ResNetNode3A(rn3_3, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_5 = ResNetNode3A(rn3_4, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn3_6 = ResNetNode3A(rn3_5, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
rn4_1 = ResNetNode3BInc(rn3_6, cMap5, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
rn4_2 = ResNetNode3A(rn4_1, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
rn4_3 = ResNetNode3A(rn4_2, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
# Global average pooling
pool2W = 7
pool2H = 7
pool2hs = 1
pool2vs = 1
pool2 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
ol = DnnLayer(cMap6, labelDim, pool2, fcWScale, fcBValue)
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
Err = ClassificationError(labels, ol, tag = Eval)
OutputNodes = ol
]

Просмотреть файл

@ -1,155 +0,0 @@
# Note: This sample uses the deprecated NdlNetworkBuilder.
# An updated version using BrainScript is coming soon.
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
#
RootDir = "."
ConfigDir = "$RootDir$"
DataDir = "$RootDir$"
OutputDir = "$RootDir$/Output"
ModelDir = "$OutputDir$/Models"
ndlMacros="$ConfigDir$/Macros.ndl"
precision="float"
deviceId="Auto"
command=Train:PBN:CreateEval:Test
parallelTrain="false"
stderr="$OutputDir$/ResNet_50"
traceLevel=1
numMBsToShowResult=500
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
stride1x1=2
stride3x3=1
Train=[
action="train"
modelPath="$ModelDir$/ResNet_50"
NDLNetworkBuilder=[
networkDescription="$ConfigDir$/ResNet_50.ndl"
]
SGD=[
epochSize=0
minibatchSize=256
# Note that learning rates are 10x more than in the paper due to a different
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
momentumPerMB=0.9
maxEpochs=125
gradUpdateType="None"
L2RegWeight=0.0001
dropoutRate=0
disableWkInBatchNormal=true
ParallelTrain=[
parallelizationMethod="DataParallelSGD"
distributedMBReading="true"
parallelizationStartEpoch=1
DataParallelSGD=[
gradientBits=32
]
]
]
reader=[
readerType="ImageReader"
file="$DataDir$/train_map.txt"
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
randomize="Auto"
features=[
# Below are the required parameters.
width=224
height=224
channels=3
# Below are the optional parameters.
# Possible values: Center, Random. Default: Center
cropType="Random"
# Horizontal random flip, will be enabled by default if cropType=Random
hflip="true"
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
cropRatio=0.46666:0.875
# Crop scale ratio jitter type.
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
jitterType="UniRatio"
# The file stores mean values for each pixel in OpenCV matrix XML format.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]
PBN=[
action="pbn"
modelPath="$ModelDir$/ResNet_50"
# Set minibatch size for testing.
minibatchSize=256
iters=30
reader=[
readerType="ImageReader"
file="$DataDir$/train_map.txt"
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
randomize="Auto"
features=[
# Below are the required parameters.
width=224
height=224
channels=3
# Below are the optional parameters.
# Possible values: Center, Random. Default: Center
cropType="Random"
# Horizontal random flip, will be enabled by default if cropType=Random
hflip="true"
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
cropRatio=0.46666:0.875
# Crop scale ratio jitter type.
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
jitterType="UniRatio"
# The file stores mean values for each pixel in OpenCV matrix XML format.
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]
CreateEval=[
action="edit"
CurModel="$ModelDir$/ResNet_50.PBN"
NewModel="$ModelDir$/ResNet_50.Eval"
editPath="$ConfigDir$/CreateEvalModel.mel"
]
Test=[
action="test"
modelPath="$ModelDir$/ResNet_50.Eval"
# Set minibatch size for testing.
minibatchSize=200
reader=[
readerType="ImageReader"
file="$DataDir$/val_map.txt"
randomize="None"
features=[
width=224
height=224
channels=3
cropType="Center"
cropRatio=0.875
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
]
labels=[
labelDim=1000
]
]
]

Просмотреть файл

@ -0,0 +1,42 @@
# Pascal VOC Dataset
The [Pascal VOC](http://host.robots.ox.ac.uk/pascal/VOC/) (PASCAL Visual Object Classes) data
is a well known set of standardised images for object class recognition.
## Getting the Pascal VOC data
The Pascal VOC dataset is not included in the CNTK distribution but can be easily
downloaded by running the following Python command:
`python install_pascalvoc.py`
This will download roughly 3.15GB of data and unpack it into the folder structure that is assumed in the [object recognition tutorial](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN#run-pascal-voc)
## Alternative: download data manually
You need the 2007 (trainval and test) and 2012 (trainval) data as well as the precomputed ROIs used in the original Fast R-CNN paper.
For the object recognition tutorial you need to follow the folder structure described below.
* Download and unpack the 2012 trainval data to `DataSets/Pascal/VOCdevkit`
* Website: [http://host.robots.ox.ac.uk/pascal/VOC/voc2012/](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/)
* Devkit: [http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar)
* Download and unpack the 2007 trainval data to `DataSets/Pascal/VOCdevkit`
* Website: [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/)
* Devkit: [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar)
* Download and unpack the 2007 test data into the same folder `DataSets/Pascal/VOCdevkit`
* [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar)
* Download and unpack the precomputed ROIs to `DataSets/Pascal/selective_search_data`
* [http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz](http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz)
The `VOCdevkit/VOC2007` folder should contain at least the following (similar for 2012):
```
VOCdevkit/VOC2007
VOCdevkit/VOC2007/Annotations
VOCdevkit/VOC2007/ImageSets
VOCdevkit/VOC2007/JPEGImages
```
## Performance
If you are curious about how well computers can perform on Pascal VOC today, the official leaderboards are maintained at
[http://host.robots.ox.ac.uk:8080/leaderboard/main_bootstrap.php](http://host.robots.ox.ac.uk:8080/leaderboard/main_bootstrap.php)

Просмотреть файл

@ -0,0 +1,63 @@
from __future__ import print_function
import os
import os.path
import tarfile
import zipfile
try:
from urllib.request import urlretrieve
except ImportError:
from urllib import urlretrieve
def download_and_untar(url, filename, filesize):
if not os.path.exists(filename):
print ('Downloading ' + filesize + ' from ' + url + ', may take a while...')
try:
urlretrieve(url, filename)
except (urllib.ContentTooShortError, IOError) as e:
print ("Error downloading file: " + str(e))
os.remove(filename)
quit()
else:
print ('Found ' + filename)
try:
print ('Extracting ' + filename + '...')
with tarfile.open(filename) as tar:
tar.extractall()
print ('Done.')
finally:
os.remove(filename)
return;
if __name__ == "__main__":
directory = "./VOCdevkit/VOC2007"
if not os.path.exists(directory):
download_and_untar(
"http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar",
"./VOCtrainval_06-Nov-2007.tar",
"450MB")
download_and_untar(
"http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar",
"./VOCtest_06-Nov-2007.tar",
"430MB")
else:
print (directory + ' data already available.')
directory = "./VOCdevkit/VOC2012"
if not os.path.exists(directory):
download_and_untar(
"http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar",
"./VOCtrainval_11-May-2012.tar",
"2GB")
else:
print (directory + ' data already available.')
directory = "./selective_search_data"
if not os.path.exists(directory):
os.makedirs(directory)
download_and_untar(
"http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz",
"./selective_search_data.tgz",
"460MB")
else:
print (directory + ' data already available.')

Просмотреть файл

@ -0,0 +1,135 @@
from __future__ import print_function
from builtins import input
import os, sys, importlib
import shutil, time
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
boSaveDebugImg = True
subDirs = ['positive', 'testImages', 'negative']
image_sets = ["train", "test"]
# no need to change these parameters
boAddSelectiveSearchROIs = True
boAddRoisOnGrid = True
####################################
# Main
####################################
# generate ROIs using selective search and grid (for pascal we use the precomputed ROIs from Ross)
if not datasetName.startswith("pascalVoc"):
# init
makeDirectory(roiDir)
roi_minDim = roi_minDimRel * roi_maxImgDim
roi_maxDim = roi_maxDimRel * roi_maxImgDim
roi_minNrPixels = roi_minNrPixelsRel * roi_maxImgDim*roi_maxImgDim
roi_maxNrPixels = roi_maxNrPixelsRel * roi_maxImgDim*roi_maxImgDim
for subdir in subDirs:
makeDirectory(roiDir + subdir)
imgFilenames = getFilesInDirectory(imgDir + subdir, ".jpg")
# loop over all images
for imgIndex,imgFilename in enumerate(imgFilenames):
roiPath = "{}/{}/{}.roi.txt".format(roiDir, subdir, imgFilename[:-4])
# load image
print (imgIndex, len(imgFilenames), subdir, imgFilename)
tstart = datetime.datetime.now()
imgPath = imgDir + subdir + "/" + imgFilename
imgOrig = imread(imgPath)
if imWidth(imgPath) > imHeight(imgPath):
print (imWidth(imgPath) , imHeight(imgPath))
# get rois
if boAddSelectiveSearchROIs:
print ("Calling selective search..")
rects, img, scale = getSelectiveSearchRois(imgOrig, ss_scale, ss_sigma, ss_minSize, roi_maxImgDim) #interpolation=cv2.INTER_AREA
print (" Number of rois detected using selective search: " + str(len(rects)))
else:
rects = []
img, scale = imresizeMaxDim(imgOrig, roi_maxImgDim, boUpscale=True, interpolation=cv2.INTER_AREA)
imgWidth, imgHeight = imArrayWidthHeight(img)
# add grid rois
if boAddRoisOnGrid:
rectsGrid = getGridRois(imgWidth, imgHeight, grid_nrScales, grid_aspectRatios)
print (" Number of rois on grid added: " + str(len(rectsGrid)))
rects += rectsGrid
# run filter
print (" Number of rectangles before filtering = " + str(len(rects)))
rois = filterRois(rects, imgWidth, imgHeight, roi_minNrPixels, roi_maxNrPixels, roi_minDim, roi_maxDim, roi_maxAspectRatio)
if len(rois) == 0: #make sure at least one roi returned per image
rois = [[5, 5, imgWidth-5, imgHeight-5]]
print (" Number of rectangles after filtering = " + str(len(rois)))
# scale up to original size and save to disk
# note: each rectangle is in original image format with [x,y,x2,y2]
rois = np.int32(np.array(rois) / scale)
assert (np.min(rois) >= 0)
assert (np.max(rois[:, [0,2]]) < imArrayWidth(imgOrig))
assert (np.max(rois[:, [1,3]]) < imArrayHeight(imgOrig))
np.savetxt(roiPath, rois, fmt='%d')
print (" Time [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000))
# clear imdb cache and other files
if os.path.exists(cntkFilesDir):
assert(cntkFilesDir.endswith("cntkFiles/"))
userInput = input('--> INPUT: Press "y" to delete directory ' + cntkFilesDir + ": ")
if userInput.lower() not in ['y', 'yes']:
print ("User input is %s: exiting now." % userInput)
exit(-1)
shutil.rmtree(cntkFilesDir)
time.sleep(0.1) # avoid access problems
# create cntk representation for each image
for image_set in image_sets:
imdb = imdbs[image_set]
print ("Number of images in set {} = {}".format(image_set, imdb.num_images))
makeDirectory(cntkFilesDir)
# open files for writing
cntkImgsPath, cntkRoiCoordsPath, cntkRoiLabelsPath, nrRoisPath = getCntkInputPaths(cntkFilesDir, image_set)
with open(nrRoisPath, 'w') as nrRoisFile, \
open(cntkImgsPath, 'w') as cntkImgsFile, \
open(cntkRoiCoordsPath, 'w') as cntkRoiCoordsFile, \
open(cntkRoiLabelsPath, 'w') as cntkRoiLabelsFile:
# for each image, transform rois etc to cntk format
for imgIndex in range(0, imdb.num_images):
if imgIndex % 50 == 0:
print ("Processing image set '{}', image {} of {}".format(image_set, imgIndex, imdb.num_images))
currBoxes = imdb.roidb[imgIndex]['boxes']
currGtOverlaps = imdb.roidb[imgIndex]['gt_overlaps']
imgPath = imdb.image_path_at(imgIndex)
imgWidth, imgHeight = imWidthHeight(imgPath)
# all rois need to be scaled + padded to cntk input image size
targetw, targeth, w_offset, h_offset, scale = roiTransformPadScaleParams(imgWidth, imgHeight,
cntk_padWidth, cntk_padHeight)
boxesStr = ""
labelsStr = ""
nrBoxes = len(currBoxes)
for boxIndex, box in enumerate(currBoxes):
rect = roiTransformPadScale(box, w_offset, h_offset, scale)
boxesStr += getCntkRoiCoordsLine(rect, cntk_padWidth, cntk_padHeight)
labelsStr += getCntkRoiLabelsLine(currGtOverlaps[boxIndex, :].toarray()[0],
train_posOverlapThres,
nrClasses)
# if less than e.g. 2000 rois per image, then fill in the rest using 'zero-padding'.
boxesStr, labelsStr = cntkPadInputs(nrBoxes, cntk_nrRois, nrClasses, boxesStr, labelsStr)
# update cntk data
nrRoisFile.write("{}\n".format(nrBoxes))
cntkImgsFile.write("{}\t{}\t0\n".format(imgIndex, imgPath))
cntkRoiCoordsFile.write("{} |rois{}\n".format(imgIndex, boxesStr))
cntkRoiLabelsFile.write("{} |roiLabels{}\n".format(imgIndex, labelsStr))
print ("DONE.")

Просмотреть файл

@ -0,0 +1,53 @@
from __future__ import print_function
import os, sys, importlib
import shutil, time
import subprocess
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
cntkCmdStrPattern = "cntk.exe configFile={0}fastrcnn.cntk currentDirectory={0} {1}"
# cntk arguments
NumLabels = nrClasses
NumTrainROIs = cntk_nrRois
TrainROIDim = cntk_nrRois * 4
TrainROILabelDim = cntk_nrRois * nrClasses
NumTestROIs = cntk_nrRois
TestROIDim = cntk_nrRois * 4
TestROILabelDim = cntk_nrRois * nrClasses
cntk_args = "NumLabels={} NumTrainROIs={}".format(NumLabels, NumTrainROIs)
cntk_args += " TrainROIDim={} TrainROILabelDim={}".format(TrainROIDim, TrainROILabelDim)
cntk_args += " NumTestROIs={}".format(NumTestROIs)
cntk_args += " TestROIDim={} TestROILabelDim={}".format(TestROIDim, TestROILabelDim)
####################################
# Main
####################################
# copy config file
shutil.copy(cntkTemplateDir + "fastrcnn.cntk", cntkFilesDir)
# run cntk
tstart = datetime.datetime.now()
os.environ['ACML_FMA'] = str(0)
cmdStr = cntkCmdStrPattern.format(cntkFilesDir, cntk_args)
print (cmdStr)
pid = subprocess.Popen(cmdStr, cwd = cntkFilesDir)
pid.wait()
print ("Time running cntk [s]: " + str((datetime.datetime.now() - tstart).total_seconds()))
# delete intermediate model files written during cntk training
modelDir = cntkFilesDir + "Output/"
filenames = getFilesInDirectory(modelDir, postfix = None)
for filename in filenames:
if filename.contains('Fast-RCNN.model.'):
os.remove(modelDir + filename)
assert pid.returncode == 0, "ERROR: cntk ended with exit code {}".format(pid.returncode)
print ("DONE.")

Просмотреть файл

@ -0,0 +1,55 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
"""Test a Fast R-CNN network on an image database."""
from __future__ import print_function
import importlib
from fastRCNN.test import test_net
from fastRCNN.timer import Timer
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
image_set = 'test' # 'train', 'test'
####################################
# Main
####################################
# parse cntk output
print ("Parsing CNTK output for image set: " + image_set)
cntkImgsListPath = cntkFilesDir + image_set + ".txt"
outParsedDir = cntkFilesDir + image_set + "_parsed/"
cntkOutputPath = cntkFilesDir + image_set + ".z"
# write cntk output for each image to separate file
makeDirectory(outParsedDir)
parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntk_nrRois, cntk_featureDimensions[classifier],
saveCompressed = True, skipCheck = True)
# delete cntk output file which can be very large
# deleteFile(cntkOutputPath)
imdb = imdbs[image_set]
net = DummyNet(4096, imdb.num_classes, outParsedDir)
# create empty directory for evaluation files
if type(imdb) == imdb_data:
evalTempDir = None
else:
# pascal_voc implementation requires temporary directory for evaluation
evalTempDir = os.path.join(procDir, "eval_mAP_" + image_set)
makeDirectory(evalTempDir)
deleteAllFilesInDirectory(evalTempDir, None)
# compute mAPs
test_net(net, imdb, evalTempDir, None, classifier, nmsThreshold, boUsePythonImpl = True)
print ("DONE.")

Просмотреть файл

@ -0,0 +1,55 @@
from __future__ import print_function
import os, importlib, sys
from cntk_helpers import *
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
image_set = 'train' # 'train', 'test'
# no need to change these parameters
parseNrImages = 10 # for speed reasons only parse CNTK file for the first N images
boUseNonMaximaSurpression = False
nmsThreshold = 0.1
####################################
# Main
####################################
print ("Load ROI co-ordinates and labels")
cntkImgsPath, cntkRoiCoordsPath, cntkRoiLabelsPath, nrRoisPath = getCntkInputPaths(cntkFilesDir, image_set)
imgPaths = getColumn(readTable(cntkImgsPath), 1)
nrRealRois = [int(s) for s in readFile(nrRoisPath)]
roiAllLabels = readCntkRoiLabels(cntkRoiLabelsPath, cntk_nrRois, len(classes), parseNrImages)
if parseNrImages:
imgPaths = imgPaths[:parseNrImages]
nrRealRois = nrRealRois[:parseNrImages]
roiAllLabels = roiAllLabels[:parseNrImages]
roiAllCoords = readCntkRoiCoordinates(imgPaths, cntkRoiCoordsPath, cntk_nrRois, cntk_padWidth, cntk_padHeight,
parseNrImages)
assert (len(imgPaths) == len(roiAllCoords) == len(roiAllLabels) == len(nrRealRois))
# loop over all images and visualize
for imgIndex, imgPath in enumerate(imgPaths):
print ("Visualizing image %d at %s..." % (imgIndex, imgPath))
roiCoords = roiAllCoords[imgIndex][:nrRealRois[imgIndex]]
roiLabels = roiAllLabels[imgIndex][:nrRealRois[imgIndex]]
# perform non-maxima surpression. note that the detected classes in the image is not affected by this.
nmsKeepIndices = []
if boUseNonMaximaSurpression:
imgWidth, imgHeight = imWidthHeight(imgPath)
nmsKeepIndices = applyNonMaximaSuppression(nmsThreshold, roiLabels, [0] * len(roiLabels), roiCoords)
print ("Non-maxima surpression kept {} of {} rois (nmsThreshold={})".format(len(nmsKeepIndices),
len(roiLabels), nmsThreshold))
# visualize results
imgDebug = visualizeResults(imgPath, roiLabels, None, roiCoords, cntk_padWidth, cntk_padHeight,
classes, nmsKeepIndices, boDrawNegativeRois=True)
imshow(imgDebug, waitDuration=0, maxDim=800)
print ("DONE.")

Просмотреть файл

@ -0,0 +1,53 @@
from __future__ import print_function
import sys, os, importlib
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
subdirs = ['positive', 'testImages']
####################################
# Main
####################################
overlaps = []
roiCounts = []
for subdir in subdirs:
imgFilenames = getFilesInDirectory(imgDir + subdir, ".jpg")
# loop over all iamges
for imgIndex,imgFilename in enumerate(imgFilenames):
if imgIndex % 20 == 0:
print ("Processing subdir '{}', image {} of {}".format(subdir, imgIndex, len(imgFilenames)))
# load ground truth
imgPath = imgDir + subdir + "/" + imgFilename
imgWidth, imgHeight = imWidthHeight(imgPath)
gtBoxes, gtLabels = readGtAnnotation(imgPath)
gtBoxes = [Bbox(*rect) for rect in gtBoxes]
# load rois and compute scale
rois = readRois(roiDir, subdir, imgFilename)
rois = [Bbox(*roi) for roi in rois]
roiCounts.append(len(rois))
# for each ground truth, compute if it is covered by an roi
maxOverlap = -1
for gtIndex, (gtLabel, gtBox) in enumerate(zip(gtLabels,gtBoxes)):
assert (gtBox.max() <= max(imgWidth, imgHeight) and gtBox.max() >= 0)
gtLabel = gtLabel.decode('utf-8')
if gtLabel in classes[1:]:
for roi in rois:
assert (roi.max() <= max(imgWidth, imgHeight) and roi.max() >= 0)
overlap = bboxComputeOverlapVoc(gtBox, roi)
maxOverlap = max(maxOverlap, overlap)
overlaps.append(maxOverlap)
print ("Average number of rois per image " + str(1.0 * sum(roiCounts) / len(overlaps)))
# compute recall at different overlaps
overlaps = np.array(overlaps, np.float32)
for overlapThreshold in np.linspace(0,1,11):
recall = 1.0 * sum(overlaps >= overlapThreshold) / len(overlaps)
print ("At threshold {:.2f}: recall = {:2.2f}".format(overlapThreshold, recall))

Просмотреть файл

@ -0,0 +1,49 @@
from __future__ import print_function
import os, importlib, sys
import PARAMETERS
locals().update(importlib.import_module("PARAMETERS").__dict__)
####################################
# Parameters
####################################
image_set = 'test' # 'train', 'test'
# no need to change these parameters
boUseNonMaximaSurpression = True
visualizationDir = resultsDir + "visualizations"
cntkParsedOutputDir = cntkFilesDir + image_set + "_parsed/"
####################################
# Main
####################################
makeDirectory(resultsDir)
makeDirectory(visualizationDir)
# loop over all images and visualize
imdb = imdbs[image_set]
for imgIndex in range(0, imdb.num_images):
imgPath = imdb.image_path_at(imgIndex)
imgWidth, imgHeight = imWidthHeight(imgPath)
# evaluate classifier for all rois
labels, scores = nnPredict(imgIndex, cntkParsedOutputDir, cntk_nrRois, len(classes), None)
# remove the zero-padded rois
scores = scores[:len(imdb.roidb[imgIndex]['boxes'])]
labels = labels[:len(imdb.roidb[imgIndex]['boxes'])]
# perform non-maxima surpression. note that the detected classes in the image is not affected by this.
nmsKeepIndices = []
if boUseNonMaximaSurpression:
nmsKeepIndices = applyNonMaximaSuppression(nmsThreshold, labels, scores, imdb.roidb[imgIndex]['boxes'])
print ("Non-maxima surpression kept {:4} of {:4} rois (nmsThreshold={})".format(len(nmsKeepIndices), len(labels), nmsThreshold))
# visualize results
imgDebug = visualizeResults(imgPath, labels, scores, imdb.roidb[imgIndex]['boxes'], cntk_padWidth, cntk_padHeight,
classes, nmsKeepIndices, boDrawNegativeRois=True)
imshow(imgDebug, waitDuration=0, maxDim = 800)
# imwrite(imgDebug, visualizationDir + "/" + str(imgIndex) + os.path.basename(imgPath))
print ("DONE.")

Просмотреть файл

@ -0,0 +1,117 @@
from __future__ import print_function
from builtins import chr
import os, sys, importlib, shutil
from cntk_helpers import *
####################################
# Parameters
####################################
imgDir = "C:/Users/chazhang/Desktop/newImgs/"
# no need to change these params
drawingImgSize = 1000.0
####################################
# Functions
####################################
def event_cv2_drawRectangles(event, x, y, flags, param):
global global_image
global global_bboxes
global global_leftButtonDownPoint
# draw all previous bounding boxes, and the most recent box in a different color
imgCopy = global_image.copy()
drawRectangles(imgCopy, global_bboxes)
if len(global_bboxes)>0:
drawRectangles(imgCopy, [global_bboxes[-1]], color = (255, 0, 0))
# handle mouse events
if event == cv2.EVENT_LBUTTONDOWN:
global_leftButtonDownPoint = (x, y)
elif event == cv2.EVENT_LBUTTONUP:
pt1 = global_leftButtonDownPoint
pt2 = (x, y)
minPt = (min(pt1[0], pt2[0]), min(pt1[1], pt2[1]))
maxPt = (max(pt1[0], pt2[0]), max(pt1[1], pt2[1]))
imgWidth, imgHeight = imArrayWidthHeight(global_image)
minPt = ptClip(minPt, imgWidth, imgHeight)
maxPt = ptClip(maxPt, imgWidth, imgHeight)
global_bboxes.append(minPt + maxPt)
elif flags == cv2.EVENT_FLAG_LBUTTON: #if left mouse button is held down
cv2.rectangle(imgCopy, global_leftButtonDownPoint, (x, y), (255, 255, 0), 1)
else:
drawCrossbar(imgCopy, (x, y))
cv2.imshow("AnnotationWindow", imgCopy)
def scaleCropBboxes(rectsIn, scaleFactor, imgWidth, imgHeight):
if len(rectsIn) <= 0:
return rectsIn
else:
rects = [ [int(round(rect[i]/scaleFactor)) for i in range(4)]
for rect in rectsIn]
rects = [Bbox(*rect).crop(imgWidth, imgHeight).rect() for rect in rects]
for rect in rects:
assert (Bbox(*rect).isValid())
return rects
####################################
# Main
####################################
imgFilenames = [f for f in os.listdir(imgDir) if f.lower().endswith(".jpg")]
# loop over each image and get annotation
for imgFilenameIndex,imgFilename in enumerate(imgFilenames):
print (imgFilenameIndex, imgFilename)
imgPath = os.path.join(imgDir, imgFilename)
bBoxPath = imgPath[:-4] + ".bboxes.tsv"
# skip image if ground truth already exists
if os.path.exists(bBoxPath):
print ("Skipping image {0} since ground truth already exists".format(imgFilename))
continue
else:
print ("Processing image {0} of {1}: {2}".format(imgFilenameIndex, len(imgFilenames), imgPath))
# prepare image window and callback
global_bboxes = []
global_image, scaleFactor = imresizeMaxDim(imread(imgPath), drawingImgSize)
cv2.namedWindow("AnnotationWindow")
cv2.setMouseCallback("AnnotationWindow", event_cv2_drawRectangles)
cv2.imshow("AnnotationWindow", global_image)
# process user input
while True:
key = chr(cv2.waitKey())
# undo/remove last rectangle
if key == "u":
if len(global_bboxes) >= 1:
global_bboxes = global_bboxes[:-1]
imgCopy = global_image.copy()
drawRectangles(imgCopy, global_bboxes)
cv2.imshow("AnnotationWindow", imgCopy)
# skip image
elif key == "s":
if os.path.exists(bBoxPath):
print ("Skipping image hence deleting existing bbox file: " + bBoxPath)
os.remove(bBoxPath)
break
# next image
elif key == "n":
bboxes = scaleCropBboxes(global_bboxes, scaleFactor, imWidth(imgPath), imHeight(imgPath))
writeTable(bBoxPath, bboxes)
break
# quit
elif key == "q":
sys.exit()
cv2.destroyAllWindows()

Просмотреть файл

@ -0,0 +1,84 @@
from __future__ import print_function
try:
# for Python2
from Tkinter import *
except ImportError:
# for Python3
from tkinter import *
from PIL import ImageTk
from cntk_helpers import *
####################################
# Parameters
####################################
imgDir = "C:/Users/chazhang/Desktop/newImgs/"
classes = ("avocado", "orange", "butter", "champagne", "cheese", "eggBox", "gerkin", "joghurt", "ketchup",
"orangeJuice", "onion", "pepper", "sausage", "tomato", "water", "apple", "milk",
"tabasco", "soySauce", "mustard", "beer")
#no need to change these
drawingImgSize = 1000
boxWidth = 10
boxHeight = 2
####################################
# Main
####################################
# define callback function for tk button
def buttonPressedCallback(s):
global global_lastButtonPressed
global_lastButtonPressed = s
# create UI
objectNames = np.sort(classes).tolist()
objectNames += ["UNDECIDED", "EXCLUDE"]
tk = Tk()
w = Canvas(tk, width=len(objectNames) * boxWidth, height=len(objectNames) * boxHeight, bd = boxWidth, bg = 'white')
w.grid(row = len(objectNames), column = 0, columnspan = 2)
for objectIndex,objectName in enumerate(objectNames):
b = Button(width=boxWidth, height=boxHeight, text=objectName, command=lambda s = objectName: buttonPressedCallback(s))
b.grid(row = objectIndex, column = 0)
# loop over all images
imgFilenames = getFilesInDirectory(imgDir, ".jpg")
for imgIndex, imgFilename in enumerate(imgFilenames):
print (imgIndex, imgFilename)
labelsPath = os.path.join(imgDir, imgFilename[:-4] + ".bboxes.labels.tsv")
if os.path.exists(labelsPath):
print ("Skipping image {:3} ({}) since annotation file already exists: {}".format(imgIndex, imgFilename, labelsPath))
continue
# load image and ground truth rectangles
img = imread(os.path.join(imgDir,imgFilename))
rectsPath = os.path.join(imgDir, imgFilename[:-4] + ".bboxes.tsv")
rects = [ToIntegers(rect) for rect in readTable(rectsPath)]
# annotate each rectangle in turn
labels = []
for rectIndex,rect in enumerate(rects):
imgCopy = img.copy()
drawRectangles(imgCopy, [rect], thickness = 15)
# draw image in tk window
imgTk, _ = imresizeMaxDim(imgCopy, drawingImgSize, boUpscale = True)
imgTk = ImageTk.PhotoImage(imconvertCv2Pil(imgTk))
label = Label(tk, image=imgTk)
label.grid(row=0, column=1, rowspan=drawingImgSize)
tk.update_idletasks()
tk.update()
# busy-wait until button pressed
global_lastButtonPressed = None
while not global_lastButtonPressed:
tk.update_idletasks()
tk.update()
# store result
print ("Button pressed = ", global_lastButtonPressed)
labels.append(global_lastButtonPressed)
writeFile(labelsPath, labels)
tk.destroy()
print ("DONE.")

Просмотреть файл

@ -0,0 +1,117 @@
from __future__ import print_function
from cntk_helpers import *
from imdb_data import imdb_data
import fastRCNN, time, datetime
from fastRCNN.pascal_voc import pascal_voc # as nmsPython
print (datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S'))
# dataset name
datasetName = "grocery"
# datasetName = "pascalVoc"
# datasetName = "pascalVoc_aeroplanesOnly"
############################
# default parameters
############################
# cntk params
cntk_nrRois = 2000 # 2000 # how many ROIs to zero-pad
cntk_padWidth = 1000
cntk_padHeight = 1000
# directories
rootDir = os.path.dirname(os.path.realpath(sys.argv[0])) + "/"
imgDir = rootDir + "../../DataSets/Grocery/"
pascalDataDir = rootDir + "../../DataSets/Pascal/"
# derived directories
procDir = rootDir + "proc/" + datasetName + "_{}/".format(cntk_nrRois)
resultsDir = rootDir + "results/" + datasetName + "_{}/".format(cntk_nrRois)
roiDir = procDir + "rois/"
cntkFilesDir = procDir + "cntkFiles/"
cntkTemplateDir = rootDir
# ROI generation
roi_minDimRel = 0.01 # minium relative width/height of a ROI
roi_maxDimRel = 1.0 # maximum relative width/height of a ROI
roi_minNrPixelsRel = 0 # minium relative area covered by ROI
roi_maxNrPixelsRel = 1.0 # maximm relative area covered by ROI
roi_maxAspectRatio = 4.0 # maximum aspect Ratio of a ROI vertically and horizontally
roi_maxImgDim = 200 # image size used for ROI generation
ss_scale = 100 # selective search ROIS: parameter controlling cluster size for segmentation
ss_sigma = 1.2 # selective search ROIs: width of gaussian kernal for segmentation
ss_minSize = 20 # selective search ROIs: minimum component size for segmentation
grid_nrScales = 7 # uniform grid ROIs: number of iterations from largest possible ROI to smaller ROIs
grid_aspectRatios = [1.0, 2.0, 0.5] # uniform grid ROIs: aspect ratio of ROIs
# thresholds
train_posOverlapThres = 0.5 # threshold for marking ROIs as positive.
nmsThreshold = 0.3 # Non-Maxima suppression threshold (in range [0,1]).
# The lower the more ROIs will be combined. Used in 5_evaluateResults and 5_visualizeResults.
############################
# project-specific parameters
############################
if datasetName.startswith("grocery"):
classes = ('__background__', # always index 0
'avocado', 'orange', 'butter', 'champagne', 'eggBox', 'gerkin', 'joghurt', 'ketchup',
'orangeJuice', 'onion', 'pepper', 'tomato', 'water', 'milk', 'tabasco', 'mustard')
# roi generation
roi_minDimRel = 0.04
roi_maxDimRel = 0.4
roi_minNrPixelsRel = 2 * roi_minDimRel * roi_minDimRel
roi_maxNrPixelsRel = 0.33 * roi_maxDimRel * roi_maxDimRel
# model training / scoring
classifier = 'nn'
# postprocessing
nmsThreshold = 0.01
# database
imdbs = dict() # database provider of images and image annotations
for image_set in ["train", "test"]:
imdbs[image_set] = imdb_data(image_set, classes, cntk_nrRois, imgDir, roiDir, cntkFilesDir, boAddGroundTruthRois = (image_set!='test'))
elif datasetName.startswith("pascalVoc"):
imgDir = pascalDataDir
if datasetName.startswith("pascalVoc_aeroplanesOnly"):
classes = ('__background__', 'aeroplane')
lutImageSet = {"train": "trainval.aeroplaneOnly", "test": "test.aeroplaneOnly"}
else:
classes = ('__background__', # always index 0
'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable',
'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')
lutImageSet = {"train": "trainval", "test": "test"}
# model training / scoring
classifier = 'nn'
#more than 99% of the test images have less than 4000 rois, but 50% more than 2000
cntk_nrRois = 4000
# database
imdbs = dict()
for image_set, year in zip(["train", "test"], ["2007", "2007"]):
imdbs[image_set] = fastRCNN.pascal_voc(lutImageSet[image_set], year, classes, cntk_nrRois, cacheDir = cntkFilesDir, devkit_path=pascalDataDir)
print ("Number of {} images: {}".format(image_set, imdbs[image_set].num_images))
else:
ERROR
############################
# computed parameters
############################
nrClasses = len(classes)
cntk_featureDimensions = {'nn': nrClasses}
assert cntk_padWidth == cntk_padHeight, "ERROR: different width and height for padding currently not supported."
assert classifier.lower() in ['svm','nn'], "ERROR: only 'nn' or 'svm' classifier supported."
assert not (datasetName == 'pascalVoc' and classifier == 'svm'), "ERROR: while technically possibly, writing 2nd-last layer of CNTK model for all pascalVOC images takes too much disk memory."
print ("PARAMETERS: datasetName = " + datasetName)
print ("PARAMETERS: cntk_nrRois = {}".format(cntk_nrRois))

Просмотреть файл

@ -0,0 +1,119 @@
# CNTK Examples: Image/Detection/Fast R-CNN
## Overview
|Data: |A toy dataset of images captured from a refrigerator.
|:---------|:---
|Purpose |This folder contains an end-to-end solution for using Fast R-CNN to perform object detection using a pre-trained AlexNet model and a set of user-supplied additional images.
|Network |Convolutional neural networks, AlexNet.
|Training |Stochastic gradient descent with momentum.
|Comments |See below.
## Tutorial
Check out the CNTK Tutorial on [Object Detection using Fast R-CNN](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN).
## Introduction
`Fast R-CNN` is an object detection algorithm proposed by `Ross Girshick` in 2015. The paper is accepted to ICCV 2015, and archived at https://arxiv.org/abs/1504.08083. Fast R-CNN builds on previous work to efficiently classify object proposals using deep convolutional networks. Compared to previous work, Fast R-CNN employs a `region of interest pooling` scheme that allows training to be single stage, with a multi-task loss. It trains the very deep VGG16 network 9x faster than R-CNN, is 213x faster at test-time, and achieves a higher mAP on PASCAL VOC 2012.
In this example, we use [AlexNet](../../Classification/AlexNet) as a pre-trained model, and adapt it to a toy dataset of images captured from a refrigerator to detect objects inside.
## Running the example
### Getting the data and AlexNet model
we use a toy dataset of images captured from a refrigerator to demonstrate Fast-R-CNN. Both the dataset and the pre-trained AlexNet model can be downloaded by running the following Python command:
`python install_fastrcnn.py`
After running the script, the toy dataset will be installed under the `Image/DataSets/Grocery` folder. And the AlexNet model will be downloaded to the `Image/PretrainedModels` folder. We recommend you to keep the downloaded data in the respective folder while downloading, as the configuration files in this folder assumes that by default.
### Setup
Currently, CNTK only supports `Python 3.4`. We recommend to install anaconda python (http://continuum.io/downloads) and create a python 3.4 environment using:
```
conda create --name cntk python=3.4.3 numpy scipy
activate cntk
```
To run the code in this example, you need to install a few additional packages. Under Python 3.4 (64bit version assumed), go to the FastRCNN folder and run:
```
pip install -r requirements.txt
```
You will further need Scikit-Image and OpenCV to run these examples. You can download the corresponding wheel packages and install them manually. For Windows users, visit http://www.lfd.uci.edu/~gohlke/pythonlibs/, and download:
scikit_image-0.12.3-cp34-cp34m-win_amd64.whl
opencv_python-3.1.0-cp34-cp34m-win_amd64.whl
Once you download the respective wheel binaries, install them with:
`pip install your_download_folder/scikit_image-0.12.3-cp34-cp34m-win_amd64.whl`
`pip install your_download_folder/opencv_python-3.1.0-cp34-cp34m-win_amd64.whl`
This example code assumes you are using 64bit version of Python 3.4, as the Fast R-CNN DLL files under [utils_win64](./fastRCNN/utils3_win64) are prebuilt for this version. If your task requires the use of a different Python version, please recompile these DLL files yourself in the correct environment.
The folder where cntk.exe resides needs to be in your PATH environment variable.
Last but not least, in `PARAMETERS.py`: make sure datasetName is set to "grocery".
### Preprocess data
The toy refrigerator data comes with labeled region of interests. To run Fast R-CNN training, the first step is to generate a large set of potential region proposals via selective search. For this purpose, you can run:
`python A1_GenerateInputROIs.py`
This script will go through all training, validation and testing images, and extract potential region of interests via selective search (https://staff.fnwi.uva.nl/th.gevers/pub/GeversIJCV2013.pdf).
To visualize the generated ROIs, you can run:
`python B1_VisualizeInputROIs.py`
Press any key to step through the images. Further, you may check the recall of the proposed regions by running:
`python B2_EvaluateInputROIs.py`
This will generate something like:
2016-10-21 07:35:03
PARAMETERS: datasetName = grocery
PARAMETERS: cntk_nrRois = 2000
Processing subdir 'positive', image 0 of 20
Processing subdir 'testImages', image 0 of 5
Average number of rois per image 1312.92
At threshold 0.00: recall = 1.00
At threshold 0.10: recall = 1.00
At threshold 0.20: recall = 1.00
At threshold 0.30: recall = 1.00
At threshold 0.40: recall = 1.00
At threshold 0.50: recall = 1.00
At threshold 0.60: recall = 1.00
At threshold 0.70: recall = 1.00
At threshold 0.80: recall = 0.84
At threshold 0.90: recall = 0.28
At threshold 1.00: recall = 0.00
It shows that up to threashold `0.70`, we have `100%` recall on the ground truth region of interests.
### Running Fast R-CNN training
Now you can start a full training of Fast R-CNN on the grocery data by running:
`python A2_RunCntk.py`
This python code will start training Fast R-CNN using the [fastrcnn.cntk](./fastrcnn.cntk) configuration file (in BrainScript).
If you carefully examine the [fastrcnn.cntk](./fastrcnn.cntk) file, you would notice we load the pre-trained AlexNet model, clone the network up to the `conv5_y` layer and freeze all bottom layer parameters, and then added pooling and dense layers on the top with trainable parameters. The training will run for 17 epochs, and reaching training error around `1.05%`. The script will also write the network output for the entire train and test dataset.
### Evaluate trained model
One the model has been trained for detection, you may run:
`python A3_ParseAndEvaluateOutput.py`
to parse and evaluate the output accuracy. You should see mean average precision (mAP) at around `0.86` for this simple toy example. You may further visualize the detection result on the test data with:
`python B3_VisualizeOutputROIs.py`
## Running Fast R-CNN on other data sets
To learn more about CNTK Fast R-CNN, e.g. how to run it on Pascal VOC data or on your own data set, please go to the CNTK tutorial on [Object Detection using Fast R-CNN](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN).

Просмотреть файл

@ -0,0 +1,947 @@
from __future__ import print_function
from builtins import str
import pdb, sys, os, time
import numpy as np
import selectivesearch
from easydict import EasyDict
from fastRCNN.nms import nms as nmsPython
from builtins import range
####################################
# Region-of-interest
####################################
def getSelectiveSearchRois(img, ssScale, ssSigma, ssMinSize, maxDim):
# Selective Search
# Parameters
# ----------
# im_orig : ndarray
# Input image
# scale : int
# Free parameter. Higher means larger clusters in felzenszwalb segmentation.
# sigma : float
# Width of Gaussian kernel for felzenszwalb segmentation.
# min_size : int
# Minimum component size for felzenszwalb segmentation.
# Returns
# -------
# img : ndarray
# image with region label
# region label is stored in the 4th value of each pixel [r,g,b,(region)]
# regions : array of dict
# [
# {
# 'rect': (left, top, right, bottom),
# 'labels': [...]
# },
# ...
# ]
# inter_area seems to give much better results esp when upscaling image
img, scale = imresizeMaxDim(img, maxDim, boUpscale=True, interpolation = cv2.INTER_AREA)
_, ssRois = selectivesearch.selective_search(img, scale=ssScale, sigma=ssSigma, min_size=ssMinSize)
rects = []
for ssRoi in ssRois:
x, y, w, h = ssRoi['rect']
rects.append([x,y,x+w,y+h])
return rects, img, scale
def getGridRois(imgWidth, imgHeight, nrGridScales, aspectRatios = [1.0]):
rects = []
# start adding large ROIs and then smaller ones
for iter in range(nrGridScales):
cellWidth = 1.0 * min(imgHeight, imgWidth) / (2 ** iter)
step = cellWidth / 2.0
for aspectRatio in aspectRatios:
wStart = 0
while wStart < imgWidth:
hStart = 0
while hStart < imgHeight:
if aspectRatio < 1:
wEnd = wStart + cellWidth
hEnd = hStart + cellWidth / aspectRatio
else:
wEnd = wStart + cellWidth * aspectRatio
hEnd = hStart + cellWidth
if wEnd < imgWidth-1 and hEnd < imgHeight-1:
rects.append([wStart, hStart, wEnd, hEnd])
hStart += step
wStart += step
return rects
def filterRois(rects, maxWidth, maxHeight, roi_minNrPixels, roi_maxNrPixels,
roi_minDim, roi_maxDim, roi_maxAspectRatio):
filteredRects = []
filteredRectsSet = set()
for rect in rects:
if tuple(rect) in filteredRectsSet: # excluding rectangles with same co-ordinates
continue
x, y, x2, y2 = rect
w = x2 - x
h = y2 - y
assert(w>=0 and h>=0)
# apply filters
if h == 0 or w == 0 or \
x2 > maxWidth or y2 > maxHeight or \
w < roi_minDim or h < roi_minDim or \
w > roi_maxDim or h > roi_maxDim or \
w * h < roi_minNrPixels or w * h > roi_maxNrPixels or \
w / h > roi_maxAspectRatio or h / w > roi_maxAspectRatio:
continue
filteredRects.append(rect)
filteredRectsSet.add(tuple(rect))
# could combine rectangles using non-maxima surpression or with similar co-ordinates
# groupedRectangles, weights = cv2.groupRectangles(np.asanyarray(rectsInput, np.float).tolist(), 1, 0.3)
# groupedRectangles = nms_python(np.asarray(rectsInput, np.float), 0.5)
assert(len(filteredRects) > 0)
return filteredRects
def readRois(roiDir, subdir, imgFilename):
roiPath = roiDir + subdir + "/" + imgFilename[:-4] + ".roi.txt"
rois = np.loadtxt(roiPath, np.int)
if len(rois) == 4 and type(rois[0]) == np.int32: # if only a single ROI in an image
rois = [rois]
return rois
####################################
# Generate and parse CNTK files
####################################
def readGtAnnotation(imgPath):
bboxesPath = imgPath[:-4] + ".bboxes.tsv"
labelsPath = imgPath[:-4] + ".bboxes.labels.tsv"
bboxes = np.array(readTable(bboxesPath), np.int32)
labels = readFile(labelsPath)
assert (len(bboxes) == len(labels))
return bboxes, labels
def getCntkInputPaths(cntkFilesDir, image_set):
cntkImgsListPath = cntkFilesDir + image_set + '.txt'
cntkRoiCoordsPath = cntkFilesDir + image_set + '.rois.txt'
cntkRoiLabelsPath = cntkFilesDir + image_set + '.roilabels.txt'
cntkNrRoisPath = cntkFilesDir + image_set + '.nrRois.txt'
return cntkImgsListPath, cntkRoiCoordsPath, cntkRoiLabelsPath, cntkNrRoisPath
def roiTransformPadScaleParams(imgWidth, imgHeight, padWidth, padHeight, boResizeImg = True):
scale = 1.0
if boResizeImg:
assert padWidth == padHeight, "currently only supported equal width/height"
scale = 1.0 * padWidth / max(imgWidth, imgHeight)
imgWidth = round(imgWidth * scale)
imgHeight = round(imgHeight * scale)
targetw = padWidth
targeth = padHeight
w_offset = ((targetw - imgWidth) / 2.)
h_offset = ((targeth - imgHeight) / 2.)
if boResizeImg and w_offset > 0 and h_offset > 0:
print ("ERROR: both offsets are > 0:", imgCounter, imgWidth, imgHeight, w_offset, h_offset)
error
if (w_offset < 0 or h_offset < 0):
print ("ERROR: at least one offset is < 0:", imgWidth, imgHeight, w_offset, h_offset, scale)
return targetw, targeth, w_offset, h_offset, scale
def roiTransformPadScale(rect, w_offset, h_offset, scale = 1.0):
rect = [int(round(scale * d)) for d in rect]
rect[0] += w_offset
rect[1] += h_offset
rect[2] += w_offset
rect[3] += h_offset
return rect
def getCntkRoiCoordsLine(rect, targetw, targeth):
# convert from absolute to relative co-ordinates
x, y, x2, y2 = rect
xrel = float(x) / (1.0 * targetw)
yrel = float(y) / (1.0 * targeth)
wrel = float(x2 - x) / (1.0 * targetw)
hrel = float(y2 - y) / (1.0 * targeth)
assert xrel <= 1.0, "Error: xrel should be <= 1 but is " + str(xrel)
assert yrel <= 1.0, "Error: yrel should be <= 1 but is " + str(yrel)
assert wrel >= 0.0, "Error: wrel should be >= 0 but is " + str(wrel)
assert hrel >= 0.0, "Error: hrel should be >= 0 but is " + str(hrel)
return " {} {} {} {}".format(xrel, yrel, wrel, hrel)
def getCntkRoiLabelsLine(overlaps, thres, nrClasses):
# get one hot encoding
maxgt = np.argmax(overlaps)
if overlaps[maxgt] < thres: # set to background label if small overlap with GT
maxgt = 0
oneHot = np.zeros((nrClasses), dtype=int)
oneHot[maxgt] = 1
oneHotString = " {}".format(" ".join(str(x) for x in oneHot))
return oneHotString
def cntkPadInputs(currentNrRois, targetNrRois, nrClasses, boxesStr, labelsStr):
assert currentNrRois <= targetNrRois, "Current number of rois ({}) should be <= target number of rois ({})".format(currentNrRois, targetNrRois)
while currentNrRois < targetNrRois:
boxesStr += " 0 0 0 0"
labelsStr += " 1" + " 0" * (nrClasses - 1)
currentNrRois += 1
return boxesStr, labelsStr
def checkCntkOutputFile(cntkImgsListPath, cntkOutputPath, cntkNrRois, outputDim):
imgPaths = getColumn(readTable(cntkImgsListPath), 1)
with open(cntkOutputPath) as fp:
for imgIndex in range(len(imgPaths)):
if imgIndex % 100 == 1:
print ("Checking cntk output file, image %d of %d..." % (imgIndex, len(imgPaths)))
for roiIndex in range(cntkNrRois):
assert (fp.readline() != "")
assert (fp.readline() == "") # test if end-of-file is reached
# parse the cntk output file and save the output for each image individually
def parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntkNrRois, outputDim,
saveCompressed = False, skipCheck = False, skip5Mod = None):
if not skipCheck and skip5Mod == None:
checkCntkOutputFile(cntkImgsListPath, cntkOutputPath, cntkNrRois, outputDim)
# parse cntk output and write file for each image
# always read in data for each image to forward file pointer
imgPaths = getColumn(readTable(cntkImgsListPath), 1)
with open(cntkOutputPath) as fp:
for imgIndex in range(len(imgPaths)):
line = fp.readline()
if skip5Mod != None and imgIndex % 5 != skip5Mod:
print ("Skipping image {} (skip5Mod = {})".format(imgIndex, skip5Mod))
continue
print ("Parsing cntk output file, image %d of %d" % (imgIndex, len(imgPaths)))
# convert to floats
data = []
values = np.fromstring(line, dtype=float, sep=" ")
assert len(values) == cntkNrRois * outputDim, "ERROR: expected dimension of {} but found {}".format(cntkNrRois * outputDim, len(values))
for i in range(cntkNrRois):
posStart = i * outputDim
posEnd = posStart + outputDim
currValues = values[posStart:posEnd]
data.append(currValues)
# save
data = np.array(data, np.float32)
outPath = outParsedDir + str(imgIndex) + ".dat"
if saveCompressed:
np.savez_compressed(outPath, data)
else:
np.savez(outPath, data)
assert (fp.readline() == "") # test if end-of-file is reached
# parse the cntk labels file and return the labels
def readCntkRoiLabels(roiLabelsPath, nrRois, roiDim, stopAtImgIndex = None):
roiLabels = []
for imgIndex, line in enumerate(readFile(roiLabelsPath)):
if stopAtImgIndex and imgIndex == stopAtImgIndex:
break
roiLabels.append([])
pos = line.find(b'|roiLabels ')
valuesString = line[pos + 10:].strip().split(b' ')
assert (len(valuesString) == nrRois * roiDim)
for boxIndex in range(nrRois):
oneHotLabels = [int(s) for s in valuesString[boxIndex*roiDim : (boxIndex+1)*roiDim]]
assert(sum(oneHotLabels) == 1)
roiLabels[imgIndex].append(np.argmax(oneHotLabels))
return roiLabels
# parse the cntk rois file and return the co-ordinates
def readCntkRoiCoordinates(imgPaths, cntkRoiCoordsPath, nrRois, padWidth, padHeight, stopAtImgIndex = None):
roiCoords = []
for imgIndex, line in enumerate(readFile(cntkRoiCoordsPath)):
if stopAtImgIndex and imgIndex == stopAtImgIndex:
break
roiCoords.append([])
pos = line.find(b'|rois ')
valuesString = line[pos + 5:].strip().split(b' ')
assert (len(valuesString) == nrRois * 4)
imgWidth, imgHeight = imWidthHeight(imgPaths[imgIndex])
for boxIndex in range(nrRois):
rect = [float(s) for s in valuesString[boxIndex*4 : (boxIndex+1)*4]]
x,y,w,h = rect
# convert back from padded-rois-co-ordinates to image co-ordinates
rect = getAbsoluteROICoordinates([x,y,x+w,y+h], imgWidth, imgHeight, padWidth, padHeight)
roiCoords[imgIndex].append(rect)
return roiCoords
# convert roi co-ordinates from CNTK file back to original image co-ordinates
def getAbsoluteROICoordinates(roi, imgWidth, imgHeight, padWidth, padHeight, resizeMethod = 'padScale'):
if roi == [0,0,0,0]: # if padded roi
return [0,0,0,0]
if resizeMethod == "crop":
minDim = min(imgWidth, imgHeight)
offsetWidth = 0.5 * abs(imgWidth - imgHeight)
if (imgWidth >= imgHeight): # horizontal photo
rect = [roi[0] * minDim + offsetWidth, roi[1] * minDim, None, None]
else:
rect = [roi[0] * minDim, roi[1] * minDim + offsetWidth, None, None]
rect[2] = rect[0] + roi[2] * minDim
rect[3] = rect[1] + roi[3] * minDim
elif resizeMethod == "pad" or resizeMethod == "padScale":
if resizeMethod == "padScale":
scale = float(padWidth) / max(imgWidth, imgHeight)
imgWidthScaled = int(round(imgWidth * scale))
imgHeightScaled = int(round(imgHeight * scale))
else:
scale = 1.0
imgWidthScaled = imgWidth
imgHeightScaled = imgHeight
w_offset = float(padWidth - imgWidthScaled) / 2.0
h_offset = float(padHeight - imgHeightScaled) / 2.0
if resizeMethod == "padScale":
assert(w_offset == 0 or h_offset == 0)
x0 = max(roi[0] * padWidth - w_offset, 0)
y0 = max(roi[1] * padHeight - h_offset, 0)
rect = [x0, y0,
x0 + (roi[2] - roi[0]) * padWidth,
y0 + (roi[3] - roi[1]) * padHeight]
rect = [int(round(r / scale)) for r in rect]
else:
print ("ERROR: Unknown resize method '%s'" % resizeMethod)
error
assert(min(rect) >=0 and max(rect[0],rect[2]) <= imgWidth and max(rect[1],rect[3]) <= imgHeight)
return rect
####################################
# Classifier training / scoring
####################################
def getSvmModelPaths(svmDir, experimentName):
svmWeightsPath = "{}svmweights_{}.txt".format(svmDir, experimentName)
svmBiasPath = "{}svmbias_{}.txt".format(svmDir, experimentName)
svmFeatScalePath = "{}svmfeature_scale_{}.txt".format(svmDir, experimentName)
return svmWeightsPath, svmBiasPath, svmFeatScalePath
def loadSvm(svmDir, experimentName):
svmWeightsPath, svmBiasPath, svmFeatScalePath = getSvmModelPaths(svmDir, experimentName)
svmWeights = np.loadtxt(svmWeightsPath, np.float32)
svmBias = np.loadtxt(svmBiasPath, np.float32)
svmFeatScale = np.loadtxt(svmFeatScalePath, np.float32)
return svmWeights, svmBias, svmFeatScale
def saveSvm(svmDir, experimentName, svmWeights, svmBias, featureScale):
svmWeightsPath, svmBiasPath, svmFeatScalePath = getSvmModelPaths(svmDir, experimentName)
np.savetxt(svmWeightsPath, svmWeights)
np.savetxt(svmBiasPath, svmBias)
np.savetxt(svmFeatScalePath, featureScale)
def svmPredict(imgIndex, cntkOutputIndividualFilesDir, svmWeights, svmBias, svmFeatScale, roiSize, roiDim, decisionThreshold = 0):
cntkOutputPath = os.path.join(cntkOutputIndividualFilesDir, str(imgIndex) + ".dat.npz")
data = np.load(cntkOutputPath)['arr_0']
assert(len(data) == roiSize)
# get prediction for each roi
labels = []
maxScores = []
for roiIndex in range(roiSize):
feat = data[roiIndex]
scores = np.dot(svmWeights, feat * 1.0 / svmFeatScale) + svmBias.ravel()
assert (len(scores) == roiDim)
maxArg = np.argmax(scores[1:]) + 1
maxScore = scores[maxArg]
if maxScore < decisionThreshold:
maxArg = 0
labels.append(maxArg)
maxScores.append(maxScore)
return labels, maxScores
def nnPredict(imgIndex, cntkParsedOutputDir, roiSize, roiDim, decisionThreshold = None):
cntkOutputPath = os.path.join(cntkParsedOutputDir, str(imgIndex) + ".dat.npz")
data = np.load(cntkOutputPath)['arr_0']
assert(len(data) == roiSize)
# get prediction for each roi
labels = []
maxScores = []
for roiIndex in range(roiSize):
scores = data[roiIndex]
scores = softmax(scores)
assert (len(scores) == roiDim)
maxArg = np.argmax(scores)
maxScore = scores[maxArg]
if decisionThreshold and maxScore < decisionThreshold:
maxArg = 0
labels.append(maxArg)
maxScores.append(maxScore)
return labels, maxScores
def imdbUpdateRoisWithHighGtOverlap(imdb, positivesGtOverlapThreshold):
addedPosCounter = 0
existingPosCounter = 0
for imgIndex in range(imdb.num_images):
for boxIndex, gtLabel in enumerate(imdb.roidb[imgIndex]['gt_classes']):
if gtLabel > 0:
existingPosCounter += 1
else:
overlaps = imdb.roidb[imgIndex]['gt_overlaps'][boxIndex, :].toarray()[0]
maxInd = np.argmax(overlaps)
maxOverlap = overlaps[maxInd]
if maxOverlap >= positivesGtOverlapThreshold and maxInd > 0:
addedPosCounter += 1
imdb.roidb[imgIndex]['gt_classes'][boxIndex] = maxInd
return existingPosCounter, addedPosCounter
####################################
# Visualize results
####################################
def visualizeResults(imgPath, roiLabels, roiScores, roiRelCoords, padWidth, padHeight, classes,
nmsKeepIndices = None, boDrawNegativeRois = True, decisionThreshold = 0.0):
# read and resize image
imgWidth, imgHeight = imWidthHeight(imgPath)
scale = 800.0 / max(imgWidth, imgHeight)
imgDebug = imresize(imread(imgPath), scale)
assert(len(roiLabels) == len(roiRelCoords))
if roiScores:
assert(len(roiLabels) == len(roiScores))
# draw multiple times to avoid occlusions
for iter in range(0,3):
for roiIndex in range(len(roiRelCoords)):
label = roiLabels[roiIndex]
if roiScores:
score = roiScores[roiIndex]
if decisionThreshold and score < decisionThreshold:
label = 0
# init drawing parameters
thickness = 1
if label == 0:
color = (255, 0, 0)
else:
color = getColorsPalette()[label]
rect = [int(scale * i) for i in roiRelCoords[roiIndex]]
# draw in higher iterations only the detections
if iter == 0 and boDrawNegativeRois:
drawRectangles(imgDebug, [rect], color=color, thickness=thickness)
elif iter==1 and label > 0:
if not nmsKeepIndices or (roiIndex in nmsKeepIndices):
thickness = 4
drawRectangles(imgDebug, [rect], color=color, thickness=thickness)
elif iter == 2 and label > 0:
if not nmsKeepIndices or (roiIndex in nmsKeepIndices):
font = ImageFont.truetype("arial.ttf", 18)
text = classes[label]
if roiScores:
text += "(" + str(round(score, 2)) + ")"
imgDebug = drawText(imgDebug, (rect[0],rect[1]), text, color = (255,255,255), font = font, colorBackground=color)
return imgDebug
def applyNonMaximaSuppression(nmsThreshold, labels, scores, coords):
# generate input for nms
allIndices = []
nmsRects = [[[]] for _ in range(max(labels) + 1)]
coordsWithScores = np.hstack((coords, np.array([scores]).T))
for i in range(max(labels) + 1):
indices = np.where(np.array(labels) == i)[0]
nmsRects[i][0] = coordsWithScores[indices,:]
allIndices.append(indices)
# call nms
_, nmsKeepIndicesList = apply_nms(nmsRects, nmsThreshold)
# map back to original roi indices
nmsKeepIndices = []
for i in range(max(labels) + 1):
for keepIndex in nmsKeepIndicesList[i][0]:
nmsKeepIndices.append(allIndices[i][keepIndex]) # for keepIndex in nmsKeepIndicesList[i][0]]
assert (len(nmsKeepIndices) == len(set(nmsKeepIndices))) # check if no roi indices was added >1 times
return nmsKeepIndices
def apply_nms(all_boxes, thresh, boUsePythonImpl = True):
"""Apply non-maximum suppression to all predicted boxes output by the test_net method."""
num_classes = len(all_boxes)
num_images = len(all_boxes[0])
nms_boxes = [[[] for _ in range(num_images)]
for _ in range(num_classes)]
nms_keepIndices = [[[] for _ in range(num_images)]
for _ in range(num_classes)]
for cls_ind in range(num_classes):
for im_ind in range(num_images):
dets = all_boxes[cls_ind][im_ind]
if dets == []:
continue
if boUsePythonImpl:
keep = nmsPython(dets, thresh)
else:
keep = nms(dets, thresh)
if len(keep) == 0:
continue
nms_boxes[cls_ind][im_ind] = dets[keep, :].copy()
nms_keepIndices[cls_ind][im_ind] = keep
return nms_boxes, nms_keepIndices
####################################
# Wrappers for compatibility with
# original fastRCNN code
####################################
class DummyNet(object):
def __init__(self, dim, num_classes, cntkParsedOutputDir):
self.name = 'dummyNet'
self.cntkParsedOutputDir = cntkParsedOutputDir
self.params = {
"cls_score": [ EasyDict({'data': np.zeros((num_classes, dim), np.float32) }),
EasyDict({'data': np.zeros((num_classes, 1), np.float32) })],
"trainers" : None,
}
def im_detect(net, im, boxes, feature_scale=None, bboxIndices=None, boReturnClassifierScore=True, classifier = 'svm'): # trainers=None,
# Return:
# scores (ndarray): R x K array of object class scores (K includes
# background as object category 0)
# (optional) boxes (ndarray): R x (4*K) array of predicted bounding boxes
# load cntk output for the given image
cntkOutputPath = os.path.join(net.cntkParsedOutputDir, str(im) + ".dat.npz")
cntkOutput = np.load(cntkOutputPath)['arr_0']
if bboxIndices != None:
cntkOutput = cntkOutput[bboxIndices, :] # only keep output for certain rois
else:
cntkOutput = cntkOutput[:len(boxes), :] # remove zero-padded rois
# compute scores for each box and each class
scores = None
if boReturnClassifierScore:
if classifier == 'nn':
scores = softmax2D(cntkOutput)
elif classifier == 'svm':
svmBias = net.params['cls_score'][1].data.transpose()
svmWeights = net.params['cls_score'][0].data.transpose()
scores = np.dot(cntkOutput * 1.0 / feature_scale, svmWeights) + svmBias
assert (np.unique(scores[:, 0]) == 0) # svm always returns 0 for label 0
else:
error
return scores, None, cntkOutput
####################################
# Subset of helper library
# used in the fastRCNN code
####################################
# Typical meaning of variable names -- Computer Vision:
# pt = 2D point (column,row)
# img = image
# width,height (or w/h) = image dimensions
# bbox = bbox object (stores: left, top,right,bottom co-ordinates)
# rect = rectangle (order: left, top, right, bottom)
# angle = rotation angle in degree
# scale = image up/downscaling factor
# Typical meaning of variable names -- general:
# lines,strings = list of strings
# line,string = single string
# xmlString = string with xml tags
# table = 2D row/column matrix implemented using a list of lists
# row,list1D = single row in a table, i.e. single 1D-list
# rowItem = single item in a row
# list1D = list of items, not necessarily strings
# item = single item of a list1D
# slotValue = e.g. "terminator" in: play <movie> terminator </movie>
# slotTag = e.g. "<movie>" or "</movie>" in: play <movie> terminator </movie>
# slotName = e.g. "movie" in: play <movie> terminator </movie>
# slot = e.g. "<movie> terminator </movie>" in: play <movie> terminator </movie>
import cv2, copy, textwrap
from PIL import Image, ImageFont, ImageDraw
from PIL.ExifTags import TAGS
def makeDirectory(directory):
if not os.path.exists(directory):
os.makedirs(directory)
def getFilesInDirectory(directory, postfix = ""):
fileNames = [s for s in os.listdir(directory) if not os.path.isdir(directory+"/"+s)]
if not postfix or postfix == "":
return fileNames
else:
return [s for s in fileNames if s.lower().endswith(postfix)]
def readFile(inputFile):
#reading as binary, to avoid problems with end-of-text characters
#note that readlines() does not remove the line ending characters
with open(inputFile,'rb') as f:
lines = f.readlines()
return [removeLineEndCharacters(s) for s in lines]
def readTable(inputFile, delimiter='\t', columnsToKeep=None):
lines = readFile(inputFile);
if columnsToKeep != None:
header = lines[0].split(delimiter)
columnsToKeepIndices = listFindItems(header, columnsToKeep)
else:
columnsToKeepIndices = None;
return splitStrings(lines, delimiter, columnsToKeepIndices)
def getColumn(table, columnIndex):
column = [];
for row in table:
column.append(row[columnIndex])
return column
def deleteFile(filePath):
if os.path.exists(filePath):
os.remove(filePath)
def writeFile(outputFile, lines):
with open(outputFile,'w') as f:
for line in lines:
f.write("%s\n" % line)
def writeTable(outputFile, table):
lines = tableToList1D(table)
writeFile(outputFile, lines)
def deleteFile(filePath):
if os.path.exists(filePath):
os.remove(filePath)
def deleteAllFilesInDirectory(directory, fileEndswithString, boPromptUser = False):
if boPromptUser:
userInput = raw_input('--> INPUT: Press "y" to delete files in directory ' + directory + ": ")
if not (userInput.lower() == 'y' or userInput.lower() == 'yes'):
print ("User input is %s: exiting now." % userInput)
exit()
for filename in getFilesInDirectory(directory):
if fileEndswithString == None or filename.lower().endswith(fileEndswithString):
deleteFile(directory + "/" + filename)
def removeLineEndCharacters(line):
if line.endswith(b'\r\n'):
return line[:-2]
elif line.endswith(b'\n'):
return line[:-1]
else:
return line
def splitString(string, delimiter='\t', columnsToKeepIndices=None):
if string == None:
return None
items = string.decode('utf-8').split(delimiter)
if columnsToKeepIndices != None:
items = getColumns([items], columnsToKeepIndices)
items = items[0]
return items;
def splitStrings(strings, delimiter, columnsToKeepIndices=None):
table = [splitString(string, delimiter, columnsToKeepIndices) for string in strings]
return table;
def find(list1D, func):
return [index for (index,item) in enumerate(list1D) if func(item)]
def tableToList1D(table, delimiter='\t'):
return [delimiter.join([str(s) for s in row]) for row in table]
def sortDictionary(dictionary, sortIndex=0, reverseSort=False):
return sorted(dictionary.items(), key=lambda x: x[sortIndex], reverse=reverseSort)
def imread(imgPath, boThrowErrorIfExifRotationTagSet = True):
if not os.path.exists(imgPath):
"ERROR: image path does not exist."
error
rotation = rotationFromExifTag(imgPath)
if boThrowErrorIfExifRotationTagSet and rotation != 0:
print ("Error: exif roation tag set, image needs to be rotated by %d degrees." % rotation)
img = cv2.imread(imgPath)
if img is None:
print ("ERROR: cannot load image " + imgPath)
error
if rotation != 0:
img = imrotate(img, -90).copy() # got this error occassionally without copy "TypeError: Layout of the output array img is incompatible with cv::Mat"
return img
def rotationFromExifTag(imgPath):
TAGSinverted = {v: k for k, v in TAGS.items()}
orientationExifId = TAGSinverted['Orientation']
try:
imageExifTags = Image.open(imgPath)._getexif()
except:
imageExifTags = None
# rotate the image if orientation exif tag is present
rotation = 0
if imageExifTags != None and orientationExifId != None and orientationExifId in imageExifTags:
orientation = imageExifTags[orientationExifId]
# print ("orientation = " + str(imageExifTags[orientationExifId]))
if orientation == 1 or orientation == 0:
rotation = 0 # no need to do anything
elif orientation == 6:
rotation = -90
elif orientation == 8:
rotation = 90
else:
print ("ERROR: orientation = " + str(orientation) + " not_supported!")
error
return rotation
def imwrite(img, imgPath):
cv2.imwrite(imgPath, img)
def imresize(img, scale, interpolation = cv2.INTER_LINEAR):
return cv2.resize(img, (0,0), fx=scale, fy=scale, interpolation=interpolation)
def imresizeMaxDim(img, maxDim, boUpscale = False, interpolation = cv2.INTER_LINEAR):
scale = 1.0 * maxDim / max(img.shape[:2])
if scale < 1 or boUpscale:
img = imresize(img, scale, interpolation)
else:
scale = 1.0
return img, scale
def imWidth(input):
return imWidthHeight(input)[0]
def imHeight(input):
return imWidthHeight(input)[1]
def imWidthHeight(input):
width, height = Image.open(input).size #this does not load the full image
return width,height
def imArrayWidth(input):
return imArrayWidthHeight(input)[0]
def imArrayHeight(input):
return imArrayWidthHeight(input)[1]
def imArrayWidthHeight(input):
width = input.shape[1]
height = input.shape[0]
return width,height
def imshow(img, waitDuration=0, maxDim = None, windowName = 'img'):
if isinstance(img, str): #test if 'img' is a string
img = cv2.imread(img)
if maxDim is not None:
scaleVal = 1.0 * maxDim / max(img.shape[:2])
if scaleVal < 1:
img = imresize(img, scaleVal)
cv2.imshow(windowName, img)
cv2.waitKey(waitDuration)
def drawRectangles(img, rects, color = (0, 255, 0), thickness = 2):
for rect in rects:
pt1 = tuple(ToIntegers(rect[0:2]))
pt2 = tuple(ToIntegers(rect[2:]))
cv2.rectangle(img, pt1, pt2, color, thickness)
def drawCrossbar(img, pt):
(x,y) = pt
cv2.rectangle(img, (0, y), (x, y), (255, 255, 0), 1)
cv2.rectangle(img, (x, 0), (x, y), (255, 255, 0), 1)
cv2.rectangle(img, (img.shape[1],y), (x, y), (255, 255, 0), 1)
cv2.rectangle(img, (x, img.shape[0]), (x, y), (255, 255, 0), 1)
def ptClip(pt, maxWidth, maxHeight):
pt = list(pt)
pt[0] = max(pt[0], 0)
pt[1] = max(pt[1], 0)
pt[0] = min(pt[0], maxWidth)
pt[1] = min(pt[1], maxHeight)
return pt
def drawText(img, pt, text, textWidth=None, color = (255,255,255), colorBackground = None, font = ImageFont.truetype("arial.ttf", 16)):
pilImg = imconvertCv2Pil(img)
pilImg = pilDrawText(pilImg, pt, text, textWidth, color, colorBackground, font)
return imconvertPil2Cv(pilImg)
def pilDrawText(pilImg, pt, text, textWidth=None, color = (255,255,255), colorBackground = None, font = ImageFont.truetype("arial.ttf", 16)):
textY = pt[1]
draw = ImageDraw.Draw(pilImg)
if textWidth == None:
lines = [text]
else:
lines = textwrap.wrap(text, width=textWidth)
for line in lines:
width, height = font.getsize(line)
if colorBackground != None:
draw.rectangle((pt[0], pt[1], pt[0] + width, pt[1] + height), fill=tuple(colorBackground[::-1]))
draw.text(pt, line, fill = tuple(color), font = font)
textY += height
return pilImg
def getColorsPalette():
colors = [[255,0,0], [0,255,0], [0,0,255], [255,255,0], [255,0,255]]
for i in range(5):
for dim in range(0,3):
for s in (0.25, 0.5, 0.75):
if colors[i][dim] != 0:
newColor = copy.deepcopy(colors[i])
newColor[dim] = int(round(newColor[dim] * s))
colors.append(newColor)
return colors
def imconvertPil2Cv(pilImg):
rgb = pilImg.convert('RGB')
return np.array(rgb).copy()[:, :, ::-1]
def imconvertCv2Pil(img):
cv2_im = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
return Image.fromarray(cv2_im)
def ToIntegers(list1D):
return [int(float(x)) for x in list1D]
def softmax(vec):
expVec = np.exp(vec)
# TODO: check numerical stability
if max(expVec) == np.inf:
outVec = np.zeros(len(expVec))
outVec[expVec == np.inf] = vec[expVec == np.inf]
outVec = outVec / np.sum(outVec)
else:
outVec = expVec / np.sum(expVec)
return outVec
def softmax2D(w):
e = np.exp(w)
dist = e / np.sum(e, axis=1)[:, np.newaxis]
return dist
def getDictionary(keys, values, boConvertValueToInt = True):
dictionary = {}
for key,value in zip(keys, values):
if (boConvertValueToInt):
value = int(value)
dictionary[key] = value
return dictionary
class Bbox:
MAX_VALID_DIM = 100000
left = top = right = bottom = None
def __init__(self, left, top, right, bottom):
self.left = int(round(float(left)))
self.top = int(round(float(top)))
self.right = int(round(float(right)))
self.bottom = int(round(float(bottom)))
self.standardize()
def __str__(self):
return ("Bbox object: left = {0}, top = {1}, right = {2}, bottom = {3}".format(self.left, self.top, self.right, self.bottom))
def __repr__(self):
return str(self)
def rect(self):
return [self.left, self.top, self.right, self.bottom]
def max(self):
return max([self.left, self.top, self.right, self.bottom])
def min(self):
return min([self.left, self.top, self.right, self.bottom])
def width(self):
width = self.right - self.left + 1
assert(width>=0)
return width
def height(self):
height = self.bottom - self.top + 1
assert(height>=0)
return height
def surfaceArea(self):
return self.width() * self.height()
def getOverlapBbox(self, bbox):
left1, top1, right1, bottom1 = self.rect()
left2, top2, right2, bottom2 = bbox.rect()
overlapLeft = max(left1, left2)
overlapTop = max(top1, top2)
overlapRight = min(right1, right2)
overlapBottom = min(bottom1, bottom2)
if (overlapLeft>overlapRight) or (overlapTop>overlapBottom):
return None
else:
return Bbox(overlapLeft, overlapTop, overlapRight, overlapBottom)
def standardize(self): #NOTE: every setter method should call standardize
leftNew = min(self.left, self.right)
topNew = min(self.top, self.bottom)
rightNew = max(self.left, self.right)
bottomNew = max(self.top, self.bottom)
self.left = leftNew
self.top = topNew
self.right = rightNew
self.bottom = bottomNew
def crop(self, maxWidth, maxHeight):
leftNew = min(max(self.left, 0), maxWidth)
topNew = min(max(self.top, 0), maxHeight)
rightNew = min(max(self.right, 0), maxWidth)
bottomNew = min(max(self.bottom, 0), maxHeight)
return Bbox(leftNew, topNew, rightNew, bottomNew)
def isValid(self):
if self.left>=self.right or self.top>=self.bottom:
return False
if min(self.rect()) < -self.MAX_VALID_DIM or max(self.rect()) > self.MAX_VALID_DIM:
return False
return True
def getEnclosingBbox(pts):
left = top = float('inf')
right = bottom = float('-inf')
for pt in pts:
left = min(left, pt[0])
top = min(top, pt[1])
right = max(right, pt[0])
bottom = max(bottom, pt[1])
return Bbox(left, top, right, bottom)
def bboxComputeOverlapVoc(bbox1, bbox2):
surfaceRect1 = bbox1.surfaceArea()
surfaceRect2 = bbox2.surfaceArea()
overlapBbox = bbox1.getOverlapBbox(bbox2)
if overlapBbox == None:
return 0
else:
surfaceOverlap = overlapBbox.surfaceArea()
overlap = max(0, 1.0 * surfaceOverlap / (surfaceRect1 + surfaceRect2 - surfaceOverlap))
assert (overlap >= 0 and overlap <= 1)
return overlap
def computeAveragePrecision(recalls, precisions, use_07_metric=False):
""" ap = voc_ap(recalls, precisions, [use_07_metric])
Compute VOC AP given precision and recall.
If use_07_metric is true, uses the
VOC 07 11 point method (default:False).
"""
if use_07_metric:
# 11 point metric
ap = 0.
for t in np.arange(0., 1.1, 0.1):
if np.sum(recalls >= t) == 0:
p = 0
else:
p = np.max(precisions[recalls >= t])
ap = ap + p / 11.
else:
# correct AP calculation
# first append sentinel values at the end
mrecalls = np.concatenate(([0.], recalls, [1.]))
mprecisions = np.concatenate(([0.], precisions, [0.]))
# compute the precision envelope
for i in range(mprecisions.size - 1, 0, -1):
mprecisions[i - 1] = np.maximum(mprecisions[i - 1], mprecisions[i])
# to calculate area under PR curve, look for points
# where X axis (recall) changes value
i = np.where(mrecalls[1:] != mrecalls[:-1])[0]
# and sum (\Delta recall) * prec
ap = np.sum((mrecalls[i + 1] - mrecalls[i]) * mprecisions[i + 1])
return ap

Просмотреть файл

@ -0,0 +1,9 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
from .imdb import imdb
from .pascal_voc import pascal_voc

Просмотреть файл

@ -0,0 +1,204 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
import os
import os.path as osp
import PIL
import numpy as np
import scipy.sparse
from builtins import range
import sys
if sys.version_info[0] < 3:
from utils2_win64.cython_bbox import bbox_overlaps
else:
from .utils3_win64.cython_bbox import bbox_overlaps
class imdb(object):
"""Image database."""
def __init__(self, name):
self._name = name
self._num_classes = 0
self._classes = []
self._image_index = []
self._obj_proposer = 'selective_search'
self._roidb = None
self._roidb_handler = self.default_roidb
# Use this dict for storing dataset specific config options
self.config = {}
@property
def name(self):
return self._name
@property
def num_classes(self):
return len(self._classes)
@property
def classes(self):
return self._classes
@property
def image_index(self):
return self._image_index
@property
def roidb_handler(self):
return self._roidb_handler
@roidb_handler.setter
def roidb_handler(self, val):
self._roidb_handler = val
@property
def roidb(self):
# A roidb is a list of dictionaries, each with the following keys:
# boxes
# gt_overlaps
# gt_classes
# flipped
if self._roidb is not None:
return self._roidb
self._roidb = self.roidb_handler()
return self._roidb
# @property
# def cache_path(self):
# cache_path = osp.abspath(osp.join(datasets.ROOT_DIR, 'data', 'cache'))
# print cache_path
# if not os.path.exists(cache_path):
# os.makedirs(cache_path)
# return cache_path
@property
def num_images(self):
return len(self.image_index)
def image_path_at(self, i):
raise NotImplementedError
def default_roidb(self):
raise NotImplementedError
def evaluate_detections(self, all_boxes, output_dir=None):
"""
all_boxes is a list of length number-of-classes.
Each list element is a list of length number-of-images.
Each of those list elements is either an empty list []
or a numpy array of detection.
all_boxes[class][image] = [] or np.array of shape #dets x 5
"""
raise NotImplementedError
def append_flipped_images(self):
num_images = self.num_images
widths = [PIL.Image.open(self.image_path_at(i)).size[0]
for i in range(num_images)]
for i in range(num_images):
boxes = self.roidb[i]['boxes'].copy()
oldx1 = boxes[:, 0].copy()
oldx2 = boxes[:, 2].copy()
boxes[:, 0] = widths[i] - oldx2 - 1
boxes[:, 2] = widths[i] - oldx1 - 1
assert (boxes[:, 2] >= boxes[:, 0]).all()
entry = {'boxes' : boxes,
'gt_overlaps' : self.roidb[i]['gt_overlaps'],
'gt_classes' : self.roidb[i]['gt_classes'],
'flipped' : True}
self.roidb.append(entry)
self._image_index = self._image_index * 2
def evaluate_recall(self, candidate_boxes, ar_thresh=0.5):
# Record max overlap value for each gt box
# Return vector of overlap values
gt_overlaps = np.zeros(0)
for i in range(self.num_images):
gt_inds = np.where(self.roidb[i]['gt_classes'] > 0)[0]
gt_boxes = self.roidb[i]['boxes'][gt_inds, :]
boxes = candidate_boxes[i]
if boxes.shape[0] == 0:
continue
overlaps = bbox_overlaps(boxes.astype(np.float),
gt_boxes.astype(np.float))
# gt_overlaps = np.hstack((gt_overlaps, overlaps.max(axis=0)))
_gt_overlaps = np.zeros((gt_boxes.shape[0]))
for j in range(gt_boxes.shape[0]):
argmax_overlaps = overlaps.argmax(axis=0)
max_overlaps = overlaps.max(axis=0)
gt_ind = max_overlaps.argmax()
gt_ovr = max_overlaps.max()
assert(gt_ovr >= 0)
box_ind = argmax_overlaps[gt_ind]
_gt_overlaps[j] = overlaps[box_ind, gt_ind]
assert(_gt_overlaps[j] == gt_ovr)
overlaps[box_ind, :] = -1
overlaps[:, gt_ind] = -1
gt_overlaps = np.hstack((gt_overlaps, _gt_overlaps))
num_pos = gt_overlaps.size
gt_overlaps = np.sort(gt_overlaps)
step = 0.001
thresholds = np.minimum(np.arange(0.5, 1.0 + step, step), 1.0)
recalls = np.zeros_like(thresholds)
for i, t in enumerate(thresholds):
recalls[i] = (gt_overlaps >= t).sum() / float(num_pos)
ar = 2 * np.trapz(recalls, thresholds)
return ar, gt_overlaps, recalls, thresholds
def create_roidb_from_box_list(self, box_list, gt_roidb):
assert len(box_list) == self.num_images, \
'Number of boxes must match number of ground-truth images'
roidb = []
for i in range(self.num_images):
boxes = box_list[i]
num_boxes = boxes.shape[0]
overlaps = np.zeros((num_boxes, self.num_classes), dtype=np.float32)
if gt_roidb and gt_roidb[i]:
gt_boxes = gt_roidb[i]['boxes']
gt_classes = gt_roidb[i]['gt_classes']
if len(gt_classes) > 0: #for pascal every image has at least one annotated object. This is not the case however if including negative images
gt_overlaps = bbox_overlaps(boxes.astype(np.float),
gt_boxes.astype(np.float))
argmaxes = gt_overlaps.argmax(axis=1)
maxes = gt_overlaps.max(axis=1)
I = np.where(maxes > 0)[0]
overlaps[I, gt_classes[argmaxes[I]]] = maxes[I]
overlaps = scipy.sparse.csr_matrix(overlaps)
roidb.append({'boxes' : boxes,
'gt_classes' : np.zeros((num_boxes,),
dtype=np.int32),
'gt_overlaps' : overlaps,
'flipped' : False})
return roidb
@staticmethod
def merge_roidbs(a, b):
assert len(a) == len(b)
for i in range(len(a)):
if a[i]: #if image has at least one annotated object
a[i]['boxes'] = np.vstack((a[i]['boxes'], b[i]['boxes']))
a[i]['gt_classes'] = np.hstack((a[i]['gt_classes'],
b[i]['gt_classes']))
a[i]['gt_overlaps'] = scipy.sparse.vstack([a[i]['gt_overlaps'],
b[i]['gt_overlaps']])
else:
a[i] = b[i]
return a
def competition_mode(self, on):
"""Turn competition mode on or off."""
pass

Просмотреть файл

@ -0,0 +1,37 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
import numpy as np
def nms(dets, thresh):
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
order = scores.argsort()[::-1]
keep = []
while order.size > 0:
i = order[0]
keep.append(i)
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
ovr = inter / (areas[i] + areas[order[1:]] - inter)
inds = np.where(ovr <= thresh)[0]
order = order[inds + 1]
return keep

Просмотреть файл

@ -0,0 +1,363 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
from __future__ import print_function
import os, pdb
import xml.dom.minidom as minidom
import numpy as np
import scipy.sparse
import scipy.io as sio
import pickle as cp
import subprocess
from .imdb import imdb
from .voc_eval import voc_eval
#from fastRCNN.imdb import imdb
#from fastRCNN.voc_eval import voc_eval
class pascal_voc(imdb):
def __init__(self, image_set, year, classes, maxNrRois, cacheDir, devkit_path=None):
imdb.__init__(self, 'voc_' + year + '_' + image_set)
self._year = year
self._image_set = image_set
self._maxNrRois = maxNrRois
self._ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
self._cacheDir = cacheDir
self._devkit_path = self._get_default_path() if devkit_path is None \
else os.path.join(devkit_path, 'VOCdevkit')
self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)
self._classes = classes
#('__background__', # always index 0
# 'aeroplane', 'bicycle', 'bird', 'boat',
# 'bottle', 'bus', 'car', 'cat', 'chair',
# 'cow', 'diningtable', 'dog', 'horse',
# 'motorbike', 'person', 'pottedplant',
# 'sheep', 'sofa', 'train', 'tvmonitor')
self._class_to_ind = dict(zip(self.classes, range(self.num_classes)))
self._image_ext = '.jpg'
self._image_index = self._load_image_set_index()
# Default to roidb handler
self._roidb_handler = self.selective_search_roidb
# PASCAL specific config options
self.config = {'cleanup' : True,
'use_salt' : True,
'top_k' : 2000}
assert os.path.exists(self._devkit_path), \
'VOCdevkit path does not exist: {}'.format(self._devkit_path)
assert os.path.exists(self._data_path), \
'Path does not exist: {}'.format(self._data_path)
@property
def cache_path(self):
cache_path = self._cacheDir
#cache_path = osp.abspath(osp.join(datasets.ROOT_DIR, 'data', 'cache'))
if not os.path.exists(cache_path):
os.makedirs(cache_path)
return cache_path
def image_path_at(self, i):
"""
Return the absolute path to image i in the image sequence.
"""
return self.image_path_from_index(self._image_index[i])
def image_path_from_index(self, index):
"""
Construct an image path from the image's "index" identifier.
"""
image_path = os.path.join(self._data_path, 'JPEGImages',
index + self._image_ext)
assert os.path.exists(image_path), \
'Path does not exist: {}'.format(image_path)
return image_path
def _load_image_set_index(self):
"""
Load the indexes listed in this dataset's image set file.
"""
# Example path to image set file:
# self._devkit_path + /VOCdevkit/VOC2007/ImageSets/Main/val.txt
image_set_file = os.path.join(self._data_path, 'ImageSets', 'Main',
self._image_set + '.txt')
assert os.path.exists(image_set_file), \
'Path does not exist: {}'.format(image_set_file)
with open(image_set_file) as f:
image_index = [x.strip() for x in f.readlines()]
return image_index
def _get_default_path(self):
"""
Return the default path where PASCAL VOC is expected to be installed.
"""
return os.path.join(self._ROOT_DIR, 'data', 'pascalVoc', 'VOCdevkit')
def gt_roidb(self):
"""
Return the database of ground-truth regions of interest.
This function loads/saves from/to a cache file to speed up future calls.
"""
cache_file = os.path.join(self.cache_path, self.name + '_gt_roidb.pkl')
if os.path.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cp.load(fid)
print ('{} gt roidb loaded from {}'.format(self.name, cache_file))
return roidb
gt_roidb = [self._load_pascal_annotation(index)
for index in self.image_index]
with open(cache_file, 'wb') as fid:
cp.dump(gt_roidb, fid, cp.HIGHEST_PROTOCOL)
print ('wrote gt roidb to {}'.format(cache_file))
return gt_roidb
def selective_search_roidb(self):
"""
Return the database of selective search regions of interest.
Ground-truth ROIs are also included.
This function loads/saves from/to a cache file to speed up future calls.
"""
cache_file = os.path.join(self.cache_path,
self.name + '_selective_search_roidb.pkl')
if os.path.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cp.load(fid, encoding='latin1')
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
return roidb
if int(self._year) == 2007 or not self._image_set.startswith('test'):
gt_roidb = self.gt_roidb()
ss_roidb = self._load_selective_search_roidb(gt_roidb)
roidb = imdb.merge_roidbs(gt_roidb, ss_roidb)
else:
roidb = self._load_selective_search_roidb(None)
# Keep max of e.g. 2000 rois
if type(self._maxNrRois) == int:
print ("Only keep the first %d ROIs..." % self._maxNrRois)
for i in range(self.num_images):
gt_overlaps = roidb[i]['gt_overlaps']
gt_overlaps = gt_overlaps.todense()[:self._maxNrRois]
gt_overlaps = scipy.sparse.csr_matrix(gt_overlaps)
roidb[i]['boxes'] = roidb[i]['boxes'][:self._maxNrRois, :]
roidb[i]['gt_classes'] = roidb[i]['gt_classes'][:self._maxNrRois]
roidb[i]['gt_overlaps'] = roidb[i]['gt_overlaps'] = gt_overlaps
with open(cache_file, 'wb') as fid:
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
print ('wrote ss roidb to {}'.format(cache_file))
return roidb
def _load_selective_search_roidb(self, gt_roidb):
filename = os.path.abspath(os.path.join(self._devkit_path, '..',
'selective_search_data',
self.name + '.mat'))
assert os.path.exists(filename), \
'Selective search data not found at: {}'.format(filename)
raw_data = sio.loadmat(filename)['boxes'].ravel()
box_list = []
for i in range(raw_data.shape[0]):
box_list.append(raw_data[i][:, (1, 0, 3, 2)] - 1)
return self.create_roidb_from_box_list(box_list, gt_roidb)
def selective_search_IJCV_roidb(self):
"""
Return the database of selective search regions of interest.
Ground-truth ROIs are also included.
This function loads/saves from/to a cache file to speed up future calls.
"""
cache_file = os.path.join(self.cache_path,
'{:s}_selective_search_IJCV_top_{:d}_roidb.pkl'.
format(self.name, self.config['top_k']))
if os.path.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cp.load(fid)
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
return roidb
gt_roidb = self.gt_roidb()
ss_roidb = self._load_selective_search_IJCV_roidb(gt_roidb)
roidb = imdb.merge_roidbs(gt_roidb, ss_roidb)
with open(cache_file, 'wb') as fid:
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
print ('wrote ss roidb to {}'.format(cache_file))
return roidb
def _load_selective_search_IJCV_roidb(self, gt_roidb):
IJCV_path = os.path.abspath(os.path.join(self.cache_path, '..',
'selective_search_IJCV_data',
'voc_' + self._year))
assert os.path.exists(IJCV_path), \
'Selective search IJCV data not found at: {}'.format(IJCV_path)
top_k = self.config['top_k']
box_list = []
for i in range(self.num_images):
filename = os.path.join(IJCV_path, self.image_index[i] + '.mat')
raw_data = sio.loadmat(filename)
box_list.append((raw_data['boxes'][:top_k, :]-1).astype(np.uint16))
return self.create_roidb_from_box_list(box_list, gt_roidb)
def _load_pascal_annotation(self, index):
"""
Load image and bounding boxes info from XML file in the PASCAL VOC
format.
"""
filename = os.path.join(self._data_path, 'Annotations', index + '.xml')
# print ('Loading: {}'.format(filename))
def get_data_from_tag(node, tag):
return node.getElementsByTagName(tag)[0].childNodes[0].data
with open(filename) as f:
data = minidom.parseString(f.read())
objs = data.getElementsByTagName('object')
num_objs = len(objs)
boxes = np.zeros((num_objs, 4), dtype=np.uint16)
gt_classes = np.zeros((num_objs), dtype=np.int32)
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
# Load object bounding boxes into a data frame.
for ix, obj in enumerate(objs):
# Make pixel indexes 0-based
x1 = float(get_data_from_tag(obj, 'xmin')) - 1
y1 = float(get_data_from_tag(obj, 'ymin')) - 1
x2 = float(get_data_from_tag(obj, 'xmax')) - 1
y2 = float(get_data_from_tag(obj, 'ymax')) - 1
cls = self._class_to_ind[
str(get_data_from_tag(obj, "name")).lower().strip()]
boxes[ix, :] = [x1, y1, x2, y2]
gt_classes[ix] = cls
overlaps[ix, cls] = 1.0
overlaps = scipy.sparse.csr_matrix(overlaps)
return {'boxes' : boxes,
'gt_classes': gt_classes,
'gt_overlaps' : overlaps,
'flipped' : False}
def _write_voc_results_file(self, all_boxes, output_dir):
comp_id = 'comp4'
if self.config['use_salt']:
comp_id += '-{}'.format(os.getpid())
for cls_ind, cls in enumerate(self.classes):
if cls == '__background__':
continue
print ('Writing {} VOC results file'.format(cls))
filename = self._get_voc_results_file_template(output_dir).format(cls)
with open(filename, 'wt') as f:
for im_ind, index in enumerate(self.image_index):
dets = all_boxes[cls_ind][im_ind]
if dets == []:
continue
# the VOCdevkit expects 1-based indices
for k in range(dets.shape[0]):
f.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.
format(index, dets[k, -1],
dets[k, 0] + 1, dets[k, 1] + 1,
dets[k, 2] + 1, dets[k, 3] + 1))
return comp_id
def evaluate_detections(self, all_boxes, output_dir, boUsePythonImpl = True, use_07_metric = False):
self._write_voc_results_file(all_boxes, output_dir)
if not boUsePythonImpl:
self._do_matlab_eval(comp_id, output_dir)
else:
self._do_python_eval(output_dir, use_07_metric)
def _do_matlab_eval(self, comp_id, output_dir='output'):
rm_results = self.config['cleanup']
path = os.path.join(os.path.dirname(__file__),
'VOCdevkit-matlab-wrapper')
cmd = 'cd {} && '.format(path)
cmd += '{:s} -nodisplay -nodesktop '.format(datasets.MATLAB)
cmd += '-r "dbstop if error; '
cmd += 'voc_eval(\'{:s}\',\'{:s}\',\'{:s}\',\'{:s}\',{:d}); quit;"' \
.format(self._devkit_path, comp_id,
self._image_set, output_dir, int(rm_results))
print('Running:\n{}'.format(cmd))
status = subprocess.call(cmd, shell=True)
def competition_mode(self, on):
if on:
self.config['use_salt'] = False
self.config['cleanup'] = False
else:
self.config['use_salt'] = True
self.config['cleanup'] = True
#########################################################################
# Python evaluation functions (copied from faster-RCNN)
##########################################################################
def _get_voc_results_file_template(self, evalDir):
if not os.path.exists(evalDir):
os.makedirs(evalDir)
filename = self._image_set + '_{:s}.txt'
return os.path.join(evalDir, filename)
def _do_python_eval(self, output_dir='output', use_07_metric=None):
annopath = os.path.join(self._devkit_path, 'VOC' + self._year, 'Annotations', '{}.xml')
imagesetfile = os.path.join(
self._devkit_path,
'VOC' + self._year,
'ImageSets',
'Main',
self._image_set + '.txt')
aps = []
# The PASCAL VOC metric changed in 2010
if use_07_metric == None:
use_07_metric = True if int(self._year) < 2010 else False
print ('VOC07 metric? ' + ('Yes' if use_07_metric else 'No'))
if not os.path.isdir(output_dir):
os.mkdir(output_dir)
for i, cls in enumerate(self._classes):
if cls == '__background__':
continue
filename = self._get_voc_results_file_template(output_dir).format(cls)
rec, prec, ap = voc_eval(
filename, annopath, imagesetfile, cls, cachedir = output_dir, ovthresh=0.5,
use_07_metric=use_07_metric)
aps += [ap]
print('AP for {} = {:.4f}'.format(cls, ap))
with open(os.path.join(output_dir, cls + '_pr.pkl'), 'wb') as f:
cp.dump({'rec': rec, 'prec': prec, 'ap': ap}, f)
print('Mean AP = {:.4f}'.format(np.mean(aps)))
# print('~~~~~~~~')
# print('Results:')
# for ap in aps:
# print('{:.3f}'.format(ap))
# print('{:.3f}'.format(np.mean(aps)))
# print('~~~~~~~~')
# print('')
print('--------------------------------------------------------------')
print('Results computed with the **unofficial** Python eval code.')
print('Results should be very close to the official MATLAB eval code.')
print('Recompute with `./tools/reval.py --matlab ...` for your paper.')
print('-- Thanks, The Management')
print('--------------------------------------------------------------')
if __name__ == '__main__':
d = datasets.pascal_voc('trainval', '2007')
res = d.roidb
from IPython import embed; embed()

Просмотреть файл

@ -0,0 +1,346 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
"""Test a Fast R-CNN network on an imdb (image database)."""
#from config import cfg #, get_output_dir
#from blob import im_list_to_blob
from __future__ import print_function
import os, sys, cv2, numpy as np, pickle as cp, heapq
from .nms import nms as nmsPython
if sys.version_info[0] < 3:
from utils2_win64.cython_nms import nms
else:
from .utils3_win64.cython_nms import nms
from .timer import Timer
from cntk_helpers import im_detect, apply_nms
from builtins import range
def _get_image_blob(im):
"""Converts an image into a network input.
Arguments:
im (ndarray): a color image in BGR order
Returns:
blob (ndarray): a data blob holding an image pyramid
im_scale_factors (list): list of image scales (relative to im) used
in the image pyramid
"""
im_orig = im.astype(np.float32, copy=True)
im_orig -= cfg.PIXEL_MEANS
im_shape = im_orig.shape
im_size_min = np.min(im_shape[0:2])
im_size_max = np.max(im_shape[0:2])
processed_ims = []
im_scale_factors = []
for target_size in cfg.TEST.SCALES:
im_scale = float(target_size) / float(im_size_min)
# Prevent the biggest axis from being more than MAX_SIZE
if np.round(im_scale * im_size_max) > cfg.TEST.MAX_SIZE:
im_scale = float(cfg.TEST.MAX_SIZE) / float(im_size_max)
im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale,
interpolation=cv2.INTER_LINEAR)
im_scale_factors.append(im_scale)
processed_ims.append(im)
# Create a blob to hold the input images
blob = im_list_to_blob(processed_ims)
return blob, np.array(im_scale_factors)
def _get_rois_blob(im_rois, im_scale_factors):
"""Converts RoIs into network inputs.
Arguments:
im_rois (ndarray): R x 4 matrix of RoIs in original image coordinates
im_scale_factors (list): scale factors as returned by _get_image_blob
Returns:
blob (ndarray): R x 5 matrix of RoIs in the image pyramid
"""
rois, levels = _project_im_rois(im_rois, im_scale_factors)
rois_blob = np.hstack((levels, rois))
return rois_blob.astype(np.float32, copy=False)
def _project_im_rois(im_rois, scales):
"""Project image RoIs into the image pyramid built by _get_image_blob.
Arguments:
im_rois (ndarray): R x 4 matrix of RoIs in original image coordinates
scales (list): scale factors as returned by _get_image_blob
Returns:
rois (ndarray): R x 4 matrix of projected RoI coordinates
levels (list): image pyramid levels used by each projected RoI
"""
im_rois = im_rois.astype(np.float, copy=False)
if len(scales) > 1:
widths = im_rois[:, 2] - im_rois[:, 0] + 1
heights = im_rois[:, 3] - im_rois[:, 1] + 1
areas = widths * heights
scaled_areas = areas[:, np.newaxis] * (scales[np.newaxis, :] ** 2)
diff_areas = np.abs(scaled_areas - 224 * 224)
levels = diff_areas.argmin(axis=1)[:, np.newaxis]
else:
levels = np.zeros((im_rois.shape[0], 1), dtype=np.int)
rois = im_rois * scales[levels]
return rois, levels
def _get_blobs(im, rois):
"""Convert an image and RoIs within that image into network inputs."""
blobs = {'data' : None, 'rois' : None}
blobs['data'], im_scale_factors = _get_image_blob(im)
blobs['rois'] = _get_rois_blob(rois, im_scale_factors)
return blobs, im_scale_factors
def _bbox_pred(boxes, box_deltas):
"""Transform the set of class-agnostic boxes into class-specific boxes
by applying the predicted offsets (box_deltas)
"""
if boxes.shape[0] == 0:
return np.zeros((0, box_deltas.shape[1]))
boxes = boxes.astype(np.float, copy=False)
widths = boxes[:, 2] - boxes[:, 0] + cfg.EPS
heights = boxes[:, 3] - boxes[:, 1] + cfg.EPS
ctr_x = boxes[:, 0] + 0.5 * widths
ctr_y = boxes[:, 1] + 0.5 * heights
dx = box_deltas[:, 0::4]
dy = box_deltas[:, 1::4]
dw = box_deltas[:, 2::4]
dh = box_deltas[:, 3::4]
pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]
pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]
pred_w = np.exp(dw) * widths[:, np.newaxis]
pred_h = np.exp(dh) * heights[:, np.newaxis]
pred_boxes = np.zeros(box_deltas.shape)
# x1
pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w
# y1
pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h
# x2
pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w
# y2
pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h
return pred_boxes
def _clip_boxes(boxes, im_shape):
"""Clip boxes to image boundaries."""
# x1 >= 0
boxes[:, 0::4] = np.maximum(boxes[:, 0::4], 0)
# y1 >= 0
boxes[:, 1::4] = np.maximum(boxes[:, 1::4], 0)
# x2 < im_shape[1]
boxes[:, 2::4] = np.minimum(boxes[:, 2::4], im_shape[1] - 1)
# y2 < im_shape[0]
boxes[:, 3::4] = np.minimum(boxes[:, 3::4], im_shape[0] - 1)
return boxes
# def im_detect(net, im, boxes):
# """Detect object classes in an image given object proposals.
#
# Arguments:
# net (caffe.Net): Fast R-CNN network to use
# im (ndarray): color image to test (in BGR order)
# boxes (ndarray): R x 4 array of object proposals
#
# Returns:
# scores (ndarray): R x K array of object class scores (K includes
# background as object category 0)
# boxes (ndarray): R x (4*K) array of predicted bounding boxes
# """
# blobs, unused_im_scale_factors = _get_blobs(im, boxes)
#
# # When mapping from image ROIs to feature map ROIs, there's some aliasing
# # (some distinct image ROIs get mapped to the same feature ROI).
# # Here, we identify duplicate feature ROIs, so we only compute features
# # on the unique subset.
# if cfg.DEDUP_BOXES > 0:
# v = np.array([1, 1e3, 1e6, 1e9, 1e12])
# hashes = np.round(blobs['rois'] * cfg.DEDUP_BOXES).dot(v)
# _, index, inv_index = np.unique(hashes, return_index=True,
# return_inverse=True)
# blobs['rois'] = blobs['rois'][index, :]
# boxes = boxes[index, :]
#
# # reshape network inputs
# net.blobs['data'].reshape(*(blobs['data'].shape))
# net.blobs['rois'].reshape(*(blobs['rois'].shape))
# blobs_out = net.forward(data=blobs['data'].astype(np.float32, copy=False),
# rois=blobs['rois'].astype(np.float32, copy=False))
# if cfg.TEST.SVM:
# # use the raw scores before softmax under the assumption they
# # were trained as linear SVMs
# scores = net.blobs['cls_score'].data
# else:
# # use softmax estimated probabilities
# scores = blobs_out['cls_prob']
#
# if cfg.TEST.BBOX_REG:
# # Apply bounding-box regression deltas
# box_deltas = blobs_out['bbox_pred']
# pred_boxes = _bbox_pred(boxes, box_deltas)
# pred_boxes = _clip_boxes(pred_boxes, im.shape)
# else:
# # Simply repeat the boxes, once for each class
# pred_boxes = np.tile(boxes, (1, scores.shape[1]))
#
# if cfg.DEDUP_BOXES > 0:
# # Map scores and predictions back to the original set of boxes
# scores = scores[inv_index, :]
# pred_boxes = pred_boxes[inv_index, :]
#
# return scores, pred_boxes
def vis_detections(im, class_name, dets, thresh=0.3):
"""Visual debugging of detections."""
import matplotlib.pyplot as plt
im = im[:, :, (2, 1, 0)]
for i in range(np.minimum(10, dets.shape[0])):
bbox = dets[i, :4]
score = dets[i, -1]
if score > thresh:
plt.cla()
plt.imshow(im)
plt.gca().add_patch(
plt.Rectangle((bbox[0], bbox[1]),
bbox[2] - bbox[0],
bbox[3] - bbox[1], fill=False,
edgecolor='g', linewidth=3)
)
plt.title('{} {:.3f}'.format(class_name, score))
plt.show()
def test_net(net, imdb, output_dir, feature_scale, classifier = 'svm', nmsThreshold = 0.3,
boUsePythonImpl = False, boThresholdDetections = True, boApplyNms = True):
"""Test a Fast R-CNN network on an image database."""
num_images = len(imdb.image_index)
# heuristic: keep an average of 40 detections per class per images prior
# to NMS
max_per_set = 40 * num_images
# heuristic: keep at most 100 detection per class per image prior to NMS
max_per_image = 100
# detection thresold for each class (this is adaptively set based on the
# max_per_set constraint)
thresh = -np.inf * np.ones(imdb.num_classes)
# top_scores will hold one minheap of scores per class (used to enforce
# the max_per_set constraint)
top_scores = [[] for _ in range(imdb.num_classes)]
# all detections are collected into:
# all_boxes[cls][image] = N x 5 array of detections in
# (x1, y1, x2, y2, score)
all_boxes = [[[] for _ in range(num_images)]
for _ in range(imdb.num_classes)]
#output_dir = get_output_dir(imdb, net)
# timers
_t = {'im_detect' : Timer(), 'misc' : Timer()}
roidb = imdb.roidb
if not boThresholdDetections:
for i in range(num_images):
if i % 1000 == 0:
print (" Processing image {} of {}..".format(i, num_images))
scores, _, _ = im_detect(net, i, roidb[i]['boxes'], feature_scale=feature_scale, classifier=classifier)
for j in range(1, imdb.num_classes):
inds = np.where(roidb[i]['gt_classes'] == 0)[0]
cls_scores = scores[inds, j]
cls_boxes = roidb[i]['boxes'][inds]
all_boxes[j][i] = \
np.hstack((cls_boxes, cls_scores[:, np.newaxis])) \
.astype(np.float32, copy=False)
else:
for i in range(num_images):
if i % 1000 == 0:
print (" Processing image {} of {}..".format(i, num_images))
#im = cv2.imread(imdb.image_path_at(i))
#_t['im_detect'].tic()
scores, _, _ = im_detect(net, i, roidb[i]['boxes'], feature_scale = feature_scale, classifier = classifier)
#_t['im_detect'].toc()
_t['misc'].tic()
for j in range(1, imdb.num_classes):
inds = np.where((scores[:, j] > thresh[j]) &
(roidb[i]['gt_classes'] == 0))[0]
cls_scores = scores[inds, j]
# cls_boxes = boxes[inds, j * 4:(j + 1) * 4]
boxes = roidb[i]['boxes']
cls_boxes = boxes[inds]
top_inds = np.argsort(-cls_scores)[:max_per_image]
cls_scores = cls_scores[top_inds]
cls_boxes = cls_boxes[top_inds, :]
# push new scores onto the minheap
for val in cls_scores:
heapq.heappush(top_scores[j], val)
# if we've collected more than the max number of detection,
# then pop items off the minheap and update the class threshold
if len(top_scores[j]) > max_per_set:
while len(top_scores[j]) > max_per_set:
heapq.heappop(top_scores[j])
thresh[j] = top_scores[j][0]
all_boxes[j][i] = \
np.hstack((cls_boxes, cls_scores[:, np.newaxis])) \
.astype(np.float32, copy=False)
#visualize rois
if False:
im = cv2.imread(imdb.image_path_at(i))
if boUsePythonImpl:
keep = nmsPython.nms(all_boxes[j][i], 0.3)
else:
keep = nms(all_boxes[j][i], 0.3)
vis_detections(im, imdb.classes[j], all_boxes[j][i][keep, :])
_t['misc'].toc()
# print ('im_detect: {:d}/{:d} {:.3f}s {:.3f}s' \
# .format(i + 1, num_images, _t['im_detect'].average_time,
# _t['misc'].average_time))
#keep only the boxes with highest score for each class
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coord+score
for j in range(1, imdb.num_classes):
for i in range(num_images):
inds = np.where(all_boxes[j][i][:, -1] > thresh[j])[0]
if len(inds) == 0:
all_boxes[j][i] = []
else:
all_boxes[j][i] = all_boxes[j][i][inds, :]
if output_dir:
det_file = os.path.join(output_dir, 'detections.pkl')
with open(det_file, 'wb') as f:
cp.dump(all_boxes, f, cp.HIGHEST_PROTOCOL)
if boApplyNms:
print ("Number of rois before non-maxima surpression: %d" % sum([len(all_boxes[i][j]) for i in range(imdb.num_classes) for j in range(imdb.num_images)]))
nms_dets,_ = apply_nms(all_boxes, nmsThreshold, boUsePythonImpl)
print ("Number of rois after non-maxima surpression: %d" % sum([len(nms_dets[i][j]) for i in range(imdb.num_classes) for j in range(imdb.num_images)]))
else:
print ("Skipping non-maxima surpression")
nms_dets = all_boxes
print ('Evaluating detections')
imdb.evaluate_detections(nms_dets, output_dir)

Просмотреть файл

@ -0,0 +1,32 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
import time
class Timer(object):
"""A simple timer."""
def __init__(self):
self.total_time = 0.
self.calls = 0
self.start_time = 0.
self.diff = 0.
self.average_time = 0.
def tic(self):
# using time.time instead of time.clock because time time.clock
# does not normalize for multithreading
self.start_time = time.time()
def toc(self, average=True):
self.diff = time.time() - self.start_time
self.total_time += self.diff
self.calls += 1
self.average_time = self.total_time / self.calls
if average:
return self.average_time
else:
return self.diff

Просмотреть файл

@ -0,0 +1,315 @@
#!/usr/bin/env python
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
"""
Train post-hoc SVMs using the algorithm and hyper-parameters from
traditional R-CNN.
"""
from timer import Timer
from sklearn import svm
import numpy as np
#################################################
# Slightly modified SVM training functions
#################################################
class SVMTrainer(object):
"""
Trains post-hoc detection SVMs for all classes using the algorithm
and hyper-parameters of traditional R-CNN.
"""
def __init__(self, net, imdb, im_detect, svmWeightsPath, svmBiasPath, svmFeatScalePath,
svm_C, svm_B, svm_nrEpochs, svm_retrainLimit, svm_evictThreshold, svm_posWeight,
svm_targetNorm, svm_penality, svm_loss, svm_rngSeed):
self.net = net
self.imdb = imdb
self.im_detect = im_detect
self.svm_nrEpochs = svm_nrEpochs
self.svm_targetNorm = svm_targetNorm
self.svmWeightsPath = svmWeightsPath
self.svmBiasPath = svmBiasPath
self.svmFeatScalePath = svmFeatScalePath
self.layer = 'fc7'
self.hard_thresh = -1.0001
self.neg_iou_thresh = 0.3
dim = net.params['cls_score'][0].data.shape[1]
self.feature_scale = self._get_feature_scale()
print('Feature dim: {}'.format(dim))
print('Feature scale: {:.3f}'.format(self.feature_scale))
self.trainers = [SVMClassTrainer(cls, dim, self.feature_scale, svm_C, svm_B, svm_posWeight, svm_penality, svm_loss,
svm_rngSeed, svm_retrainLimit, svm_evictThreshold) for cls in imdb.classes]
def _get_feature_scale(self, num_images=100):
_t = Timer()
roidb = self.imdb.roidb
total_norm = 0.0
total_sum = 0.0
count = 0.0
num_images = min(num_images, self.imdb.num_images)
inds = np.random.choice(range(self.imdb.num_images), size=num_images, replace=False)
for i_, i in enumerate(inds):
#im = cv2.imread(self.imdb.image_path_at(i))
#if roidb[i]['flipped']:
# im = im[:, ::-1, :]
#im = self.imdb.image_path_at(i)
_t.tic()
scores, boxes, feat = self.im_detect(self.net, i, roidb[i]['boxes'], boReturnClassifierScore = False)
_t.toc()
#feat = self.net.blobs[self.layer].data
total_norm += np.sqrt((feat ** 2).sum(axis=1)).sum()
total_sum += 1.0 * sum(sum(feat)) / len(feat)
count += feat.shape[0]
print('{}/{}: avg feature norm: {:.3f}, average value: {:.3f}'.format(i_ + 1, num_images,
total_norm / count, total_sum / count))
return self.svm_targetNorm * 1.0 / (total_norm / count)
def _get_pos_counts(self):
counts = np.zeros((len(self.imdb.classes)), dtype=np.int)
roidb = self.imdb.roidb
for i in range(len(roidb)):
for j in range(1, self.imdb.num_classes):
I = np.where(roidb[i]['gt_classes'] == j)[0]
counts[j] += len(I)
for j in range(1, self.imdb.num_classes):
print('class {:s} has {:d} positives'.
format(self.imdb.classes[j], counts[j]))
return counts
def get_pos_examples(self):
counts = self._get_pos_counts()
for i in range(len(counts)):
self.trainers[i].alloc_pos(counts[i])
_t = Timer()
roidb = self.imdb.roidb
num_images = len(roidb)
for i in range(num_images):
#im = cv2.imread(self.imdb.image_path_at(i))
#if roidb[i]['flipped']:
# im = im[:, ::-1, :]
#im = self.imdb.image_path_at(i)
gt_inds = np.where(roidb[i]['gt_classes'] > 0)[0]
gt_boxes = roidb[i]['boxes'][gt_inds]
_t.tic()
scores, boxes, feat = self.im_detect(self.net, i, gt_boxes, self.feature_scale, gt_inds, boReturnClassifierScore = False)
_t.toc()
#feat = self.net.blobs[self.layer].data
for j in range(1, self.imdb.num_classes):
cls_inds = np.where(roidb[i]['gt_classes'][gt_inds] == j)[0]
if len(cls_inds) > 0:
cls_feat = feat[cls_inds, :]
self.trainers[j].append_pos(cls_feat)
if i % 50 == 0:
print 'get_pos_examples: {:d}/{:d} {:.3f}s' \
.format(i + 1, len(roidb), _t.average_time)
def initialize_net(self):
# Start all SVM parameters at zero
self.net.params['cls_score'][0].data[...] = 0
self.net.params['cls_score'][1].data[...] = 0
# Initialize SVMs in a smart way. Not doing this because its such
# a good initialization that we might not learn something close to
# the SVM solution.
# # subtract background weights and biases for the foreground classes
# w_bg = self.net.params['cls_score'][0].data[0, :]
# b_bg = self.net.params['cls_score'][1].data[0]
# self.net.params['cls_score'][0].data[1:, :] -= w_bg
# self.net.params['cls_score'][1].data[1:] -= b_bg
# # set the background weights and biases to 0 (where they shall remain)
# self.net.params['cls_score'][0].data[0, :] = 0
# self.net.params['cls_score'][1].data[0] = 0
def update_net(self, cls_ind, w, b):
self.net.params['cls_score'][0].data[cls_ind, :] = w
self.net.params['cls_score'][1].data[cls_ind] = b
def train_with_hard_negatives(self):
_t = Timer()
roidb = self.imdb.roidb
num_images = len(roidb)
for epoch in range(0,self.svm_nrEpochs):
# num_images = 100
for i in range(num_images):
print "*** EPOCH = %d, IMAGE = %d *** " % (epoch, i)
#im = cv2.imread(self.imdb.image_path_at(i))
#if roidb[i]['flipped']:
# im = im[:, ::-1, :]
#im = self.imdb.image_path_at(i)
_t.tic()
scores, boxes, feat = self.im_detect(self.net, i, roidb[i]['boxes'], self.feature_scale)
_t.toc()
#feat = self.net.blobs[self.layer].data
for j in range(1, self.imdb.num_classes):
hard_inds = \
np.where((scores[:, j] > self.hard_thresh) &
(roidb[i]['gt_overlaps'][:, j].toarray().ravel() <
self.neg_iou_thresh))[0]
if len(hard_inds) > 0:
hard_feat = feat[hard_inds, :].copy()
new_w_b = \
self.trainers[j].append_neg_and_retrain(feat=hard_feat)
if new_w_b is not None:
self.update_net(j, new_w_b[0], new_w_b[1])
np.savetxt(self.svmWeightsPath[:-4] + "_epoch" + str(epoch) + ".txt", self.net.params['cls_score'][0].data)
np.savetxt(self.svmBiasPath[:-4] + "_epoch" + str(epoch) + ".txt", self.net.params['cls_score'][1].data)
np.savetxt(self.svmFeatScalePath[:-4] + "_epoch" + str(epoch) + ".txt", [self.feature_scale])
print(('train_with_hard_negatives: '
'{:d}/{:d} {:.3f}s').format(i + 1, len(roidb),
_t.average_time))
def train(self):
# Initialize SVMs using
# a. w_i = fc8_w_i - fc8_w_0
# b. b_i = fc8_b_i - fc8_b_0
# c. Install SVMs into net
self.initialize_net()
# Pass over roidb to count num positives for each class
# a. Pre-allocate arrays for positive feature vectors
# Pass over roidb, computing features for positives only
self.get_pos_examples()
# Pass over roidb
# a. Compute cls_score with forward pass
# b. For each class
# i. Select hard negatives
# ii. Add them to cache
# c. For each class
# i. If SVM retrain criteria met, update SVM
# ii. Install new SVM into net
self.train_with_hard_negatives()
# One final SVM retraining for each class
# Install SVMs into net
for j in range(1, self.imdb.num_classes):
new_w_b = self.trainers[j].append_neg_and_retrain(force=True)
self.update_net(j, new_w_b[0], new_w_b[1])
#save svm
np.savetxt(self.svmWeightsPath, self.net.params['cls_score'][0].data)
np.savetxt(self.svmBiasPath, self.net.params['cls_score'][1].data)
np.savetxt(self.svmFeatScalePath, [self.feature_scale])
class SVMClassTrainer(object):
"""Manages post-hoc SVM training for a single object class."""
def __init__(self, cls, dim, feature_scale,
C, B, pos_weight, svm_penality, svm_loss, svm_rngSeed, svm_retrainLimit, svm_evictThreshold):
self.pos = np.zeros((0, dim), dtype=np.float32)
self.neg = np.zeros((0, dim), dtype=np.float32)
self.B = B
self.C = C
self.cls = cls
self.pos_weight = pos_weight
self.dim = dim
self.feature_scale = feature_scale
if type(pos_weight) == str: #e.g. pos_weight == 'auto'
class_weight = pos_weight
else:
class_weight = {1: pos_weight, -1: 1}
self.svm = svm.LinearSVC(C=C, class_weight=class_weight,
intercept_scaling=B, verbose=1,
penalty=svm_penality, loss=svm_loss,
random_state=svm_rngSeed, dual=True)
self.pos_cur = 0
self.num_neg_added = 0
self.retrain_limit = svm_retrainLimit
self.evict_thresh = svm_evictThreshold
self.loss_history = []
def alloc_pos(self, count):
self.pos_cur = 0
self.pos = np.zeros((count, self.dim), dtype=np.float32)
def append_pos(self, feat):
num = feat.shape[0]
self.pos[self.pos_cur:self.pos_cur + num, :] = feat
self.pos_cur += num
def train(self):
print('>>> Updating {} detector <<<'.format(self.cls))
num_pos = self.pos.shape[0]
num_neg = self.neg.shape[0]
print('Cache holds {} pos examples and {} neg examples'.
format(num_pos, num_neg))
X = np.vstack((self.pos, self.neg)) * self.feature_scale
y = np.hstack((np.ones(num_pos),
-np.ones(num_neg)))
self.svm.fit(X, y)
w = self.svm.coef_
b = self.svm.intercept_[0]
scores = self.svm.decision_function(X)
pos_scores = scores[:num_pos]
neg_scores = scores[num_pos:]
num_neg_wrong = sum(neg_scores > 0)
num_pos_wrong = sum(pos_scores < 0)
meanAcc = 0.5 * (num_pos - num_pos_wrong) / num_pos + 0.5*(num_neg - num_neg_wrong) / num_neg
if type(self.pos_weight) == str:
pos_loss = 0
else:
pos_loss = (self.C * self.pos_weight *
np.maximum(0, 1 - pos_scores).sum())
neg_loss = self.C * np.maximum(0, 1 + neg_scores).sum()
reg_loss = 0.5 * np.dot(w.ravel(), w.ravel()) + 0.5 * b ** 2
tot_loss = pos_loss + neg_loss + reg_loss
self.loss_history.append((meanAcc, num_pos_wrong, num_pos, num_neg_wrong, num_neg, tot_loss, pos_loss, neg_loss, reg_loss))
for i, losses in enumerate(self.loss_history):
print((' {:4d}: meanAcc={:.3f} -- pos wrong: {:5}/{:5}; neg wrong: {:5}/{:5}; '
' obj val: {:.3f} = {:.3f} (posUnscaled) + {:.3f} (neg) + {:.3f} (reg)').format(i, *losses))
# Sanity check
scores_ret = (
X * 1.0 / self.feature_scale).dot(w.T * self.feature_scale) + b
assert np.allclose(scores, scores_ret[:, 0], atol=1e-5), \
"Scores from returned model don't match decision function"
return ((w * self.feature_scale, b), pos_scores, neg_scores)
def append_neg_and_retrain(self, feat=None, force=False):
if feat is not None:
num = feat.shape[0]
self.neg = np.vstack((self.neg, feat))
self.num_neg_added += num
if self.num_neg_added > self.retrain_limit or force:
self.num_neg_added = 0
new_w_b, pos_scores, neg_scores = self.train()
# scores = np.dot(self.neg, new_w_b[0].T) + new_w_b[1]
# easy_inds = np.where(neg_scores < self.evict_thresh)[0]
print(' Pruning easy negatives')
print(' before pruning: #neg = ' + str(len(self.neg)))
not_easy_inds = np.where(neg_scores >= self.evict_thresh)[0]
if len(not_easy_inds) > 0:
self.neg = self.neg[not_easy_inds, :]
# self.neg = np.delete(self.neg, easy_inds)
print(' after pruning: #neg = ' + str(len(self.neg)))
print(' Cache holds {} pos examples and {} neg examples'.
format(self.pos.shape[0], self.neg.shape[0]))
print(' {} pos support vectors'.format((pos_scores <= 1).sum()))
print(' {} neg support vectors'.format((neg_scores >= -1).sum()))
return new_w_b
else:
return None

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,2 @@

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,204 @@
# --------------------------------------------------------
# Fast/er R-CNN
# Licensed under The MIT License [see LICENSE for details]
# Written by Bharath Hariharan
# --------------------------------------------------------
from __future__ import print_function
import xml.etree.ElementTree as ET
import os
import pickle as cp
import numpy as np
def parse_rec(filename):
""" Parse a PASCAL VOC xml file """
tree = ET.parse(filename)
objects = []
for obj in tree.findall('object'):
obj_struct = {}
obj_struct['name'] = obj.find('name').text
obj_struct['pose'] = obj.find('pose').text
obj_struct['truncated'] = int(obj.find('truncated').text)
obj_struct['difficult'] = int(obj.find('difficult').text)
bbox = obj.find('bndbox')
obj_struct['bbox'] = [int(bbox.find('xmin').text),
int(bbox.find('ymin').text),
int(bbox.find('xmax').text),
int(bbox.find('ymax').text)]
objects.append(obj_struct)
return objects
def voc_ap(rec, prec, use_07_metric=False):
""" ap = voc_ap(rec, prec, [use_07_metric])
Compute VOC AP given precision and recall.
If use_07_metric is true, uses the
VOC 07 11 point method (default:False).
"""
if use_07_metric:
# 11 point metric
ap = 0.
for t in np.arange(0., 1.1, 0.1):
if np.sum(rec >= t) == 0:
p = 0
else:
p = np.max(prec[rec >= t])
ap = ap + p / 11.
else:
# correct AP calculation
# first append sentinel values at the end
mrec = np.concatenate(([0.], rec, [1.]))
mpre = np.concatenate(([0.], prec, [0.]))
# compute the precision envelope
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
# to calculate area under PR curve, look for points
# where X axis (recall) changes value
i = np.where(mrec[1:] != mrec[:-1])[0]
# and sum (\Delta recall) * prec
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
return ap
def voc_eval(detpath,
annopath,
imagesetfile,
classname,
cachedir,
ovthresh=0.5,
use_07_metric=False):
"""rec, prec, ap = voc_eval(detpath,
annopath,
imagesetfile,
classname,
[ovthresh],
[use_07_metric])
Top level function that does the PASCAL VOC evaluation.
detpath: Path to detections
detpath.format(classname) should produce the detection results file.
annopath: Path to annotations
annopath.format(imagename) should be the xml annotations file.
imagesetfile: Text file containing the list of images, one image per line.
classname: Category name (duh)
cachedir: Directory for caching the annotations
[ovthresh]: Overlap threshold (default = 0.5)
[use_07_metric]: Whether to use VOC07's 11 point AP computation
(default False)
"""
# assumes detections are in detpath.format(classname)
# assumes annotations are in annopath.format(imagename)
# assumes imagesetfile is a text file with each line an image name
# cachedir caches the annotations in a pickle file
# first load gt
if cachedir:
if not os.path.isdir(cachedir):
os.mkdir(cachedir)
cachefile = os.path.join(cachedir, 'annots.pkl')
# read list of images
with open(imagesetfile, 'r') as f:
lines = f.readlines()
imagenames = [x.strip() for x in lines]
if not cachedir or not os.path.isfile(cachefile):
# load annots
recs = {}
for i, imagename in enumerate(imagenames):
recs[imagename] = parse_rec(annopath.format(imagename))
if i % 1000 == 0:
print ('Reading annotation for {:d}/{:d}'.format(
i + 1, len(imagenames)))
# save
if cachedir:
print ('Saving cached annotations to {:s}'.format(cachefile))
with open(cachefile, 'wb') as f:
cp.dump(recs, f)
else:
# load
with open(cachefile, 'rb') as f:
recs = cp.load(f)
# extract gt objects for this class
class_recs = {}
npos = 0
for imagename in imagenames:
R = [obj for obj in recs[imagename] if obj['name'] == classname]
bbox = np.array([x['bbox'] for x in R])
difficult = np.array([x['difficult'] for x in R]).astype(np.bool)
det = [False] * len(R)
npos = npos + sum(~difficult)
class_recs[imagename] = {'bbox': bbox,
'difficult': difficult,
'det': det}
# read dets
detfile = detpath.format(classname)
with open(detfile, 'r') as f:
lines = f.readlines()
splitlines = [x.strip().split(' ') for x in lines]
image_ids = [x[0] for x in splitlines]
confidence = np.array([float(x[1]) for x in splitlines])
BB = np.array([[float(z) for z in x[2:]] for x in splitlines])
# sort by confidence
sorted_ind = np.argsort(-confidence)
sorted_scores = np.sort(-confidence)
BB = BB[sorted_ind, :]
image_ids = [image_ids[x] for x in sorted_ind]
# go down dets and mark TPs and FPs
nd = len(image_ids)
tp = np.zeros(nd)
fp = np.zeros(nd)
for d in range(nd):
R = class_recs[image_ids[d]]
bb = BB[d, :].astype(float)
ovmax = -np.inf
BBGT = R['bbox'].astype(float)
if BBGT.size > 0:
# compute overlaps
# intersection
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
# union
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni
ovmax = np.max(overlaps)
jmax = np.argmax(overlaps)
if ovmax > ovthresh:
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
# compute precision recall
fp = np.cumsum(fp)
tp = np.cumsum(tp)
rec = tp / float(npos)
# avoid divide by zero in case the first detection matches a difficult
# ground truth
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
ap = voc_ap(rec, prec, use_07_metric)
return rec, prec, ap

Просмотреть файл

@ -10,8 +10,8 @@
# by the following layer (usually a set of pretrained fully connected layers).
# Classification error and evaluation criterion are computed for each ROI.
command = Train:Test
#command = Write
#makeMode = false
command = Train:WriteTest:WriteTrain
deviceId = "Auto"
precision = "float"
@ -22,22 +22,21 @@ rootDir = "."
dataDir = "$rootDir$/data/"
outputDir = "$rootDir$/Output"
modelPath = "$outputDir$/Fast-RCNN"
stderr = "$outputDir$/Fast-RCNN.log"
modelPath = "$outputDir$/Fast-RCNN.model"
#stderr = "$outputDir$/Fast-RCNN.log"
ImageH = 1000
ImageW = 1000
ImageC = 3
NumLabels = 21
NumLabels = 22
NumTrainROIs = 200
NumTestROIs = 2000
NumTrainROIs = 64
TrainROIDim = 256 # $NumTrainROIs$ * 4
TrainROILabelDim = 1344 # $NumTrainROIs$ * $NumLabels$
NumTestROIs = 200
TestROIDim = 800
TestROILabelDim = 4200
TrainROIDim = 800 # $NumTrainROIs$ * 4
TrainROILabelDim = 4400 # $NumTrainROIs$ * $NumLabels$
TestROIDim = 4000 # $NumTestROIs$ * 4
TestROILabelDim = 22000 # $NumTestROIs$ * $NumLabels$
# For training we load a pretrained AlexNet model (AlexNet.89) and clone three parts of it.
# For the first part (up to pool1) we keep the weights fixed. The middle part contains the
@ -52,22 +51,20 @@ Train = {
BrainScriptNetworkBuilder = {
imageShape = $ImageH$:$ImageW$:$ImageC$ # 1000:1000:3
labelShape = $NumLabels$:$NumTrainROIs$ # 21:64
ROIShape = 4:$NumTrainROIs$ # 4:64
labelShape = $NumLabels$:$NumTrainROIs$ # 21:200
ROIShape = 4:$NumTrainROIs$ # 4:200
network = BS.Network.Load ("AlexNet.89")
pool1 = BS.Network.CloneFunction(network.features, network.pool1, parameters = "constant")
convLayers = BS.Network.CloneFunction(network.pool1, network.conv5_y)
network = BS.Network.Load ("../../../../../PretrainedModels/AlexNet.model")
convLayers = BS.Network.CloneFunction(network.features, network.conv5_y, parameters = "constant")
fcLayers = BS.Network.CloneFunction(network.pool3, network.h2_d)
model (features, rois) = {
featNorm = features - 114
pool1Out = pool1 (featNorm)
conv5Out = convLayers (pool1Out)
roiOut = ROIPooling (conv5Out, rois, (6:6))
convOut = convLayers (featNorm)
roiOut = ROIPooling (convOut, rois, (6:6))
fcOut = fcLayers (roiOut)
W = ParameterTensor{(21:4096)}
b = ParameterTensor{21, init = 'zero'}
W = ParameterTensor{($NumLabels$:4096), init="glorotUniform"}
b = ParameterTensor{$NumLabels$, init = 'zero'}
z = W * fcOut + b
}.z
@ -89,13 +86,14 @@ Train = {
SGD = {
epochSize = 0
minibatchSize = 2
maxEpochs = 15
minibatchSize = 1
maxEpochs = 17
learningRatesPerSample = 0.00005
momentumAsTimeConstant = 0*5:1024 # was: 0.9 per MB
L2RegWeight = 0.0001
dropoutRate = 0.5
learningRatesPerSample=0.00001*10:0.000001*5:0.0000001
momentumPerMB=0.9
gradUpdateType=None
L2RegWeight=0.0005
dropoutRate=0.5
numMBsToShowResult = 50
}
@ -105,15 +103,15 @@ Train = {
verbosity = 2
deserializers = ({
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/tv2012pad.rois.txt"
file = train.rois.txt
input = { rois = { dim = $TrainROIDim$ ; format = "dense" } }
}:{
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/tv2012pad.roilabels.txt"
file = train.roilabels.txt
input = { roiLabels = { dim = $TrainROILabelDim$ ; format = "dense" } }
}:{
type = "ImageDeserializer" ; module = "ImageReader"
file = "$dataDir$/tv2012pad.txt"
file = train.txt
input = {
features = { transforms = (
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
@ -125,22 +123,86 @@ Train = {
}
}
# For testing we load the trained Fast-RCNN model and modify the input size,
# such that the network accepts 200 ROIs per image. To this end we load and
# clone the entire network and define new inputs with the desired size
# corresponding to 200 ROIs.
Test = {
action = "test"
# Write network output for entire test data set
WriteTest = {
action = "write"
minibatchSize = 1
# use this for write action
# action = "write"
# outputPath = "$OutputDir$/fastrcnnNetOutput"
outputPath=test
reader = {
randomize = false
verbosity = 2
deserializers = ({
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = test.rois.txt
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
}:{
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = test.roilabels.txt
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
}:{
type = "ImageDeserializer" ; module = "ImageReader"
file = test.txt
input = {
features = { transforms = (
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
{ type = "Transpose" }
)}
ignored = {labelDim = 1000}
}
})
}
}
# Write network output for entire train data set
WriteTrain = {
action = "write"
minibatchSize = 1
# outputPath = "$OutputDir$/fastrcnnNetOutput"
outputPath=train
reader = {
randomize = false
verbosity = 2
deserializers = ({
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = train.rois.txt
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
}:{
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = train.roilabels.txt
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
}:{
type = "ImageDeserializer" ; module = "ImageReader"
file = train.txt
input = {
features = { transforms = (
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
{ type = "Transpose" }
)}
ignored = {labelDim = 1000}
}
})
}
}
# For testing you can optionally load the trained Fast-RCNN model and modify the input size,
# such that the network accepts a different number of ROIs per image, e.g. 2000. To this end we load and
# clone the network and define new inputs with the desired size corresponding to 2000 ROIs.
WriteTestModify = {
action = "write"
minibatchSize = 1
# outputPath = "$OutputDir$/fastrcnnNetOutput"
outputPath=test
BrainScriptNetworkBuilder = {
imageShape = $ImageH$:$ImageW$:$ImageC$ # 1000:1000:3
labelShape = $NumLabels$:$NumTestROIs$ # 21:200
ROIShape = 4:$NumTestROIs$ # 4:200
labelShape = $NumLabels$:$NumTestROIs$ # 21:2000
ROIShape = 4:$NumTestROIs$ # 4:2000
# load network
network = BS.Network.Load ("$modelPath$")
@ -167,15 +229,15 @@ Test = {
verbosity = 2
deserializers = ({
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/test2007pad_all.rois.txt"
file = test.rois.txt
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
}:{
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/test2007pad_all.roilabels.txt"
file = test.roilabels.txt
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
}:{
type = "ImageDeserializer" ; module = "ImageReader"
file = "$dataDir$/test2007pad_all.txt"
file = test.txt
input = {
features = { transforms = (
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:

Просмотреть файл

@ -0,0 +1,303 @@
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
from __future__ import print_function
from builtins import range
import sys, os
from cntk_helpers import *
import scipy.sparse
import scipy.io as sio
import pickle as cp
import numpy as np
import fastRCNN
class imdb_data(fastRCNN.imdb):
def __init__(self, image_set, classes, maxNrRois, imgDir, roiDir, cacheDir, boAddGroundTruthRois):
fastRCNN.imdb.__init__(self, image_set + ".cache") #'data_' + image_set)
self._image_set = image_set
self._maxNrRois = maxNrRois
self._imgDir = imgDir
self._roiDir = roiDir
self._cacheDir = cacheDir #cache_path
self._imgSubdirs ={'train': ['positive', 'negative'], 'test': ['testImages']}
self._classes = classes
self._class_to_ind = dict(zip(self.classes, range(self.num_classes)))
self._image_ext = '.jpg'
self._image_index, self._image_subdirs = self._load_image_set_index()
self._roidb_handler = self.selective_search_roidb
self._boAddGroundTruthRois = boAddGroundTruthRois
#overwrite parent definition
@property
def cache_path(self):
return self._cacheDir
def image_path_at(self, i):
"""
Return the absolute path to image i in the image sequence.
"""
return self.image_path_from_index(self._image_subdirs[i], self._image_index[i])
def image_path_from_index(self, subdir, fname):
"""
Construct an image path from the image's "index" identifier.
"""
image_path = os.path.join(self._imgDir, subdir, fname)
assert os.path.exists(image_path), \
'Path does not exist: {}'.format(image_path)
return image_path
def _load_image_set_index(self):
"""
Compile list of image indices and the subdirectories they are in.
"""
image_index = []
image_subdirs = []
for subdir in self._imgSubdirs[self._image_set]:
imgFilenames = getFilesInDirectory(self._imgDir + subdir, self._image_ext)
image_index += imgFilenames
image_subdirs += [subdir] * len(imgFilenames)
return image_index, image_subdirs
def gt_roidb(self):
"""
Return the database of ground-truth regions of interest.
This function loads/saves from/to a cache file to speed up future calls.
"""
cache_file = os.path.join(self.cache_path, self.name + '_gt_roidb.pkl')
if os.path.exists(cache_file):
with open(cache_file, 'rb') as fid:
roidb = cp.load(fid)
print ('{} gt roidb loaded from {}'.format(self.name, cache_file))
return roidb
gt_roidb = [self._load_annotation(i) for i in range(self.num_images)]
with open(cache_file, 'wb') as fid:
cp.dump(gt_roidb, fid, cp.HIGHEST_PROTOCOL)
print ('wrote gt roidb to {}'.format(cache_file))
return gt_roidb
def selective_search_roidb(self):
"""
Return the database of selective search regions of interest.
Ground-truth ROIs are also included.
This function loads/saves from/to a cache file to speed up future calls.
"""
cache_file = os.path.join(self.cache_path,
self.name + '_selective_search_roidb.pkl')
if os.path.exists(cache_file):
with open(cache_file, 'rb') as fid:
if sys.version_info[0] < 3:
roidb = cp.load(fid)
else:
roidb = cp.load(fid, encoding='latin1')
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
return roidb
gt_roidb = self.gt_roidb()
ss_roidb = self._load_selective_search_roidb(gt_roidb)
#add ground truth ROIs
if self._boAddGroundTruthRois:
roidb = self.merge_roidbs(gt_roidb, ss_roidb)
else:
roidb = ss_roidb
#Keep max of e.g. 2000 rois
if self._maxNrRois and self._maxNrRois > 0:
print ("Only keeping the first %d ROIs.." % self._maxNrRois)
for i in range(self.num_images):
gt_overlaps = roidb[i]['gt_overlaps']
gt_overlaps = gt_overlaps.todense()[:self._maxNrRois]
gt_overlaps = scipy.sparse.csr_matrix(gt_overlaps)
roidb[i]['gt_overlaps'] = gt_overlaps
roidb[i]['boxes'] = roidb[i]['boxes'][:self._maxNrRois,:]
roidb[i]['gt_classes'] = roidb[i]['gt_classes'][:self._maxNrRois]
with open(cache_file, 'wb') as fid:
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
print ('wrote ss roidb to {}'.format(cache_file))
return roidb
def _load_selective_search_roidb(self, gt_roidb):
# box_list = nrImages x nrBoxes x 4
box_list = []
for imgFilename, subdir in zip(self._image_index, self._image_subdirs):
roiPath = "{}/{}/{}.roi.txt".format(self._roiDir, subdir, imgFilename[:-4])
assert os.path.exists(roiPath), "Error: rois file not found: " + roiPath
rois = np.loadtxt(roiPath, np.int32)
box_list.append(rois)
return self.create_roidb_from_box_list(box_list, gt_roidb)
def _load_annotation(self, imgIndex):
"""
Load image and bounding boxes info from human annotations.
"""
#negative images do not have any ground truth annotations
if self._image_subdirs[imgIndex].lower() == "negative":
return None
imgPath = self.image_path_at(imgIndex)
bboxesPaths = imgPath[:-4] + ".bboxes.tsv"
labelsPaths = imgPath[:-4] + ".bboxes.labels.tsv"
assert os.path.exists(bboxesPaths), "Error: ground truth bounding boxes file not found: " + bboxesPaths
assert os.path.exists(labelsPaths), "Error: ground truth labels file not found: " + bboxesPaths
bboxes = np.loadtxt(bboxesPaths, np.float32)
labels = readFile(labelsPaths)
#remove boxes marked as 'undecided' or 'exclude'
indicesToKeep = find(labels, lambda x: x!='EXCLUDE' and x!='UNDECIDED')
bboxes = [bboxes[i] for i in indicesToKeep]
labels = [labels[i] for i in indicesToKeep]
# Load object bounding boxes into a data frame.
num_objs = len(bboxes)
boxes = np.zeros((num_objs,4), dtype=np.uint16)
gt_classes = np.zeros(num_objs, dtype=np.int32)
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
for bboxIndex,(bbox,label) in enumerate(zip(bboxes,labels)):
cls = self._class_to_ind[label.decode('utf-8')]
boxes[bboxIndex, :] = bbox
gt_classes[bboxIndex] = cls
overlaps[bboxIndex, cls] = 1.0
overlaps = scipy.sparse.csr_matrix(overlaps)
return {'boxes' : boxes,
'gt_classes': gt_classes,
'gt_overlaps' : overlaps,
'flipped' : False}
# main call to compute per-calass average precision
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coords+score
# (see also test_net() in fastRCNN\test.py)
def evaluate_detections(self, all_boxes, output_dir, use_07_metric=False):
aps = []
for classIndex, className in enumerate(self._classes):
if className != '__background__':
rec, prec, ap = self._evaluate_detections(classIndex, all_boxes, use_07_metric = use_07_metric)
aps += [ap]
print('AP for {:>15} = {:.4f}'.format(className, ap))
print('Mean AP = {:.4f}'.format(np.nanmean(aps)))
def _evaluate_detections(self, classIndex, all_boxes, overlapThreshold = 0.5, use_07_metric = False):
"""
Top level function that does the PASCAL VOC evaluation.
[overlapThreshold]: Overlap threshold (default = 0.5)
[use_07_metric]: Whether to use VOC07's 11 point AP computation (default False)
"""
assert (len(all_boxes) == self.num_classes)
assert (len(all_boxes[0]) == self.num_images)
# load ground truth annotations for this class
gtInfos = []
for imgIndex in range(self.num_images):
imgPath = self.image_path_at(imgIndex)
imgSubir = os.path.normpath(imgPath).split(os.path.sep)[-2]
if imgSubir != 'negative':
gtBoxes, gtLabels = readGtAnnotation(imgPath)
gtBoxes = [box for box, label in zip(gtBoxes, gtLabels) if label.decode('utf-8') == self.classes[classIndex]]
else:
gtBoxes = []
gtInfos.append({'bbox': np.array(gtBoxes),
'difficult': [False] * len(gtBoxes),
'det': [False] * len(gtBoxes)})
# parse detections for this class
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coords+score
detBboxes = []
detImgIndices = []
detConfidences = []
for imgIndex in range(self.num_images):
dets = all_boxes[classIndex][imgIndex]
if dets != []:
for k in range(dets.shape[0]):
detImgIndices.append(imgIndex)
detConfidences.append(dets[k, -1])
# the VOCdevkit expects 1-based indices
detBboxes.append([dets[k, 0] + 1, dets[k, 1] + 1, dets[k, 2] + 1, dets[k, 3] + 1])
detBboxes = np.array(detBboxes)
detConfidences = np.array(detConfidences)
# compute precision / recall / ap
rec, prec, ap = self._voc_computePrecisionRecallAp(
class_recs=gtInfos,
confidence=detConfidences,
image_ids=detImgIndices,
BB=detBboxes,
ovthresh=overlapThreshold,
use_07_metric=use_07_metric)
return rec, prec, ap
#########################################################################
# Python evaluation functions (copied/refactored from faster-RCNN)
##########################################################################
def _voc_computePrecisionRecallAp(self, class_recs, confidence, image_ids, BB, ovthresh=0.5, use_07_metric=False):
# sort by confidence
sorted_ind = np.argsort(-confidence)
BB = BB[sorted_ind, :]
image_ids = [image_ids[x] for x in sorted_ind]
# go down dets and mark TPs and FPs
nd = len(image_ids)
tp = np.zeros(nd)
fp = np.zeros(nd)
for d in range(nd):
R = class_recs[image_ids[d]]
bb = BB[d, :].astype(float)
ovmax = -np.inf
BBGT = R['bbox'].astype(float)
if BBGT.size > 0:
# compute overlaps
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
# union
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni
ovmax = np.max(overlaps)
jmax = np.argmax(overlaps)
if ovmax > ovthresh:
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
# compute precision recall
npos = sum([len(cr['bbox']) for cr in class_recs])
fp = np.cumsum(fp)
tp = np.cumsum(tp)
rec = tp / float(npos)
# avoid divide by zero in case the first detection matches a difficult
# ground truth
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
ap = computeAveragePrecision(rec, prec, use_07_metric)
return rec, prec, ap

Просмотреть файл

@ -0,0 +1,40 @@
from __future__ import print_function
import os
import zipfile
import os
import os.path
try:
from urllib.request import urlretrieve
except ImportError:
from urllib import urlretrieve
if __name__ == "__main__":
directory = "./../../DataSets"
if not os.path.exists(directory + "/Grocery"):
filename = directory + "/Grocery.zip"
if not os.path.exists(filename):
url = "https://www.cntk.ai/DataSets/Grocery/Grocery.zip"
print ('Downloading data from ' + url + '...')
urlretrieve(url, filename)
try:
print ('Extracting ' + filename + '...')
with zipfile.ZipFile(filename) as myzip:
myzip.extractall(directory)
finally:
os.remove(filename)
print ('Done.')
else:
print ('Data already available at ' + directory)
directory = "./../../PretrainedModels"
if not os.path.exists(directory):
os.makedirs(directory)
filename = directory + "/AlexNet.model"
if not os.path.exists(filename):
url = "https://www.cntk.ai/Models/AlexNet/AlexNet.model"
print ('Downloading model from ' + url + ', may take a while...')
urlretrieve(url, filename)
print ('Saved model as ' + filename)
else:
print ('CNTK model already available at ' + filename)

Просмотреть файл

@ -0,0 +1,9 @@
future
Pillow
xmltodict
wheel
matplotlib
EasyDict
numpy
scikit-learn
scipy

Просмотреть файл

@ -0,0 +1,20 @@
# Selective Search
This code is a revision of the selective search implementation at:
https://github.com/AlpacaDB/selectivesearch, such that the code can work under Python 3 environment.
This file is based on or incorporates material from the projects listed below (Third Party OSS). The original copyright notice and the license under which Microsoft received such Third Party OSS, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party OSS to you under the licensing terms for the Microsoft product or service. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise.
`alpacadb-selectivesearch`
Copyright (c) 2015-2016 AlpacaDB
Copyright (c) 2016 Oussama ENNAFII
Provided for Informational Purposes Only
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Просмотреть файл

@ -0,0 +1,2 @@
from .selectivesearch import selective_search

Просмотреть файл

@ -0,0 +1,342 @@
# -*- coding: utf-8 -*-
import sys
from past.builtins import cmp
import skimage.io
import skimage.feature
import skimage.color
import skimage.transform
import skimage.util
import skimage.segmentation
import numpy
# "Selective Search for Object Recognition" by J.R.R. Uijlings et al.
#
# - Modified version with LBP extractor for texture vectorization
def _generate_segments(im_orig, scale, sigma, min_size):
"""
segment smallest regions by the algorithm of Felzenswalb and
Huttenlocher
"""
# open the Image
im_mask = skimage.segmentation.felzenszwalb(
skimage.util.img_as_float(im_orig), scale=scale, sigma=sigma,
min_size=min_size)
# merge mask channel to the image as a 4th channel
im_orig = numpy.append(
im_orig, numpy.zeros(im_orig.shape[:2])[:, :, numpy.newaxis], axis=2)
im_orig[:, :, 3] = im_mask
return im_orig
def _sim_colour(r1, r2):
"""
calculate the sum of histogram intersection of colour
"""
return sum([min(a, b) for a, b in zip(r1["hist_c"], r2["hist_c"])])
def _sim_texture(r1, r2):
"""
calculate the sum of histogram intersection of texture
"""
return sum([min(a, b) for a, b in zip(r1["hist_t"], r2["hist_t"])])
def _sim_size(r1, r2, imsize):
"""
calculate the size similarity over the image
"""
return 1.0 - (r1["size"] + r2["size"]) / imsize
def _sim_fill(r1, r2, imsize):
"""
calculate the fill similarity over the image
"""
bbsize = (
(max(r1["max_x"], r2["max_x"]) - min(r1["min_x"], r2["min_x"]))
* (max(r1["max_y"], r2["max_y"]) - min(r1["min_y"], r2["min_y"]))
)
return 1.0 - (bbsize - r1["size"] - r2["size"]) / imsize
def _calc_sim(r1, r2, imsize):
return (_sim_colour(r1, r2) + _sim_texture(r1, r2)
+ _sim_size(r1, r2, imsize) + _sim_fill(r1, r2, imsize))
def _calc_colour_hist(img):
"""
calculate colour histogram for each region
the size of output histogram will be BINS * COLOUR_CHANNELS(3)
number of bins is 25 as same as [uijlings_ijcv2013_draft.pdf]
extract HSV
"""
BINS = 25
hist = numpy.array([])
for colour_channel in (0, 1, 2):
# extracting one colour channel
c = img[:, colour_channel]
# calculate histogram for each colour and join to the result
hist = numpy.concatenate(
[hist] + [numpy.histogram(c, BINS, (0.0, 255.0))[0]])
# L1 normalize
hist = hist / len(img)
return hist
def _calc_texture_gradient(img):
"""
calculate texture gradient for entire image
The original SelectiveSearch algorithm proposed Gaussian derivative
for 8 orientations, but we use LBP instead.
output will be [height(*)][width(*)]
"""
ret = numpy.zeros((img.shape[0], img.shape[1], img.shape[2]))
for colour_channel in (0, 1, 2):
ret[:, :, colour_channel] = skimage.feature.local_binary_pattern(
img[:, :, colour_channel], 8, 1.0)
return ret
def _calc_texture_hist(img):
"""
calculate texture histogram for each region
calculate the histogram of gradient for each colours
the size of output histogram will be
BINS * ORIENTATIONS * COLOUR_CHANNELS(3)
"""
BINS = 10
hist = numpy.array([])
for colour_channel in (0, 1, 2):
# mask by the colour channel
fd = img[:, colour_channel]
# calculate histogram for each orientation and concatenate them all
# and join to the result
hist = numpy.concatenate(
[hist] + [numpy.histogram(fd, BINS, (0.0, 1.0))[0]])
# L1 Normalize
hist = hist / len(img)
return hist
def _extract_regions(img):
R = {}
# get hsv image
hsv = skimage.color.rgb2hsv(img[:, :, :3])
# pass 1: count pixel positions
for y, i in enumerate(img):
for x, (r, g, b, l) in enumerate(i):
# initialize a new region
if l not in R:
R[l] = {
"min_x": 0xffff, "min_y": 0xffff,
"max_x": 0, "max_y": 0, "labels": [l]}
# bounding box
if R[l]["min_x"] > x:
R[l]["min_x"] = x
if R[l]["min_y"] > y:
R[l]["min_y"] = y
if R[l]["max_x"] < x:
R[l]["max_x"] = x
if R[l]["max_y"] < y:
R[l]["max_y"] = y
# pass 2: calculate texture gradient
tex_grad = _calc_texture_gradient(img)
# pass 3: calculate colour histogram of each region
for k, v in R.items():
# colour histogram
masked_pixels = hsv[:, :, :][img[:, :, 3] == k]
R[k]["size"] = len(masked_pixels / 4)
R[k]["hist_c"] = _calc_colour_hist(masked_pixels)
# texture histogram
R[k]["hist_t"] = _calc_texture_hist(tex_grad[:, :][img[:, :, 3] == k])
return R
def _extract_neighbours(regions):
def intersect(a, b):
if (a["min_x"] < b["min_x"] < a["max_x"]
and a["min_y"] < b["min_y"] < a["max_y"]) or (
a["min_x"] < b["max_x"] < a["max_x"]
and a["min_y"] < b["max_y"] < a["max_y"]) or (
a["min_x"] < b["min_x"] < a["max_x"]
and a["min_y"] < b["max_y"] < a["max_y"]) or (
a["min_x"] < b["max_x"] < a["max_x"]
and a["min_y"] < b["min_y"] < a["max_y"]):
return True
return False
R = list(regions.items())
neighbours = []
for cur, a in enumerate(R[:-1]):
for b in R[cur + 1:]:
if intersect(a[1], b[1]):
neighbours.append((a, b))
return neighbours
def _merge_regions(r1, r2):
new_size = r1["size"] + r2["size"]
rt = {
"min_x": min(r1["min_x"], r2["min_x"]),
"min_y": min(r1["min_y"], r2["min_y"]),
"max_x": max(r1["max_x"], r2["max_x"]),
"max_y": max(r1["max_y"], r2["max_y"]),
"size": new_size,
"hist_c": (
r1["hist_c"] * r1["size"] + r2["hist_c"] * r2["size"]) / new_size,
"hist_t": (
r1["hist_t"] * r1["size"] + r2["hist_t"] * r2["size"]) / new_size,
"labels": r1["labels"] + r2["labels"]
}
return rt
def mycmp(x, y):
return cmp(x[1],y[1])
def cmp_to_key(mycmp):
'Convert a cmp= function into a key= function'
class K(object):
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
def selective_search(
im_orig, scale=1.0, sigma=0.8, min_size=50):
'''Selective Search
Parameters
----------
im_orig : ndarray
Input image
scale : int
Free parameter. Higher means larger clusters in felzenszwalb segmentation.
sigma : float
Width of Gaussian kernel for felzenszwalb segmentation.
min_size : int
Minimum component size for felzenszwalb segmentation.
Returns
-------
img : ndarray
image with region label
region label is stored in the 4th value of each pixel [r,g,b,(region)]
regions : array of dict
[
{
'rect': (left, top, right, bottom),
'labels': [...]
},
...
]
'''
assert im_orig.shape[2] == 3, "3ch image is expected"
# load image and get smallest regions
# region label is stored in the 4th value of each pixel [r,g,b,(region)]
img = _generate_segments(im_orig, scale, sigma, min_size)
if img is None:
return None, {}
imsize = img.shape[0] * img.shape[1]
R = _extract_regions(img)
# extract neighbouring information
neighbours = list(_extract_neighbours(R))
# calculate initial similarities
S = {}
for (ai, ar), (bi, br) in neighbours:
S[(ai, bi)] = _calc_sim(ar, br, imsize)
# hierarchal search
while S != {}:
# get highest similarity
if sys.version_info[0] < 3:
i, j = sorted(S.items(), cmp=mycmp)[-1][0]
else:
i, j = sorted(S.items(), key=cmp_to_key(mycmp))[-1][0]
# merge corresponding regions
t = max(R.keys()) + 1.0
R[t] = _merge_regions(R[i], R[j])
# mark similarities for regions to be removed
key_to_delete = []
for k, v in S.items():
if (i in k) or (j in k):
key_to_delete.append(k)
# remove old similarities of related regions
for k in key_to_delete:
del S[k]
# calculate similarity set with the new region
for k in filter(lambda a: a != (i, j), key_to_delete):
n = k[1] if k[0] in (i, j) else k[0]
S[(t, n)] = _calc_sim(R[t], R[n], imsize)
regions = []
for k, r in R.items():
regions.append({
'rect': (
r['min_x'], r['min_y'],
r['max_x'] - r['min_x'], r['max_y'] - r['min_y']),
'size': r['size'],
'labels': r['labels']
})
return img, regions

Просмотреть файл

@ -8,7 +8,7 @@ command = TrainConvNet:Write:Test
makeMode = false ; traceLevel = 1 ; deviceId = "auto"
rootDir = ".." ; dataDir = "$rootDir$/DataSets/CIFAR10" ;
rootDir = ".." ; dataDir = "$rootDir$/DataSets/CIFAR-10" ;
outputDir = "Output" ; modelDir = "$outputDir$/Models"
modelPath = "$ModelDir$/RegrSimple_CIFAR10.cmf"

Просмотреть файл

@ -38,12 +38,12 @@ or prefix the call to the cntk executable with the corresponding folder.
### Run
Run the example from the Speech/Data folder using:
Run the example from the Speech/Data folder using (or use the LSTM variant):
`cntk configFile=../Config/FeedForward.cntk`
or run from any folder and specify the Data folder as the `currentDirectory`,
e.g. running from the Speech folder using:
e.g. running from the Speech folder using (or use the LSTM variant):
`cntk configFile=Config/FeedForward.cntk currentDirectory=Data`

Просмотреть файл

@ -1,6 +1,6 @@
# Build Language Understanding Models with CNTK
This example demonstrates how to use build language understanding model with CNTK using ATIS data set. This example is similar to
This example demonstrates how to use build language understanding model with CNTK using ATIS data set. The recipeice in this example are in BrainScript. For Python click [here](https://github.com/Microsoft/CNTK/blob/master/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py). This example is similar to
[SLU example](https://github.com/Microsoft/CNTK/tree/master/Examples/Text/Miscellaneous/SLU). They are different in that
- CNTKTextFormatReader is used here, instead of LUSequenceReader
- With CNTKTextFormatReader, the input format is much more flexible. In the example setting, sparse contextual feature vectors are explored

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше