├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── code
├── Makefile
├── include
│ └── caffe
│ │ ├── common_layers.hpp
│ │ └── loss_layers.hpp
└── src
│ └── caffe
│ ├── layers
│ ├── super_category_fm_layer.cpp
│ ├── super_category_fm_layer.cu
│ ├── super_category_fm_post_layer.cpp
│ └── super_category_layer.cpp
│ └── proto
│ └── caffe.proto
├── example
├── solver.prototxt
├── super_category.prototxt
└── train_val.prototxt
├── miscellaneous
└── headline.png
└── run.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | cifar100
2 | example/*.log
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "caffe"]
2 | path = caffe
3 | url = https://github.com/BVLC/caffe.git
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 GOO WONJOON
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Taxonomy-Regularized Semantic Deep Convolutional Neural Networks
2 |
3 | + Wonjoon Goo(SNU, now at UT Austin), Juyong Kim(SNU), Gunhee Kim(SNU), and Sung Ju Hwang(UNIST)
4 |
5 | 
6 |
7 | This project hosts the code for our **ECCV 2016** paper. [[pdf](http://vision.snu.ac.kr/wordpress/wp-content/uploads/2016/08/eccv16_taxonomy.pdf)]
8 |
9 | We propose a novel convolutional neural network architecture
10 | that abstracts and differentiates the categories based on a given class
11 | hierarchy. We exploit grouped and discriminative information provided
12 | by the taxonomy, by focusing on the general and specific components
13 | that comprise each category, through the min- and difference-pooling
14 | operations. Without using any additional parameters or substantial increase
15 | in time complexity, our model is able to learn the features that are
16 | discriminative for classifying often confusing sub-classes belonging to the
17 | same superclass, and thus improve the overall classification performance.
18 |
19 |
20 | ##Reference
21 |
22 | If you use this code as part of any published research, please refer the following paper.
23 |
24 | ```
25 | @inproceedings{taxonomy:2016:ECCV,
26 | author = {Wonjoon Goo, Juyong Kim, Gunhee Kim and Sung Ju Hwang},
27 | title = "{Taxonomy-Regularized Semantic Deep Convolutional Neural Networks}"
28 | booktitle = {ECCV},
29 | year = 2016
30 | }
31 | ```
32 |
33 | ## Running Code
34 |
35 | We implemented a new type of regularize layer as described in the paper based on BVLC caffe deep learning library.
36 | It would be better to go through tutorials of [Caffe](https://github.com/BVLC/caffe]) deep learning library before running our code. Most of error you might encounter will be the problem on running caffe, not ours.
37 |
38 | ### Get our code
39 | ```
40 | git clone --recursive https://github.com/hiwonjoon/eccv16-taxonomy.git taxonomy
41 | ```
42 |
43 | If you look at directory, there will be three important sub-directories; caffe, code, example.
44 |
45 | 'caffe' directory is the code of BVLC caffe on specific branch "dd6e8e6" commit, which was our working branch. The directory added in the form of git submodule, so if you want to use latest caffe version, then try it :)
46 |
47 | 'code' directory contains our implementations(super category label layer, etc.)
48 |
49 | 'example' directory contains the sample prototxt files that is required for training and validation.
50 |
51 |
52 | ### Apply & Build caffe
53 |
54 | First, copy our implementation into original caffe code.
55 | ```
56 | $copy -r ./code/* ./caffe/
57 | ```
58 | Then, build caffe as same as original caffe; Config by modifying Makefile.config and `make all`.
59 |
60 | ### Run examples
61 |
62 | Before you start and acquire the same experiment result of ours, you need preprocessed Cifar 100 dataset as described on the paper. We assumed that the dataset is located on the top directory(cloned directory), named 'cifar100'. Please change lmdb file locations which are specified on train_val.prototxt
63 |
64 | You also need taxonomy tree in the form of prototxt. The sample taxonomy tree for Cifar 100 dataset is given on the directory.
65 |
66 | If you execute run.sh script, then you can start training, or you can directly start it from a shell. The script provided is only for less typing :) And, with provided trained model and small modification of scripts and prototxt, you can reproduce our experiment results.
67 |
68 | ```
69 | ./run.sh
70 | ```
71 |
72 | ### Try it yourself!
73 |
74 | You can use our code for your own datasets or taxonmy trees with minor modification of example prototxt files.
75 | If you find any problems, please contact me. Enjoy :)
76 |
77 |
78 | ## Acknowledgement
79 |
80 | This work was supported by Samsung Research Funding Center of Samsung Electronics under Project Number SRFC-IT1502-03.
81 |
82 |
83 | ## Authors
84 |
85 | [Wonjoon Goo](http://vision.snu.ac.kr/wonjoongoo/)1, [Juyong Kim](http://juyongkim.com/)1, [Gunhee Kim](http://www.cs.cmu.edu/~gunhee/)1, and [Sung Ju Hwang](http://www.sungjuhwang.com/)2
86 |
87 | 1[Vision and Learning Lab](http://vision.snu.ac.kr/) @ Computer Science and Engineering, Seoul National University, Seoul, Korea
88 |
89 | 2[MLVR Lab](http://ml.unist.ac.kr/) @ School of Electrical and Computer Engineering, UNIST, Ulsan, South Korea
90 |
91 |
92 | ## License
93 | MIT license
94 |
--------------------------------------------------------------------------------
/code/Makefile:
--------------------------------------------------------------------------------
1 | PROJECT := caffe
2 |
3 | CONFIG_FILE := Makefile.config
4 | # Explicitly check for the config file, otherwise make -k will proceed anyway.
5 | ifeq ($(wildcard $(CONFIG_FILE)),)
6 | $(error $(CONFIG_FILE) not found. See $(CONFIG_FILE).example.)
7 | endif
8 | include $(CONFIG_FILE)
9 |
10 | BUILD_DIR_LINK := $(BUILD_DIR)
11 | ifeq ($(RELEASE_BUILD_DIR),)
12 | RELEASE_BUILD_DIR := .$(BUILD_DIR)_release
13 | endif
14 | ifeq ($(DEBUG_BUILD_DIR),)
15 | DEBUG_BUILD_DIR := .$(BUILD_DIR)_debug
16 | endif
17 |
18 | DEBUG ?= 0
19 | ifeq ($(DEBUG), 1)
20 | BUILD_DIR := $(DEBUG_BUILD_DIR)
21 | OTHER_BUILD_DIR := $(RELEASE_BUILD_DIR)
22 | else
23 | BUILD_DIR := $(RELEASE_BUILD_DIR)
24 | OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR)
25 | endif
26 |
27 | # All of the directories containing code.
28 | SRC_DIRS := $(shell find * -type d -exec bash -c "find {} -maxdepth 1 \
29 | \( -name '*.cpp' -o -name '*.proto' \) | grep -q ." \; -print)
30 |
31 | # The target shared library name
32 | LIB_BUILD_DIR := $(BUILD_DIR)/lib
33 | STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a
34 | DYNAMIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so
35 |
36 | ##############################
37 | # Get all source files
38 | ##############################
39 | # CXX_SRCS are the source files excluding the test ones.
40 | CXX_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cpp" -name "*.cpp")
41 | # CU_SRCS are the cuda source files
42 | CU_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cu" -name "*.cu")
43 | # TEST_SRCS are the test source files
44 | TEST_MAIN_SRC := src/$(PROJECT)/test/test_caffe_main.cpp
45 | TEST_SRCS := $(shell find src/$(PROJECT) -name "test_*.cpp")
46 | TEST_SRCS := $(filter-out $(TEST_MAIN_SRC), $(TEST_SRCS))
47 | TEST_CU_SRCS := $(shell find src/$(PROJECT) -name "test_*.cu")
48 | GTEST_SRC := src/gtest/gtest-all.cpp
49 | # TOOL_SRCS are the source files for the tool binaries
50 | TOOL_SRCS := $(shell find tools -name "*.cpp")
51 | # EXAMPLE_SRCS are the source files for the example binaries
52 | EXAMPLE_SRCS := $(shell find examples -name "*.cpp")
53 | # BUILD_INCLUDE_DIR contains any generated header files we want to include.
54 | BUILD_INCLUDE_DIR := $(BUILD_DIR)/src
55 | # PROTO_SRCS are the protocol buffer definitions
56 | PROTO_SRC_DIR := src/$(PROJECT)/proto
57 | PROTO_SRCS := $(wildcard $(PROTO_SRC_DIR)/*.proto)
58 | # PROTO_BUILD_DIR will contain the .cc and obj files generated from
59 | # PROTO_SRCS; PROTO_BUILD_INCLUDE_DIR will contain the .h header files
60 | PROTO_BUILD_DIR := $(BUILD_DIR)/$(PROTO_SRC_DIR)
61 | PROTO_BUILD_INCLUDE_DIR := $(BUILD_INCLUDE_DIR)/$(PROJECT)/proto
62 | # NONGEN_CXX_SRCS includes all source/header files except those generated
63 | # automatically (e.g., by proto).
64 | NONGEN_CXX_SRCS := $(shell find \
65 | src/$(PROJECT) \
66 | include/$(PROJECT) \
67 | python/$(PROJECT) \
68 | matlab/+$(PROJECT)/private \
69 | examples \
70 | tools \
71 | -name "*.cpp" -or -name "*.hpp" -or -name "*.cu" -or -name "*.cuh")
72 | LINT_SCRIPT := scripts/cpp_lint.py
73 | LINT_OUTPUT_DIR := $(BUILD_DIR)/.lint
74 | LINT_EXT := lint.txt
75 | LINT_OUTPUTS := $(addsuffix .$(LINT_EXT), $(addprefix $(LINT_OUTPUT_DIR)/, $(NONGEN_CXX_SRCS)))
76 | EMPTY_LINT_REPORT := $(BUILD_DIR)/.$(LINT_EXT)
77 | NONEMPTY_LINT_REPORT := $(BUILD_DIR)/$(LINT_EXT)
78 | # PY$(PROJECT)_SRC is the python wrapper for $(PROJECT)
79 | PY$(PROJECT)_SRC := python/$(PROJECT)/_$(PROJECT).cpp
80 | PY$(PROJECT)_SO := python/$(PROJECT)/_$(PROJECT).so
81 | PY$(PROJECT)_HXX := include/$(PROJECT)/python_layer.hpp
82 | # MAT$(PROJECT)_SRC is the mex entrance point of matlab package for $(PROJECT)
83 | MAT$(PROJECT)_SRC := matlab/+$(PROJECT)/private/$(PROJECT)_.cpp
84 | ifneq ($(MATLAB_DIR),)
85 | MAT_SO_EXT := $(shell $(MATLAB_DIR)/bin/mexext)
86 | endif
87 | MAT$(PROJECT)_SO := matlab/+$(PROJECT)/private/$(PROJECT)_.$(MAT_SO_EXT)
88 |
89 | ##############################
90 | # Derive generated files
91 | ##############################
92 | # The generated files for protocol buffers
93 | PROTO_GEN_HEADER_SRCS := $(addprefix $(PROTO_BUILD_DIR)/, \
94 | $(notdir ${PROTO_SRCS:.proto=.pb.h}))
95 | PROTO_GEN_HEADER := $(addprefix $(PROTO_BUILD_INCLUDE_DIR)/, \
96 | $(notdir ${PROTO_SRCS:.proto=.pb.h}))
97 | PROTO_GEN_CC := $(addprefix $(BUILD_DIR)/, ${PROTO_SRCS:.proto=.pb.cc})
98 | PY_PROTO_BUILD_DIR := python/$(PROJECT)/proto
99 | PY_PROTO_INIT := python/$(PROJECT)/proto/__init__.py
100 | PROTO_GEN_PY := $(foreach file,${PROTO_SRCS:.proto=_pb2.py}, \
101 | $(PY_PROTO_BUILD_DIR)/$(notdir $(file)))
102 | # The objects corresponding to the source files
103 | # These objects will be linked into the final shared library, so we
104 | # exclude the tool, example, and test objects.
105 | CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o})
106 | CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o})
107 | PROTO_OBJS := ${PROTO_GEN_CC:.cc=.o}
108 | OBJS := $(PROTO_OBJS) $(CXX_OBJS) $(CU_OBJS)
109 | # tool, example, and test objects
110 | TOOL_OBJS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o})
111 | TOOL_BUILD_DIR := $(BUILD_DIR)/tools
112 | TEST_CXX_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT)/test
113 | TEST_CU_BUILD_DIR := $(BUILD_DIR)/cuda/src/$(PROJECT)/test
114 | TEST_CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o})
115 | TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o})
116 | TEST_OBJS := $(TEST_CXX_OBJS) $(TEST_CU_OBJS)
117 | GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o})
118 | EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o})
119 | # Output files for automatic dependency generation
120 | DEPS := ${CXX_OBJS:.o=.d} ${CU_OBJS:.o=.d} ${TEST_CXX_OBJS:.o=.d} \
121 | ${TEST_CU_OBJS:.o=.d} $(BUILD_DIR)/${MAT$(PROJECT)_SO:.$(MAT_SO_EXT)=.d}
122 | # tool, example, and test bins
123 | TOOL_BINS := ${TOOL_OBJS:.o=.bin}
124 | EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin}
125 | # symlinks to tool bins without the ".bin" extension
126 | TOOL_BIN_LINKS := ${TOOL_BINS:.bin=}
127 | # Put the test binaries in build/test for convenience.
128 | TEST_BIN_DIR := $(BUILD_DIR)/test
129 | TEST_CU_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \
130 | $(foreach obj,$(TEST_CU_OBJS),$(basename $(notdir $(obj))))))
131 | TEST_CXX_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \
132 | $(foreach obj,$(TEST_CXX_OBJS),$(basename $(notdir $(obj))))))
133 | TEST_BINS := $(TEST_CXX_BINS) $(TEST_CU_BINS)
134 | # TEST_ALL_BIN is the test binary that links caffe dynamically.
135 | TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin
136 |
137 | ##############################
138 | # Derive compiler warning dump locations
139 | ##############################
140 | WARNS_EXT := warnings.txt
141 | CXX_WARNS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o.$(WARNS_EXT)})
142 | CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o.$(WARNS_EXT)})
143 | TOOL_WARNS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o.$(WARNS_EXT)})
144 | EXAMPLE_WARNS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o.$(WARNS_EXT)})
145 | TEST_WARNS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o.$(WARNS_EXT)})
146 | TEST_CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o.$(WARNS_EXT)})
147 | ALL_CXX_WARNS := $(CXX_WARNS) $(TOOL_WARNS) $(EXAMPLE_WARNS) $(TEST_WARNS)
148 | ALL_CU_WARNS := $(CU_WARNS) $(TEST_CU_WARNS)
149 | ALL_WARNS := $(ALL_CXX_WARNS) $(ALL_CU_WARNS)
150 |
151 | EMPTY_WARN_REPORT := $(BUILD_DIR)/.$(WARNS_EXT)
152 | NONEMPTY_WARN_REPORT := $(BUILD_DIR)/$(WARNS_EXT)
153 |
154 | ##############################
155 | # Derive include and lib directories
156 | ##############################
157 | CUDA_INCLUDE_DIR := $(CUDA_DIR)/include
158 |
159 | CUDA_LIB_DIR :=
160 | # add /lib64 only if it exists
161 | ifneq ("$(wildcard $(CUDA_DIR)/lib64)","")
162 | CUDA_LIB_DIR += $(CUDA_DIR)/lib64
163 | endif
164 | CUDA_LIB_DIR += $(CUDA_DIR)/lib
165 |
166 | INCLUDE_DIRS += $(BUILD_INCLUDE_DIR) ./src ./include
167 | ifneq ($(CPU_ONLY), 1)
168 | INCLUDE_DIRS += $(CUDA_INCLUDE_DIR)
169 | LIBRARY_DIRS += $(CUDA_LIB_DIR)
170 | LIBRARIES := cudart cublas curand
171 | endif
172 | LIBRARIES += glog gflags protobuf leveldb snappy \
173 | lmdb boost_system hdf5_hl hdf5 m \
174 | opencv_core opencv_highgui opencv_imgproc
175 | PYTHON_LIBRARIES := boost_python python2.7
176 | WARNINGS := -Wall -Wno-sign-compare
177 |
178 | ##############################
179 | # Set build directories
180 | ##############################
181 |
182 | DISTRIBUTE_DIR ?= distribute
183 | DISTRIBUTE_SUBDIRS := $(DISTRIBUTE_DIR)/bin $(DISTRIBUTE_DIR)/lib
184 | DIST_ALIASES := dist
185 | ifneq ($(strip $(DISTRIBUTE_DIR)),distribute)
186 | DIST_ALIASES += distribute
187 | endif
188 |
189 | ALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \
190 | $(addprefix $(BUILD_DIR)/cuda/, $(SRC_DIRS)) \
191 | $(LIB_BUILD_DIR) $(TEST_BIN_DIR) $(PY_PROTO_BUILD_DIR) $(LINT_OUTPUT_DIR) \
192 | $(DISTRIBUTE_SUBDIRS) $(PROTO_BUILD_INCLUDE_DIR))
193 |
194 | ##############################
195 | # Set directory for Doxygen-generated documentation
196 | ##############################
197 | DOXYGEN_CONFIG_FILE ?= ./.Doxyfile
198 | # should be the same as OUTPUT_DIRECTORY in the .Doxyfile
199 | DOXYGEN_OUTPUT_DIR ?= ./doxygen
200 | DOXYGEN_COMMAND ?= doxygen
201 | # All the files that might have Doxygen documentation.
202 | DOXYGEN_SOURCES := $(shell find \
203 | src/$(PROJECT) \
204 | include/$(PROJECT) \
205 | python/ \
206 | matlab/ \
207 | examples \
208 | tools \
209 | -name "*.cpp" -or -name "*.hpp" -or -name "*.cu" -or -name "*.cuh" -or \
210 | -name "*.py" -or -name "*.m")
211 | DOXYGEN_SOURCES += $(DOXYGEN_CONFIG_FILE)
212 |
213 |
214 | ##############################
215 | # Configure build
216 | ##############################
217 |
218 | # Determine platform
219 | UNAME := $(shell uname -s)
220 | ifeq ($(UNAME), Linux)
221 | LINUX := 1
222 | else ifeq ($(UNAME), Darwin)
223 | OSX := 1
224 | endif
225 |
226 | # Linux
227 | ifeq ($(LINUX), 1)
228 | CXX ?= /usr/bin/g++
229 | GCCVERSION := $(shell $(CXX) -dumpversion | cut -f1,2 -d.)
230 | # older versions of gcc are too dumb to build boost with -Wuninitalized
231 | ifeq ($(shell echo $(GCCVERSION) \< 4.6 | bc), 1)
232 | WARNINGS += -Wno-uninitialized
233 | endif
234 | # boost::thread is reasonably called boost_thread (compare OS X)
235 | # We will also explicitly add stdc++ to the link target.
236 | LIBRARIES += boost_thread stdc++
237 | endif
238 |
239 | # OS X:
240 | # clang++ instead of g++
241 | # libstdc++ for NVCC compatibility on OS X >= 10.9 with CUDA < 7.0
242 | ifeq ($(OSX), 1)
243 | CXX := /usr/bin/clang++
244 | ifneq ($(CPU_ONLY), 1)
245 | CUDA_VERSION := $(shell $(CUDA_DIR)/bin/nvcc -V | grep -o 'release \d' | grep -o '\d')
246 | ifeq ($(shell echo $(CUDA_VERSION) \< 7.0 | bc), 1)
247 | CXXFLAGS += -stdlib=libstdc++
248 | LINKFLAGS += -stdlib=libstdc++
249 | endif
250 | # clang throws this warning for cuda headers
251 | WARNINGS += -Wno-unneeded-internal-declaration
252 | endif
253 | # gtest needs to use its own tuple to not conflict with clang
254 | COMMON_FLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1
255 | # boost::thread is called boost_thread-mt to mark multithreading on OS X
256 | LIBRARIES += boost_thread-mt
257 | # we need to explicitly ask for the rpath to be obeyed
258 | DYNAMIC_FLAGS := -install_name @rpath/libcaffe.so
259 | ORIGIN := @loader_path
260 | else
261 | ORIGIN := \$$ORIGIN
262 | endif
263 |
264 | # Custom compiler
265 | ifdef CUSTOM_CXX
266 | CXX := $(CUSTOM_CXX)
267 | endif
268 |
269 | # Static linking
270 | ifneq (,$(findstring clang++,$(CXX)))
271 | STATIC_LINK_COMMAND := -Wl,-force_load $(STATIC_NAME)
272 | else ifneq (,$(findstring g++,$(CXX)))
273 | STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive
274 | else
275 | # The following line must not be indented with a tab, since we are not inside a target
276 | $(error Cannot static link with the $(CXX) compiler)
277 | endif
278 |
279 | # Debugging
280 | ifeq ($(DEBUG), 1)
281 | COMMON_FLAGS += -DDEBUG -g -O0
282 | NVCCFLAGS += -G
283 | else
284 | COMMON_FLAGS += -DNDEBUG -O2
285 | endif
286 |
287 | # cuDNN acceleration configuration.
288 | ifeq ($(USE_CUDNN), 1)
289 | LIBRARIES += cudnn
290 | COMMON_FLAGS += -DUSE_CUDNN
291 | endif
292 |
293 | # CPU-only configuration
294 | ifeq ($(CPU_ONLY), 1)
295 | OBJS := $(PROTO_OBJS) $(CXX_OBJS)
296 | TEST_OBJS := $(TEST_CXX_OBJS)
297 | TEST_BINS := $(TEST_CXX_BINS)
298 | ALL_WARNS := $(ALL_CXX_WARNS)
299 | TEST_FILTER := --gtest_filter="-*GPU*"
300 | COMMON_FLAGS += -DCPU_ONLY
301 | endif
302 |
303 | # Python layer support
304 | ifeq ($(WITH_PYTHON_LAYER), 1)
305 | COMMON_FLAGS += -DWITH_PYTHON_LAYER
306 | LIBRARIES += $(PYTHON_LIBRARIES)
307 | endif
308 |
309 | # BLAS configuration (default = ATLAS)
310 | BLAS ?= atlas
311 | ifeq ($(BLAS), mkl)
312 | # MKL
313 | LIBRARIES += mkl_rt
314 | COMMON_FLAGS += -DUSE_MKL
315 | MKL_DIR ?= /opt/intel/mkl
316 | BLAS_INCLUDE ?= $(MKL_DIR)/include
317 | BLAS_LIB ?= $(MKL_DIR)/lib $(MKL_DIR)/lib/intel64
318 | else ifeq ($(BLAS), open)
319 | # OpenBLAS
320 | LIBRARIES += openblas
321 | else
322 | # ATLAS
323 | ifeq ($(LINUX), 1)
324 | ifeq ($(BLAS), atlas)
325 | # Linux simply has cblas and atlas
326 | LIBRARIES += cblas atlas
327 | endif
328 | else ifeq ($(OSX), 1)
329 | # OS X packages atlas as the vecLib framework
330 | LIBRARIES += cblas
331 | # 10.10 has accelerate while 10.9 has veclib
332 | XCODE_CLT_VER := $(shell pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep -o 'version: 6')
333 | ifneq (,$(findstring version: 6,$(XCODE_CLT_VER)))
334 | BLAS_INCLUDE ?= /System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/
335 | LDFLAGS += -framework Accelerate
336 | else
337 | BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/
338 | LDFLAGS += -framework vecLib
339 | endif
340 | endif
341 | endif
342 | INCLUDE_DIRS += $(BLAS_INCLUDE)
343 | LIBRARY_DIRS += $(BLAS_LIB)
344 |
345 | LIBRARY_DIRS += $(LIB_BUILD_DIR)
346 |
347 | # Automatic dependency generation (nvcc is handled separately)
348 | CXXFLAGS += -MMD -MP
349 |
350 | # Complete build flags.
351 | COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir))
352 | CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) -std=c++11
353 | NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS)
354 | # mex may invoke an older gcc that is too liberal with -Wuninitalized
355 | MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized
356 | LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS)
357 |
358 | USE_PKG_CONFIG ?= 0
359 | ifeq ($(USE_PKG_CONFIG), 1)
360 | PKG_CONFIG := $(shell pkg-config opencv --libs)
361 | else
362 | PKG_CONFIG :=
363 | endif
364 | LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \
365 | $(foreach library,$(LIBRARIES),-l$(library))
366 | PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library))
367 |
368 | # 'superclean' target recursively* deletes all files ending with an extension
369 | # in $(SUPERCLEAN_EXTS) below. This may be useful if you've built older
370 | # versions of Caffe that do not place all generated files in a location known
371 | # to the 'clean' target.
372 | #
373 | # 'supercleanlist' will list the files to be deleted by make superclean.
374 | #
375 | # * Recursive with the exception that symbolic links are never followed, per the
376 | # default behavior of 'find'.
377 | SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo
378 |
379 | # Set the sub-targets of the 'everything' target.
380 | EVERYTHING_TARGETS := all py$(PROJECT) test warn lint
381 | # Only build matcaffe as part of "everything" if MATLAB_DIR is specified.
382 | ifneq ($(MATLAB_DIR),)
383 | EVERYTHING_TARGETS += mat$(PROJECT)
384 | endif
385 |
386 | ##############################
387 | # Define build targets
388 | ##############################
389 | .PHONY: all test clean docs linecount lint lintclean tools examples $(DIST_ALIASES) \
390 | py mat py$(PROJECT) mat$(PROJECT) proto runtest \
391 | superclean supercleanlist supercleanfiles warn everything
392 |
393 | all: $(STATIC_NAME) $(DYNAMIC_NAME) tools examples
394 |
395 | everything: $(EVERYTHING_TARGETS)
396 |
397 | linecount:
398 | cloc --read-lang-def=$(PROJECT).cloc \
399 | src/$(PROJECT) include/$(PROJECT) tools examples \
400 | python matlab
401 |
402 | lint: $(EMPTY_LINT_REPORT)
403 |
404 | lintclean:
405 | @ $(RM) -r $(LINT_OUTPUT_DIR) $(EMPTY_LINT_REPORT) $(NONEMPTY_LINT_REPORT)
406 |
407 | docs: $(DOXYGEN_OUTPUT_DIR)
408 | @ cd ./docs ; ln -sfn ../$(DOXYGEN_OUTPUT_DIR)/html doxygen
409 |
410 | $(DOXYGEN_OUTPUT_DIR): $(DOXYGEN_CONFIG_FILE) $(DOXYGEN_SOURCES)
411 | $(DOXYGEN_COMMAND) $(DOXYGEN_CONFIG_FILE)
412 |
413 | $(EMPTY_LINT_REPORT): $(LINT_OUTPUTS) | $(BUILD_DIR)
414 | @ cat $(LINT_OUTPUTS) > $@
415 | @ if [ -s "$@" ]; then \
416 | cat $@; \
417 | mv $@ $(NONEMPTY_LINT_REPORT); \
418 | echo "Found one or more lint errors."; \
419 | exit 1; \
420 | fi; \
421 | $(RM) $(NONEMPTY_LINT_REPORT); \
422 | echo "No lint errors!";
423 |
424 | $(LINT_OUTPUTS): $(LINT_OUTPUT_DIR)/%.lint.txt : % $(LINT_SCRIPT) | $(LINT_OUTPUT_DIR)
425 | @ mkdir -p $(dir $@)
426 | @ python $(LINT_SCRIPT) $< 2>&1 \
427 | | grep -v "^Done processing " \
428 | | grep -v "^Total errors found: 0" \
429 | > $@ \
430 | || true
431 |
432 | test: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) $(TEST_BINS)
433 |
434 | tools: $(TOOL_BINS) $(TOOL_BIN_LINKS)
435 |
436 | examples: $(EXAMPLE_BINS)
437 |
438 | py$(PROJECT): py
439 |
440 | py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY)
441 |
442 | $(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX) | $(DYNAMIC_NAME)
443 | @ echo CXX/LD -o $@ $<
444 | $(Q)$(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \
445 | -o $@ $(LINKFLAGS) -l$(PROJECT) $(PYTHON_LDFLAGS) \
446 | -Wl,-rpath,$(ORIGIN)/../../build/lib
447 |
448 | mat$(PROJECT): mat
449 |
450 | mat: $(MAT$(PROJECT)_SO)
451 |
452 | $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME)
453 | @ if [ -z "$(MATLAB_DIR)" ]; then \
454 | echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \
455 | "to build mat$(PROJECT)."; \
456 | exit 1; \
457 | fi
458 | @ echo MEX $<
459 | $(Q)$(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \
460 | CXX="$(CXX)" \
461 | CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \
462 | CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@
463 | @ if [ -f "$(PROJECT)_.d" ]; then \
464 | mv -f $(PROJECT)_.d $(BUILD_DIR)/${MAT$(PROJECT)_SO:.$(MAT_SO_EXT)=.d}; \
465 | fi
466 |
467 | runtest: $(TEST_ALL_BIN)
468 | $(TOOL_BUILD_DIR)/caffe
469 | $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER)
470 |
471 | pytest: py
472 | cd python; python -m unittest discover -s caffe/test
473 |
474 | mattest: mat
475 | cd matlab; $(MATLAB_DIR)/bin/matlab -nodisplay -r 'caffe.run_tests(), exit()'
476 |
477 | warn: $(EMPTY_WARN_REPORT)
478 |
479 | $(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR)
480 | @ cat $(ALL_WARNS) > $@
481 | @ if [ -s "$@" ]; then \
482 | cat $@; \
483 | mv $@ $(NONEMPTY_WARN_REPORT); \
484 | echo "Compiler produced one or more warnings."; \
485 | exit 1; \
486 | fi; \
487 | $(RM) $(NONEMPTY_WARN_REPORT); \
488 | echo "No compiler warnings!";
489 |
490 | $(ALL_WARNS): %.o.$(WARNS_EXT) : %.o
491 |
492 | $(BUILD_DIR_LINK): $(BUILD_DIR)/.linked
493 |
494 | # Create a target ".linked" in this BUILD_DIR to tell Make that the "build" link
495 | # is currently correct, then delete the one in the OTHER_BUILD_DIR in case it
496 | # exists and $(DEBUG) is toggled later.
497 | $(BUILD_DIR)/.linked:
498 | @ mkdir -p $(BUILD_DIR)
499 | @ $(RM) $(OTHER_BUILD_DIR)/.linked
500 | @ $(RM) -r $(BUILD_DIR_LINK)
501 | @ ln -s $(BUILD_DIR) $(BUILD_DIR_LINK)
502 | @ touch $@
503 |
504 | $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK)
505 | @ mkdir -p $@
506 |
507 | $(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
508 | @ echo LD -o $@
509 | $(Q)$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_FLAGS)
510 |
511 | $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
512 | @ echo AR -o $@
513 | $(Q)ar rcs $@ $(OBJS)
514 |
515 | $(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS)
516 | @ echo CXX $<
517 | $(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \
518 | || (cat $@.$(WARNS_EXT); exit 1)
519 | @ cat $@.$(WARNS_EXT)
520 |
521 | $(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \
522 | | $(PROTO_BUILD_DIR)
523 | @ echo CXX $<
524 | $(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \
525 | || (cat $@.$(WARNS_EXT); exit 1)
526 | @ cat $@.$(WARNS_EXT)
527 |
528 | $(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS)
529 | @ echo NVCC $<
530 | $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \
531 | -odir $(@D)
532 | $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \
533 | || (cat $@.$(WARNS_EXT); exit 1)
534 | @ cat $@.$(WARNS_EXT)
535 |
536 | $(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \
537 | | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
538 | @ echo CXX/LD -o $@ $<
539 | $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \
540 | -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib
541 |
542 | $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \
543 | $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
544 | @ echo LD $<
545 | $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \
546 | -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib
547 |
548 | $(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o \
549 | $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR)
550 | @ echo LD $<
551 | $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \
552 | -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib
553 |
554 | # Target for extension-less symlinks to tool binaries with extension '*.bin'.
555 | $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR)
556 | @ $(RM) $@
557 | @ ln -s $(abspath $<) $@
558 |
559 | $(TOOL_BINS): %.bin : %.o | $(DYNAMIC_NAME)
560 | @ echo CXX/LD -o $@
561 | $(Q)$(CXX) $< -o $@ $(LINKFLAGS) -l$(PROJECT) $(LDFLAGS) \
562 | -Wl,-rpath,$(ORIGIN)/../lib
563 |
564 | $(EXAMPLE_BINS): %.bin : %.o | $(DYNAMIC_NAME)
565 | @ echo CXX/LD -o $@
566 | $(Q)$(CXX) $< -o $@ $(LINKFLAGS) -l$(PROJECT) $(LDFLAGS) \
567 | -Wl,-rpath,$(ORIGIN)/../../lib
568 |
569 | proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER)
570 |
571 | $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_BUILD_DIR)/%.pb.h : \
572 | $(PROTO_SRC_DIR)/%.proto | $(PROTO_BUILD_DIR)
573 | @ echo PROTOC $<
574 | $(Q)protoc --proto_path=$(PROTO_SRC_DIR) --cpp_out=$(PROTO_BUILD_DIR) $<
575 |
576 | $(PY_PROTO_BUILD_DIR)/%_pb2.py : $(PROTO_SRC_DIR)/%.proto \
577 | $(PY_PROTO_INIT) | $(PY_PROTO_BUILD_DIR)
578 | @ echo PROTOC \(python\) $<
579 | $(Q)protoc --proto_path=$(PROTO_SRC_DIR) --python_out=$(PY_PROTO_BUILD_DIR) $<
580 |
581 | $(PY_PROTO_INIT): | $(PY_PROTO_BUILD_DIR)
582 | touch $(PY_PROTO_INIT)
583 |
584 | clean:
585 | @- $(RM) -rf $(ALL_BUILD_DIRS)
586 | @- $(RM) -rf $(OTHER_BUILD_DIR)
587 | @- $(RM) -rf $(BUILD_DIR_LINK)
588 | @- $(RM) -rf $(DISTRIBUTE_DIR)
589 | @- $(RM) $(PY$(PROJECT)_SO)
590 | @- $(RM) $(MAT$(PROJECT)_SO)
591 |
592 | supercleanfiles:
593 | $(eval SUPERCLEAN_FILES := $(strip \
594 | $(foreach ext,$(SUPERCLEAN_EXTS), $(shell find . -name '*$(ext)' \
595 | -not -path './data/*'))))
596 |
597 | supercleanlist: supercleanfiles
598 | @ \
599 | if [ -z "$(SUPERCLEAN_FILES)" ]; then \
600 | echo "No generated files found."; \
601 | else \
602 | echo $(SUPERCLEAN_FILES) | tr ' ' '\n'; \
603 | fi
604 |
605 | superclean: clean supercleanfiles
606 | @ \
607 | if [ -z "$(SUPERCLEAN_FILES)" ]; then \
608 | echo "No generated files found."; \
609 | else \
610 | echo "Deleting the following generated files:"; \
611 | echo $(SUPERCLEAN_FILES) | tr ' ' '\n'; \
612 | $(RM) $(SUPERCLEAN_FILES); \
613 | fi
614 |
615 | $(DIST_ALIASES): $(DISTRIBUTE_DIR)
616 |
617 | $(DISTRIBUTE_DIR): all py | $(DISTRIBUTE_SUBDIRS)
618 | # add include
619 | cp -r include $(DISTRIBUTE_DIR)/
620 | mkdir -p $(DISTRIBUTE_DIR)/include/caffe/proto
621 | cp $(PROTO_GEN_HEADER_SRCS) $(DISTRIBUTE_DIR)/include/caffe/proto
622 | # add tool and example binaries
623 | cp $(TOOL_BINS) $(DISTRIBUTE_DIR)/bin
624 | cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin
625 | # add libraries
626 | cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib
627 | cp $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib
628 | # add python - it's not the standard way, indeed...
629 | cp -r python $(DISTRIBUTE_DIR)/python
630 |
631 | -include $(DEPS)
632 |
--------------------------------------------------------------------------------
/code/include/caffe/common_layers.hpp:
--------------------------------------------------------------------------------
1 | #ifndef CAFFE_COMMON_LAYERS_HPP_
2 | #define CAFFE_COMMON_LAYERS_HPP_
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "caffe/blob.hpp"
10 | #include "caffe/common.hpp"
11 | #include "caffe/data_layers.hpp"
12 | #include "caffe/layer.hpp"
13 | #include "caffe/loss_layers.hpp"
14 | #include "caffe/neuron_layers.hpp"
15 | #include "caffe/proto/caffe.pb.h"
16 |
17 | namespace caffe {
18 |
19 | /**
20 | * @brief Compute the index of the @f$ K @f$ max values for each datum across
21 | * all dimensions @f$ (C \times H \times W) @f$.
22 | *
23 | * Intended for use after a classification layer to produce a prediction.
24 | * If parameter out_max_val is set to true, output is a vector of pairs
25 | * (max_ind, max_val) for each image.
26 | *
27 | * NOTE: does not implement Backwards operation.
28 | */
29 | template
30 | class ArgMaxLayer : public Layer {
31 | public:
32 | /**
33 | * @param param provides ArgMaxParameter argmax_param,
34 | * with ArgMaxLayer options:
35 | * - top_k (\b optional uint, default 1).
36 | * the number @f$ K @f$ of maximal items to output.
37 | * - out_max_val (\b optional bool, default false).
38 | * if set, output a vector of pairs (max_ind, max_val) for each image.
39 | */
40 | explicit ArgMaxLayer(const LayerParameter& param)
41 | : Layer(param) {}
42 | virtual void LayerSetUp(const vector*>& bottom,
43 | const vector*>& top);
44 | virtual void Reshape(const vector*>& bottom,
45 | const vector*>& top);
46 |
47 | virtual inline const char* type() const { return "ArgMax"; }
48 | virtual inline int ExactNumBottomBlobs() const { return 1; }
49 | virtual inline int ExactNumTopBlobs() const { return 1; }
50 |
51 | protected:
52 | /**
53 | * @param bottom input Blob vector (length 1)
54 | * -# @f$ (N \times C \times H \times W) @f$
55 | * the inputs @f$ x @f$
56 | * @param top output Blob vector (length 1)
57 | * -# @f$ (N \times 1 \times K \times 1) @f$ or, if out_max_val
58 | * @f$ (N \times 2 \times K \times 1) @f$
59 | * the computed outputs @f$
60 | * y_n = \arg\max\limits_i x_{ni}
61 | * @f$ (for @f$ K = 1 @f$).
62 | */
63 | virtual void Forward_cpu(const vector*>& bottom,
64 | const vector*>& top);
65 | /// @brief Not implemented (non-differentiable function)
66 | virtual void Backward_cpu(const vector*>& top,
67 | const vector& propagate_down, const vector*>& bottom) {
68 | NOT_IMPLEMENTED;
69 | }
70 | bool out_max_val_;
71 | size_t top_k_;
72 | };
73 |
74 | /**
75 | * @brief Takes at least two Blob%s and concatenates them along either the num
76 | * or channel dimension, outputting the result.
77 | */
78 | template
79 | class ConcatLayer : public Layer {
80 | public:
81 | explicit ConcatLayer(const LayerParameter& param)
82 | : Layer(param) {}
83 | virtual void LayerSetUp(const vector*>& bottom,
84 | const vector*>& top);
85 | virtual void Reshape(const vector*>& bottom,
86 | const vector*>& top);
87 |
88 | virtual inline const char* type() const { return "Concat"; }
89 | virtual inline int MinBottomBlobs() const { return 2; }
90 | virtual inline int ExactNumTopBlobs() const { return 1; }
91 |
92 | protected:
93 | /**
94 | * @param bottom input Blob vector (length 2+)
95 | * -# @f$ (N \times C \times H \times W) @f$
96 | * the inputs @f$ x_1 @f$
97 | * -# @f$ (N \times C \times H \times W) @f$
98 | * the inputs @f$ x_2 @f$
99 | * -# ...
100 | * - K @f$ (N \times C \times H \times W) @f$
101 | * the inputs @f$ x_K @f$
102 | * @param top output Blob vector (length 1)
103 | * -# @f$ (KN \times C \times H \times W) @f$ if axis == 0, or
104 | * @f$ (N \times KC \times H \times W) @f$ if axis == 1:
105 | * the concatenated output @f$
106 | * y = [\begin{array}{cccc} x_1 & x_2 & ... & x_K \end{array}]
107 | * @f$
108 | */
109 | virtual void Forward_cpu(const vector*>& bottom,
110 | const vector*>& top);
111 | virtual void Forward_gpu(const vector*>& bottom,
112 | const vector*>& top);
113 |
114 | /**
115 | * @brief Computes the error gradient w.r.t. the concatenate inputs.
116 | *
117 | * @param top output Blob vector (length 1), providing the error gradient with
118 | * respect to the outputs
119 | * -# @f$ (KN \times C \times H \times W) @f$ if axis == 0, or
120 | * @f$ (N \times KC \times H \times W) @f$ if axis == 1:
121 | * containing error gradients @f$ \frac{\partial E}{\partial y} @f$
122 | * with respect to concatenated outputs @f$ y @f$
123 | * @param propagate_down see Layer::Backward.
124 | * @param bottom input Blob vector (length K), into which the top gradient
125 | * @f$ \frac{\partial E}{\partial y} @f$ is deconcatenated back to the
126 | * inputs @f$
127 | * \left[ \begin{array}{cccc}
128 | * \frac{\partial E}{\partial x_1} &
129 | * \frac{\partial E}{\partial x_2} &
130 | * ... &
131 | * \frac{\partial E}{\partial x_K}
132 | * \end{array} \right] =
133 | * \frac{\partial E}{\partial y}
134 | * @f$
135 | */
136 | virtual void Backward_cpu(const vector*>& top,
137 | const vector& propagate_down, const vector*>& bottom);
138 | virtual void Backward_gpu(const vector*>& top,
139 | const vector& propagate_down, const vector*>& bottom);
140 |
141 | int count_;
142 | int num_concats_;
143 | int concat_input_size_;
144 | int concat_axis_;
145 | };
146 |
147 | /**
148 | * @brief Compute elementwise operations, such as product and sum,
149 | * along multiple input Blobs.
150 | *
151 | * TODO(dox): thorough documentation for Forward, Backward, and proto params.
152 | */
153 | template
154 | class EltwiseLayer : public Layer {
155 | public:
156 | explicit EltwiseLayer(const LayerParameter& param)
157 | : Layer(param) {}
158 | virtual void LayerSetUp(const vector*>& bottom,
159 | const vector*>& top);
160 | virtual void Reshape(const vector*>& bottom,
161 | const vector*>& top);
162 |
163 | virtual inline const char* type() const { return "Eltwise"; }
164 | virtual inline int MinBottomBlobs() const { return 2; }
165 | virtual inline int ExactNumTopBlobs() const { return 1; }
166 |
167 | protected:
168 | virtual void Forward_cpu(const vector*>& bottom,
169 | const vector*>& top);
170 | virtual void Forward_gpu(const vector*>& bottom,
171 | const vector*>& top);
172 | virtual void Backward_cpu(const vector*>& top,
173 | const vector& propagate_down, const vector*>& bottom);
174 | virtual void Backward_gpu(const vector*>& top,
175 | const vector& propagate_down, const vector*>& bottom);
176 |
177 | EltwiseParameter_EltwiseOp op_;
178 | vector coeffs_;
179 | Blob max_idx_;
180 |
181 | bool stable_prod_grad_;
182 | };
183 |
184 | /**
185 | * @brief Takes two+ Blobs, interprets last Blob as a selector and
186 | * filter remaining Blobs accordingly with selector data (0 means that
187 | * the corresponding item has to be filtered, non-zero means that corresponding
188 | * item needs to stay).
189 | */
190 | template
191 | class FilterLayer : public Layer {
192 | public:
193 | explicit FilterLayer(const LayerParameter& param)
194 | : Layer(param) {}
195 | virtual void LayerSetUp(const vector*>& bottom,
196 | const vector*>& top);
197 | virtual void Reshape(const vector*>& bottom,
198 | const vector*>& top);
199 |
200 | virtual inline const char* type() const { return "Filter"; }
201 | virtual inline int MinBottomBlobs() const { return 2; }
202 | virtual inline int MinTopBlobs() const { return 1; }
203 |
204 | protected:
205 | /**
206 | * @param bottom input Blob vector (length 2+)
207 | * -# @f$ (N \times C \times H \times W) @f$
208 | * the inputs to be filtered @f$ x_1 @f$
209 | * -# ...
210 | * -# @f$ (N \times C \times H \times W) @f$
211 | * the inputs to be filtered @f$ x_K @f$
212 | * -# @f$ (N \times 1 \times 1 \times 1) @f$
213 | * the selector blob
214 | * @param top output Blob vector (length 1+)
215 | * -# @f$ (S \times C \times H \times W) @f$ ()
216 | * the filtered output @f$ x_1 @f$
217 | * where S is the number of items
218 | * that haven't been filtered
219 | * @f$ (S \times C \times H \times W) @f$
220 | * the filtered output @f$ x_K @f$
221 | * where S is the number of items
222 | * that haven't been filtered
223 | */
224 | virtual void Forward_cpu(const vector*>& bottom,
225 | const vector*>& top);
226 | virtual void Forward_gpu(const vector*>& bottom,
227 | const vector*>& top);
228 |
229 | /**
230 | * @brief Computes the error gradient w.r.t. the forwarded inputs.
231 | *
232 | * @param top output Blob vector (length 1+), providing the error gradient with
233 | * respect to the outputs
234 | * @param propagate_down see Layer::Backward.
235 | * @param bottom input Blob vector (length 2+), into which the top error
236 | * gradient is copied
237 | */
238 | virtual void Backward_cpu(const vector*>& top,
239 | const vector& propagate_down, const vector*>& bottom);
240 | virtual void Backward_gpu(const vector*>& top,
241 | const vector& propagate_down, const vector*>& bottom);
242 |
243 | bool first_reshape_;
244 | vector indices_to_forward_;
245 | };
246 |
247 | /**
248 | * @brief Reshapes the input Blob into flat vectors.
249 | *
250 | * Note: because this layer does not change the input values -- merely the
251 | * dimensions -- it can simply copy the input. The copy happens "virtually"
252 | * (thus taking effectively 0 real time) by setting, in Forward, the data
253 | * pointer of the top Blob to that of the bottom Blob (see Blob::ShareData),
254 | * and in Backward, the diff pointer of the bottom Blob to that of the top Blob
255 | * (see Blob::ShareDiff).
256 | */
257 | template
258 | class FlattenLayer : public Layer {
259 | public:
260 | explicit FlattenLayer(const LayerParameter& param)
261 | : Layer(param) {}
262 | virtual void Reshape(const vector*>& bottom,
263 | const vector*>& top);
264 |
265 | virtual inline const char* type() const { return "Flatten"; }
266 | virtual inline int ExactNumBottomBlobs() const { return 1; }
267 | virtual inline int ExactNumTopBlobs() const { return 1; }
268 |
269 | protected:
270 | /**
271 | * @param bottom input Blob vector (length 2+)
272 | * -# @f$ (N \times C \times H \times W) @f$
273 | * the inputs
274 | * @param top output Blob vector (length 1)
275 | * -# @f$ (N \times CHW \times 1 \times 1) @f$
276 | * the outputs -- i.e., the (virtually) copied, flattened inputs
277 | */
278 | virtual void Forward_cpu(const vector*>& bottom,
279 | const vector*>& top);
280 |
281 | /**
282 | * @brief Computes the error gradient w.r.t. the concatenate inputs.
283 | *
284 | * @param top output Blob vector (length 1), providing the error gradient with
285 | * respect to the outputs
286 | * @param propagate_down see Layer::Backward.
287 | * @param bottom input Blob vector (length K), into which the top error
288 | * gradient is (virtually) copied
289 | */
290 | virtual void Backward_cpu(const vector*>& top,
291 | const vector& propagate_down, const vector*>& bottom);
292 | };
293 |
294 | /**
295 | * @brief Also known as a "fully-connected" layer, computes an inner product
296 | * with a set of learned weights, and (optionally) adds biases.
297 | *
298 | * TODO(dox): thorough documentation for Forward, Backward, and proto params.
299 | */
300 | template
301 | class InnerProductLayer : public Layer {
302 | public:
303 | explicit InnerProductLayer(const LayerParameter& param)
304 | : Layer(param) {}
305 | virtual void LayerSetUp(const vector*>& bottom,
306 | const vector*>& top);
307 | virtual void Reshape(const vector*>& bottom,
308 | const vector*>& top);
309 |
310 | virtual inline const char* type() const { return "InnerProduct"; }
311 | virtual inline int ExactNumBottomBlobs() const { return 1; }
312 | virtual inline int ExactNumTopBlobs() const { return 1; }
313 |
314 | protected:
315 | virtual void Forward_cpu(const vector*>& bottom,
316 | const vector*>& top);
317 | virtual void Forward_gpu(const vector*>& bottom,
318 | const vector*>& top);
319 | virtual void Backward_cpu(const vector*>& top,
320 | const vector& propagate_down, const vector*>& bottom);
321 | virtual void Backward_gpu(const vector*>& top,
322 | const vector& propagate_down, const vector*>& bottom);
323 |
324 | int M_;
325 | int K_;
326 | int N_;
327 | bool bias_term_;
328 | Blob bias_multiplier_;
329 | };
330 |
331 | //Tree Class for SuperCategory Layer
332 | //Class Location..?
333 | class Tree {
334 | public :
335 | Tree() : label(-1) {}
336 | ~Tree() {}
337 |
338 | int GetLabel() const { return label; }
339 | int GetIndex() const { return index; }
340 | Tree * InsertChild(shared_ptr child) {
341 | children.push_back(child);
342 | child->parent = this;
343 | return this;
344 | }
345 | void SetLabel(int label_) { this->label = label_; }
346 | const Tree * GetParent() const { return parent; }
347 | const std::vector > * GetChildren() const {
348 | return &children;
349 | }
350 |
351 | int Depth() const;
352 | void MakeBalance(int remain);
353 |
354 | //Tree helper
355 | static void GiveIndex(Tree * root, std::vector& serialized_tree);
356 | static void GetNodeNumPerLevelAndGiveLabel(std::vector& node_num, std::vector& base_index,Tree * root, std::vector& serialized_tree, std::vector& label_to_index);
357 | static void MakeTree(Tree * node, const SuperCategoryParameter::TreeScheme * node_param);
358 |
359 | private :
360 | int label;
361 | int index;
362 |
363 | Tree * parent;
364 | std::vector > children;
365 | };
366 |
367 | template
368 | class SuperCategoryFMLayer : public Layer {
369 | public:
370 | explicit SuperCategoryFMLayer(const LayerParameter& param)
371 | : Layer(param) {}
372 | virtual void LayerSetUp(
373 | const vector*>& bottom, const vector*>& top);
374 | virtual void Reshape(const vector*>& bottom,
375 | const vector*>& top);
376 |
377 | virtual inline int ExactNumBottomBlobs() const { return 1; }
378 | virtual inline const char* type() const { return "SuperCategoryFM"; }
379 |
380 | protected:
381 | virtual void Forward_cpu(const vector*>& bottom,
382 | const vector*>& top);
383 | virtual void Forward_gpu(const vector*>& bottom,
384 | const vector*>& top)
385 | {
386 | return Forward_cpu(bottom,top);
387 | }
388 | virtual void Backward_cpu(const vector*>& top,
389 | const vector& propagate_down, const vector*>& bottom);
390 | virtual void Backward_gpu(const vector*>& top,
391 | const vector& propagate_down, const vector*>& bottom)
392 | {
393 | return Backward_cpu(top,propagate_down,bottom);
394 | }
395 |
396 | int M_; //Batch Size
397 | int N_; //Filter Size(# of category)
398 | int H_; //height of feature map size
399 | int W_; //width of feature map size
400 |
401 | Tree root_;
402 | int depth_;
403 | std::vector node_num_per_level_;
404 | std::vector base_index_per_level_;
405 | std::vector label_to_index_;
406 | std::vector serialized_tree_;
407 |
408 | EltwiseParameter_EltwiseOp op_;
409 | std::vector > > mark_;
410 | };
411 |
412 | template
413 | class SuperCategoryFMPostLayer : public Layer {
414 | public:
415 | explicit SuperCategoryFMPostLayer(const LayerParameter& param)
416 | : Layer(param) {}
417 | virtual void LayerSetUp(
418 | const vector*>& bottom, const vector*>& top);
419 | virtual void Reshape(const vector*>& bottom,
420 | const vector*>& top);
421 |
422 | virtual inline int MinBottomBlobs() const { return 2; }
423 | virtual inline int MinTopBlobs() const { return 2; }
424 | virtual inline const char* type() const { return "SuperCategoryFMPost"; }
425 |
426 | protected:
427 | virtual void Forward_cpu(const vector*>& bottom,
428 | const vector*>& top);
429 | virtual void Forward_gpu(const vector*>& bottom,
430 | const vector*>& top)
431 | {
432 | return Forward_cpu(bottom,top);
433 | }
434 | virtual void Backward_cpu(const vector*>& top,
435 | const vector& propagate_down, const vector*>& bottom);
436 | virtual void Backward_gpu(const vector*>& top,
437 | const vector& propagate_down, const vector*>& bottom)
438 | {
439 | return Backward_cpu(top,propagate_down,bottom);
440 | }
441 |
442 | int M_; //Batch Size
443 | int N_; //Filter Size(# of category)
444 | int H_; //height of feature map size
445 | int W_; //width of feature map size
446 |
447 | Tree root_;
448 | int depth_;
449 | std::vector node_num_per_level_;
450 | std::vector base_index_per_level_;
451 | std::vector label_to_index_;
452 | std::vector serialized_tree_;
453 |
454 | EltwiseParameter_EltwiseOp op_;
455 | //std::vector > > mark_;
456 | };
457 | template
458 | class SuperCategoryLayer : public Layer {
459 | public:
460 | explicit SuperCategoryLayer(const LayerParameter& param)
461 | : Layer(param) {}
462 | virtual void LayerSetUp(
463 | const vector*>& bottom, const vector*>& top);
464 | virtual void Reshape(const vector*>& bottom,
465 | const vector*>& top);
466 |
467 | virtual inline int ExactNumBottomBlobs() const { return 1; }
468 | virtual inline const char* type() const { return "SuperCategory"; }
469 |
470 | protected:
471 | virtual void Forward_cpu(const vector*>& bottom,
472 | const vector*>& top);
473 | virtual void Forward_gpu(const vector*>& bottom,
474 | const vector*>& top)
475 | {
476 | return Forward_cpu(bottom,top);
477 | }
478 | virtual void Backward_cpu(const vector*>& top,
479 | const vector& propagate_down, const vector*>& bottom);
480 | virtual void Backward_gpu(const vector*>& top,
481 | const vector& propagate_down, const vector*>& bottom)
482 | {
483 | return Backward_cpu(top,propagate_down,bottom);
484 | }
485 |
486 |
487 | int N_; //Batch Size
488 | Blob temp_; //temporary blob for intermediate result
489 | std::vector > > mark_;
490 |
491 | Tree root_;
492 | int depth_;
493 | std::vector node_num_per_level_;
494 | std::vector base_index_per_level_;
495 | std::vector label_to_index_;
496 | std::vector serialized_tree_;
497 | };
498 | template
499 | class SuperCategoryLabelLayer : public Layer {
500 | public:
501 | explicit SuperCategoryLabelLayer(const LayerParameter& param)
502 | : Layer(param) {}
503 | virtual void LayerSetUp(
504 | const vector*>& bottom, const vector*>& top);
505 | virtual void Reshape(const vector*>& bottom,
506 | const vector*>& top);
507 |
508 | virtual inline int ExactNumBottomBlobs() const { return 1; }
509 | virtual inline const char* type() const { return "SuperCategoryLabel"; }
510 |
511 | protected:
512 | virtual void Forward_cpu(const vector*>& bottom,
513 | const vector*>& top);
514 | virtual void Backward_cpu(const vector*>& top,
515 | const vector& propagate_down, const vector*>& bottom){}
516 |
517 | int N_; //Batch Size
518 |
519 | Tree root_;
520 | int depth_;
521 | std::vector node_num_per_level_;
522 | std::vector base_index_per_level_;
523 | std::vector label_to_index_;
524 | std::vector serialized_tree_;
525 | };
526 |
527 | /**
528 | * @brief Normalizes the input to have 0-mean and/or unit (1) variance.
529 | *
530 | * TODO(dox): thorough documentation for Forward, Backward, and proto params.
531 | */
532 | template
533 | class MVNLayer : public Layer {
534 | public:
535 | explicit MVNLayer(const LayerParameter& param)
536 | : Layer(param) {}
537 | virtual void Reshape(const vector*>& bottom,
538 | const vector*>& top);
539 |
540 | virtual inline const char* type() const { return "MVN"; }
541 | virtual inline int ExactNumBottomBlobs() const { return 1; }
542 | virtual inline int ExactNumTopBlobs() const { return 1; }
543 |
544 | protected:
545 | virtual void Forward_cpu(const vector*>& bottom,
546 | const vector*>& top);
547 | virtual void Forward_gpu(const vector*>& bottom,
548 | const vector*>& top);
549 | virtual void Backward_cpu(const vector*>& top,
550 | const vector& propagate_down, const vector*>& bottom);
551 | virtual void Backward_gpu(const vector*>& top,
552 | const vector& propagate_down, const vector*>& bottom);
553 |
554 | Blob mean_, variance_, temp_;
555 |
556 | /// sum_multiplier is used to carry out sum using BLAS
557 | Blob sum_multiplier_;
558 | Dtype eps_;
559 | };
560 |
561 | /*
562 | * @brief Reshapes the input Blob into an arbitrary-sized output Blob.
563 | *
564 | * Note: similarly to FlattenLayer, this layer does not change the input values
565 | * (see FlattenLayer, Blob::ShareData and Blob::ShareDiff).
566 | */
567 | template
568 | class ReshapeLayer : public Layer {
569 | public:
570 | explicit ReshapeLayer(const LayerParameter& param)
571 | : Layer(param) {}
572 | virtual void LayerSetUp(const vector*>& bottom,
573 | const vector*>& top);
574 | virtual void Reshape(const vector*>& bottom,
575 | const vector*>& top);
576 |
577 | virtual inline const char* type() const { return "Reshape"; }
578 | virtual inline int ExactNumBottomBlobs() const { return 1; }
579 | virtual inline int ExactNumTopBlobs() const { return 1; }
580 |
581 | protected:
582 | virtual void Forward_cpu(const vector*>& bottom,
583 | const vector*>& top) {}
584 | virtual void Backward_cpu(const vector*>& top,
585 | const vector& propagate_down, const vector*>& bottom) {}
586 | virtual void Forward_gpu(const vector*>& bottom,
587 | const vector*>& top) {}
588 | virtual void Backward_gpu(const vector*>& top,
589 | const vector& propagate_down, const vector*>& bottom) {}
590 |
591 | /// @brief vector of axes indices whose dimensions we'll copy from the bottom
592 | vector copy_axes_;
593 | /// @brief the index of the axis whose dimension we infer, or -1 if none
594 | int inferred_axis_;
595 | /// @brief the product of the "constant" output dimensions
596 | int constant_count_;
597 | };
598 |
599 | /**
600 | * @brief Compute "reductions" -- operations that return a scalar output Blob
601 | * for an input Blob of arbitrary size, such as the sum, absolute sum,
602 | * and sum of squares.
603 | *
604 | * TODO(dox): thorough documentation for Forward, Backward, and proto params.
605 | */
606 | template
607 | class ReductionLayer : public Layer {
608 | public:
609 | explicit ReductionLayer(const LayerParameter& param)
610 | : Layer(param) {}
611 | virtual void LayerSetUp(const vector*>& bottom,
612 | const vector*>& top);
613 | virtual void Reshape(const vector*>& bottom,
614 | const vector*>& top);
615 |
616 | virtual inline const char* type() const { return "Reduction"; }
617 | virtual inline int ExactNumBottomBlobs() const { return 1; }
618 | virtual inline int ExactNumTopBlobs() const { return 1; }
619 |
620 | protected:
621 | virtual void Forward_cpu(const vector*>& bottom,
622 | const vector*>& top);
623 | virtual void Forward_gpu(const vector*>& bottom,
624 | const vector*>& top);
625 | virtual void Backward_cpu(const vector*>& top,
626 | const vector& propagate_down, const vector*>& bottom);
627 | virtual void Backward_gpu(const vector*>& top,
628 | const vector& propagate_down, const vector*>& bottom);
629 |
630 | /// @brief the reduction operation performed by the layer
631 | ReductionParameter_ReductionOp op_;
632 | /// @brief a scalar coefficient applied to all outputs
633 | Dtype coeff_;
634 | /// @brief the index of the first input axis to reduce
635 | int axis_;
636 | /// @brief the number of reductions performed
637 | int num_;
638 | /// @brief the input size of each reduction
639 | int dim_;
640 | /// @brief a helper Blob used for summation (op_ == SUM)
641 | Blob sum_multiplier_;
642 | };
643 |
644 | /**
645 | * @brief Ignores bottom blobs while producing no top blobs. (This is useful
646 | * to suppress outputs during testing.)
647 | */
648 | template
649 | class SilenceLayer : public Layer {
650 | public:
651 | explicit SilenceLayer(const LayerParameter& param)
652 | : Layer(param) {}
653 | virtual void Reshape(const vector*>& bottom,
654 | const vector*>& top) {}
655 |
656 | virtual inline const char* type() const { return "Silence"; }
657 | virtual inline int MinBottomBlobs() const { return 1; }
658 | virtual inline int ExactNumTopBlobs() const { return 0; }
659 |
660 | protected:
661 | virtual void Forward_cpu(const vector*>& bottom,
662 | const vector*>& top) {}
663 | // We can't define Forward_gpu here, since STUB_GPU will provide
664 | // its own definition for CPU_ONLY mode.
665 | virtual void Forward_gpu(const vector*>& bottom,
666 | const vector*>& top);
667 | virtual void Backward_cpu(const vector*>& top,
668 | const vector& propagate_down, const vector