├── README.md ├── WORKSPACE └── inception ├── BUILD ├── data ├── build_peta_region_data.py ├── build_rap_data.py └── build_rap_region_data.py ├── dataset.py ├── image_processing.py ├── inception_distributed_train.py ├── inception_peta_eval.py ├── inception_peta_model.py ├── inception_peta_train.py ├── inception_rap_eval.py ├── inception_rap_model.py ├── inception_rap_train.py ├── peta_data.py ├── peta_eval.py ├── peta_train.py ├── rap_data.py ├── rap_eval.py ├── rap_train.py └── slim ├── BUILD ├── __pycache__ ├── inception_model.cpython-34.pyc ├── losses.cpython-34.pyc ├── ops.cpython-34.pyc ├── peta_model.cpython-34.pyc ├── scopes.cpython-34.pyc ├── slim.cpython-34.pyc └── variables.cpython-34.pyc ├── collections_test.py ├── inception_model.py ├── inception_test.py ├── losses.py ├── losses_test.py ├── ops.py ├── ops_test.py ├── peta_model.py ├── scopes.py ├── scopes_test.py ├── slim.py ├── variables.py └── variables_test.py /README.md: -------------------------------------------------------------------------------- 1 | 2 | code for IJCAI 18 paper: Grouping Attribute Recognition for Pedestrian with Joint Recurrent Learning 3 | 4 | ### runtime environment 5 | 6 | - python version : 3.4 7 | - tensorflow version: >= 1.4 8 | 9 | ### resource 10 | best rap model is: 链接: https://pan.baidu.com/s/1m_bOW2x9_fyhy8dSlPWCuw 提取码: y9ip 11 | best peta model is: 链接: https://pan.baidu.com/s/1acNTb668IVppJyhfzop_ow 提取码: 3upe 12 | rap TFRecord file: 链接: https://pan.baidu.com/s/15MRSqdg7izo8HgnOD2uCTQ 提取码: 85uk 13 | dataset label file: 链接: https://pan.baidu.com/s/16D1spNxN2SjZZR5l6v22Uw 提取码: iswu 14 | 15 | ### prepare data (use rap as example) 16 | - ROI data: 17 | 18 | use pose estimation model provided in Spindle Net (github link is https://github.com/yokattame/SpindleNet) to get region proposal data. 19 | 20 | - put rap or peta label data and region proposal data together. 21 | 22 | file format is: 23 | 24 | # 0 25 | CAM12_2014-03-05_20140305110334-20140305111754_tarid1199_frame8675_line1.png 26 | -1 -1 -1 1 -1 1 -1 1 -1 -1 -1 1 -1 -1 -1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1 -1 -1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 27 | 19.75390625 0 68 48.6875 28 | 0 28.796875 68 112.9609375 29 | 0 72.4375 68 188.8125 30 | 49.3738839286 29.6875 68 112.8125 31 | 0 31.3203125 31.921875 97.8203125 32 | 20.4285714286 85.796875 47.5714285714 186.5859375 33 | 8.18247767857 74.8125 35.3253348214 174.5625 34 | 35 | that is 36 | 37 | image index 38 | attribute labels 39 | head region coordinate 40 | up region coordinate 41 | down region coordinate 42 | left arm coordinate 43 | right arm coordinate 44 | left leg coordinate 45 | eight leg coordinate 46 | - run data/build_rap_region_data.py to get tensorflow TFRecord input 47 | 48 | 49 | ### train 50 | 51 | 52 | - install bazel 53 | - in root dir, run "bazel build //inception:rap_train" or "bazel build //inception:rap_test" 54 | 55 | 56 | 57 | run command for example: 58 | 59 | TRAIN_DIR=DIR for train models 60 | RAP_DATA_DIR= DIR for rap tensorflow TFRecord file 61 | MODEL_PATH=DIR for pretrained model 62 | 63 | bazel-bin/inception/rap_train \ 64 | --train_dir="${TRAIN_DIR}" \ 65 | --data_dir="${RAP_DATA_DIR}" \ 66 | --pretrained_model_checkpoint_path="${MODEL_PATH}" \ 67 | --fine_tune=False \ 68 | --initial_learning_rate=0.1 \ 69 | --input_queue_memory_factor=1 \ 70 | --num_gpus=1 \ 71 | --max_steps=1001 72 | 73 | ### test 74 | 75 | TRAIN_DIR=DIR for train models 76 | EVAL_DIR= DIR for eval event logs 77 | RAP_DATA_DIR=DIR for rap tensorflow TFRecord file 78 | 79 | 80 | bazel-bin/inception/rap_eval \ 81 | --eval_dir="${EVAL_DIR}" \ 82 | --data_dir="${RAP_DATA_DIR}" \ 83 | --subset=validation \ 84 | --num_examples=8317 \ 85 | --checkpoint_dir="${TRAIN_DIR}" \ 86 | --input_queue_memory_factor=1 \ 87 | --run_once 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "inception") 2 | -------------------------------------------------------------------------------- /inception/BUILD: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Example TensorFlow models for ImageNet. 3 | 4 | package(default_visibility = [":internal"]) 5 | 6 | licenses(["notice"]) # Apache 2.0 7 | 8 | exports_files(["LICENSE"]) 9 | 10 | package_group( 11 | name = "internal", 12 | packages = ["//inception/..."], 13 | ) 14 | 15 | py_library( 16 | name = "dataset", 17 | srcs = [ 18 | "dataset.py", 19 | ], 20 | ) 21 | 22 | py_library( 23 | name = "imagenet_data", 24 | srcs = [ 25 | "imagenet_data.py", 26 | ], 27 | deps = [ 28 | ":dataset", 29 | ], 30 | ) 31 | 32 | py_library( 33 | name = "flowers_data", 34 | srcs = [ 35 | "flowers_data.py", 36 | ], 37 | deps = [ 38 | ":dataset", 39 | ], 40 | ) 41 | 42 | py_library( 43 | name = "rap_data", 44 | srcs = [ 45 | "rap_data.py", 46 | ], 47 | deps = [ 48 | ":dataset", 49 | ], 50 | ) 51 | 52 | py_library( 53 | name = "peta_data", 54 | srcs = [ 55 | "peta_data.py", 56 | ], 57 | deps = [ 58 | ":dataset", 59 | ], 60 | ) 61 | 62 | py_library( 63 | name = "image_processing", 64 | srcs = [ 65 | "image_processing.py", 66 | ], 67 | ) 68 | 69 | py_library( 70 | name = "inception", 71 | srcs = [ 72 | "inception_model.py", 73 | ], 74 | visibility = ["//visibility:public"], 75 | deps = [ 76 | ":dataset", 77 | "//inception/slim", 78 | ], 79 | ) 80 | 81 | py_library( 82 | name = "inception_rap", 83 | srcs = [ 84 | "inception_rap_model.py", 85 | ], 86 | visibility = ["//visibility:public"], 87 | deps = [ 88 | ":dataset", 89 | "//inception/slim", 90 | ], 91 | ) 92 | 93 | py_library( 94 | name = "inception_peta", 95 | srcs = [ 96 | "inception_peta_model.py", 97 | ], 98 | visibility = ["//visibility:public"], 99 | deps = [ 100 | ":dataset", 101 | "//inception/slim", 102 | ], 103 | ) 104 | 105 | py_library( 106 | name = "inception_region", 107 | srcs = [ 108 | "inception_region_model.py", 109 | ], 110 | visibility = ["//visibility:public"], 111 | deps = [ 112 | ":dataset", 113 | "//inception/slim", 114 | ], 115 | ) 116 | 117 | 118 | py_binary( 119 | name = "imagenet_eval", 120 | srcs = [ 121 | "imagenet_eval.py", 122 | ], 123 | deps = [ 124 | ":imagenet_data", 125 | ":inception_eval", 126 | ], 127 | ) 128 | 129 | py_binary( 130 | name = "flowers_eval", 131 | srcs = [ 132 | "flowers_eval.py", 133 | ], 134 | deps = [ 135 | ":flowers_data", 136 | ":inception_eval", 137 | ], 138 | ) 139 | 140 | py_binary( 141 | name = "rap_eval", 142 | srcs = [ 143 | "rap_eval.py", 144 | ], 145 | deps = [ 146 | ":rap_data", 147 | ":inception_rap_eval", 148 | ], 149 | ) 150 | py_binary( 151 | name = "peta_eval", 152 | srcs = [ 153 | "peta_eval.py", 154 | ], 155 | deps = [ 156 | ":peta_data", 157 | ":inception_peta_eval", 158 | ], 159 | ) 160 | 161 | py_library( 162 | name = "inception_eval", 163 | srcs = [ 164 | "inception_eval.py", 165 | ], 166 | deps = [ 167 | ":image_processing", 168 | ":inception_rap", 169 | ], 170 | ) 171 | 172 | py_library( 173 | name = "inception_rap_eval", 174 | srcs = [ 175 | "inception_rap_eval.py", 176 | ], 177 | deps = [ 178 | ":image_processing", 179 | ":inception_rap", 180 | ], 181 | ) 182 | 183 | py_library( 184 | name = "inception_peta_eval", 185 | srcs = [ 186 | "inception_peta_eval.py", 187 | ], 188 | deps = [ 189 | ":image_processing", 190 | ":inception_peta", 191 | ], 192 | ) 193 | 194 | 195 | py_binary( 196 | name = "imagenet_train", 197 | srcs = [ 198 | "imagenet_train.py", 199 | ], 200 | deps = [ 201 | ":imagenet_data", 202 | ":inception_train", 203 | ], 204 | ) 205 | 206 | py_binary( 207 | name = "imagenet_distributed_train", 208 | srcs = [ 209 | "imagenet_distributed_train.py", 210 | ], 211 | deps = [ 212 | ":imagenet_data", 213 | ":inception_distributed_train", 214 | ], 215 | ) 216 | 217 | py_binary( 218 | name = "flowers_train", 219 | srcs = [ 220 | "flowers_train.py", 221 | ], 222 | deps = [ 223 | ":flowers_data", 224 | ":inception_train", 225 | ], 226 | ) 227 | 228 | py_binary( 229 | name = "rap_train", 230 | srcs = [ 231 | "rap_train.py", 232 | ], 233 | deps = [ 234 | ":rap_data", 235 | ":inception_rap_train", 236 | ], 237 | ) 238 | 239 | py_binary( 240 | name = "peta_train", 241 | srcs = [ 242 | "peta_train.py", 243 | ], 244 | deps = [ 245 | ":peta_data", 246 | ":inception_peta_train", 247 | ], 248 | ) 249 | 250 | 251 | py_library( 252 | name = "inception_train", 253 | srcs = [ 254 | "inception_train.py", 255 | ], 256 | deps = [ 257 | ":image_processing", 258 | ":inception", 259 | ], 260 | ) 261 | 262 | py_library( 263 | name = "inception_rap_train", 264 | srcs = [ 265 | "inception_rap_train.py", 266 | ], 267 | deps = [ 268 | ":image_processing", 269 | ":inception_rap", 270 | ], 271 | ) 272 | 273 | py_library( 274 | name = "inception_peta_train", 275 | srcs = [ 276 | "inception_peta_train.py", 277 | ], 278 | deps = [ 279 | ":image_processing", 280 | ":inception_peta", 281 | ], 282 | ) 283 | 284 | py_library( 285 | name = "inception_distributed_train", 286 | srcs = [ 287 | "inception_distributed_train.py", 288 | ], 289 | deps = [ 290 | ":image_processing", 291 | ":inception", 292 | ], 293 | ) 294 | 295 | py_binary( 296 | name = "build_image_data", 297 | srcs = ["data/build_image_data.py"], 298 | ) 299 | 300 | sh_binary( 301 | name = "download_and_preprocess_flowers", 302 | srcs = ["data/download_and_preprocess_flowers.sh"], 303 | data = [ 304 | ":build_image_data", 305 | ], 306 | ) 307 | 308 | sh_binary( 309 | name = "download_and_preprocess_imagenet", 310 | srcs = ["data/download_and_preprocess_imagenet.sh"], 311 | data = [ 312 | "data/download_imagenet.sh", 313 | "data/imagenet_2012_validation_synset_labels.txt", 314 | "data/imagenet_lsvrc_2015_synsets.txt", 315 | "data/imagenet_metadata.txt", 316 | "data/preprocess_imagenet_validation_data.py", 317 | "data/process_bounding_boxes.py", 318 | ":build_imagenet_data", 319 | ], 320 | ) 321 | 322 | py_binary( 323 | name = "build_imagenet_data", 324 | srcs = ["data/build_imagenet_data.py"], 325 | ) 326 | 327 | filegroup( 328 | name = "srcs", 329 | srcs = glob( 330 | [ 331 | "**/*.py", 332 | "BUILD", 333 | ], 334 | ), 335 | ) 336 | 337 | filegroup( 338 | name = "imagenet_metadata", 339 | srcs = [ 340 | "data/imagenet_lsvrc_2015_synsets.txt", 341 | "data/imagenet_metadata.txt", 342 | ], 343 | visibility = ["//visibility:public"], 344 | ) 345 | -------------------------------------------------------------------------------- /inception/data/build_peta_region_data.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Converts image data to TFRecords file format with Example protos. 16 | 17 | The image data set is expected to reside in JPEG files located in the 18 | following directory structure. 19 | 20 | data_dir/label_0/image0.jpeg 21 | data_dir/label_0/image1.jpg 22 | ... 23 | data_dir/label_1/weird-image.jpeg 24 | data_dir/label_1/my-image.jpeg 25 | ... 26 | 27 | where the sub-directory is the unique label associated with these images. 28 | 29 | This TensorFlow script converts the training and evaluation data into 30 | a sharded data set consisting of TFRecord files 31 | 32 | output_directory/train-00000-of-01024 33 | output_directory/train-00001-of-01024 34 | ... 35 | output_directory/train-01023-of-01024 36 | 37 | and 38 | 39 | output_directory/validation-00000-of-00128 40 | output_directory/validation-00001-of-00128 41 | ... 42 | output_directory/validation-00127-of-00128 43 | 44 | where we have selected 1024 and 128 shards for each data set. Each record 45 | within the TFRecord file is a serialized Example proto. The Example proto 46 | contains the following fields: 47 | 48 | image/encoded: string containing JPEG encoded image in RGB colorspace 49 | image/height: integer, image height in pixels 50 | image/width: integer, image width in pixels 51 | image/colorspace: string, specifying the colorspace, always 'RGB' 52 | image/channels: integer, specifying the number of channels, always 3 53 | image/format: string, specifying the format, always 'JPEG' 54 | 55 | image/filename: string containing the basename of the image file 56 | e.g. 'n01440764_10026.JPEG' or 'ILSVRC2012_val_00000293.JPEG' 57 | image/class/label: integer specifying the index in a classification layer. 58 | The label ranges from [0, num_labels] where 0 is unused and left as 59 | the background class. 60 | image/class/text: string specifying the human-readable version of the label 61 | e.g. 'dog' 62 | 63 | If your data set involves bounding boxes, please look at build_imagenet_data.py. 64 | """ 65 | from __future__ import absolute_import 66 | from __future__ import division 67 | from __future__ import print_function 68 | 69 | from datetime import datetime 70 | import os 71 | import random 72 | import sys 73 | import threading 74 | 75 | import numpy as np 76 | import tensorflow as tf 77 | 78 | tf.app.flags.DEFINE_string('output_directory', '', 79 | 'Output data directory') 80 | 81 | tf.app.flags.DEFINE_integer('train_shards', 10, 82 | 'Number of shards in training TFRecord files.') 83 | tf.app.flags.DEFINE_integer('validation_shards', 10, 84 | 'Number of shards in validation TFRecord files.') 85 | 86 | tf.app.flags.DEFINE_integer('num_threads', 10, 87 | 'Number of threads to preprocess the images.') 88 | 89 | tf.app.flags.DEFINE_string('train_txt', '', 'Training txt file') 90 | tf.app.flags.DEFINE_string('test_txt', '', 'Testing txt files') 91 | tf.app.flags.DEFINE_string('image_dir', '', 'Image dir') 92 | 93 | 94 | # The labels file contains a list of valid labels are held in this file. 95 | # Assumes that the file contains entries as such: 96 | # dog 97 | # cat 98 | # flower 99 | # where each line corresponds to a label. We map each label contained in 100 | # the file to an integer corresponding to the line number starting from 0. 101 | tf.app.flags.DEFINE_string('labels_file', '', 'Labels file') 102 | 103 | 104 | FLAGS = tf.app.flags.FLAGS 105 | 106 | 107 | def _int64_feature(value): 108 | """Wrapper for inserting int64 features into Example proto.""" 109 | if not isinstance(value, list): 110 | value = [value] 111 | return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) 112 | 113 | 114 | def _bytes_feature(value): 115 | """Wrapper for inserting bytes features into Example proto.""" 116 | return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 117 | 118 | def _int64_list_feature(value): 119 | return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) 120 | 121 | def _float_list_feature(value): 122 | return tf.train.Feature(float_list=tf.train.FloatList(value=value)) 123 | 124 | def _convert_to_example(filename, image_buffer, label, text, roi, height, width): 125 | """Build an Example proto for an example. 126 | 127 | Args: 128 | filename: string, path to an image file, e.g., '/path/to/example.JPG' 129 | image_buffer: string, JPEG encoding of RGB image 130 | label: integer, identifier for the ground truth for the network 131 | text: string, unique human-readable, e.g. 'dog' 132 | height: integer, image height in pixels 133 | width: integer, image width in pixels 134 | Returns: 135 | Example proto 136 | """ 137 | 138 | colorspace = 'RGB' 139 | channels = 3 140 | image_format = 'JPEG' 141 | 142 | example = tf.train.Example(features=tf.train.Features(feature={ 143 | 'image/height': _int64_feature(height), 144 | 'image/width': _int64_feature(width), 145 | 'image/colorspace': _bytes_feature(tf.compat.as_bytes(colorspace)), 146 | 'image/channels': _int64_feature(channels), 147 | 'image/class/label': _int64_list_feature(label), 148 | 'image/class/text': _bytes_feature(tf.compat.as_bytes(' '.join(text))), 149 | 'image/format': _bytes_feature(tf.compat.as_bytes(image_format)), 150 | 'image/filename': _bytes_feature(tf.compat.as_bytes(os.path.basename(filename))), 151 | 'image/encoded': _bytes_feature(tf.compat.as_bytes(image_buffer)), 152 | 'image/roi': _float_list_feature(roi)})) 153 | return example 154 | 155 | 156 | class ImageCoder(object): 157 | """Helper class that provides TensorFlow image coding utilities.""" 158 | 159 | def __init__(self): 160 | # Create a single Session to run all image coding calls. 161 | self._sess = tf.Session() 162 | 163 | # Initializes function that converts PNG to JPEG data. 164 | self._png_data = tf.placeholder(dtype=tf.string) 165 | image = tf.image.decode_png(self._png_data, channels=3) 166 | self._png_to_jpeg = tf.image.encode_jpeg(image, format='rgb', quality=100) 167 | 168 | # Initializes function that decodes RGB JPEG data. 169 | self._decode_jpeg_data = tf.placeholder(dtype=tf.string) 170 | self._decode_jpeg = tf.image.decode_jpeg(self._decode_jpeg_data, channels=3) 171 | 172 | def png_to_jpeg(self, image_data): 173 | return self._sess.run(self._png_to_jpeg, 174 | feed_dict={self._png_data: image_data}) 175 | 176 | def decode_jpeg(self, image_data): 177 | image = self._sess.run(self._decode_jpeg, 178 | feed_dict={self._decode_jpeg_data: image_data}) 179 | assert len(image.shape) == 3 180 | assert image.shape[2] == 3 181 | return image 182 | 183 | 184 | def _is_png(filename): 185 | """Determine if a file contains a PNG format image. 186 | 187 | Args: 188 | filename: string, path of the image file. 189 | 190 | Returns: 191 | boolean indicating if the image is a PNG. 192 | """ 193 | return filename.endswith('.png') 194 | 195 | 196 | def _process_image(filename, coder): 197 | """Process a single image file. 198 | 199 | Args: 200 | filename: string, path to an image file e.g., '/path/to/example.JPG'. 201 | coder: instance of ImageCoder to provide TensorFlow image coding utils. 202 | Returns: 203 | image_buffer: string, JPEG encoding of RGB image. 204 | height: integer, image height in pixels. 205 | width: integer, image width in pixels. 206 | """ 207 | # Read the image file. 208 | with tf.gfile.FastGFile(filename, 'rb') as f: 209 | image_data = f.read() 210 | 211 | # Convert any PNG to JPEG's for consistency. 212 | if _is_png(filename): 213 | print('Converting PNG to JPEG for %s' % filename) 214 | image_data = coder.png_to_jpeg(image_data) 215 | 216 | # Decode the RGB JPEG. 217 | image = coder.decode_jpeg(image_data) 218 | 219 | # Check that image converted to RGB 220 | assert len(image.shape) == 3 221 | height = image.shape[0] 222 | width = image.shape[1] 223 | assert image.shape[2] == 3 224 | 225 | return image_data, height, width 226 | 227 | 228 | 229 | def _process_image_files_batch(coder, thread_index, ranges, name, filenames, 230 | texts, labels, rois, num_shards): 231 | """Processes and saves list of images as TFRecord in 1 thread. 232 | 233 | Args: 234 | coder: instance of ImageCoder to provide TensorFlow image coding utils. 235 | thread_index: integer, unique batch to run index is within [0, len(ranges)). 236 | ranges: list of pairs of integers specifying ranges of each batches to 237 | analyze in parallel. 238 | name: string, unique identifier specifying the data set 239 | filenames: list of strings; each string is a path to an image file 240 | texts: list of strings; each string is human readable, e.g. 'dog' 241 | labels: list of integer; each integer identifies the ground truth 242 | num_shards: integer number of shards for this data set. 243 | """ 244 | # Each thread produces N shards where N = int(num_shards / num_threads). 245 | # For instance, if num_shards = 128, and the num_threads = 2, then the first 246 | # thread would produce shards [0, 64). 247 | num_threads = len(ranges) 248 | assert not num_shards % num_threads 249 | num_shards_per_batch = int(num_shards / num_threads) 250 | 251 | shard_ranges = np.linspace(ranges[thread_index][0], 252 | ranges[thread_index][1], 253 | num_shards_per_batch + 1).astype(int) 254 | num_files_in_thread = ranges[thread_index][1] - ranges[thread_index][0] 255 | 256 | labels = np.asarray(labels) 257 | counter = 0 258 | for s in range(num_shards_per_batch): 259 | # Generate a sharded version of the file name, e.g. 'train-00002-of-00010' 260 | shard = thread_index * num_shards_per_batch + s 261 | output_filename = '%s-%.5d-of-%.5d' % (name, shard, num_shards) 262 | output_file = os.path.join(FLAGS.output_directory, output_filename) 263 | writer = tf.python_io.TFRecordWriter(output_file) 264 | 265 | shard_counter = 0 266 | files_in_shard = np.arange(shard_ranges[s], shard_ranges[s + 1], dtype=int) 267 | for i in files_in_shard: 268 | filename = filenames[i] 269 | label = labels[i] 270 | text = texts[i] 271 | roi = rois[i] 272 | 273 | try: 274 | image_buffer, height, width = _process_image(filename, coder) 275 | except Exception as e: 276 | print(e) 277 | print('SKIPPED: Unexpected error while decoding %s.' % filename) 278 | continue 279 | 280 | example = _convert_to_example(filename, image_buffer, label, 281 | text, roi, height, width) 282 | writer.write(example.SerializeToString()) 283 | shard_counter += 1 284 | counter += 1 285 | 286 | if not counter % 1000: 287 | print('%s [thread %d]: Processed %d of %d images in thread batch.' % 288 | (datetime.now(), thread_index, counter, num_files_in_thread)) 289 | sys.stdout.flush() 290 | 291 | writer.close() 292 | print('%s [thread %d]: Wrote %d images to %s' % 293 | (datetime.now(), thread_index, shard_counter, output_file)) 294 | sys.stdout.flush() 295 | shard_counter = 0 296 | print('%s [thread %d]: Wrote %d images to %d shards.' % 297 | (datetime.now(), thread_index, counter, num_files_in_thread)) 298 | sys.stdout.flush() 299 | 300 | 301 | def _process_image_files(name, filenames, texts, labels, rois, num_shards): 302 | """Process and save list of images as TFRecord of Example protos. 303 | 304 | Args: 305 | name: string, unique identifier specifying the data set 306 | filenames: list of strings; each string is a path to an image file 307 | texts: list of strings; each string is human readable, e.g. 'dog' 308 | labels: list of integer; each integer identifies the ground truth 309 | num_shards: integer number of shards for this data set. 310 | """ 311 | assert len(filenames) == len(texts) 312 | assert len(filenames) == len(labels) 313 | assert len(filenames) == len(rois) 314 | 315 | # Break all images into batches with a [ranges[i][0], ranges[i][1]]. 316 | spacing = np.linspace(0, len(filenames), FLAGS.num_threads + 1).astype(np.int) 317 | ranges = [] 318 | for i in range(len(spacing) - 1): 319 | ranges.append([spacing[i], spacing[i + 1]]) 320 | 321 | # Launch a thread for each batch. 322 | print('Launching %d threads for spacings: %s' % (FLAGS.num_threads, ranges)) 323 | sys.stdout.flush() 324 | 325 | # Create a mechanism for monitoring when all threads are finished. 326 | coord = tf.train.Coordinator() 327 | 328 | # Create a generic TensorFlow-based utility for converting all image codings. 329 | coder = ImageCoder() 330 | 331 | threads = [] 332 | for thread_index in range(len(ranges)): 333 | args = (coder, thread_index, ranges, name, filenames, 334 | texts, labels, rois, num_shards) 335 | t = threading.Thread(target=_process_image_files_batch, args=args) 336 | t.start() 337 | threads.append(t) 338 | 339 | # Wait for all the threads to terminate. 340 | coord.join(threads) 341 | print('%s: Finished writing all %d images in data set.' % 342 | (datetime.now(), len(filenames))) 343 | sys.stdout.flush() 344 | 345 | 346 | def _find_image_files(name, data_dir, labels_file): 347 | """Build a list of all images files and labels in the data set. 348 | 349 | Args: 350 | data_dir: string, path to the root directory of images. 351 | 352 | Assumes that the image data set resides in JPEG files located in 353 | the following directory structure. 354 | 355 | data_dir/dog/another-image.JPEG 356 | data_dir/dog/my-image.jpg 357 | 358 | where 'dog' is the label associated with these images. 359 | 360 | labels_file: string, path to the labels file. 361 | 362 | The list of valid labels are held in this file. Assumes that the file 363 | contains entries as such: 364 | dog 365 | cat 366 | flower 367 | where each line corresponds to a label. We map each label contained in 368 | the file to an integer starting with the integer 0 corresponding to the 369 | label contained in the first line. 370 | 371 | Returns: 372 | filenames: list of strings; each string is a path to an image file. 373 | texts: list of strings; each string is the class, e.g. 'dog' 374 | labels: list of integer; each integer identifies the ground truth. 375 | """ 376 | print('Determining list of input files and labels from %s.' % data_dir) 377 | unique_labels = [l.strip() for l in tf.gfile.FastGFile( 378 | labels_file, 'r').readlines()] 379 | 380 | labels = [] 381 | filenames = [] 382 | texts = [] 383 | rois = [] 384 | 385 | # # Leave label index 0 empty as a background class. 386 | # label_index = 1 387 | 388 | # # Construct the list of JPEG files and labels. 389 | # for text in unique_labels: 390 | # jpeg_file_path = '%s/%s/*' % (data_dir, text) 391 | # matching_files = tf.gfile.Glob(jpeg_file_path) 392 | 393 | # labels.extend([label_index] * len(matching_files)) 394 | # texts.extend([text] * len(matching_files)) 395 | # filenames.extend(matching_files) 396 | 397 | # if not label_index % 100: 398 | # print('Finished finding files in %d of %d classes.' % ( 399 | # label_index, len(labels))) 400 | # label_index += 1 401 | if name == 'validation': 402 | print(FLAGS.test_txt) 403 | image_lists = [l.strip() for l in tf.gfile.FastGFile(FLAGS.test_txt, 'r').readlines()] 404 | else: 405 | image_lists = [l.strip() for l in tf.gfile.FastGFile(FLAGS.train_txt, 'r').readlines()] 406 | 407 | print(len(image_lists)) 408 | 409 | for i in range(len(image_lists)): 410 | if i % 7 != 0: 411 | continue 412 | image_file_path = os.path.join(FLAGS.image_dir, image_lists[i+1]) 413 | arrays = image_lists[i+2].split() 414 | label = [int((int(x)+1) / 2) for x in arrays] 415 | roi = [] 416 | for j in range(3, 7): 417 | arrays = image_lists[i+j].split() 418 | for r in arrays: 419 | roi.append(float(r)) 420 | filenames.append(image_file_path) 421 | labels.append(label) 422 | rois.append(roi) 423 | texts.append('useless') 424 | 425 | """ 426 | for image in image_lists: 427 | arrays = image.split() 428 | image_file_path = os.path.join(FLAGS.image_dir, arrays[0]) 429 | label = [] 430 | text = [] 431 | # gender age 432 | ind = 0 433 | for i in range(4): 434 | label.append(int(arrays[i+1])) 435 | text.append(unique_labels[ind]) 436 | ind+=1 437 | # head 438 | for i in range(9, 15): 439 | label.append(int(arrays[i+1])) 440 | text.append(unique_labels[ind]) 441 | ind+=1 442 | # up 443 | for i in range(15, 24): 444 | label.append(int(arrays[i+1])) 445 | text.append(unique_labels[ind]) 446 | ind+=1 447 | #down 448 | for i in range(24, 30): 449 | label.append(int(arrays[i+1])) 450 | text.append(unique_labels[i]) 451 | ind+=1 452 | # shoes 453 | for i in range(30, 35): 454 | label.append(int(arrays[i+1])) 455 | text.append(unique_labels[ind]) 456 | ind+=1 457 | filenames.append(image_file_path) 458 | for i in range(len(label)): 459 | if label[i] == -1: 460 | label[i] = 0 461 | filenames.append(image_file_path) 462 | 463 | for i in range(51): 464 | tmp = int(arrays[i+1]) 465 | if tmp == -1: 466 | tmp = 0 467 | label.append(tmp) 468 | text.append('useless') 469 | labels.append(label) 470 | texts.append(text) 471 | """ 472 | 473 | # Shuffle the ordering of all image files in order to guarantee 474 | # random ordering of the images with respect to label in the 475 | # saved TFRecord files. Make the randomization repeatable. 476 | shuffled_index = list(range(len(filenames))) 477 | random.seed(12345) 478 | random.shuffle(shuffled_index) 479 | 480 | filenames = [filenames[i] for i in shuffled_index] 481 | texts = [texts[i] for i in shuffled_index] 482 | labels = [labels[i] for i in shuffled_index] 483 | rois = [rois[i] for i in shuffled_index] 484 | 485 | print('Found %d JPEG files across %d labels inside %s.' % 486 | (len(filenames), len(unique_labels), data_dir)) 487 | return filenames, texts, labels, rois 488 | 489 | 490 | def _process_dataset(name, directory, num_shards, labels_file): 491 | """Process a complete data set and save it as a TFRecord. 492 | 493 | Args: 494 | name: string, unique identifier specifying the data set. 495 | directory: string, root path to the data set. 496 | num_shards: integer number of shards for this data set. 497 | labels_file: string, path to the labels file. 498 | """ 499 | filenames, texts, labels, rois = _find_image_files(name, directory, labels_file) 500 | _process_image_files(name, filenames, texts, labels, rois, num_shards) 501 | 502 | 503 | def main(unused_argv): 504 | assert not FLAGS.train_shards % FLAGS.num_threads, ( 505 | 'Please make the FLAGS.num_threads commensurate with FLAGS.train_shards') 506 | assert not FLAGS.validation_shards % FLAGS.num_threads, ( 507 | 'Please make the FLAGS.num_threads commensurate with ' 508 | 'FLAGS.validation_shards') 509 | print('Saving results to %s' % FLAGS.output_directory) 510 | 511 | # Run it! 512 | _process_dataset('validation', FLAGS.image_dir, 513 | FLAGS.validation_shards, FLAGS.labels_file) 514 | _process_dataset('train', FLAGS.image_dir, 515 | FLAGS.train_shards, FLAGS.labels_file) 516 | 517 | 518 | if __name__ == '__main__': 519 | tf.app.run() 520 | -------------------------------------------------------------------------------- /inception/data/build_rap_region_data.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Converts image data to TFRecords file format with Example protos. 16 | 17 | The image data set is expected to reside in JPEG files located in the 18 | following directory structure. 19 | 20 | data_dir/label_0/image0.jpeg 21 | data_dir/label_0/image1.jpg 22 | ... 23 | data_dir/label_1/weird-image.jpeg 24 | data_dir/label_1/my-image.jpeg 25 | ... 26 | 27 | where the sub-directory is the unique label associated with these images. 28 | 29 | This TensorFlow script converts the training and evaluation data into 30 | a sharded data set consisting of TFRecord files 31 | 32 | output_directory/train-00000-of-01024 33 | output_directory/train-00001-of-01024 34 | ... 35 | output_directory/train-01023-of-01024 36 | 37 | and 38 | 39 | output_directory/validation-00000-of-00128 40 | output_directory/validation-00001-of-00128 41 | ... 42 | output_directory/validation-00127-of-00128 43 | 44 | where we have selected 1024 and 128 shards for each data set. Each record 45 | within the TFRecord file is a serialized Example proto. The Example proto 46 | contains the following fields: 47 | 48 | image/encoded: string containing JPEG encoded image in RGB colorspace 49 | image/height: integer, image height in pixels 50 | image/width: integer, image width in pixels 51 | image/colorspace: string, specifying the colorspace, always 'RGB' 52 | image/channels: integer, specifying the number of channels, always 3 53 | image/format: string, specifying the format, always 'JPEG' 54 | 55 | image/filename: string containing the basename of the image file 56 | e.g. 'n01440764_10026.JPEG' or 'ILSVRC2012_val_00000293.JPEG' 57 | image/class/label: integer specifying the index in a classification layer. 58 | The label ranges from [0, num_labels] where 0 is unused and left as 59 | the background class. 60 | image/class/text: string specifying the human-readable version of the label 61 | e.g. 'dog' 62 | 63 | If your data set involves bounding boxes, please look at build_imagenet_data.py. 64 | """ 65 | from __future__ import absolute_import 66 | from __future__ import division 67 | from __future__ import print_function 68 | 69 | from datetime import datetime 70 | import os 71 | import random 72 | import sys 73 | import threading 74 | 75 | import numpy as np 76 | import tensorflow as tf 77 | 78 | tf.app.flags.DEFINE_string('output_directory', '/home/sangliufang/ijcai/inception/rap/', 79 | 'Output data directory') 80 | 81 | tf.app.flags.DEFINE_integer('train_shards', 10, 82 | 'Number of shards in training TFRecord files.') 83 | tf.app.flags.DEFINE_integer('validation_shards', 10, 84 | 'Number of shards in validation TFRecord files.') 85 | 86 | tf.app.flags.DEFINE_integer('num_threads', 10, 87 | 'Number of threads to preprocess the images.') 88 | 89 | tf.app.flags.DEFINE_string('train_txt', '/home/sangliufang/ijcai/inception/rap/train_p.txt', 'Training txt file') 90 | tf.app.flags.DEFINE_string('test_txt', '/home/sangliufang/ijcai/inception/rap/test_p.txt', 'Testing txt files') 91 | tf.app.flags.DEFINE_string('image_dir', '/home/sangliufang/ijcai/inception/rap/RAP_dataset/', 'Image dir') 92 | 93 | 94 | # The labels file contains a list of valid labels are held in this file. 95 | # Assumes that the file contains entries as such: 96 | # dog 97 | # cat 98 | # flower 99 | # where each line corresponds to a label. We map each label contained in 100 | # the file to an integer corresponding to the line number starting from 0. 101 | tf.app.flags.DEFINE_string('labels_file', '/home/sangliufang/ijcai/inception/data/rap/rap_labels.txt', 'Labels file') 102 | 103 | 104 | FLAGS = tf.app.flags.FLAGS 105 | 106 | 107 | def _int64_feature(value): 108 | """Wrapper for inserting int64 features into Example proto.""" 109 | if not isinstance(value, list): 110 | value = [value] 111 | return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) 112 | 113 | 114 | def _bytes_feature(value): 115 | """Wrapper for inserting bytes features into Example proto.""" 116 | return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 117 | 118 | def _int64_list_feature(value): 119 | return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) 120 | 121 | def _float_list_feature(value): 122 | return tf.train.Feature(float_list=tf.train.FloatList(value=value)) 123 | 124 | def _convert_to_example(filename, image_buffer, label, text, roi, height, width): 125 | """Build an Example proto for an example. 126 | 127 | Args: 128 | filename: string, path to an image file, e.g., '/path/to/example.JPG' 129 | image_buffer: string, JPEG encoding of RGB image 130 | label: integer, identifier for the ground truth for the network 131 | text: string, unique human-readable, e.g. 'dog' 132 | height: integer, image height in pixels 133 | width: integer, image width in pixels 134 | Returns: 135 | Example proto 136 | """ 137 | 138 | colorspace = 'RGB' 139 | channels = 3 140 | image_format = 'JPEG' 141 | 142 | example = tf.train.Example(features=tf.train.Features(feature={ 143 | 'image/height': _int64_feature(height), 144 | 'image/width': _int64_feature(width), 145 | 'image/colorspace': _bytes_feature(tf.compat.as_bytes(colorspace)), 146 | 'image/channels': _int64_feature(channels), 147 | 'image/class/label': _int64_list_feature(label), 148 | 'image/class/text': _bytes_feature(tf.compat.as_bytes(' '.join(text))), 149 | 'image/format': _bytes_feature(tf.compat.as_bytes(image_format)), 150 | 'image/filename': _bytes_feature(tf.compat.as_bytes(os.path.basename(filename))), 151 | 'image/encoded': _bytes_feature(tf.compat.as_bytes(image_buffer)), 152 | 'image/roi': _float_list_feature(roi)})) 153 | return example 154 | 155 | 156 | class ImageCoder(object): 157 | """Helper class that provides TensorFlow image coding utilities.""" 158 | 159 | def __init__(self): 160 | # Create a single Session to run all image coding calls. 161 | self._sess = tf.Session() 162 | 163 | # Initializes function that converts PNG to JPEG data. 164 | self._png_data = tf.placeholder(dtype=tf.string) 165 | image = tf.image.decode_png(self._png_data, channels=3) 166 | self._png_to_jpeg = tf.image.encode_jpeg(image, format='rgb', quality=100) 167 | 168 | # Initializes function that decodes RGB JPEG data. 169 | self._decode_jpeg_data = tf.placeholder(dtype=tf.string) 170 | self._decode_jpeg = tf.image.decode_jpeg(self._decode_jpeg_data, channels=3) 171 | 172 | def png_to_jpeg(self, image_data): 173 | return self._sess.run(self._png_to_jpeg, 174 | feed_dict={self._png_data: image_data}) 175 | 176 | def decode_jpeg(self, image_data): 177 | image = self._sess.run(self._decode_jpeg, 178 | feed_dict={self._decode_jpeg_data: image_data}) 179 | assert len(image.shape) == 3 180 | assert image.shape[2] == 3 181 | return image 182 | 183 | 184 | def _is_png(filename): 185 | """Determine if a file contains a PNG format image. 186 | 187 | Args: 188 | filename: string, path of the image file. 189 | 190 | Returns: 191 | boolean indicating if the image is a PNG. 192 | """ 193 | return filename.endswith('.png') 194 | 195 | 196 | def _process_image(filename, coder): 197 | """Process a single image file. 198 | 199 | Args: 200 | filename: string, path to an image file e.g., '/path/to/example.JPG'. 201 | coder: instance of ImageCoder to provide TensorFlow image coding utils. 202 | Returns: 203 | image_buffer: string, JPEG encoding of RGB image. 204 | height: integer, image height in pixels. 205 | width: integer, image width in pixels. 206 | """ 207 | # Read the image file. 208 | with tf.gfile.FastGFile(filename, 'rb') as f: 209 | image_data = f.read() 210 | 211 | # Convert any PNG to JPEG's for consistency. 212 | if _is_png(filename): 213 | print('Converting PNG to JPEG for %s' % filename) 214 | image_data = coder.png_to_jpeg(image_data) 215 | 216 | # Decode the RGB JPEG. 217 | image = coder.decode_jpeg(image_data) 218 | 219 | # Check that image converted to RGB 220 | assert len(image.shape) == 3 221 | height = image.shape[0] 222 | width = image.shape[1] 223 | assert image.shape[2] == 3 224 | 225 | return image_data, height, width 226 | 227 | 228 | 229 | def _process_image_files_batch(coder, thread_index, ranges, name, filenames, 230 | texts, labels, rois, num_shards): 231 | """Processes and saves list of images as TFRecord in 1 thread. 232 | 233 | Args: 234 | coder: instance of ImageCoder to provide TensorFlow image coding utils. 235 | thread_index: integer, unique batch to run index is within [0, len(ranges)). 236 | ranges: list of pairs of integers specifying ranges of each batches to 237 | analyze in parallel. 238 | name: string, unique identifier specifying the data set 239 | filenames: list of strings; each string is a path to an image file 240 | texts: list of strings; each string is human readable, e.g. 'dog' 241 | labels: list of integer; each integer identifies the ground truth 242 | num_shards: integer number of shards for this data set. 243 | """ 244 | # Each thread produces N shards where N = int(num_shards / num_threads). 245 | # For instance, if num_shards = 128, and the num_threads = 2, then the first 246 | # thread would produce shards [0, 64). 247 | num_threads = len(ranges) 248 | assert not num_shards % num_threads 249 | num_shards_per_batch = int(num_shards / num_threads) 250 | 251 | shard_ranges = np.linspace(ranges[thread_index][0], 252 | ranges[thread_index][1], 253 | num_shards_per_batch + 1).astype(int) 254 | num_files_in_thread = ranges[thread_index][1] - ranges[thread_index][0] 255 | 256 | labels = np.asarray(labels) 257 | counter = 0 258 | for s in range(num_shards_per_batch): 259 | # Generate a sharded version of the file name, e.g. 'train-00002-of-00010' 260 | shard = thread_index * num_shards_per_batch + s 261 | output_filename = '%s-%.5d-of-%.5d' % (name, shard, num_shards) 262 | output_file = os.path.join(FLAGS.output_directory, output_filename) 263 | writer = tf.python_io.TFRecordWriter(output_file) 264 | 265 | shard_counter = 0 266 | files_in_shard = np.arange(shard_ranges[s], shard_ranges[s + 1], dtype=int) 267 | for i in files_in_shard: 268 | filename = filenames[i] 269 | label = labels[i] 270 | text = texts[i] 271 | roi = rois[i] 272 | 273 | try: 274 | image_buffer, height, width = _process_image(filename, coder) 275 | except Exception as e: 276 | print(e) 277 | print('SKIPPED: Unexpected error while decoding %s.' % filename) 278 | continue 279 | 280 | example = _convert_to_example(filename, image_buffer, label, 281 | text, roi, height, width) 282 | writer.write(example.SerializeToString()) 283 | shard_counter += 1 284 | counter += 1 285 | 286 | if not counter % 1000: 287 | print('%s [thread %d]: Processed %d of %d images in thread batch.' % 288 | (datetime.now(), thread_index, counter, num_files_in_thread)) 289 | sys.stdout.flush() 290 | 291 | writer.close() 292 | print('%s [thread %d]: Wrote %d images to %s' % 293 | (datetime.now(), thread_index, shard_counter, output_file)) 294 | sys.stdout.flush() 295 | shard_counter = 0 296 | print('%s [thread %d]: Wrote %d images to %d shards.' % 297 | (datetime.now(), thread_index, counter, num_files_in_thread)) 298 | sys.stdout.flush() 299 | 300 | 301 | def _process_image_files(name, filenames, texts, labels, rois, num_shards): 302 | """Process and save list of images as TFRecord of Example protos. 303 | 304 | Args: 305 | name: string, unique identifier specifying the data set 306 | filenames: list of strings; each string is a path to an image file 307 | texts: list of strings; each string is human readable, e.g. 'dog' 308 | labels: list of integer; each integer identifies the ground truth 309 | num_shards: integer number of shards for this data set. 310 | """ 311 | assert len(filenames) == len(texts) 312 | assert len(filenames) == len(labels) 313 | assert len(filenames) == len(rois) 314 | 315 | # Break all images into batches with a [ranges[i][0], ranges[i][1]]. 316 | spacing = np.linspace(0, len(filenames), FLAGS.num_threads + 1).astype(np.int) 317 | ranges = [] 318 | for i in range(len(spacing) - 1): 319 | ranges.append([spacing[i], spacing[i + 1]]) 320 | 321 | # Launch a thread for each batch. 322 | print('Launching %d threads for spacings: %s' % (FLAGS.num_threads, ranges)) 323 | sys.stdout.flush() 324 | 325 | # Create a mechanism for monitoring when all threads are finished. 326 | coord = tf.train.Coordinator() 327 | 328 | # Create a generic TensorFlow-based utility for converting all image codings. 329 | coder = ImageCoder() 330 | 331 | threads = [] 332 | for thread_index in range(len(ranges)): 333 | args = (coder, thread_index, ranges, name, filenames, 334 | texts, labels, rois, num_shards) 335 | t = threading.Thread(target=_process_image_files_batch, args=args) 336 | t.start() 337 | threads.append(t) 338 | 339 | # Wait for all the threads to terminate. 340 | coord.join(threads) 341 | print('%s: Finished writing all %d images in data set.' % 342 | (datetime.now(), len(filenames))) 343 | sys.stdout.flush() 344 | 345 | 346 | def _find_image_files(name, data_dir, labels_file): 347 | """Build a list of all images files and labels in the data set. 348 | 349 | Args: 350 | data_dir: string, path to the root directory of images. 351 | 352 | Assumes that the image data set resides in JPEG files located in 353 | the following directory structure. 354 | 355 | data_dir/dog/another-image.JPEG 356 | data_dir/dog/my-image.jpg 357 | 358 | where 'dog' is the label associated with these images. 359 | 360 | labels_file: string, path to the labels file. 361 | 362 | The list of valid labels are held in this file. Assumes that the file 363 | contains entries as such: 364 | dog 365 | cat 366 | flower 367 | where each line corresponds to a label. We map each label contained in 368 | the file to an integer starting with the integer 0 corresponding to the 369 | label contained in the first line. 370 | 371 | Returns: 372 | filenames: list of strings; each string is a path to an image file. 373 | texts: list of strings; each string is the class, e.g. 'dog' 374 | labels: list of integer; each integer identifies the ground truth. 375 | """ 376 | print('Determining list of input files and labels from %s.' % data_dir) 377 | unique_labels = [l.strip() for l in tf.gfile.FastGFile( 378 | labels_file, 'r').readlines()] 379 | 380 | labels = [] 381 | filenames = [] 382 | texts = [] 383 | rois = [] 384 | 385 | if name == 'validation': 386 | print(FLAGS.test_txt) 387 | image_lists = [l.strip() for l in tf.gfile.FastGFile(FLAGS.test_txt, 'r').readlines()] 388 | else: 389 | image_lists = [l.strip() for l in tf.gfile.FastGFile(FLAGS.train_txt, 'r').readlines()] 390 | 391 | print(len(image_lists)) 392 | 393 | for i in range(len(image_lists)): 394 | if i % 10 != 0: 395 | continue 396 | image_file_path = os.path.join(FLAGS.image_dir, image_lists[i+1]) 397 | arrays = image_lists[i+2].split() 398 | label = [int((int(x)+1) / 2) for x in arrays] 399 | roi = [] 400 | for j in range(3, 10): 401 | arrays = image_lists[i+j].split() 402 | for r in arrays: 403 | roi.append(float(r)) 404 | filenames.append(image_file_path) 405 | labels.append(label) 406 | rois.append(roi) 407 | texts.append('useless') 408 | 409 | 410 | # Shuffle the ordering of all image files in order to guarantee 411 | # random ordering of the images with respect to label in the 412 | # saved TFRecord files. Make the randomization repeatable. 413 | shuffled_index = list(range(len(filenames))) 414 | random.seed(12345) 415 | random.shuffle(shuffled_index) 416 | 417 | filenames = [filenames[i] for i in shuffled_index] 418 | texts = [texts[i] for i in shuffled_index] 419 | labels = [labels[i] for i in shuffled_index] 420 | rois = [rois[i] for i in shuffled_index] 421 | 422 | print('Found %d JPEG files across %d labels inside %s.' % 423 | (len(filenames), len(unique_labels), data_dir)) 424 | return filenames, texts, labels, rois 425 | 426 | 427 | def _process_dataset(name, directory, num_shards, labels_file): 428 | """Process a complete data set and save it as a TFRecord. 429 | 430 | Args: 431 | name: string, unique identifier specifying the data set. 432 | directory: string, root path to the data set. 433 | num_shards: integer number of shards for this data set. 434 | labels_file: string, path to the labels file. 435 | """ 436 | filenames, texts, labels, rois = _find_image_files(name, directory, labels_file) 437 | _process_image_files(name, filenames, texts, labels, rois, num_shards) 438 | 439 | 440 | def main(unused_argv): 441 | assert not FLAGS.train_shards % FLAGS.num_threads, ( 442 | 'Please make the FLAGS.num_threads commensurate with FLAGS.train_shards') 443 | assert not FLAGS.validation_shards % FLAGS.num_threads, ( 444 | 'Please make the FLAGS.num_threads commensurate with ' 445 | 'FLAGS.validation_shards') 446 | print('Saving results to %s' % FLAGS.output_directory) 447 | 448 | # Run it! 449 | _process_dataset('validation', FLAGS.image_dir, 450 | FLAGS.validation_shards, FLAGS.labels_file) 451 | _process_dataset('train', FLAGS.image_dir, 452 | FLAGS.train_shards, FLAGS.labels_file) 453 | 454 | 455 | if __name__ == '__main__': 456 | tf.app.run() 457 | -------------------------------------------------------------------------------- /inception/dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Small library that points to a data set. 16 | 17 | Methods of Data class: 18 | data_files: Returns a python list of all (sharded) data set files. 19 | num_examples_per_epoch: Returns the number of examples in the data set. 20 | num_classes: Returns the number of classes in the data set. 21 | reader: Return a reader for a single entry from the data set. 22 | """ 23 | from __future__ import absolute_import 24 | from __future__ import division 25 | from __future__ import print_function 26 | 27 | from abc import ABCMeta 28 | from abc import abstractmethod 29 | import os 30 | 31 | 32 | import tensorflow as tf 33 | 34 | FLAGS = tf.app.flags.FLAGS 35 | 36 | # Basic model parameters. 37 | tf.app.flags.DEFINE_string('data_dir', '/', 38 | """Path to the processed data, i.e. """ 39 | """TFRecord of Example protos.""") 40 | 41 | 42 | class Dataset(object): 43 | """A simple class for handling data sets.""" 44 | __metaclass__ = ABCMeta 45 | 46 | def __init__(self, name, subset): 47 | """Initialize dataset using a subset and the path to the data.""" 48 | assert subset in self.available_subsets(), self.available_subsets() 49 | self.name = name 50 | self.subset = subset 51 | 52 | @abstractmethod 53 | def num_classes(self): 54 | """Returns the number of classes in the data set.""" 55 | pass 56 | # return 10 57 | 58 | @abstractmethod 59 | def num_examples_per_epoch(self): 60 | """Returns the number of examples in the data subset.""" 61 | pass 62 | # if self.subset == 'train': 63 | # return 10000 64 | # if self.subset == 'validation': 65 | # return 1000 66 | 67 | @abstractmethod 68 | def download_message(self): 69 | """Prints a download message for the Dataset.""" 70 | pass 71 | 72 | def available_subsets(self): 73 | """Returns the list of available subsets.""" 74 | return ['train', 'validation'] 75 | 76 | def data_files(self): 77 | """Returns a python list of all (sharded) data subset files. 78 | 79 | Returns: 80 | python list of all (sharded) data set files. 81 | Raises: 82 | ValueError: if there are not data_files matching the subset. 83 | """ 84 | tf_record_pattern = os.path.join(FLAGS.data_dir, '%s-*' % self.subset) 85 | data_files = tf.gfile.Glob(tf_record_pattern) 86 | if not data_files: 87 | print('No files found for dataset %s/%s at %s' % (self.name, 88 | self.subset, 89 | FLAGS.data_dir)) 90 | 91 | self.download_message() 92 | exit(-1) 93 | return data_files 94 | 95 | def reader(self): 96 | """Return a reader for a single entry from the data set. 97 | 98 | See io_ops.py for details of Reader class. 99 | 100 | Returns: 101 | Reader object that reads the data set. 102 | """ 103 | return tf.TFRecordReader() 104 | -------------------------------------------------------------------------------- /inception/inception_distributed_train.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A library to train Inception using multiple replicas with synchronous update. 16 | 17 | Please see accompanying README.md for details and instructions. 18 | """ 19 | from __future__ import absolute_import 20 | from __future__ import division 21 | from __future__ import print_function 22 | 23 | from datetime import datetime 24 | import os.path 25 | import time 26 | 27 | import numpy as np 28 | import tensorflow as tf 29 | 30 | from inception import image_processing 31 | from inception import inception_model as inception 32 | from inception.slim import slim 33 | 34 | FLAGS = tf.app.flags.FLAGS 35 | 36 | tf.app.flags.DEFINE_string('job_name', '', 'One of "ps", "worker"') 37 | tf.app.flags.DEFINE_string('ps_hosts', '', 38 | """Comma-separated list of hostname:port for the """ 39 | """parameter server jobs. e.g. """ 40 | """'machine1:2222,machine2:1111,machine2:2222'""") 41 | tf.app.flags.DEFINE_string('worker_hosts', '', 42 | """Comma-separated list of hostname:port for the """ 43 | """worker jobs. e.g. """ 44 | """'machine1:2222,machine2:1111,machine2:2222'""") 45 | tf.app.flags.DEFINE_string('protocol', 'grpc', 46 | """Communication protocol to use in distributed """ 47 | """execution (default grpc) """) 48 | 49 | tf.app.flags.DEFINE_string('train_dir', '/tmp/imagenet_train', 50 | """Directory where to write event logs """ 51 | """and checkpoint.""") 52 | tf.app.flags.DEFINE_integer('max_steps', 1000000, 'Number of batches to run.') 53 | tf.app.flags.DEFINE_string('subset', 'train', 'Either "train" or "validation".') 54 | tf.app.flags.DEFINE_boolean('log_device_placement', False, 55 | 'Whether to log device placement.') 56 | 57 | # Task ID is used to select the chief and also to access the local_step for 58 | # each replica to check staleness of the gradients in SyncReplicasOptimizer. 59 | tf.app.flags.DEFINE_integer( 60 | 'task_id', 0, 'Task ID of the worker/replica running the training.') 61 | 62 | # More details can be found in the SyncReplicasOptimizer class: 63 | # tensorflow/python/training/sync_replicas_optimizer.py 64 | tf.app.flags.DEFINE_integer('num_replicas_to_aggregate', -1, 65 | """Number of gradients to collect before """ 66 | """updating the parameters.""") 67 | tf.app.flags.DEFINE_integer('save_interval_secs', 10 * 60, 68 | 'Save interval seconds.') 69 | tf.app.flags.DEFINE_integer('save_summaries_secs', 180, 70 | 'Save summaries interval seconds.') 71 | 72 | # **IMPORTANT** 73 | # Please note that this learning rate schedule is heavily dependent on the 74 | # hardware architecture, batch size and any changes to the model architecture 75 | # specification. Selecting a finely tuned learning rate schedule is an 76 | # empirical process that requires some experimentation. Please see README.md 77 | # more guidance and discussion. 78 | # 79 | # Learning rate decay factor selected from https://arxiv.org/abs/1604.00981 80 | tf.app.flags.DEFINE_float('initial_learning_rate', 0.045, 81 | 'Initial learning rate.') 82 | tf.app.flags.DEFINE_float('num_epochs_per_decay', 2.0, 83 | 'Epochs after which learning rate decays.') 84 | tf.app.flags.DEFINE_float('learning_rate_decay_factor', 0.94, 85 | 'Learning rate decay factor.') 86 | 87 | # Constants dictating the learning rate schedule. 88 | RMSPROP_DECAY = 0.9 # Decay term for RMSProp. 89 | RMSPROP_MOMENTUM = 0.9 # Momentum in RMSProp. 90 | RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp. 91 | 92 | 93 | def train(target, dataset, cluster_spec): 94 | """Train Inception on a dataset for a number of steps.""" 95 | # Number of workers and parameter servers are inferred from the workers and ps 96 | # hosts string. 97 | num_workers = len(cluster_spec.as_dict()['worker']) 98 | num_parameter_servers = len(cluster_spec.as_dict()['ps']) 99 | # If no value is given, num_replicas_to_aggregate defaults to be the number of 100 | # workers. 101 | if FLAGS.num_replicas_to_aggregate == -1: 102 | num_replicas_to_aggregate = num_workers 103 | else: 104 | num_replicas_to_aggregate = FLAGS.num_replicas_to_aggregate 105 | 106 | # Both should be greater than 0 in a distributed training. 107 | assert num_workers > 0 and num_parameter_servers > 0, (' num_workers and ' 108 | 'num_parameter_servers' 109 | ' must be > 0.') 110 | 111 | # Choose worker 0 as the chief. Note that any worker could be the chief 112 | # but there should be only one chief. 113 | is_chief = (FLAGS.task_id == 0) 114 | 115 | # Ops are assigned to worker by default. 116 | with tf.device('/job:worker/task:%d' % FLAGS.task_id): 117 | # Variables and its related init/assign ops are assigned to ps. 118 | with slim.scopes.arg_scope( 119 | [slim.variables.variable, slim.variables.global_step], 120 | device=slim.variables.VariableDeviceChooser(num_parameter_servers)): 121 | # Create a variable to count the number of train() calls. This equals the 122 | # number of updates applied to the variables. 123 | global_step = slim.variables.global_step() 124 | 125 | # Calculate the learning rate schedule. 126 | num_batches_per_epoch = (dataset.num_examples_per_epoch() / 127 | FLAGS.batch_size) 128 | # Decay steps need to be divided by the number of replicas to aggregate. 129 | decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay / 130 | num_replicas_to_aggregate) 131 | 132 | # Decay the learning rate exponentially based on the number of steps. 133 | lr = tf.train.exponential_decay(FLAGS.initial_learning_rate, 134 | global_step, 135 | decay_steps, 136 | FLAGS.learning_rate_decay_factor, 137 | staircase=True) 138 | # Add a summary to track the learning rate. 139 | tf.summary.scalar('learning_rate', lr) 140 | 141 | # Create an optimizer that performs gradient descent. 142 | opt = tf.train.RMSPropOptimizer(lr, 143 | RMSPROP_DECAY, 144 | momentum=RMSPROP_MOMENTUM, 145 | epsilon=RMSPROP_EPSILON) 146 | 147 | images, labels = image_processing.distorted_inputs( 148 | dataset, 149 | batch_size=FLAGS.batch_size, 150 | num_preprocess_threads=FLAGS.num_preprocess_threads) 151 | 152 | # Number of classes in the Dataset label set plus 1. 153 | # Label 0 is reserved for an (unused) background class. 154 | num_classes = dataset.num_classes() + 1 155 | logits = inception.inference(images, num_classes, for_training=True) 156 | # Add classification loss. 157 | inception.loss(logits, labels) 158 | 159 | # Gather all of the losses including regularization losses. 160 | losses = tf.get_collection(slim.losses.LOSSES_COLLECTION) 161 | losses += tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 162 | 163 | total_loss = tf.add_n(losses, name='total_loss') 164 | 165 | if is_chief: 166 | # Compute the moving average of all individual losses and the 167 | # total loss. 168 | loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg') 169 | loss_averages_op = loss_averages.apply(losses + [total_loss]) 170 | 171 | # Attach a scalar summmary to all individual losses and the total loss; 172 | # do the same for the averaged version of the losses. 173 | for l in losses + [total_loss]: 174 | loss_name = l.op.name 175 | # Name each loss as '(raw)' and name the moving average version of the 176 | # loss as the original loss name. 177 | tf.summary.scalar(loss_name + ' (raw)', l) 178 | tf.summary.scalar(loss_name, loss_averages.average(l)) 179 | 180 | # Add dependency to compute loss_averages. 181 | with tf.control_dependencies([loss_averages_op]): 182 | total_loss = tf.identity(total_loss) 183 | 184 | # Track the moving averages of all trainable variables. 185 | # Note that we maintain a 'double-average' of the BatchNormalization 186 | # global statistics. 187 | # This is not needed when the number of replicas are small but important 188 | # for synchronous distributed training with tens of workers/replicas. 189 | exp_moving_averager = tf.train.ExponentialMovingAverage( 190 | inception.MOVING_AVERAGE_DECAY, global_step) 191 | 192 | variables_to_average = ( 193 | tf.trainable_variables() + tf.moving_average_variables()) 194 | 195 | # Add histograms for model variables. 196 | for var in variables_to_average: 197 | tf.summary.histogram(var.op.name, var) 198 | 199 | # Create synchronous replica optimizer. 200 | opt = tf.train.SyncReplicasOptimizer( 201 | opt, 202 | replicas_to_aggregate=num_replicas_to_aggregate, 203 | total_num_replicas=num_workers, 204 | variable_averages=exp_moving_averager, 205 | variables_to_average=variables_to_average) 206 | 207 | batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION) 208 | assert batchnorm_updates, 'Batchnorm updates are missing' 209 | batchnorm_updates_op = tf.group(*batchnorm_updates) 210 | # Add dependency to compute batchnorm_updates. 211 | with tf.control_dependencies([batchnorm_updates_op]): 212 | total_loss = tf.identity(total_loss) 213 | 214 | # Compute gradients with respect to the loss. 215 | grads = opt.compute_gradients(total_loss) 216 | 217 | # Add histograms for gradients. 218 | for grad, var in grads: 219 | if grad is not None: 220 | tf.summary.histogram(var.op.name + '/gradients', grad) 221 | 222 | apply_gradients_op = opt.apply_gradients(grads, global_step=global_step) 223 | 224 | with tf.control_dependencies([apply_gradients_op]): 225 | train_op = tf.identity(total_loss, name='train_op') 226 | 227 | # Get chief queue_runners and init_tokens, which is used to synchronize 228 | # replicas. More details can be found in SyncReplicasOptimizer. 229 | chief_queue_runners = [opt.get_chief_queue_runner()] 230 | init_tokens_op = opt.get_init_tokens_op() 231 | 232 | # Create a saver. 233 | saver = tf.train.Saver() 234 | 235 | # Build the summary operation based on the TF collection of Summaries. 236 | summary_op = tf.summary.merge_all() 237 | 238 | # Build an initialization operation to run below. 239 | init_op = tf.global_variables_initializer() 240 | 241 | # We run the summaries in the same thread as the training operations by 242 | # passing in None for summary_op to avoid a summary_thread being started. 243 | # Running summaries and training operations in parallel could run out of 244 | # GPU memory. 245 | sv = tf.train.Supervisor(is_chief=is_chief, 246 | logdir=FLAGS.train_dir, 247 | init_op=init_op, 248 | summary_op=None, 249 | global_step=global_step, 250 | saver=saver, 251 | save_model_secs=FLAGS.save_interval_secs) 252 | 253 | tf.logging.info('%s Supervisor' % datetime.now()) 254 | 255 | sess_config = tf.ConfigProto( 256 | allow_soft_placement=True, 257 | log_device_placement=FLAGS.log_device_placement) 258 | 259 | # Get a session. 260 | sess = sv.prepare_or_wait_for_session(target, config=sess_config) 261 | 262 | # Start the queue runners. 263 | queue_runners = tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS) 264 | sv.start_queue_runners(sess, queue_runners) 265 | tf.logging.info('Started %d queues for processing input data.', 266 | len(queue_runners)) 267 | 268 | if is_chief: 269 | sv.start_queue_runners(sess, chief_queue_runners) 270 | sess.run(init_tokens_op) 271 | 272 | # Train, checking for Nans. Concurrently run the summary operation at a 273 | # specified interval. Note that the summary_op and train_op never run 274 | # simultaneously in order to prevent running out of GPU memory. 275 | next_summary_time = time.time() + FLAGS.save_summaries_secs 276 | while not sv.should_stop(): 277 | try: 278 | start_time = time.time() 279 | loss_value, step = sess.run([train_op, global_step]) 280 | assert not np.isnan(loss_value), 'Model diverged with loss = NaN' 281 | if step > FLAGS.max_steps: 282 | break 283 | duration = time.time() - start_time 284 | 285 | if step % 30 == 0: 286 | examples_per_sec = FLAGS.batch_size / float(duration) 287 | format_str = ('Worker %d: %s: step %d, loss = %.2f' 288 | '(%.1f examples/sec; %.3f sec/batch)') 289 | tf.logging.info(format_str % 290 | (FLAGS.task_id, datetime.now(), step, loss_value, 291 | examples_per_sec, duration)) 292 | 293 | # Determine if the summary_op should be run on the chief worker. 294 | if is_chief and next_summary_time < time.time(): 295 | tf.logging.info('Running Summary operation on the chief.') 296 | summary_str = sess.run(summary_op) 297 | sv.summary_computed(sess, summary_str) 298 | tf.logging.info('Finished running Summary operation.') 299 | 300 | # Determine the next time for running the summary. 301 | next_summary_time += FLAGS.save_summaries_secs 302 | except: 303 | if is_chief: 304 | tf.logging.info('Chief got exception while running!') 305 | raise 306 | 307 | # Stop the supervisor. This also waits for service threads to finish. 308 | sv.stop() 309 | 310 | # Save after the training ends. 311 | if is_chief: 312 | saver.save(sess, 313 | os.path.join(FLAGS.train_dir, 'model.ckpt'), 314 | global_step=global_step) 315 | -------------------------------------------------------------------------------- /inception/inception_peta_eval.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A library to evaluate Inception on a single GPU. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | from datetime import datetime 22 | import math 23 | import os.path 24 | import time 25 | 26 | 27 | import numpy as np 28 | import tensorflow as tf 29 | 30 | from inception import image_processing 31 | from inception import inception_peta_model as inception 32 | 33 | num_classes = 35 34 | 35 | FLAGS = tf.app.flags.FLAGS 36 | 37 | tf.app.flags.DEFINE_string('eval_dir', '/home/sangliufang/tensorflow/models/research/inception/inception/rap_train', 38 | """Directory where to write event logs.""") 39 | tf.app.flags.DEFINE_string('checkpoint_dir', '/tmp/imagenet_train', 40 | """Directory where to read model checkpoints.""") 41 | 42 | # Flags governing the frequency of the eval. 43 | tf.app.flags.DEFINE_integer('eval_interval_secs', 60 * 5, 44 | """How often to run the eval.""") 45 | tf.app.flags.DEFINE_boolean('run_once', False, 46 | """Whether to run eval only once.""") 47 | 48 | tf.app.flags.DEFINE_boolean('pad', False, 49 | """Whether to run eval only once.""") 50 | 51 | # Flags governing the data used for the eval. 52 | tf.app.flags.DEFINE_integer('num_examples', 8317, 53 | """Number of examples to run. Note that the eval """ 54 | """ImageNet dataset contains 50000 examples.""") 55 | tf.app.flags.DEFINE_string('subset', 'validation', 56 | """Either 'validation' or 'train'.""") 57 | 58 | def mA(attr, gt): 59 | num = attr.__len__() 60 | num_attr = attr[0].__len__() 61 | # for i in range(num): 62 | # if(i % 100 == 0): 63 | # print(attr[i]) 64 | 65 | challenging = [] 66 | acc_collect = [] 67 | accuracy_neg = [] 68 | accuracy_pos = [] 69 | accuracy_all = [] 70 | for i in range(num_attr): 71 | print('--------------------------------------------') 72 | print(i) 73 | print(sum([attr[j][i] for j in range(num)]), \ 74 | ':', sum([attr[j][i] * gt[j][i] for j in range(num)]), \ 75 | ':', sum([gt[j][i] for j in range(num)])) 76 | # print(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 77 | accuracy_pos.append(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 78 | 79 | print("accuracy_pos: {}\n".format(accuracy_pos[i])) 80 | print(sum([(1 - attr[j][i]) for j in range(num)]), \ 81 | ':', sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]), \ 82 | ':', sum([(1 - gt[j][i]) for j in range(num)])) 83 | # print(sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) 84 | # accuracy_pos.append(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 85 | 86 | # print("accuracy_pos: {}\n".format(accuracy_pos[i])) 87 | accuracy_neg.append(sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) 88 | 89 | print("accuracy_neg: {}\n".format(accuracy_neg[i])) 90 | 91 | accuracy_all.append((accuracy_neg[i]+accuracy_pos[i])/2) 92 | print("accuracy_all: {}\n".format(accuracy_all[i])) 93 | 94 | # acc = (sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)]) + sum( 95 | # [(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) / 2 96 | # acc_collect.append(acc) 97 | # print("accuracy: {}\n".format(acc)) 98 | if accuracy_all[i] < 0.75: 99 | challenging.append(i) 100 | 101 | # mA = (sum([( 102 | # sum([attr[j][i] * gt[j][i] for j in range(num)]) 103 | # / sum([gt[j][i] for j in range(num)]) 104 | # + sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) 105 | # / sum([(1 - gt[j][i]) for j in range(num)]) 106 | # ) for i in range(num_attr)])) / (2 * num_attr) 107 | return np.mean(accuracy_all), accuracy_all, challenging 108 | 109 | def example_based(attr, gt): 110 | num = attr.__len__() 111 | num_attr = attr[0].__len__() 112 | 113 | acc = 0 114 | prec = 0 115 | rec = 0 116 | f1 = 0 117 | 118 | attr = np.array(attr).astype(bool) 119 | gt = np.array(gt).astype(bool) 120 | 121 | for i in range(num): 122 | intersect = sum((attr[i] & gt[i]).astype(float)) 123 | union = sum((attr[i] | gt[i]).astype(float)) 124 | attr_sum = sum((attr[i]).astype(float)) 125 | gt_sum = sum((gt[i]).astype(float)) 126 | 127 | acc += 0 if union == 0 else intersect / union 128 | prec += 0 if attr_sum == 0 else intersect / attr_sum 129 | rec += 0 if gt_sum == 0 else intersect / gt_sum 130 | 131 | acc /= num 132 | prec /= num 133 | rec /= num 134 | f1 = 2 * prec * rec / (prec + rec) 135 | 136 | return acc, prec, rec, f1 137 | 138 | def softmax_or_not(predict, is_softmax=False, threshold=[0.5]*num_classes): 139 | res = [] 140 | 141 | if not is_softmax: 142 | for i in range(FLAGS.batch_size): 143 | res1 = [0] * num_classes 144 | for j in range(num_classes): 145 | if predict[i][j] >= threshold[j]: 146 | res1[j] = 1 147 | res.append(res1) 148 | return res 149 | 150 | for i in range(FLAGS.batch_size): 151 | res1 = [0] * num_classes 152 | for j in range(num_classes): 153 | if j == 1: 154 | max_id, max_v = -1, -1 155 | for k in range(1, 4): 156 | if predict[i][k] > max_v: 157 | max_id = k 158 | max_v = predict[i][k] 159 | res1[max_id] = 1 160 | elif j == 4: 161 | max_id, max_v = -1, -1 162 | for k in range(4, 7): 163 | if predict[i][k] > max_v: 164 | max_id = k 165 | max_v = predict[i][k] 166 | if max_v >= threshold[j]: 167 | res1[max_id] = 1 168 | elif j == 7: 169 | max_id, max_v = -1, -1 170 | for k in range(7, 9): 171 | if predict[i][k] > max_v: 172 | max_id = k 173 | max_v = predict[i][k] 174 | if max_v >= threshold[j]: 175 | res1[max_id] = 1 176 | elif j == 9: 177 | max_id, max_v = -1, -1 178 | for k in range(9, 11): 179 | if predict[i][k] > max_v: 180 | max_id = k 181 | max_v = predict[i][k] 182 | if max_v >= threshold[j]: 183 | res1[max_id] = 1 184 | elif j < 1 or j >= 11: 185 | if predict[i][j] >= threshold[j]: 186 | res1[j] = 1 187 | else: 188 | continue 189 | res.append(res1) 190 | return res 191 | 192 | def _eval_once_mA(saver, mA_op, summary_writer, summary_op): 193 | with tf.Session() as sess: 194 | if os.path.exists(FLAGS.checkpoint_dir): 195 | ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir) 196 | if ckpt and ckpt.model_checkpoint_path: 197 | if os.path.isabs(ckpt.model_checkpoint_path): 198 | # Restores from checkpoint with absolute path. 199 | saver.restore(sess, ckpt.model_checkpoint_path) 200 | else: 201 | # Restores from checkpoint with relative path. 202 | saver.restore(sess, os.path.join(FLAGS.checkpoint_dir, 203 | ckpt.model_checkpoint_path)) 204 | 205 | # Assuming model_checkpoint_path looks something like: 206 | # /my-favorite-path/imagenet_train/model.ckpt-0, 207 | # extract global_step from it. 208 | global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] 209 | print('Successfully loaded model from %s at step=%s.' % 210 | (ckpt.model_checkpoint_path, global_step)) 211 | else: 212 | print('No checkpoint file found') 213 | return 214 | else: 215 | saver.restore(sess, FLAGS.checkpoint_dir) 216 | global_step = FLAGS.checkpoint_dir.split('/')[-1].split('-')[-1] 217 | print('Successfully loaded model from %s at step=%s.' % 218 | (FLAGS.checkpoint_dir, global_step)) 219 | 220 | 221 | # Start the queue runners. 222 | coord = tf.train.Coordinator() 223 | try: 224 | threads = [] 225 | for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS): 226 | threads.extend(qr.create_threads(sess, coord=coord, daemon=True, 227 | start=True)) 228 | 229 | num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size)) 230 | # Counts the number of correct predictions. 231 | total_sample_count = num_iter * FLAGS.batch_size 232 | attrs = np.zeros((total_sample_count , num_classes)) 233 | labels = np.zeros((total_sample_count, num_classes)) 234 | step = 0 235 | 236 | print('%s: starting evaluation on (%s).' % (datetime.now(), FLAGS.subset)) 237 | start_time = time.time() 238 | while step < num_iter and not coord.should_stop(): 239 | predict, label = sess.run(mA_op) 240 | 241 | threshold = [0.0] * num_classes 242 | predict = softmax_or_not(predict, is_softmax=False, threshold=threshold) 243 | attrs[step*FLAGS.batch_size : (step+1)*FLAGS.batch_size,:] = predict 244 | labels[step*FLAGS.batch_size : (step+1)*FLAGS.batch_size,:] = label 245 | # np.append(attrs, predict, axis=0) 246 | # np.append(labels, label, axis=0) 247 | 248 | step += 1 249 | if step % 20 == 0: 250 | duration = time.time() - start_time 251 | sec_per_batch = duration / 20.0 252 | examples_per_sec = FLAGS.batch_size / sec_per_batch 253 | print('%s: [%d batches out of %d] (%.1f examples/sec; %.3f' 254 | 'sec/batch)' % (datetime.now(), step, num_iter, 255 | examples_per_sec, sec_per_batch)) 256 | start_time = time.time() 257 | 258 | # Compute mA. 259 | print(mA(attrs, labels)) 260 | print(example_based(attrs, labels)) 261 | #mA = sum_mA / total_sample_count 262 | summary = tf.Summary() 263 | summary.ParseFromString(sess.run(summary_op)) 264 | summary_writer.add_summary(summary, global_step) 265 | except Exception as e: # pylint: disable=broad-except 266 | coord.request_stop(e) 267 | 268 | coord.request_stop() 269 | coord.join(threads, stop_grace_period_secs=10) 270 | 271 | def _eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op): 272 | """Runs Eval once. 273 | 274 | Args: 275 | saver: Saver. 276 | summary_writer: Summary writer. 277 | top_1_op: Top 1 op. 278 | top_5_op: Top 5 op. 279 | summary_op: Summary op. 280 | """ 281 | with tf.Session() as sess: 282 | if os.path.exists(FLAGS.checkpoint_dir): 283 | ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir) 284 | if ckpt and ckpt.model_checkpoint_path: 285 | if os.path.isabs(ckpt.model_checkpoint_path): 286 | # Restores from checkpoint with absolute path. 287 | saver.restore(sess, ckpt.model_checkpoint_path) 288 | else: 289 | # Restores from checkpoint with relative path. 290 | saver.restore(sess, os.path.join(FLAGS.checkpoint_dir, 291 | ckpt.model_checkpoint_path)) 292 | 293 | # Assuming model_checkpoint_path looks something like: 294 | # /my-favorite-path/imagenet_train/model.ckpt-0, 295 | # extract global_step from it. 296 | global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] 297 | print('Successfully loaded model from %s at step=%s.' % 298 | (ckpt.model_checkpoint_path, global_step)) 299 | else: 300 | print('No checkpoint file found') 301 | return 302 | else: 303 | saver.restore(sess, FLAGS.checkpoint_dir) 304 | global_step = FLAGS.checkpoint_dir.split('/')[-1].split('-')[-1] 305 | print('Successfully loaded model from %s at step=%s.' % 306 | (FLAGS.checkpoint_dir, global_step)) 307 | 308 | # Start the queue runners. 309 | coord = tf.train.Coordinator() 310 | try: 311 | threads = [] 312 | for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS): 313 | threads.extend(qr.create_threads(sess, coord=coord, daemon=True, 314 | start=True)) 315 | 316 | num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size)) 317 | # Counts the number of correct predictions. 318 | count_top_1 = 0.0 319 | count_top_5 = 0.0 320 | total_sample_count = num_iter * FLAGS.batch_size 321 | step = 0 322 | 323 | print('%s: starting evaluation on (%s).' % (datetime.now(), FLAGS.subset)) 324 | start_time = time.time() 325 | while step < num_iter and not coord.should_stop(): 326 | top_1, top_5 = sess.run([top_1_op, top_5_op]) 327 | count_top_1 += np.sum(top_1) 328 | count_top_5 += np.sum(top_5) 329 | step += 1 330 | if step % 20 == 0: 331 | duration = time.time() - start_time 332 | sec_per_batch = duration / 20.0 333 | examples_per_sec = FLAGS.batch_size / sec_per_batch 334 | print('%s: [%d batches out of %d] (%.1f examples/sec; %.3f' 335 | 'sec/batch)' % (datetime.now(), step, num_iter, 336 | examples_per_sec, sec_per_batch)) 337 | start_time = time.time() 338 | 339 | # Compute precision @ 1. 340 | precision_at_1 = count_top_1 / total_sample_count 341 | recall_at_5 = count_top_5 / total_sample_count 342 | print('%s: precision @ 1 = %.4f recall @ 5 = %.4f [%d examples]' % 343 | (datetime.now(), precision_at_1, recall_at_5, total_sample_count)) 344 | 345 | summary = tf.Summary() 346 | summary.ParseFromString(sess.run(summary_op)) 347 | summary.value.add(tag='Precision @ 1', simple_value=precision_at_1) 348 | summary.value.add(tag='Recall @ 5', simple_value=recall_at_5) 349 | summary_writer.add_summary(summary, global_step) 350 | 351 | except Exception as e: # pylint: disable=broad-except 352 | coord.request_stop(e) 353 | 354 | coord.request_stop() 355 | coord.join(threads, stop_grace_period_secs=10) 356 | 357 | def mean_accuracy(logits, labels): 358 | print(logits) 359 | labels = tf.to_float(labels) 360 | # logits = tf.sigmoid(logits) 361 | # logits = (tf.sign(tf.sigmoid(logits) - 0.5) + 1) /2 362 | 363 | 364 | 365 | #num_pp = tf.reduce_sum(predict * labels, 0) 366 | #num_nn = tf.reduce_sum((predict-1) * (labels - 1), 0) 367 | #num_pn = tf.reduce_sum(predict * (1 - labels), 0) 368 | #num_np = tf.reduce_sum((1-predict) * labels, 0) 369 | return logits, labels 370 | 371 | def evaluate(dataset): 372 | """Evaluate model on Dataset for a number of steps.""" 373 | with tf.Graph().as_default(): 374 | # Get images and labels from the dataset. 375 | images, labels, rois = image_processing.inputs(dataset) 376 | 377 | # Number of classes in the Dataset label set plus 1. 378 | # Label 0 is reserved for an (unused) background class. 379 | num_classes = dataset.num_classes() 380 | 381 | # Build a Graph that computes the logits predictions from the 382 | # inference model. 383 | logits, _ = inception.inference_roi_lstm_bn(images, rois, num_classes) 384 | 385 | # Calculate predictions. 386 | #top_1_op = tf.nn.in_top_k(logits, labels, 1) 387 | #top_5_op = tf.nn.in_top_k(logits, labels, 5) 388 | mA_op = mean_accuracy(logits, labels) 389 | 390 | # Restore the moving average version of the learned variables for eval. 391 | variable_averages = tf.train.ExponentialMovingAverage( 392 | inception.MOVING_AVERAGE_DECAY) 393 | variables_to_restore = variable_averages.variables_to_restore() 394 | saver = tf.train.Saver(variables_to_restore) 395 | 396 | # Build the summary operation based on the TF collection of Summaries. 397 | summary_op = tf.summary.merge_all() 398 | 399 | graph_def = tf.get_default_graph().as_graph_def() 400 | summary_writer = tf.summary.FileWriter(FLAGS.eval_dir, 401 | graph_def=graph_def) 402 | 403 | while True: 404 | #_eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op) 405 | _eval_once_mA(saver, mA_op, summary_writer, summary_op) 406 | if FLAGS.run_once: 407 | break 408 | time.sleep(FLAGS.eval_interval_secs) 409 | -------------------------------------------------------------------------------- /inception/inception_peta_train.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A library to train Inception using multiple GPUs with synchronous updates. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import copy 22 | from datetime import datetime 23 | import os.path 24 | import re 25 | import time 26 | 27 | import numpy as np 28 | import tensorflow as tf 29 | from tensorflow.python import debug as tf_debug 30 | 31 | from inception import image_processing 32 | from inception import inception_peta_model as inception 33 | from inception.slim import slim 34 | 35 | FLAGS = tf.app.flags.FLAGS 36 | 37 | tf.app.flags.DEFINE_string('train_dir', '/home/sangliufang/tensorflow/models/research/inception/inception/rap_train', 38 | """Directory where to write event logs """ 39 | """and checkpoint.""") 40 | tf.app.flags.DEFINE_integer('max_steps', 5000, 41 | """Number of batches to run.""") 42 | tf.app.flags.DEFINE_string('subset', 'train', 43 | """Either 'train' or 'validation'.""") 44 | 45 | # Flags governing the hardware employed for running TensorFlow. 46 | tf.app.flags.DEFINE_integer('num_gpus', 2, 47 | """How many GPUs to use.""") 48 | tf.app.flags.DEFINE_boolean('log_device_placement', False, 49 | """Whether to log device placement.""") 50 | 51 | # Flags governing the type of training. 52 | tf.app.flags.DEFINE_boolean('fine_tune', False, 53 | """If set, randomly initialize the final layer """ 54 | """of weights in order to train the network on a """ 55 | """new task""") 56 | # tf.app.flags.DEFINE_boolean('debug', False, 57 | # """If set, randomly initialize the final layer """ 58 | # """of weights in order to train the network on a """ 59 | # """new task.""") 60 | tf.app.flags.DEFINE_string('pretrained_model_checkpoint_path', '', 61 | """If specified, restore this pretrained model """ 62 | """before beginning any training.""") 63 | 64 | # **IMPORTANT** 65 | # Please note that this learning rate schedule is heavily dependent on the 66 | # hardware architecture, batch size and any changes to the model architecture 67 | # specification. Selecting a finely tuned learning rate schedule is an 68 | # empirical process that requires some experimentation. Please see README.md 69 | # more guidance and discussion. 70 | # 71 | # With 8 Tesla K40's and a batch size = 256, the following setup achieves 72 | # precision@1 = 73.5% after 100 hours and 100K steps (20 epochs). 73 | # Learning rate decay factor selected from http://arxiv.org/abs/1404.5997. 74 | tf.app.flags.DEFINE_float('initial_learning_rate', 0.0001, 75 | """Initial learning rate.""") 76 | tf.app.flags.DEFINE_float('num_epochs_per_decay', 64.0, 77 | """Epochs after which learning rate decays.""") 78 | tf.app.flags.DEFINE_float('learning_rate_decay_factor', 0.16, 79 | """Learning rate decay factor.""") 80 | 81 | tf.app.flags.DEFINE_boolean('pad', False, 82 | """Whether to run eval only once.""") 83 | 84 | # Constants dictating the learning rate schedule. 85 | RMSPROP_DECAY = 0.9 # Decay term for RMSProp. 86 | RMSPROP_MOMENTUM = 0.9 # Momentum in RMSProp. 87 | RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp. 88 | 89 | 90 | def _tower_loss(images, labels, rois, num_classes, scope, reuse_variables=None): 91 | """Calculate the total loss on a single tower running the ImageNet model. 92 | 93 | We perform 'batch splitting'. This means that we cut up a batch across 94 | multiple GPUs. For instance, if the batch size = 32 and num_gpus = 2, 95 | then each tower will operate on an batch of 16 images. 96 | 97 | Args: 98 | images: Images. 4D tensor of size [batch_size, FLAGS.image_size, 99 | FLAGS.image_size, 3]. 100 | labels: 1-D integer Tensor of [batch_size]. 101 | num_classes: number of classes 102 | scope: unique prefix string identifying the ImageNet tower, e.g. 103 | 'tower_0'. 104 | 105 | Returns: 106 | Tensor of shape [] containing the total loss for a batch of data 107 | """ 108 | # When fine-tuning a model, we do not restore the logits but instead we 109 | # randomly initialize the logits. The number of classes in the output of the 110 | # logit is the number of classes in specified Dataset. 111 | restore_logits = not FLAGS.fine_tune 112 | 113 | #print(num_classes) 114 | #print(labels) 115 | 116 | # Build inference Graph. 117 | with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables): 118 | logits = inception.inference_roi_lstm_bn(images, rois, num_classes, for_training=True, 119 | restore_logits=restore_logits, 120 | scope=scope) 121 | # print(logits) 122 | # Build the portion of the Graph calculating the losses. Note that we will 123 | # assemble the total_loss using a custom function below. 124 | split_batch_size = images.get_shape().as_list()[0] 125 | # print(logits[0].get_shape()) 126 | # print(labels.get_shape()) 127 | # print(logits) 128 | inception.loss(logits, labels, batch_size=split_batch_size) 129 | 130 | # print(labels.get_shape()) 131 | # Assemble all of the losses for the current tower only. 132 | losses = tf.get_collection(slim.losses.LOSSES_COLLECTION, scope) 133 | 134 | # Calculate the total loss for the current tower. 135 | regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 136 | total_loss = tf.add_n(losses + regularization_losses, name='total_loss') 137 | 138 | # Compute the moving average of all individual losses and the total loss. 139 | loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg') 140 | loss_averages_op = loss_averages.apply(losses + [total_loss]) 141 | 142 | # Attach a scalar summmary to all individual losses and the total loss; do the 143 | # same for the averaged version of the losses. 144 | for l in losses + [total_loss]: 145 | # Remove 'tower_[0-9]/' from the name in case this is a multi-GPU training 146 | # session. This helps the clarity of presentation on TensorBoard. 147 | loss_name = re.sub('%s_[0-9]*/' % inception.TOWER_NAME, '', l.op.name) 148 | # Name each loss as '(raw)' and name the moving average version of the loss 149 | # as the original loss name. 150 | tf.summary.scalar(loss_name +' (raw)', l) 151 | tf.summary.scalar(loss_name, loss_averages.average(l)) 152 | 153 | with tf.control_dependencies([loss_averages_op]): 154 | total_loss = tf.identity(total_loss) 155 | # return total_loss, losses, regularization_losses 156 | return total_loss 157 | 158 | 159 | def _average_gradients(tower_grads): 160 | """Calculate the average gradient for each shared variable across all towers. 161 | 162 | Note that this function provides a synchronization point across all towers. 163 | 164 | Args: 165 | tower_grads: List of lists of (gradient, variable) tuples. The outer list 166 | is over individual gradients. The inner list is over the gradient 167 | calculation for each tower. 168 | Returns: 169 | List of pairs of (gradient, variable) where the gradient has been averaged 170 | across all towers. 171 | """ 172 | average_grads = [] 173 | for grad_and_vars in zip(*tower_grads): 174 | # Note that each grad_and_vars looks like the following: 175 | # ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN)) 176 | grads = [] 177 | for g, _ in grad_and_vars: 178 | # Add 0 dimension to the gradients to represent the tower. 179 | expanded_g = tf.expand_dims(g, 0) 180 | 181 | # Append on a 'tower' dimension which we will average over below. 182 | grads.append(expanded_g) 183 | 184 | # Average over the 'tower' dimension. 185 | grad = tf.concat(axis=0, values=grads) 186 | grad = tf.reduce_mean(grad, 0) 187 | 188 | # Keep in mind that the Variables are redundant because they are shared 189 | # across towers. So .. we will just return the first tower's pointer to 190 | # the Variable. 191 | v = grad_and_vars[0][1] 192 | # if 'logits_bn' in v.name: 193 | # grad_and_var = (grad, v) 194 | # else: 195 | # grad_and_var = (0 * grad, v) 196 | grad_and_var = (grad, v) 197 | average_grads.append(grad_and_var) 198 | return average_grads 199 | 200 | 201 | def train(dataset): 202 | """Train on dataset for a number of steps.""" 203 | with tf.Graph().as_default(), tf.device('/cpu:0'): 204 | # Create a variable to count the number of train() calls. This equals the 205 | # number of batches processed * FLAGS.num_gpus. 206 | global_step = tf.get_variable( 207 | 'global_step', [], 208 | initializer=tf.constant_initializer(0), trainable=False) 209 | 210 | # Calculate the learning rate schedule. 211 | num_batches_per_epoch = (dataset.num_examples_per_epoch() / 212 | FLAGS.batch_size) 213 | decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay) 214 | 215 | # Decay the learning rate exponentially based on the number of steps. 216 | lr = tf.train.exponential_decay(FLAGS.initial_learning_rate, 217 | global_step, 218 | decay_steps, 219 | FLAGS.learning_rate_decay_factor, 220 | staircase=True) 221 | 222 | # Create an optimizer that performs gradient descent. 223 | # opt = tf.train.RMSPropOptimizer(lr, RMSPROP_DECAY, 224 | # momentum=RMSPROP_MOMENTUM, 225 | # epsilon=RMSPROP_EPSILON) 226 | opt = tf.train.MomentumOptimizer(lr, 0.9) 227 | 228 | # Get images and labels for ImageNet and split the batch across GPUs. 229 | assert FLAGS.batch_size % FLAGS.num_gpus == 0, ( 230 | 'Batch size must be divisible by number of GPUs') 231 | split_batch_size = int(FLAGS.batch_size / FLAGS.num_gpus) 232 | 233 | # Override the number of preprocessing threads to account for the increased 234 | # number of GPU towers. 235 | num_preprocess_threads = FLAGS.num_preprocess_threads * FLAGS.num_gpus 236 | images, labels, rois = image_processing.distorted_inputs( 237 | dataset, 238 | num_preprocess_threads=num_preprocess_threads) 239 | 240 | input_summaries = copy.copy(tf.get_collection(tf.GraphKeys.SUMMARIES)) 241 | 242 | # Number of classes in the Dataset label set plus 1. 243 | # Label 0 is reserved for an (unused) background class. 244 | num_classes = dataset.num_classes() 245 | 246 | # Split the batch of images and labels for towers. 247 | images_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=images) 248 | labels_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=labels) 249 | rois_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=rois) 250 | 251 | # Calculate the gradients for each model tower. 252 | tower_grads = [] 253 | reuse_variables = None 254 | for i in range(FLAGS.num_gpus): 255 | with tf.device('/gpu:%d' % i): 256 | with tf.name_scope('%s_%d' % (inception.TOWER_NAME, i)) as scope: 257 | # Force all Variables to reside on the CPU. 258 | with slim.arg_scope([slim.variables.variable], device='/cpu:0'): 259 | # Calculate the loss for one tower of the ImageNet model. This 260 | # function constructs the entire ImageNet model but shares the 261 | # variables across all towers. 262 | loss = _tower_loss(images_splits[i], labels_splits[i], rois_splits[i], num_classes, 263 | scope, reuse_variables) 264 | 265 | # Reuse variables for the next tower. 266 | reuse_variables = True 267 | 268 | # Retain the summaries from the final tower. 269 | summaries = tf.get_collection(tf.GraphKeys.SUMMARIES, scope) 270 | 271 | # Retain the Batch Normalization updates operations only from the 272 | # final tower. Ideally, we should grab the updates from all towers 273 | # but these stats accumulate extremely fast so we can ignore the 274 | # other stats from the other towers without significant detriment. 275 | batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION, 276 | scope) 277 | 278 | # Calculate the gradients for the batch of data on this ImageNet 279 | # tower. 280 | grads = opt.compute_gradients(loss) 281 | 282 | # Keep track of the gradients across all towers. 283 | tower_grads.append(grads) 284 | 285 | # We must calculate the mean of each gradient. Note that this is the 286 | # synchronization point across all towers. 287 | grads = _average_gradients(tower_grads) 288 | 289 | # Add a summaries for the input processing and global_step. 290 | summaries.extend(input_summaries) 291 | 292 | # Add a summary to track the learning rate. 293 | summaries.append(tf.summary.scalar('learning_rate', lr)) 294 | 295 | # Add histograms for gradients. 296 | for grad, var in grads: 297 | if grad is not None: 298 | summaries.append( 299 | tf.summary.histogram(var.op.name + '/gradients', grad)) 300 | 301 | # Apply the gradients to adjust the shared variables. 302 | apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) 303 | 304 | # Add histograms for trainable variables. 305 | for var in tf.trainable_variables(): 306 | summaries.append(tf.summary.histogram(var.op.name, var)) 307 | 308 | # Track the moving averages of all trainable variables. 309 | # Note that we maintain a "double-average" of the BatchNormalization 310 | # global statistics. This is more complicated then need be but we employ 311 | # this for backward-compatibility with our previous models. 312 | variable_averages = tf.train.ExponentialMovingAverage( 313 | inception.MOVING_AVERAGE_DECAY, global_step) 314 | 315 | # Another possibility is to use tf.slim.get_variables(). 316 | variables_to_average = (tf.trainable_variables() + 317 | tf.moving_average_variables()) 318 | variables_averages_op = variable_averages.apply(variables_to_average) 319 | 320 | # Group all updates to into a single train op. 321 | batchnorm_updates_op = tf.group(*batchnorm_updates) 322 | train_op = tf.group(apply_gradient_op, variables_averages_op, 323 | batchnorm_updates_op) 324 | 325 | # Create a saver. 326 | saver = tf.train.Saver(tf.global_variables(), max_to_keep=10) 327 | 328 | # Build the summary operation from the last tower summaries. 329 | summary_op = tf.summary.merge(summaries) 330 | 331 | # Build an initialization operation to run below. 332 | init = tf.global_variables_initializer() 333 | 334 | # Start running operations on the Graph. allow_soft_placement must be set to 335 | # True to build towers on GPU, as some of the ops do not have GPU 336 | # implementations. 337 | sess = tf.Session(config=tf.ConfigProto( 338 | allow_soft_placement=True, 339 | log_device_placement=FLAGS.log_device_placement)) 340 | sess.run(init) 341 | 342 | if FLAGS.pretrained_model_checkpoint_path: 343 | # assert tf.gfile.Exists(FLAGS.pretrained_model_checkpoint_path) 344 | variables_to_restore = tf.get_collection( 345 | slim.variables.VARIABLES_TO_RESTORE) 346 | restorer = tf.train.Saver(variables_to_restore) 347 | restorer.restore(sess, FLAGS.pretrained_model_checkpoint_path) 348 | print('%s: Pre-trained model restored from %s' % 349 | (datetime.now(), FLAGS.pretrained_model_checkpoint_path)) 350 | 351 | # Start the queue runners. 352 | tf.train.start_queue_runners(sess=sess) 353 | 354 | summary_writer = tf.summary.FileWriter( 355 | FLAGS.train_dir, 356 | graph=sess.graph) 357 | 358 | # if FLAGS.debug: 359 | # sess = tf_debug.LocalCLIDebugWrapperSession(sess, ui_type=FLAGS.ui_type) 360 | 361 | for step in range(FLAGS.max_steps): 362 | start_time = time.time() 363 | _, loss_value = sess.run([train_op, loss]) 364 | # _, loss_value = sess.run([train_op, loss]) 365 | duration = time.time() - start_time 366 | 367 | assert not np.isnan(loss_value), 'Model diverged with loss = NaN' 368 | # assert not np.isnan(weighted_loss), 'Model diverged with loss = NaN' 369 | # assert not np.isnan(regularization_loss), 'Model diverged with loss = NaN' 370 | 371 | if step % 10 == 0: 372 | examples_per_sec = FLAGS.batch_size / float(duration) 373 | format_str = ('%s: step %d ,loss = %.2f, (%.1f examples/sec; %.3f ' 374 | 'sec/batch)') 375 | print(format_str % (datetime.now(), step, loss_value, examples_per_sec, duration)) 376 | 377 | if step % 100 == 0: 378 | summary_str = sess.run(summary_op) 379 | summary_writer.add_summary(summary_str, step) 380 | 381 | # Save the model checkpoint periodically. 382 | if step % 50 == 0 or (step + 1) == FLAGS.max_steps: 383 | checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt') 384 | saver.save(sess, checkpoint_path, global_step=step) 385 | -------------------------------------------------------------------------------- /inception/inception_rap_eval.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A library to evaluate Inception on a single GPU. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | from datetime import datetime 22 | import math 23 | import os.path 24 | import time 25 | 26 | 27 | import numpy as np 28 | import tensorflow as tf 29 | 30 | from inception import image_processing 31 | from inception import inception_rap_model as inception 32 | 33 | 34 | FLAGS = tf.app.flags.FLAGS 35 | 36 | tf.app.flags.DEFINE_string('eval_dir', '/home/sangliufang/tensorflow/models/research/inception/inception/rap_train', 37 | """Directory where to write event logs.""") 38 | tf.app.flags.DEFINE_string('checkpoint_dir', '/tmp/imagenet_train', 39 | """Directory where to read model checkpoints.""") 40 | 41 | # Flags governing the frequency of the eval. 42 | tf.app.flags.DEFINE_integer('eval_interval_secs', 60 * 5, 43 | """How often to run the eval.""") 44 | tf.app.flags.DEFINE_boolean('run_once', False, 45 | """Whether to run eval only once.""") 46 | 47 | tf.app.flags.DEFINE_boolean('pad', False, 48 | """Whether to run eval only once.""") 49 | 50 | # Flags governing the data used for the eval. 51 | tf.app.flags.DEFINE_integer('num_examples', 8317, 52 | """Number of examples to run. Note that the eval """ 53 | """ImageNet dataset contains 50000 examples.""") 54 | tf.app.flags.DEFINE_string('subset', 'validation', 55 | """Either 'validation' or 'train'.""") 56 | 57 | def mA(attr, gt): 58 | num = attr.__len__() 59 | num_attr = attr[0].__len__() 60 | # for i in range(num): 61 | # if(i % 100 == 0): 62 | # print(attr[i]) 63 | 64 | challenging = [] 65 | acc_collect = [] 66 | accuracy_neg = [] 67 | accuracy_pos = [] 68 | accuracy_all = [] 69 | for i in range(num_attr): 70 | print('--------------------------------------------') 71 | print(i) 72 | print(sum([attr[j][i] for j in range(num)]), \ 73 | ':', sum([attr[j][i] * gt[j][i] for j in range(num)]), \ 74 | ':', sum([gt[j][i] for j in range(num)])) 75 | # print(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 76 | accuracy_pos.append(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 77 | 78 | print("accuracy_pos: {}\n".format(accuracy_pos[i])) 79 | print(sum([(1 - attr[j][i]) for j in range(num)]), \ 80 | ':', sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]), \ 81 | ':', sum([(1 - gt[j][i]) for j in range(num)])) 82 | # print(sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) 83 | # accuracy_pos.append(sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)])) 84 | 85 | # print("accuracy_pos: {}\n".format(accuracy_pos[i])) 86 | accuracy_neg.append(sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) 87 | 88 | print("accuracy_neg: {}\n".format(accuracy_neg[i])) 89 | 90 | accuracy_all.append((accuracy_neg[i]+accuracy_pos[i])/2) 91 | print("accuracy_all: {}\n".format(accuracy_all[i])) 92 | 93 | # acc = (sum([attr[j][i] * gt[j][i] for j in range(num)]) / sum([gt[j][i] for j in range(num)]) + sum( 94 | # [(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) / sum([(1 - gt[j][i]) for j in range(num)])) / 2 95 | # acc_collect.append(acc) 96 | # print("accuracy: {}\n".format(acc)) 97 | if accuracy_all[i] < 0.75: 98 | challenging.append(i) 99 | 100 | # mA = (sum([( 101 | # sum([attr[j][i] * gt[j][i] for j in range(num)]) 102 | # / sum([gt[j][i] for j in range(num)]) 103 | # + sum([(1 - attr[j][i]) * (1 - gt[j][i]) for j in range(num)]) 104 | # / sum([(1 - gt[j][i]) for j in range(num)]) 105 | # ) for i in range(num_attr)])) / (2 * num_attr) 106 | return np.mean(accuracy_all), accuracy_all, challenging 107 | 108 | def example_based(attr, gt): 109 | num = attr.__len__() 110 | num_attr = attr[0].__len__() 111 | 112 | acc = 0 113 | prec = 0 114 | rec = 0 115 | f1 = 0 116 | 117 | attr = np.array(attr).astype(bool) 118 | gt = np.array(gt).astype(bool) 119 | 120 | for i in range(num): 121 | intersect = sum((attr[i] & gt[i]).astype(float)) 122 | union = sum((attr[i] | gt[i]).astype(float)) 123 | attr_sum = sum((attr[i]).astype(float)) 124 | gt_sum = sum((gt[i]).astype(float)) 125 | 126 | acc += 0 if union == 0 else intersect / union 127 | prec += 0 if attr_sum == 0 else intersect / attr_sum 128 | rec += 0 if gt_sum == 0 else intersect / gt_sum 129 | 130 | acc /= num 131 | prec /= num 132 | rec /= num 133 | f1 = 2 * prec * rec / (prec + rec) 134 | 135 | return acc, prec, rec, f1 136 | 137 | def softmax_or_not(predict, is_softmax=False, threshold=[0.5]*51): 138 | res = [] 139 | 140 | if not is_softmax: 141 | for i in range(FLAGS.batch_size): 142 | res1 = [0] * 51 143 | for j in range(51): 144 | if predict[i][j] >= threshold[j]: 145 | res1[j] = 1 146 | res.append(res1) 147 | return res 148 | 149 | for i in range(FLAGS.batch_size): 150 | res1 = [0] * 51 151 | for j in range(51): 152 | if j == 1: 153 | max_id, max_v = -1, -1 154 | for k in range(1, 4): 155 | if predict[i][k] > max_v: 156 | max_id = k 157 | max_v = predict[i][k] 158 | res1[max_id] = 1 159 | elif j == 4: 160 | max_id, max_v = -1, -1 161 | for k in range(4, 7): 162 | if predict[i][k] > max_v: 163 | max_id = k 164 | max_v = predict[i][k] 165 | if max_v >= threshold[j]: 166 | res1[max_id] = 1 167 | elif j == 7: 168 | max_id, max_v = -1, -1 169 | for k in range(7, 9): 170 | if predict[i][k] > max_v: 171 | max_id = k 172 | max_v = predict[i][k] 173 | if max_v >= threshold[j]: 174 | res1[max_id] = 1 175 | elif j == 9: 176 | max_id, max_v = -1, -1 177 | for k in range(9, 11): 178 | if predict[i][k] > max_v: 179 | max_id = k 180 | max_v = predict[i][k] 181 | if max_v >= threshold[j]: 182 | res1[max_id] = 1 183 | elif j < 1 or j >= 11: 184 | if predict[i][j] >= threshold[j]: 185 | res1[j] = 1 186 | else: 187 | continue 188 | res.append(res1) 189 | return res 190 | 191 | def save_to_file(attrs, labels): 192 | file = open('rap_final.txt', 'w') 193 | attrs = attrs.astype(int) 194 | labels = labels.astype(int) 195 | for i in range(len(attrs)): 196 | file.write(" ".join('%s' % id for id in attrs[i])) 197 | file.write("---") 198 | file.write(" ".join('%s' % id for id in labels[i])) 199 | file.write("\n") 200 | 201 | def _eval_once_mA(saver, mA_op, summary_writer, summary_op): 202 | with tf.Session() as sess: 203 | if os.path.exists(FLAGS.checkpoint_dir): 204 | ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir) 205 | if ckpt and ckpt.model_checkpoint_path: 206 | if os.path.isabs(ckpt.model_checkpoint_path): 207 | # Restores from checkpoint with absolute path. 208 | saver.restore(sess, ckpt.model_checkpoint_path) 209 | else: 210 | # Restores from checkpoint with relative path. 211 | saver.restore(sess, os.path.join(FLAGS.checkpoint_dir, 212 | ckpt.model_checkpoint_path)) 213 | 214 | # Assuming model_checkpoint_path looks something like: 215 | # /my-favorite-path/imagenet_train/model.ckpt-0, 216 | # extract global_step from it. 217 | global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] 218 | print('Successfully loaded model from %s at step=%s.' % 219 | (ckpt.model_checkpoint_path, global_step)) 220 | else: 221 | print('No checkpoint file found') 222 | return 223 | else: 224 | saver.restore(sess, FLAGS.checkpoint_dir) 225 | global_step = FLAGS.checkpoint_dir.split('/')[-1].split('-')[-1] 226 | print('Successfully loaded model from %s at step=%s.' % 227 | (FLAGS.checkpoint_dir, global_step)) 228 | 229 | 230 | # Start the queue runners. 231 | coord = tf.train.Coordinator() 232 | try: 233 | threads = [] 234 | for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS): 235 | threads.extend(qr.create_threads(sess, coord=coord, daemon=True, 236 | start=True)) 237 | 238 | num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size)) 239 | # Counts the number of correct predictions. 240 | total_sample_count = num_iter * FLAGS.batch_size 241 | attrs = np.zeros((total_sample_count , 51)) 242 | labels = np.zeros((total_sample_count, 51)) 243 | step = 0 244 | 245 | print('%s: starting evaluation on (%s).' % (datetime.now(), FLAGS.subset)) 246 | start_time = time.time() 247 | while step < num_iter and not coord.should_stop(): 248 | predict, label = sess.run(mA_op) 249 | # threshold= [ -1.63896918, -2.92778826, -0.85942656, -0.18633965, -2.28389955, 0.64350349, 250 | # -2.49138522, 1.69379652, -2.7792089, -2.94575572, -2.16644192, 1.65624774, 251 | # -2.90464497, -2.6456902, -2.91939425, -1.9960742, -2.35979962, -2.7363832, 252 | # -1.86692214, -2.19749665, -1.53251255, -2.86584759, -2.82985973, -2.89830303, 253 | # -0.28588042, -2.70379686, -2.70369697, -2.70372081, -1.78928852, -2.40788651, 254 | # -1.56871521, -1.63923609, -2.46088076, -2.8779881, -2.09501028, -2.89457226, 255 | # -2.69188547, -2.85242891, -2.77874351, -2.84279823, -2.90740204, -2.87133193, 256 | # -1.38525283, -2.83333468, -2.78677249, -2.47449708, -2.84807682, -2.92042303, 257 | # -2.9037981 , -2.86978507, -2.39694023] 258 | # threshold = [x / 2 for x in threshold] 259 | threshold = [0.0] * 51 260 | predict = softmax_or_not(predict, is_softmax=False, threshold=threshold) 261 | attrs[step*FLAGS.batch_size : (step+1)*FLAGS.batch_size,:] = predict 262 | labels[step*FLAGS.batch_size : (step+1)*FLAGS.batch_size,:] = label 263 | # np.append(attrs, predict, axis=0) 264 | # np.append(labels, label, axis=0) 265 | 266 | step += 1 267 | if step % 20 == 0: 268 | duration = time.time() - start_time 269 | sec_per_batch = duration / 20.0 270 | examples_per_sec = FLAGS.batch_size / sec_per_batch 271 | print('%s: [%d batches out of %d] (%.1f examples/sec; %.3f' 272 | 'sec/batch)' % (datetime.now(), step, num_iter, 273 | examples_per_sec, sec_per_batch)) 274 | start_time = time.time() 275 | 276 | # Compute mA. 277 | save_to_file(attrs, labels) 278 | print(mA(attrs, labels)) 279 | print(example_based(attrs, labels)) 280 | #mA = sum_mA / total_sample_count 281 | summary = tf.Summary() 282 | summary.ParseFromString(sess.run(summary_op)) 283 | summary_writer.add_summary(summary, global_step) 284 | except Exception as e: # pylint: disable=broad-except 285 | coord.request_stop(e) 286 | 287 | coord.request_stop() 288 | coord.join(threads, stop_grace_period_secs=10) 289 | 290 | def _eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op): 291 | """Runs Eval once. 292 | 293 | Args: 294 | saver: Saver. 295 | summary_writer: Summary writer. 296 | top_1_op: Top 1 op. 297 | top_5_op: Top 5 op. 298 | summary_op: Summary op. 299 | """ 300 | with tf.Session() as sess: 301 | if os.path.exists(FLAGS.checkpoint_dir): 302 | ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir) 303 | if ckpt and ckpt.model_checkpoint_path: 304 | if os.path.isabs(ckpt.model_checkpoint_path): 305 | # Restores from checkpoint with absolute path. 306 | saver.restore(sess, ckpt.model_checkpoint_path) 307 | else: 308 | # Restores from checkpoint with relative path. 309 | saver.restore(sess, os.path.join(FLAGS.checkpoint_dir, 310 | ckpt.model_checkpoint_path)) 311 | 312 | # Assuming model_checkpoint_path looks something like: 313 | # /my-favorite-path/imagenet_train/model.ckpt-0, 314 | # extract global_step from it. 315 | global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] 316 | print('Successfully loaded model from %s at step=%s.' % 317 | (ckpt.model_checkpoint_path, global_step)) 318 | else: 319 | print('No checkpoint file found') 320 | return 321 | else: 322 | saver.restore(sess, FLAGS.checkpoint_dir) 323 | global_step = FLAGS.checkpoint_dir.split('/')[-1].split('-')[-1] 324 | print('Successfully loaded model from %s at step=%s.' % 325 | (FLAGS.checkpoint_dir, global_step)) 326 | 327 | # Start the queue runners. 328 | coord = tf.train.Coordinator() 329 | try: 330 | threads = [] 331 | for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS): 332 | threads.extend(qr.create_threads(sess, coord=coord, daemon=True, 333 | start=True)) 334 | 335 | num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size)) 336 | # Counts the number of correct predictions. 337 | count_top_1 = 0.0 338 | count_top_5 = 0.0 339 | total_sample_count = num_iter * FLAGS.batch_size 340 | step = 0 341 | 342 | print('%s: starting evaluation on (%s).' % (datetime.now(), FLAGS.subset)) 343 | start_time = time.time() 344 | while step < num_iter and not coord.should_stop(): 345 | top_1, top_5 = sess.run([top_1_op, top_5_op]) 346 | count_top_1 += np.sum(top_1) 347 | count_top_5 += np.sum(top_5) 348 | step += 1 349 | if step % 20 == 0: 350 | duration = time.time() - start_time 351 | sec_per_batch = duration / 20.0 352 | examples_per_sec = FLAGS.batch_size / sec_per_batch 353 | print('%s: [%d batches out of %d] (%.1f examples/sec; %.3f' 354 | 'sec/batch)' % (datetime.now(), step, num_iter, 355 | examples_per_sec, sec_per_batch)) 356 | start_time = time.time() 357 | 358 | # Compute precision @ 1. 359 | precision_at_1 = count_top_1 / total_sample_count 360 | recall_at_5 = count_top_5 / total_sample_count 361 | print('%s: precision @ 1 = %.4f recall @ 5 = %.4f [%d examples]' % 362 | (datetime.now(), precision_at_1, recall_at_5, total_sample_count)) 363 | 364 | summary = tf.Summary() 365 | summary.ParseFromString(sess.run(summary_op)) 366 | summary.value.add(tag='Precision @ 1', simple_value=precision_at_1) 367 | summary.value.add(tag='Recall @ 5', simple_value=recall_at_5) 368 | summary_writer.add_summary(summary, global_step) 369 | 370 | except Exception as e: # pylint: disable=broad-except 371 | coord.request_stop(e) 372 | 373 | coord.request_stop() 374 | coord.join(threads, stop_grace_period_secs=10) 375 | 376 | def mean_accuracy(logits, labels): 377 | print(logits) 378 | labels = tf.to_float(labels) 379 | # logits = tf.sigmoid(logits) 380 | # logits = (tf.sign(tf.sigmoid(logits) - 0.5) + 1) /2 381 | 382 | 383 | 384 | #num_pp = tf.reduce_sum(predict * labels, 0) 385 | #num_nn = tf.reduce_sum((predict-1) * (labels - 1), 0) 386 | #num_pn = tf.reduce_sum(predict * (1 - labels), 0) 387 | #num_np = tf.reduce_sum((1-predict) * labels, 0) 388 | return logits, labels 389 | 390 | def evaluate(dataset): 391 | """Evaluate model on Dataset for a number of steps.""" 392 | with tf.Graph().as_default(): 393 | # Get images and labels from the dataset. 394 | images, labels, rois = image_processing.inputs(dataset) 395 | 396 | # Number of classes in the Dataset label set plus 1. 397 | # Label 0 is reserved for an (unused) background class. 398 | num_classes = dataset.num_classes() 399 | 400 | # Build a Graph that computes the logits predictions from the 401 | # inference model. 402 | logits, _ = inception.inference_roi_lstm_bn(images, rois, num_classes) 403 | 404 | # Calculate predictions. 405 | #top_1_op = tf.nn.in_top_k(logits, labels, 1) 406 | #top_5_op = tf.nn.in_top_k(logits, labels, 5) 407 | mA_op = mean_accuracy(logits, labels) 408 | 409 | # Restore the moving average version of the learned variables for eval. 410 | variable_averages = tf.train.ExponentialMovingAverage( 411 | inception.MOVING_AVERAGE_DECAY) 412 | variables_to_restore = variable_averages.variables_to_restore() 413 | saver = tf.train.Saver(variables_to_restore) 414 | 415 | # Build the summary operation based on the TF collection of Summaries. 416 | summary_op = tf.summary.merge_all() 417 | 418 | graph_def = tf.get_default_graph().as_graph_def() 419 | summary_writer = tf.summary.FileWriter(FLAGS.eval_dir, 420 | graph_def=graph_def) 421 | 422 | while True: 423 | #_eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op) 424 | _eval_once_mA(saver, mA_op, summary_writer, summary_op) 425 | if FLAGS.run_once: 426 | break 427 | time.sleep(FLAGS.eval_interval_secs) 428 | -------------------------------------------------------------------------------- /inception/inception_rap_train.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A library to train Inception using multiple GPUs with synchronous updates. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import copy 22 | from datetime import datetime 23 | import os.path 24 | import re 25 | import time 26 | 27 | import numpy as np 28 | import tensorflow as tf 29 | from tensorflow.python import debug as tf_debug 30 | 31 | from inception import image_processing 32 | from inception import inception_rap_model as inception 33 | from inception.slim import slim 34 | 35 | FLAGS = tf.app.flags.FLAGS 36 | 37 | tf.app.flags.DEFINE_string('train_dir', '/home/sangliufang/tensorflow/models/research/inception/inception/rap_train', 38 | """Directory where to write event logs """ 39 | """and checkpoint.""") 40 | tf.app.flags.DEFINE_integer('max_steps', 5000, 41 | """Number of batches to run.""") 42 | tf.app.flags.DEFINE_string('subset', 'train', 43 | """Either 'train' or 'validation'.""") 44 | 45 | # Flags governing the hardware employed for running TensorFlow. 46 | tf.app.flags.DEFINE_integer('num_gpus', 2, 47 | """How many GPUs to use.""") 48 | tf.app.flags.DEFINE_boolean('log_device_placement', False, 49 | """Whether to log device placement.""") 50 | 51 | # Flags governing the type of training. 52 | tf.app.flags.DEFINE_boolean('fine_tune', False, 53 | """If set, randomly initialize the final layer """ 54 | """of weights in order to train the network on a """ 55 | """new task""") 56 | # tf.app.flags.DEFINE_boolean('debug', False, 57 | # """If set, randomly initialize the final layer """ 58 | # """of weights in order to train the network on a """ 59 | # """new task.""") 60 | tf.app.flags.DEFINE_string('pretrained_model_checkpoint_path', '', 61 | """If specified, restore this pretrained model """ 62 | """before beginning any training.""") 63 | 64 | # **IMPORTANT** 65 | # Please note that this learning rate schedule is heavily dependent on the 66 | # hardware architecture, batch size and any changes to the model architecture 67 | # specification. Selecting a finely tuned learning rate schedule is an 68 | # empirical process that requires some experimentation. Please see README.md 69 | # more guidance and discussion. 70 | # 71 | # With 8 Tesla K40's and a batch size = 256, the following setup achieves 72 | # precision@1 = 73.5% after 100 hours and 100K steps (20 epochs). 73 | # Learning rate decay factor selected from http://arxiv.org/abs/1404.5997. 74 | tf.app.flags.DEFINE_float('initial_learning_rate', 0.0001, 75 | """Initial learning rate.""") 76 | tf.app.flags.DEFINE_float('num_epochs_per_decay', 64.0, 77 | """Epochs after which learning rate decays.""") 78 | tf.app.flags.DEFINE_float('learning_rate_decay_factor', 0.16, 79 | """Learning rate decay factor.""") 80 | 81 | tf.app.flags.DEFINE_boolean('pad', False, 82 | """Whether to run eval only once.""") 83 | 84 | # Constants dictating the learning rate schedule. 85 | RMSPROP_DECAY = 0.9 # Decay term for RMSProp. 86 | RMSPROP_MOMENTUM = 0.9 # Momentum in RMSProp. 87 | RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp. 88 | 89 | 90 | def _tower_loss(images, labels, rois, num_classes, scope, reuse_variables=None): 91 | """Calculate the total loss on a single tower running the ImageNet model. 92 | 93 | We perform 'batch splitting'. This means that we cut up a batch across 94 | multiple GPUs. For instance, if the batch size = 32 and num_gpus = 2, 95 | then each tower will operate on an batch of 16 images. 96 | 97 | Args: 98 | images: Images. 4D tensor of size [batch_size, FLAGS.image_size, 99 | FLAGS.image_size, 3]. 100 | labels: 1-D integer Tensor of [batch_size]. 101 | num_classes: number of classes 102 | scope: unique prefix string identifying the ImageNet tower, e.g. 103 | 'tower_0'. 104 | 105 | Returns: 106 | Tensor of shape [] containing the total loss for a batch of data 107 | """ 108 | # When fine-tuning a model, we do not restore the logits but instead we 109 | # randomly initialize the logits. The number of classes in the output of the 110 | # logit is the number of classes in specified Dataset. 111 | restore_logits = not FLAGS.fine_tune 112 | 113 | #print(num_classes) 114 | #print(labels) 115 | 116 | # Build inference Graph. 117 | with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables): 118 | logits = inception.inference_lstm(images, rois, num_classes, for_training=True, 119 | restore_logits=restore_logits, 120 | scope=scope) 121 | # print(logits) 122 | # Build the portion of the Graph calculating the losses. Note that we will 123 | # assemble the total_loss using a custom function below. 124 | split_batch_size = images.get_shape().as_list()[0] 125 | # print(logits[0].get_shape()) 126 | # print(labels.get_shape()) 127 | # print(logits) 128 | inception.loss(logits, labels, batch_size=split_batch_size) 129 | 130 | # print(labels.get_shape()) 131 | # Assemble all of the losses for the current tower only. 132 | losses = tf.get_collection(slim.losses.LOSSES_COLLECTION, scope) 133 | 134 | # Calculate the total loss for the current tower. 135 | regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 136 | total_loss = tf.add_n(losses + regularization_losses, name='total_loss') 137 | 138 | # Compute the moving average of all individual losses and the total loss. 139 | loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg') 140 | loss_averages_op = loss_averages.apply(losses + [total_loss]) 141 | 142 | # Attach a scalar summmary to all individual losses and the total loss; do the 143 | # same for the averaged version of the losses. 144 | for l in losses + [total_loss]: 145 | # Remove 'tower_[0-9]/' from the name in case this is a multi-GPU training 146 | # session. This helps the clarity of presentation on TensorBoard. 147 | loss_name = re.sub('%s_[0-9]*/' % inception.TOWER_NAME, '', l.op.name) 148 | # Name each loss as '(raw)' and name the moving average version of the loss 149 | # as the original loss name. 150 | tf.summary.scalar(loss_name +' (raw)', l) 151 | tf.summary.scalar(loss_name, loss_averages.average(l)) 152 | 153 | with tf.control_dependencies([loss_averages_op]): 154 | total_loss = tf.identity(total_loss) 155 | # return total_loss, losses, regularization_losses 156 | return total_loss 157 | 158 | 159 | def _average_gradients(tower_grads): 160 | """Calculate the average gradient for each shared variable across all towers. 161 | 162 | Note that this function provides a synchronization point across all towers. 163 | 164 | Args: 165 | tower_grads: List of lists of (gradient, variable) tuples. The outer list 166 | is over individual gradients. The inner list is over the gradient 167 | calculation for each tower. 168 | Returns: 169 | List of pairs of (gradient, variable) where the gradient has been averaged 170 | across all towers. 171 | """ 172 | average_grads = [] 173 | for grad_and_vars in zip(*tower_grads): 174 | # Note that each grad_and_vars looks like the following: 175 | # ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN)) 176 | grads = [] 177 | for g, _ in grad_and_vars: 178 | # Add 0 dimension to the gradients to represent the tower. 179 | expanded_g = tf.expand_dims(g, 0) 180 | 181 | # Append on a 'tower' dimension which we will average over below. 182 | grads.append(expanded_g) 183 | 184 | # Average over the 'tower' dimension. 185 | grad = tf.concat(axis=0, values=grads) 186 | grad = tf.reduce_mean(grad, 0) 187 | 188 | # Keep in mind that the Variables are redundant because they are shared 189 | # across towers. So .. we will just return the first tower's pointer to 190 | # the Variable. 191 | v = grad_and_vars[0][1] 192 | # if 'logits_bn' in v.name: 193 | # grad_and_var = (grad, v) 194 | # else: 195 | # grad_and_var = (0 * grad, v) 196 | grad_and_var = (grad, v) 197 | average_grads.append(grad_and_var) 198 | return average_grads 199 | 200 | 201 | def train(dataset): 202 | """Train on dataset for a number of steps.""" 203 | with tf.Graph().as_default(), tf.device('/cpu:0'): 204 | # Create a variable to count the number of train() calls. This equals the 205 | # number of batches processed * FLAGS.num_gpus. 206 | global_step = tf.get_variable( 207 | 'global_step', [], 208 | initializer=tf.constant_initializer(0), trainable=False) 209 | 210 | # Calculate the learning rate schedule. 211 | num_batches_per_epoch = (dataset.num_examples_per_epoch() / 212 | FLAGS.batch_size) 213 | decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay) 214 | 215 | # Decay the learning rate exponentially based on the number of steps. 216 | lr = tf.train.exponential_decay(FLAGS.initial_learning_rate, 217 | global_step, 218 | decay_steps, 219 | FLAGS.learning_rate_decay_factor, 220 | staircase=True) 221 | 222 | # Create an optimizer that performs gradient descent. 223 | # opt = tf.train.RMSPropOptimizer(lr, RMSPROP_DECAY, 224 | # momentum=RMSPROP_MOMENTUM, 225 | # epsilon=RMSPROP_EPSILON) 226 | opt = tf.train.MomentumOptimizer(lr, 0.9) 227 | 228 | # Get images and labels for ImageNet and split the batch across GPUs. 229 | assert FLAGS.batch_size % FLAGS.num_gpus == 0, ( 230 | 'Batch size must be divisible by number of GPUs') 231 | split_batch_size = int(FLAGS.batch_size / FLAGS.num_gpus) 232 | 233 | # Override the number of preprocessing threads to account for the increased 234 | # number of GPU towers. 235 | num_preprocess_threads = FLAGS.num_preprocess_threads * FLAGS.num_gpus 236 | images, labels, rois = image_processing.distorted_inputs( 237 | dataset, 238 | num_preprocess_threads=num_preprocess_threads) 239 | 240 | input_summaries = copy.copy(tf.get_collection(tf.GraphKeys.SUMMARIES)) 241 | 242 | # Number of classes in the Dataset label set plus 1. 243 | # Label 0 is reserved for an (unused) background class. 244 | num_classes = dataset.num_classes() 245 | 246 | # Split the batch of images and labels for towers. 247 | images_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=images) 248 | labels_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=labels) 249 | rois_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=rois) 250 | 251 | # Calculate the gradients for each model tower. 252 | tower_grads = [] 253 | reuse_variables = None 254 | for i in range(FLAGS.num_gpus): 255 | with tf.device('/gpu:%d' % i): 256 | with tf.name_scope('%s_%d' % (inception.TOWER_NAME, i)) as scope: 257 | # Force all Variables to reside on the CPU. 258 | with slim.arg_scope([slim.variables.variable], device='/cpu:0'): 259 | # Calculate the loss for one tower of the ImageNet model. This 260 | # function constructs the entire ImageNet model but shares the 261 | # variables across all towers. 262 | loss = _tower_loss(images_splits[i], labels_splits[i], rois_splits[i], num_classes, 263 | scope, reuse_variables) 264 | 265 | # Reuse variables for the next tower. 266 | reuse_variables = True 267 | 268 | # Retain the summaries from the final tower. 269 | summaries = tf.get_collection(tf.GraphKeys.SUMMARIES, scope) 270 | 271 | # Retain the Batch Normalization updates operations only from the 272 | # final tower. Ideally, we should grab the updates from all towers 273 | # but these stats accumulate extremely fast so we can ignore the 274 | # other stats from the other towers without significant detriment. 275 | batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION, 276 | scope) 277 | 278 | # Calculate the gradients for the batch of data on this ImageNet 279 | # tower. 280 | grads = opt.compute_gradients(loss) 281 | 282 | # Keep track of the gradients across all towers. 283 | tower_grads.append(grads) 284 | 285 | # We must calculate the mean of each gradient. Note that this is the 286 | # synchronization point across all towers. 287 | grads = _average_gradients(tower_grads) 288 | 289 | # Add a summaries for the input processing and global_step. 290 | summaries.extend(input_summaries) 291 | 292 | # Add a summary to track the learning rate. 293 | summaries.append(tf.summary.scalar('learning_rate', lr)) 294 | 295 | # Add histograms for gradients. 296 | for grad, var in grads: 297 | if grad is not None: 298 | summaries.append( 299 | tf.summary.histogram(var.op.name + '/gradients', grad)) 300 | 301 | # Apply the gradients to adjust the shared variables. 302 | apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) 303 | 304 | # Add histograms for trainable variables. 305 | for var in tf.trainable_variables(): 306 | summaries.append(tf.summary.histogram(var.op.name, var)) 307 | 308 | # Track the moving averages of all trainable variables. 309 | # Note that we maintain a "double-average" of the BatchNormalization 310 | # global statistics. This is more complicated then need be but we employ 311 | # this for backward-compatibility with our previous models. 312 | variable_averages = tf.train.ExponentialMovingAverage( 313 | inception.MOVING_AVERAGE_DECAY, global_step) 314 | 315 | # Another possibility is to use tf.slim.get_variables(). 316 | variables_to_average = (tf.trainable_variables() + 317 | tf.moving_average_variables()) 318 | variables_averages_op = variable_averages.apply(variables_to_average) 319 | 320 | # Group all updates to into a single train op. 321 | batchnorm_updates_op = tf.group(*batchnorm_updates) 322 | train_op = tf.group(apply_gradient_op, variables_averages_op, 323 | batchnorm_updates_op) 324 | 325 | # Create a saver. 326 | saver = tf.train.Saver(tf.global_variables(), max_to_keep=10) 327 | 328 | # Build the summary operation from the last tower summaries. 329 | summary_op = tf.summary.merge(summaries) 330 | 331 | # Build an initialization operation to run below. 332 | init = tf.global_variables_initializer() 333 | 334 | # Start running operations on the Graph. allow_soft_placement must be set to 335 | # True to build towers on GPU, as some of the ops do not have GPU 336 | # implementations. 337 | sess = tf.Session(config=tf.ConfigProto( 338 | allow_soft_placement=True, 339 | log_device_placement=FLAGS.log_device_placement)) 340 | sess.run(init) 341 | 342 | if FLAGS.pretrained_model_checkpoint_path: 343 | # assert tf.gfile.Exists(FLAGS.pretrained_model_checkpoint_path) 344 | variables_to_restore = tf.get_collection( 345 | slim.variables.VARIABLES_TO_RESTORE) 346 | restorer = tf.train.Saver(variables_to_restore) 347 | restorer.restore(sess, FLAGS.pretrained_model_checkpoint_path) 348 | print('%s: Pre-trained model restored from %s' % 349 | (datetime.now(), FLAGS.pretrained_model_checkpoint_path)) 350 | 351 | # Start the queue runners. 352 | tf.train.start_queue_runners(sess=sess) 353 | 354 | summary_writer = tf.summary.FileWriter( 355 | FLAGS.train_dir, 356 | graph=sess.graph) 357 | 358 | # if FLAGS.debug: 359 | # sess = tf_debug.LocalCLIDebugWrapperSession(sess, ui_type=FLAGS.ui_type) 360 | 361 | for step in range(FLAGS.max_steps): 362 | start_time = time.time() 363 | _, loss_value = sess.run([train_op, loss]) 364 | # _, loss_value = sess.run([train_op, loss]) 365 | duration = time.time() - start_time 366 | 367 | assert not np.isnan(loss_value), 'Model diverged with loss = NaN' 368 | # assert not np.isnan(weighted_loss), 'Model diverged with loss = NaN' 369 | # assert not np.isnan(regularization_loss), 'Model diverged with loss = NaN' 370 | 371 | if step % 10 == 0: 372 | examples_per_sec = FLAGS.batch_size / float(duration) 373 | format_str = ('%s: step %d ,loss = %.2f, (%.1f examples/sec; %.3f ' 374 | 'sec/batch)') 375 | print(format_str % (datetime.now(), step, loss_value, examples_per_sec, duration)) 376 | 377 | if step % 100 == 0: 378 | summary_str = sess.run(summary_op) 379 | summary_writer.add_summary(summary_str, step) 380 | 381 | # Save the model checkpoint periodically. 382 | if step % 100 == 0 or (step + 1) == FLAGS.max_steps: 383 | checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt') 384 | saver.save(sess, checkpoint_path, global_step=step) 385 | -------------------------------------------------------------------------------- /inception/peta_data.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Small library that points to the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | 23 | from inception.dataset import Dataset 24 | 25 | 26 | class PETAData(Dataset): 27 | """Flowers data set.""" 28 | 29 | def __init__(self, subset): 30 | super(PETAData, self).__init__('PETA51', subset) 31 | 32 | def num_classes(self): 33 | """Returns the number of classes in the data set.""" 34 | return 35 35 | 36 | def num_examples_per_epoch(self): 37 | """Returns the number of examples in the data subset.""" 38 | if self.subset == 'train': 39 | return 9500 40 | if self.subset == 'validation': 41 | return 7600 42 | 43 | def download_message(self): 44 | """Instruction to download and extract the tarball from Flowers website.""" 45 | 46 | print('Failed to find any image %s files'% self.subset) 47 | print('') 48 | print('If you have already downloaded and processed the data, then make ' 49 | 'sure to set --data_dir to point to the directory containing the ' 50 | 'location of the sharded TFRecords.\n') 51 | print('Please see README.md for instructions on how to build ' 52 | 'the PETA dataset using precess PETA.\n') 53 | -------------------------------------------------------------------------------- /inception/peta_eval.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A binary to evaluate Inception on the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | import tensorflow as tf 23 | 24 | from inception import inception_peta_eval 25 | from inception.peta_data import PETAData 26 | 27 | FLAGS = tf.app.flags.FLAGS 28 | 29 | 30 | def main(unused_argv=None): 31 | dataset = PETAData(subset=FLAGS.subset) 32 | assert dataset.data_files() 33 | if tf.gfile.Exists(FLAGS.eval_dir): 34 | tf.gfile.DeleteRecursively(FLAGS.eval_dir) 35 | tf.gfile.MakeDirs(FLAGS.eval_dir) 36 | #inception_rap_eval.evaluate(dataset) 37 | inception_peta_eval.evaluate(dataset) 38 | 39 | 40 | if __name__ == '__main__': 41 | tf.app.run() 42 | -------------------------------------------------------------------------------- /inception/peta_train.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A binary to train Inception on the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | 23 | import tensorflow as tf 24 | 25 | from inception import inception_peta_train 26 | from inception.peta_data import PETAData 27 | 28 | FLAGS = tf.app.flags.FLAGS 29 | 30 | 31 | def main(_): 32 | dataset = PETAData(subset=FLAGS.subset) 33 | assert dataset.data_files() 34 | if tf.gfile.Exists(FLAGS.train_dir): 35 | print('>>>>>>> train dir is : '+FLAGS.train_dir) 36 | tf.gfile.DeleteRecursively(FLAGS.train_dir) 37 | #print(FLAGS.train_dir) 38 | tf.gfile.MakeDirs(FLAGS.train_dir) 39 | #inception_rap_train.train(dataset) 40 | inception_peta_train.train(dataset) 41 | 42 | 43 | if __name__ == '__main__': 44 | tf.app.run() 45 | -------------------------------------------------------------------------------- /inception/rap_data.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Small library that points to the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | 23 | from inception.dataset import Dataset 24 | 25 | 26 | class RAPData(Dataset): 27 | """Flowers data set.""" 28 | 29 | def __init__(self, subset): 30 | super(RAPData, self).__init__('RAP51', subset) 31 | 32 | def num_classes(self): 33 | """Returns the number of classes in the data set.""" 34 | return 51 35 | 36 | def num_examples_per_epoch(self): 37 | """Returns the number of examples in the data subset.""" 38 | if self.subset == 'train': 39 | return 33268 40 | if self.subset == 'validation': 41 | return 8317 42 | 43 | def download_message(self): 44 | """Instruction to download and extract the tarball from Flowers website.""" 45 | 46 | print('Failed to find any image %s files'% self.subset) 47 | print('') 48 | print('If you have already downloaded and processed the data, then make ' 49 | 'sure to set --data_dir to point to the directory containing the ' 50 | 'location of the sharded TFRecords.\n') 51 | print('Please see README.md for instructions on how to build ' 52 | 'the rap dataset using precess rap.\n') 53 | -------------------------------------------------------------------------------- /inception/rap_eval.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A binary to evaluate Inception on the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | import tensorflow as tf 23 | 24 | from inception import inception_rap_eval 25 | from inception.rap_data import RAPData 26 | 27 | FLAGS = tf.app.flags.FLAGS 28 | 29 | 30 | def main(unused_argv=None): 31 | dataset = RAPData(subset=FLAGS.subset) 32 | assert dataset.data_files() 33 | if tf.gfile.Exists(FLAGS.eval_dir): 34 | tf.gfile.DeleteRecursively(FLAGS.eval_dir) 35 | tf.gfile.MakeDirs(FLAGS.eval_dir) 36 | #inception_rap_eval.evaluate(dataset) 37 | inception_rap_eval.evaluate(dataset) 38 | 39 | 40 | if __name__ == '__main__': 41 | tf.app.run() 42 | -------------------------------------------------------------------------------- /inception/rap_train.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """A binary to train Inception on the flowers data set. 16 | """ 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | 22 | 23 | import tensorflow as tf 24 | 25 | from inception import inception_rap_train 26 | from inception.rap_data import RAPData 27 | 28 | FLAGS = tf.app.flags.FLAGS 29 | 30 | 31 | def main(_): 32 | dataset = RAPData(subset=FLAGS.subset) 33 | assert dataset.data_files() 34 | if tf.gfile.Exists(FLAGS.train_dir): 35 | print('>>>>>>> train dir is : '+FLAGS.train_dir) 36 | tf.gfile.DeleteRecursively(FLAGS.train_dir) 37 | #print(FLAGS.train_dir) 38 | tf.gfile.MakeDirs(FLAGS.train_dir) 39 | #inception_rap_train.train(dataset) 40 | inception_rap_train.train(dataset) 41 | 42 | 43 | if __name__ == '__main__': 44 | tf.app.run() 45 | -------------------------------------------------------------------------------- /inception/slim/BUILD: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Contains the operations and nets for building TensorFlow-Slim models. 3 | 4 | package(default_visibility = ["//inception:internal"]) 5 | 6 | licenses(["notice"]) # Apache 2.0 7 | 8 | exports_files(["LICENSE"]) 9 | 10 | py_library( 11 | name = "scopes", 12 | srcs = ["scopes.py"], 13 | ) 14 | 15 | py_test( 16 | name = "scopes_test", 17 | size = "small", 18 | srcs = ["scopes_test.py"], 19 | deps = [ 20 | ":scopes", 21 | ], 22 | ) 23 | 24 | py_library( 25 | name = "variables", 26 | srcs = ["variables.py"], 27 | deps = [ 28 | ":scopes", 29 | ], 30 | ) 31 | 32 | py_test( 33 | name = "variables_test", 34 | size = "small", 35 | srcs = ["variables_test.py"], 36 | deps = [ 37 | ":variables", 38 | ], 39 | ) 40 | 41 | py_library( 42 | name = "losses", 43 | srcs = ["losses.py"], 44 | ) 45 | 46 | py_test( 47 | name = "losses_test", 48 | size = "small", 49 | srcs = ["losses_test.py"], 50 | deps = [ 51 | ":losses", 52 | ], 53 | ) 54 | 55 | py_library( 56 | name = "ops", 57 | srcs = ["ops.py"], 58 | deps = [ 59 | ":losses", 60 | ":scopes", 61 | ":variables", 62 | ], 63 | ) 64 | 65 | py_test( 66 | name = "ops_test", 67 | size = "small", 68 | srcs = ["ops_test.py"], 69 | deps = [ 70 | ":ops", 71 | ":variables", 72 | ], 73 | ) 74 | 75 | py_library( 76 | name = "inception", 77 | srcs = ["inception_model.py"], 78 | deps = [ 79 | ":ops", 80 | ":scopes", 81 | ], 82 | ) 83 | 84 | py_library( 85 | name = "peta", 86 | srcs = ["peta_model.py"], 87 | deps = [ 88 | ":ops", 89 | ":scopes", 90 | ], 91 | ) 92 | 93 | py_test( 94 | name = "inception_test", 95 | size = "medium", 96 | srcs = ["inception_test.py"], 97 | deps = [ 98 | ":inception", 99 | ], 100 | ) 101 | 102 | py_library( 103 | name = "slim", 104 | srcs = ["slim.py"], 105 | deps = [ 106 | ":inception", 107 | ":losses", 108 | ":ops", 109 | ":scopes", 110 | ":variables", 111 | ":peta" 112 | ], 113 | ) 114 | 115 | py_test( 116 | name = "collections_test", 117 | size = "small", 118 | srcs = ["collections_test.py"], 119 | deps = [ 120 | ":slim", 121 | ], 122 | ) 123 | -------------------------------------------------------------------------------- /inception/slim/__pycache__/inception_model.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/inception_model.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/losses.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/losses.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/ops.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/ops.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/peta_model.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/peta_model.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/scopes.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/scopes.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/slim.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/slim.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/__pycache__/variables.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slf12/GRLModel/21495dac0df20388def0f7deaebc17b74538524a/inception/slim/__pycache__/variables.cpython-34.pyc -------------------------------------------------------------------------------- /inception/slim/collections_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Tests for inception.""" 16 | from __future__ import absolute_import 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | import tensorflow as tf 21 | 22 | from inception.slim import slim 23 | 24 | 25 | def get_variables(scope=None): 26 | return slim.variables.get_variables(scope) 27 | 28 | 29 | def get_variables_by_name(name): 30 | return slim.variables.get_variables_by_name(name) 31 | 32 | 33 | class CollectionsTest(tf.test.TestCase): 34 | 35 | def testVariables(self): 36 | batch_size = 5 37 | height, width = 299, 299 38 | with self.test_session(): 39 | inputs = tf.random_uniform((batch_size, height, width, 3)) 40 | with slim.arg_scope([slim.ops.conv2d], 41 | batch_norm_params={'decay': 0.9997}): 42 | slim.inception.inception_v3(inputs) 43 | self.assertEqual(len(get_variables()), 388) 44 | self.assertEqual(len(get_variables_by_name('weights')), 98) 45 | self.assertEqual(len(get_variables_by_name('biases')), 2) 46 | self.assertEqual(len(get_variables_by_name('beta')), 96) 47 | self.assertEqual(len(get_variables_by_name('gamma')), 0) 48 | self.assertEqual(len(get_variables_by_name('moving_mean')), 96) 49 | self.assertEqual(len(get_variables_by_name('moving_variance')), 96) 50 | 51 | def testVariablesWithoutBatchNorm(self): 52 | batch_size = 5 53 | height, width = 299, 299 54 | with self.test_session(): 55 | inputs = tf.random_uniform((batch_size, height, width, 3)) 56 | with slim.arg_scope([slim.ops.conv2d], 57 | batch_norm_params=None): 58 | slim.inception.inception_v3(inputs) 59 | self.assertEqual(len(get_variables()), 196) 60 | self.assertEqual(len(get_variables_by_name('weights')), 98) 61 | self.assertEqual(len(get_variables_by_name('biases')), 98) 62 | self.assertEqual(len(get_variables_by_name('beta')), 0) 63 | self.assertEqual(len(get_variables_by_name('gamma')), 0) 64 | self.assertEqual(len(get_variables_by_name('moving_mean')), 0) 65 | self.assertEqual(len(get_variables_by_name('moving_variance')), 0) 66 | 67 | def testVariablesByLayer(self): 68 | batch_size = 5 69 | height, width = 299, 299 70 | with self.test_session(): 71 | inputs = tf.random_uniform((batch_size, height, width, 3)) 72 | with slim.arg_scope([slim.ops.conv2d], 73 | batch_norm_params={'decay': 0.9997}): 74 | slim.inception.inception_v3(inputs) 75 | self.assertEqual(len(get_variables()), 388) 76 | self.assertEqual(len(get_variables('conv0')), 4) 77 | self.assertEqual(len(get_variables('conv1')), 4) 78 | self.assertEqual(len(get_variables('conv2')), 4) 79 | self.assertEqual(len(get_variables('conv3')), 4) 80 | self.assertEqual(len(get_variables('conv4')), 4) 81 | self.assertEqual(len(get_variables('mixed_35x35x256a')), 28) 82 | self.assertEqual(len(get_variables('mixed_35x35x288a')), 28) 83 | self.assertEqual(len(get_variables('mixed_35x35x288b')), 28) 84 | self.assertEqual(len(get_variables('mixed_17x17x768a')), 16) 85 | self.assertEqual(len(get_variables('mixed_17x17x768b')), 40) 86 | self.assertEqual(len(get_variables('mixed_17x17x768c')), 40) 87 | self.assertEqual(len(get_variables('mixed_17x17x768d')), 40) 88 | self.assertEqual(len(get_variables('mixed_17x17x768e')), 40) 89 | self.assertEqual(len(get_variables('mixed_8x8x2048a')), 36) 90 | self.assertEqual(len(get_variables('mixed_8x8x2048b')), 36) 91 | self.assertEqual(len(get_variables('logits')), 2) 92 | self.assertEqual(len(get_variables('aux_logits')), 10) 93 | 94 | def testVariablesToRestore(self): 95 | batch_size = 5 96 | height, width = 299, 299 97 | with self.test_session(): 98 | inputs = tf.random_uniform((batch_size, height, width, 3)) 99 | with slim.arg_scope([slim.ops.conv2d], 100 | batch_norm_params={'decay': 0.9997}): 101 | slim.inception.inception_v3(inputs) 102 | variables_to_restore = tf.get_collection( 103 | slim.variables.VARIABLES_TO_RESTORE) 104 | self.assertEqual(len(variables_to_restore), 388) 105 | self.assertListEqual(variables_to_restore, get_variables()) 106 | 107 | def testVariablesToRestoreWithoutLogits(self): 108 | batch_size = 5 109 | height, width = 299, 299 110 | with self.test_session(): 111 | inputs = tf.random_uniform((batch_size, height, width, 3)) 112 | with slim.arg_scope([slim.ops.conv2d], 113 | batch_norm_params={'decay': 0.9997}): 114 | slim.inception.inception_v3(inputs, restore_logits=False) 115 | variables_to_restore = tf.get_collection( 116 | slim.variables.VARIABLES_TO_RESTORE) 117 | self.assertEqual(len(variables_to_restore), 384) 118 | 119 | def testRegularizationLosses(self): 120 | batch_size = 5 121 | height, width = 299, 299 122 | with self.test_session(): 123 | inputs = tf.random_uniform((batch_size, height, width, 3)) 124 | with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004): 125 | slim.inception.inception_v3(inputs) 126 | losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 127 | self.assertEqual(len(losses), len(get_variables_by_name('weights'))) 128 | 129 | def testTotalLossWithoutRegularization(self): 130 | batch_size = 5 131 | height, width = 299, 299 132 | num_classes = 1001 133 | with self.test_session(): 134 | inputs = tf.random_uniform((batch_size, height, width, 3)) 135 | dense_labels = tf.random_uniform((batch_size, num_classes)) 136 | with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0): 137 | logits, end_points = slim.inception.inception_v3( 138 | inputs, 139 | num_classes=num_classes) 140 | # Cross entropy loss for the main softmax prediction. 141 | slim.losses.cross_entropy_loss(logits, 142 | dense_labels, 143 | label_smoothing=0.1, 144 | weight=1.0) 145 | # Cross entropy loss for the auxiliary softmax head. 146 | slim.losses.cross_entropy_loss(end_points['aux_logits'], 147 | dense_labels, 148 | label_smoothing=0.1, 149 | weight=0.4, 150 | scope='aux_loss') 151 | losses = tf.get_collection(slim.losses.LOSSES_COLLECTION) 152 | self.assertEqual(len(losses), 2) 153 | 154 | def testTotalLossWithRegularization(self): 155 | batch_size = 5 156 | height, width = 299, 299 157 | num_classes = 1000 158 | with self.test_session(): 159 | inputs = tf.random_uniform((batch_size, height, width, 3)) 160 | dense_labels = tf.random_uniform((batch_size, num_classes)) 161 | with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004): 162 | logits, end_points = slim.inception.inception_v3(inputs, num_classes) 163 | # Cross entropy loss for the main softmax prediction. 164 | slim.losses.cross_entropy_loss(logits, 165 | dense_labels, 166 | label_smoothing=0.1, 167 | weight=1.0) 168 | # Cross entropy loss for the auxiliary softmax head. 169 | slim.losses.cross_entropy_loss(end_points['aux_logits'], 170 | dense_labels, 171 | label_smoothing=0.1, 172 | weight=0.4, 173 | scope='aux_loss') 174 | losses = tf.get_collection(slim.losses.LOSSES_COLLECTION) 175 | self.assertEqual(len(losses), 2) 176 | reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 177 | self.assertEqual(len(reg_losses), 98) 178 | 179 | 180 | if __name__ == '__main__': 181 | tf.test.main() 182 | -------------------------------------------------------------------------------- /inception/slim/inception_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Tests for slim.inception.""" 16 | from __future__ import absolute_import 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | import tensorflow as tf 21 | 22 | from inception.slim import inception_model as inception 23 | 24 | 25 | class InceptionTest(tf.test.TestCase): 26 | 27 | def testBuildLogits(self): 28 | batch_size = 5 29 | height, width = 299, 299 30 | num_classes = 1000 31 | with self.test_session(): 32 | inputs = tf.random_uniform((batch_size, height, width, 3)) 33 | logits, _ = inception.inception_v3(inputs, num_classes) 34 | self.assertTrue(logits.op.name.startswith('logits')) 35 | self.assertListEqual(logits.get_shape().as_list(), 36 | [batch_size, num_classes]) 37 | 38 | def testBuildEndPoints(self): 39 | batch_size = 5 40 | height, width = 299, 299 41 | num_classes = 1000 42 | with self.test_session(): 43 | inputs = tf.random_uniform((batch_size, height, width, 3)) 44 | _, end_points = inception.inception_v3(inputs, num_classes) 45 | self.assertTrue('logits' in end_points) 46 | logits = end_points['logits'] 47 | self.assertListEqual(logits.get_shape().as_list(), 48 | [batch_size, num_classes]) 49 | self.assertTrue('aux_logits' in end_points) 50 | aux_logits = end_points['aux_logits'] 51 | self.assertListEqual(aux_logits.get_shape().as_list(), 52 | [batch_size, num_classes]) 53 | pre_pool = end_points['mixed_8x8x2048b'] 54 | self.assertListEqual(pre_pool.get_shape().as_list(), 55 | [batch_size, 8, 8, 2048]) 56 | 57 | def testVariablesSetDevice(self): 58 | batch_size = 5 59 | height, width = 299, 299 60 | num_classes = 1000 61 | with self.test_session(): 62 | inputs = tf.random_uniform((batch_size, height, width, 3)) 63 | # Force all Variables to reside on the device. 64 | with tf.variable_scope('on_cpu'), tf.device('/cpu:0'): 65 | inception.inception_v3(inputs, num_classes) 66 | with tf.variable_scope('on_gpu'), tf.device('/gpu:0'): 67 | inception.inception_v3(inputs, num_classes) 68 | for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='on_cpu'): 69 | self.assertDeviceEqual(v.device, '/cpu:0') 70 | for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='on_gpu'): 71 | self.assertDeviceEqual(v.device, '/gpu:0') 72 | 73 | def testHalfSizeImages(self): 74 | batch_size = 5 75 | height, width = 150, 150 76 | num_classes = 1000 77 | with self.test_session(): 78 | inputs = tf.random_uniform((batch_size, height, width, 3)) 79 | logits, end_points = inception.inception_v3(inputs, num_classes) 80 | self.assertTrue(logits.op.name.startswith('logits')) 81 | self.assertListEqual(logits.get_shape().as_list(), 82 | [batch_size, num_classes]) 83 | pre_pool = end_points['mixed_8x8x2048b'] 84 | self.assertListEqual(pre_pool.get_shape().as_list(), 85 | [batch_size, 3, 3, 2048]) 86 | 87 | def testUnknowBatchSize(self): 88 | batch_size = 1 89 | height, width = 299, 299 90 | num_classes = 1000 91 | with self.test_session() as sess: 92 | inputs = tf.placeholder(tf.float32, (None, height, width, 3)) 93 | logits, _ = inception.inception_v3(inputs, num_classes) 94 | self.assertTrue(logits.op.name.startswith('logits')) 95 | self.assertListEqual(logits.get_shape().as_list(), 96 | [None, num_classes]) 97 | images = tf.random_uniform((batch_size, height, width, 3)) 98 | sess.run(tf.global_variables_initializer()) 99 | output = sess.run(logits, {inputs: images.eval()}) 100 | self.assertEquals(output.shape, (batch_size, num_classes)) 101 | 102 | def testEvaluation(self): 103 | batch_size = 2 104 | height, width = 299, 299 105 | num_classes = 1000 106 | with self.test_session() as sess: 107 | eval_inputs = tf.random_uniform((batch_size, height, width, 3)) 108 | logits, _ = inception.inception_v3(eval_inputs, num_classes, 109 | is_training=False) 110 | predictions = tf.argmax(logits, 1) 111 | sess.run(tf.global_variables_initializer()) 112 | output = sess.run(predictions) 113 | self.assertEquals(output.shape, (batch_size,)) 114 | 115 | def testTrainEvalWithReuse(self): 116 | train_batch_size = 5 117 | eval_batch_size = 2 118 | height, width = 150, 150 119 | num_classes = 1000 120 | with self.test_session() as sess: 121 | train_inputs = tf.random_uniform((train_batch_size, height, width, 3)) 122 | inception.inception_v3(train_inputs, num_classes) 123 | tf.get_variable_scope().reuse_variables() 124 | eval_inputs = tf.random_uniform((eval_batch_size, height, width, 3)) 125 | logits, _ = inception.inception_v3(eval_inputs, num_classes, 126 | is_training=False) 127 | predictions = tf.argmax(logits, 1) 128 | sess.run(tf.global_variables_initializer()) 129 | output = sess.run(predictions) 130 | self.assertEquals(output.shape, (eval_batch_size,)) 131 | 132 | 133 | if __name__ == '__main__': 134 | tf.test.main() 135 | -------------------------------------------------------------------------------- /inception/slim/losses.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Contains convenience wrappers for various Neural Network TensorFlow losses. 16 | 17 | All the losses defined here add themselves to the LOSSES_COLLECTION 18 | collection. 19 | 20 | l1_loss: Define a L1 Loss, useful for regularization, i.e. lasso. 21 | l2_loss: Define a L2 Loss, useful for regularization, i.e. weight decay. 22 | cross_entropy_loss: Define a cross entropy loss using 23 | softmax_cross_entropy_with_logits. Useful for classification. 24 | """ 25 | from __future__ import absolute_import 26 | from __future__ import division 27 | from __future__ import print_function 28 | 29 | import tensorflow as tf 30 | 31 | # In order to gather all losses in a network, the user should use this 32 | # key for get_collection, i.e: 33 | # losses = tf.get_collection(slim.losses.LOSSES_COLLECTION) 34 | LOSSES_COLLECTION = '_losses' 35 | 36 | 37 | def l1_regularizer(weight=1.0, scope=None): 38 | """Define a L1 regularizer. 39 | 40 | Args: 41 | weight: scale the loss by this factor. 42 | scope: Optional scope for name_scope. 43 | 44 | Returns: 45 | a regularizer function. 46 | """ 47 | def regularizer(tensor): 48 | with tf.name_scope(scope, 'L1Regularizer', [tensor]): 49 | l1_weight = tf.convert_to_tensor(weight, 50 | dtype=tensor.dtype.base_dtype, 51 | name='weight') 52 | return tf.multiply(l1_weight, tf.reduce_sum(tf.abs(tensor)), name='value') 53 | return regularizer 54 | 55 | 56 | def l2_regularizer(weight=1.0, scope=None): 57 | """Define a L2 regularizer. 58 | 59 | Args: 60 | weight: scale the loss by this factor. 61 | scope: Optional scope for name_scope. 62 | 63 | Returns: 64 | a regularizer function. 65 | """ 66 | def regularizer(tensor): 67 | with tf.name_scope(scope, 'L2Regularizer', [tensor]): 68 | l2_weight = tf.convert_to_tensor(weight, 69 | dtype=tensor.dtype.base_dtype, 70 | name='weight') 71 | return tf.multiply(l2_weight, tf.nn.l2_loss(tensor), name='value') 72 | return regularizer 73 | 74 | 75 | def l1_l2_regularizer(weight_l1=1.0, weight_l2=1.0, scope=None): 76 | """Define a L1L2 regularizer. 77 | 78 | Args: 79 | weight_l1: scale the L1 loss by this factor. 80 | weight_l2: scale the L2 loss by this factor. 81 | scope: Optional scope for name_scope. 82 | 83 | Returns: 84 | a regularizer function. 85 | """ 86 | def regularizer(tensor): 87 | with tf.name_scope(scope, 'L1L2Regularizer', [tensor]): 88 | weight_l1_t = tf.convert_to_tensor(weight_l1, 89 | dtype=tensor.dtype.base_dtype, 90 | name='weight_l1') 91 | weight_l2_t = tf.convert_to_tensor(weight_l2, 92 | dtype=tensor.dtype.base_dtype, 93 | name='weight_l2') 94 | reg_l1 = tf.multiply(weight_l1_t, tf.reduce_sum(tf.abs(tensor)), 95 | name='value_l1') 96 | reg_l2 = tf.multiply(weight_l2_t, tf.nn.l2_loss(tensor), 97 | name='value_l2') 98 | return tf.add(reg_l1, reg_l2, name='value') 99 | return regularizer 100 | 101 | 102 | def l1_loss(tensor, weight=1.0, scope=None): 103 | """Define a L1Loss, useful for regularize, i.e. lasso. 104 | 105 | Args: 106 | tensor: tensor to regularize. 107 | weight: scale the loss by this factor. 108 | scope: Optional scope for name_scope. 109 | 110 | Returns: 111 | the L1 loss op. 112 | """ 113 | with tf.name_scope(scope, 'L1Loss', [tensor]): 114 | weight = tf.convert_to_tensor(weight, 115 | dtype=tensor.dtype.base_dtype, 116 | name='loss_weight') 117 | loss = tf.multiply(weight, tf.reduce_sum(tf.abs(tensor)), name='value') 118 | tf.add_to_collection(LOSSES_COLLECTION, loss) 119 | return loss 120 | 121 | 122 | def l2_loss(tensor, weight=1.0, scope=None): 123 | """Define a L2Loss, useful for regularize, i.e. weight decay. 124 | 125 | Args: 126 | tensor: tensor to regularize. 127 | weight: an optional weight to modulate the loss. 128 | scope: Optional scope for name_scope. 129 | 130 | Returns: 131 | the L2 loss op. 132 | """ 133 | with tf.name_scope(scope, 'L2Loss', [tensor]): 134 | weight = tf.convert_to_tensor(weight, 135 | dtype=tensor.dtype.base_dtype, 136 | name='loss_weight') 137 | loss = tf.multiply(weight, tf.nn.l2_loss(tensor), name='value') 138 | tf.add_to_collection(LOSSES_COLLECTION, loss) 139 | return loss 140 | 141 | 142 | def cross_entropy_loss(logits, one_hot_labels, label_smoothing=0, 143 | weight=1.0, scope=None): 144 | """Define a Cross Entropy loss using softmax_cross_entropy_with_logits. 145 | 146 | It can scale the loss by weight factor, and smooth the labels. 147 | 148 | Args: 149 | logits: [batch_size, num_classes] logits outputs of the network . 150 | one_hot_labels: [batch_size, num_classes] target one_hot_encoded labels. 151 | label_smoothing: if greater than 0 then smooth the labels. 152 | weight: scale the loss by this factor. 153 | scope: Optional scope for name_scope. 154 | 155 | Returns: 156 | A tensor with the softmax_cross_entropy loss. 157 | """ 158 | logits.get_shape().assert_is_compatible_with(one_hot_labels.get_shape()) 159 | with tf.name_scope(scope, 'CrossEntropyLoss', [logits, one_hot_labels]): 160 | num_classes = one_hot_labels.get_shape()[-1].value 161 | one_hot_labels = tf.cast(one_hot_labels, logits.dtype) 162 | if label_smoothing > 0: 163 | smooth_positives = 1.0 - label_smoothing 164 | smooth_negatives = label_smoothing / num_classes 165 | one_hot_labels = one_hot_labels * smooth_positives + smooth_negatives 166 | cross_entropy = tf.contrib.nn.deprecated_flipped_softmax_cross_entropy_with_logits( 167 | logits, one_hot_labels, name='xentropy') 168 | 169 | weight = tf.convert_to_tensor(weight, 170 | dtype=logits.dtype.base_dtype, 171 | name='loss_weight') 172 | loss = tf.multiply(weight, tf.reduce_mean(cross_entropy), name='value') 173 | tf.add_to_collection(LOSSES_COLLECTION, loss) 174 | return loss 175 | 176 | def sigmoid_cross_entropy_loss(logits, one_hot_labels, label_smoothing=0, 177 | weight=1.0, scope=None): 178 | """Define a Cross Entropy loss using softmax_cross_entropy_with_logits. 179 | 180 | It can scale the loss by weight factor, and smooth the labels. 181 | 182 | Args: 183 | logits: [batch_size, num_classes] logits outputs of the network . 184 | one_hot_labels: [batch_size, num_classes] target one_hot_encoded labels. 185 | label_smoothing: if greater than 0 then smooth the labels. 186 | weight: scale the loss by this factor. 187 | scope: Optional scope for name_scope. 188 | 189 | Returns: 190 | A tensor with the softmax_cross_entropy loss. 191 | """ 192 | logits.get_shape().assert_is_compatible_with(one_hot_labels.get_shape()) 193 | with tf.name_scope(scope, 'CrossEntropyLoss', [logits, one_hot_labels]): 194 | num_classes = one_hot_labels.get_shape()[-1].value 195 | one_hot_labels = tf.cast(one_hot_labels, logits.dtype) 196 | if label_smoothing > 0: 197 | smooth_positives = 1.0 - label_smoothing 198 | smooth_negatives = label_smoothing / num_classes 199 | one_hot_labels = one_hot_labels * smooth_positives + smooth_negatives 200 | cross_entropy = tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits( 201 | logits, one_hot_labels, name='xentropy') 202 | 203 | weight = tf.convert_to_tensor(weight, 204 | dtype=logits.dtype.base_dtype, 205 | name='loss_weight') 206 | loss = tf.multiply(weight, tf.reduce_mean(cross_entropy), name='value') 207 | tf.add_to_collection(LOSSES_COLLECTION, loss) 208 | return loss 209 | 210 | def weighted_sigmoid_cross_entropy_loss_backup(logits, one_hot_labels, label_weight, label_smoothing=0, weight=1.0, scope=None): 211 | """Define a Cross Entropy loss using softmax_cross_entropy_with_logits. 212 | 213 | It can scale the loss by weight factor, and smooth the labels. 214 | 215 | Args: 216 | logits: [batch_size, num_classes] logits outputs of the network . 217 | one_hot_labels: [batch_size, num_classes] target one_hot_encoded labels. 218 | label_smoothing: if greater than 0 then smooth the labels. 219 | weight: scale the loss by this factor. 220 | scope: Optional scope for name_scope. 221 | 222 | Returns: 223 | A tensor with the softmax_cross_entropy loss. 224 | """ 225 | logits.get_shape().assert_is_compatible_with(one_hot_labels.get_shape()) 226 | with tf.name_scope(scope, 'WeightedCrossEntropyLoss', [logits, one_hot_labels]): 227 | num_classes = one_hot_labels.get_shape()[-1].value 228 | one_hot_labels = tf.cast(one_hot_labels, logits.dtype) 229 | if label_smoothing > 0: 230 | smooth_positives = 1.0 - label_smoothing 231 | smooth_negatives = label_smoothing / num_classes 232 | one_hot_labels = one_hot_labels * smooth_positives + smooth_negatives 233 | 234 | #cross_entropy = tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits( 235 | # logits, one_hot_labels, name='xentropy') 236 | label_weight = tf.convert_to_tensor(label_weight, dtype=logits.dtype.base_dtype, name='attr_label_weight') 237 | lamda = (1-label_weight) * (1-one_hot_labels) 238 | 239 | cross_entropy = tf.add(lamda * logits + (label_weight * one_hot_labels + lamda) * tf.log(1 + tf.exp(-tf.abs(logits))) , tf.maximum(-logits, 0)) 240 | 241 | weight = tf.convert_to_tensor(weight, 242 | dtype=logits.dtype.base_dtype, 243 | name='loss_weight') 244 | loss = tf.multiply(weight, tf.reduce_mean(cross_entropy), name='value') 245 | tf.add_to_collection(LOSSES_COLLECTION, loss) 246 | return loss 247 | def weighted_sigmoid_cross_entropy_loss(logits, one_hot_labels, label_weight, label_smoothing=0, weight=1.0, scope=None): 248 | logits.get_shape().assert_is_compatible_with(one_hot_labels.get_shape()) 249 | with tf.name_scope(scope, 'WeightedCrossEntropyLoss', [logits, one_hot_labels]): 250 | num_classes = one_hot_labels.get_shape()[-1].value 251 | one_hot_labels = tf.cast(one_hot_labels, logits.dtype) 252 | if label_smoothing > 0: 253 | smooth_positives = 1.0 - label_smoothing 254 | smooth_negatives = label_smoothing / num_classes 255 | one_hot_labels = one_hot_labels * smooth_positives + smooth_negatives 256 | label_weight = tf.convert_to_tensor(label_weight, dtype=logits.dtype.base_dtype, name='attr_label_weight') 257 | label_weight_w = [] 258 | for i in range(one_hot_labels.get_shape()[0].value): 259 | label_weight_w.append(tf.exp(one_hot_labels[i] - tf.multiply( tf.sign(one_hot_labels[i]-0.5) ,label_weight))) 260 | label_weight_w = tf.convert_to_tensor(label_weight_w, dtype=logits.dtype.base_dtype, name='attr_label_weight') 261 | # label_weight_w = tf.exp(one_hot_labels[0] - tf.multiply( tf.sign(one_hot_labels[0]-0.5) ,label_weight)) 262 | print(label_weight_w) 263 | 264 | cross_entropy = tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits( 265 | logits, one_hot_labels, name='xentropy') 266 | weighted_cross_entropy = tf.multiply(cross_entropy, label_weight_w) 267 | 268 | weight = tf.convert_to_tensor(weight, 269 | dtype=logits.dtype.base_dtype, 270 | name='loss_weight') 271 | loss = tf.multiply(weight, tf.reduce_mean(weighted_cross_entropy), name='value') 272 | tf.add_to_collection(LOSSES_COLLECTION, loss) 273 | return loss 274 | -------------------------------------------------------------------------------- /inception/slim/losses_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Tests for slim.losses.""" 16 | from __future__ import absolute_import 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | 21 | import tensorflow as tf 22 | 23 | from inception.slim import losses 24 | 25 | 26 | class LossesTest(tf.test.TestCase): 27 | 28 | def testL1Loss(self): 29 | with self.test_session(): 30 | shape = [5, 5, 5] 31 | num_elem = 5 * 5 * 5 32 | weights = tf.constant(1.0, shape=shape) 33 | wd = 0.01 34 | loss = losses.l1_loss(weights, wd) 35 | self.assertEquals(loss.op.name, 'L1Loss/value') 36 | self.assertAlmostEqual(loss.eval(), num_elem * wd, 5) 37 | 38 | def testL2Loss(self): 39 | with self.test_session(): 40 | shape = [5, 5, 5] 41 | num_elem = 5 * 5 * 5 42 | weights = tf.constant(1.0, shape=shape) 43 | wd = 0.01 44 | loss = losses.l2_loss(weights, wd) 45 | self.assertEquals(loss.op.name, 'L2Loss/value') 46 | self.assertAlmostEqual(loss.eval(), num_elem * wd / 2, 5) 47 | 48 | 49 | class RegularizersTest(tf.test.TestCase): 50 | 51 | def testL1Regularizer(self): 52 | with self.test_session(): 53 | shape = [5, 5, 5] 54 | num_elem = 5 * 5 * 5 55 | tensor = tf.constant(1.0, shape=shape) 56 | loss = losses.l1_regularizer()(tensor) 57 | self.assertEquals(loss.op.name, 'L1Regularizer/value') 58 | self.assertAlmostEqual(loss.eval(), num_elem, 5) 59 | 60 | def testL1RegularizerWithScope(self): 61 | with self.test_session(): 62 | shape = [5, 5, 5] 63 | num_elem = 5 * 5 * 5 64 | tensor = tf.constant(1.0, shape=shape) 65 | loss = losses.l1_regularizer(scope='L1')(tensor) 66 | self.assertEquals(loss.op.name, 'L1/value') 67 | self.assertAlmostEqual(loss.eval(), num_elem, 5) 68 | 69 | def testL1RegularizerWithWeight(self): 70 | with self.test_session(): 71 | shape = [5, 5, 5] 72 | num_elem = 5 * 5 * 5 73 | tensor = tf.constant(1.0, shape=shape) 74 | weight = 0.01 75 | loss = losses.l1_regularizer(weight)(tensor) 76 | self.assertEquals(loss.op.name, 'L1Regularizer/value') 77 | self.assertAlmostEqual(loss.eval(), num_elem * weight, 5) 78 | 79 | def testL2Regularizer(self): 80 | with self.test_session(): 81 | shape = [5, 5, 5] 82 | num_elem = 5 * 5 * 5 83 | tensor = tf.constant(1.0, shape=shape) 84 | loss = losses.l2_regularizer()(tensor) 85 | self.assertEquals(loss.op.name, 'L2Regularizer/value') 86 | self.assertAlmostEqual(loss.eval(), num_elem / 2, 5) 87 | 88 | def testL2RegularizerWithScope(self): 89 | with self.test_session(): 90 | shape = [5, 5, 5] 91 | num_elem = 5 * 5 * 5 92 | tensor = tf.constant(1.0, shape=shape) 93 | loss = losses.l2_regularizer(scope='L2')(tensor) 94 | self.assertEquals(loss.op.name, 'L2/value') 95 | self.assertAlmostEqual(loss.eval(), num_elem / 2, 5) 96 | 97 | def testL2RegularizerWithWeight(self): 98 | with self.test_session(): 99 | shape = [5, 5, 5] 100 | num_elem = 5 * 5 * 5 101 | tensor = tf.constant(1.0, shape=shape) 102 | weight = 0.01 103 | loss = losses.l2_regularizer(weight)(tensor) 104 | self.assertEquals(loss.op.name, 'L2Regularizer/value') 105 | self.assertAlmostEqual(loss.eval(), num_elem * weight / 2, 5) 106 | 107 | def testL1L2Regularizer(self): 108 | with self.test_session(): 109 | shape = [5, 5, 5] 110 | num_elem = 5 * 5 * 5 111 | tensor = tf.constant(1.0, shape=shape) 112 | loss = losses.l1_l2_regularizer()(tensor) 113 | self.assertEquals(loss.op.name, 'L1L2Regularizer/value') 114 | self.assertAlmostEqual(loss.eval(), num_elem + num_elem / 2, 5) 115 | 116 | def testL1L2RegularizerWithScope(self): 117 | with self.test_session(): 118 | shape = [5, 5, 5] 119 | num_elem = 5 * 5 * 5 120 | tensor = tf.constant(1.0, shape=shape) 121 | loss = losses.l1_l2_regularizer(scope='L1L2')(tensor) 122 | self.assertEquals(loss.op.name, 'L1L2/value') 123 | self.assertAlmostEqual(loss.eval(), num_elem + num_elem / 2, 5) 124 | 125 | def testL1L2RegularizerWithWeights(self): 126 | with self.test_session(): 127 | shape = [5, 5, 5] 128 | num_elem = 5 * 5 * 5 129 | tensor = tf.constant(1.0, shape=shape) 130 | weight_l1 = 0.01 131 | weight_l2 = 0.05 132 | loss = losses.l1_l2_regularizer(weight_l1, weight_l2)(tensor) 133 | self.assertEquals(loss.op.name, 'L1L2Regularizer/value') 134 | self.assertAlmostEqual(loss.eval(), 135 | num_elem * weight_l1 + num_elem * weight_l2 / 2, 5) 136 | 137 | 138 | class CrossEntropyLossTest(tf.test.TestCase): 139 | 140 | def testCrossEntropyLossAllCorrect(self): 141 | with self.test_session(): 142 | logits = tf.constant([[10.0, 0.0, 0.0], 143 | [0.0, 10.0, 0.0], 144 | [0.0, 0.0, 10.0]]) 145 | labels = tf.constant([[1, 0, 0], 146 | [0, 1, 0], 147 | [0, 0, 1]]) 148 | loss = losses.cross_entropy_loss(logits, labels) 149 | self.assertEquals(loss.op.name, 'CrossEntropyLoss/value') 150 | self.assertAlmostEqual(loss.eval(), 0.0, 3) 151 | 152 | def testCrossEntropyLossAllWrong(self): 153 | with self.test_session(): 154 | logits = tf.constant([[10.0, 0.0, 0.0], 155 | [0.0, 10.0, 0.0], 156 | [0.0, 0.0, 10.0]]) 157 | labels = tf.constant([[0, 0, 1], 158 | [1, 0, 0], 159 | [0, 1, 0]]) 160 | loss = losses.cross_entropy_loss(logits, labels) 161 | self.assertEquals(loss.op.name, 'CrossEntropyLoss/value') 162 | self.assertAlmostEqual(loss.eval(), 10.0, 3) 163 | 164 | def testCrossEntropyLossAllWrongWithWeight(self): 165 | with self.test_session(): 166 | logits = tf.constant([[10.0, 0.0, 0.0], 167 | [0.0, 10.0, 0.0], 168 | [0.0, 0.0, 10.0]]) 169 | labels = tf.constant([[0, 0, 1], 170 | [1, 0, 0], 171 | [0, 1, 0]]) 172 | loss = losses.cross_entropy_loss(logits, labels, weight=0.5) 173 | self.assertEquals(loss.op.name, 'CrossEntropyLoss/value') 174 | self.assertAlmostEqual(loss.eval(), 5.0, 3) 175 | 176 | if __name__ == '__main__': 177 | tf.test.main() 178 | -------------------------------------------------------------------------------- /inception/slim/scopes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Contains the new arg_scope used for TF-Slim ops. 16 | 17 | Allows one to define models much more compactly by eliminating boilerplate 18 | code. This is accomplished through the use of argument scoping (arg_scope). 19 | 20 | Example of how to use scopes.arg_scope: 21 | 22 | with scopes.arg_scope(ops.conv2d, padding='SAME', 23 | stddev=0.01, weight_decay=0.0005): 24 | net = ops.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1') 25 | net = ops.conv2d(net, 256, [5, 5], scope='conv2') 26 | 27 | The first call to conv2d will overwrite padding: 28 | ops.conv2d(inputs, 64, [11, 11], 4, padding='VALID', 29 | stddev=0.01, weight_decay=0.0005, scope='conv1') 30 | 31 | The second call to Conv will use predefined args: 32 | ops.conv2d(inputs, 256, [5, 5], padding='SAME', 33 | stddev=0.01, weight_decay=0.0005, scope='conv2') 34 | 35 | Example of how to reuse an arg_scope: 36 | with scopes.arg_scope(ops.conv2d, padding='SAME', 37 | stddev=0.01, weight_decay=0.0005) as conv2d_arg_scope: 38 | net = ops.conv2d(net, 256, [5, 5], scope='conv1') 39 | .... 40 | 41 | with scopes.arg_scope(conv2d_arg_scope): 42 | net = ops.conv2d(net, 256, [5, 5], scope='conv2') 43 | 44 | Example of how to use scopes.add_arg_scope: 45 | 46 | @scopes.add_arg_scope 47 | def conv2d(*args, **kwargs) 48 | """ 49 | from __future__ import absolute_import 50 | from __future__ import division 51 | from __future__ import print_function 52 | 53 | import contextlib 54 | import functools 55 | 56 | from tensorflow.python.framework import ops 57 | 58 | _ARGSTACK_KEY = ("__arg_stack",) 59 | 60 | _DECORATED_OPS = set() 61 | 62 | 63 | def _get_arg_stack(): 64 | stack = ops.get_collection(_ARGSTACK_KEY) 65 | if stack: 66 | return stack[0] 67 | else: 68 | stack = [{}] 69 | ops.add_to_collection(_ARGSTACK_KEY, stack) 70 | return stack 71 | 72 | 73 | def _current_arg_scope(): 74 | stack = _get_arg_stack() 75 | return stack[-1] 76 | 77 | 78 | def _add_op(op): 79 | key_op = (op.__module__, op.__name__) 80 | if key_op not in _DECORATED_OPS: 81 | _DECORATED_OPS.add(key_op) 82 | 83 | 84 | @contextlib.contextmanager 85 | def arg_scope(list_ops_or_scope, **kwargs): 86 | """Stores the default arguments for the given set of list_ops. 87 | 88 | For usage, please see examples at top of the file. 89 | 90 | Args: 91 | list_ops_or_scope: List or tuple of operations to set argument scope for or 92 | a dictionary containg the current scope. When list_ops_or_scope is a dict, 93 | kwargs must be empty. When list_ops_or_scope is a list or tuple, then 94 | every op in it need to be decorated with @add_arg_scope to work. 95 | **kwargs: keyword=value that will define the defaults for each op in 96 | list_ops. All the ops need to accept the given set of arguments. 97 | 98 | Yields: 99 | the current_scope, which is a dictionary of {op: {arg: value}} 100 | Raises: 101 | TypeError: if list_ops is not a list or a tuple. 102 | ValueError: if any op in list_ops has not be decorated with @add_arg_scope. 103 | """ 104 | if isinstance(list_ops_or_scope, dict): 105 | # Assumes that list_ops_or_scope is a scope that is being reused. 106 | if kwargs: 107 | raise ValueError("When attempting to re-use a scope by suppling a" 108 | "dictionary, kwargs must be empty.") 109 | current_scope = list_ops_or_scope.copy() 110 | try: 111 | _get_arg_stack().append(current_scope) 112 | yield current_scope 113 | finally: 114 | _get_arg_stack().pop() 115 | else: 116 | # Assumes that list_ops_or_scope is a list/tuple of ops with kwargs. 117 | if not isinstance(list_ops_or_scope, (list, tuple)): 118 | raise TypeError("list_ops_or_scope must either be a list/tuple or reused" 119 | "scope (i.e. dict)") 120 | try: 121 | current_scope = _current_arg_scope().copy() 122 | for op in list_ops_or_scope: 123 | key_op = (op.__module__, op.__name__) 124 | if not has_arg_scope(op): 125 | raise ValueError("%s is not decorated with @add_arg_scope", key_op) 126 | if key_op in current_scope: 127 | current_kwargs = current_scope[key_op].copy() 128 | current_kwargs.update(kwargs) 129 | current_scope[key_op] = current_kwargs 130 | else: 131 | current_scope[key_op] = kwargs.copy() 132 | _get_arg_stack().append(current_scope) 133 | yield current_scope 134 | finally: 135 | _get_arg_stack().pop() 136 | 137 | 138 | def add_arg_scope(func): 139 | """Decorates a function with args so it can be used within an arg_scope. 140 | 141 | Args: 142 | func: function to decorate. 143 | 144 | Returns: 145 | A tuple with the decorated function func_with_args(). 146 | """ 147 | @functools.wraps(func) 148 | def func_with_args(*args, **kwargs): 149 | current_scope = _current_arg_scope() 150 | current_args = kwargs 151 | key_func = (func.__module__, func.__name__) 152 | if key_func in current_scope: 153 | current_args = current_scope[key_func].copy() 154 | current_args.update(kwargs) 155 | return func(*args, **current_args) 156 | _add_op(func) 157 | return func_with_args 158 | 159 | 160 | def has_arg_scope(func): 161 | """Checks whether a func has been decorated with @add_arg_scope or not. 162 | 163 | Args: 164 | func: function to check. 165 | 166 | Returns: 167 | a boolean. 168 | """ 169 | key_op = (func.__module__, func.__name__) 170 | return key_op in _DECORATED_OPS 171 | -------------------------------------------------------------------------------- /inception/slim/scopes_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Tests slim.scopes.""" 16 | from __future__ import absolute_import 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | 21 | import tensorflow as tf 22 | from inception.slim import scopes 23 | 24 | 25 | @scopes.add_arg_scope 26 | def func1(*args, **kwargs): 27 | return (args, kwargs) 28 | 29 | 30 | @scopes.add_arg_scope 31 | def func2(*args, **kwargs): 32 | return (args, kwargs) 33 | 34 | 35 | class ArgScopeTest(tf.test.TestCase): 36 | 37 | def testEmptyArgScope(self): 38 | with self.test_session(): 39 | self.assertEqual(scopes._current_arg_scope(), {}) 40 | 41 | def testCurrentArgScope(self): 42 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 43 | key_op = (func1.__module__, func1.__name__) 44 | current_scope = {key_op: func1_kwargs.copy()} 45 | with self.test_session(): 46 | with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope: 47 | self.assertDictEqual(scope, current_scope) 48 | 49 | def testCurrentArgScopeNested(self): 50 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 51 | func2_kwargs = {'b': 2, 'd': [2]} 52 | key = lambda f: (f.__module__, f.__name__) 53 | current_scope = {key(func1): func1_kwargs.copy(), 54 | key(func2): func2_kwargs.copy()} 55 | with self.test_session(): 56 | with scopes.arg_scope([func1], a=1, b=None, c=[1]): 57 | with scopes.arg_scope([func2], b=2, d=[2]) as scope: 58 | self.assertDictEqual(scope, current_scope) 59 | 60 | def testReuseArgScope(self): 61 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 62 | key_op = (func1.__module__, func1.__name__) 63 | current_scope = {key_op: func1_kwargs.copy()} 64 | with self.test_session(): 65 | with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope1: 66 | pass 67 | with scopes.arg_scope(scope1) as scope: 68 | self.assertDictEqual(scope, current_scope) 69 | 70 | def testReuseArgScopeNested(self): 71 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 72 | func2_kwargs = {'b': 2, 'd': [2]} 73 | key = lambda f: (f.__module__, f.__name__) 74 | current_scope1 = {key(func1): func1_kwargs.copy()} 75 | current_scope2 = {key(func1): func1_kwargs.copy(), 76 | key(func2): func2_kwargs.copy()} 77 | with self.test_session(): 78 | with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope1: 79 | with scopes.arg_scope([func2], b=2, d=[2]) as scope2: 80 | pass 81 | with scopes.arg_scope(scope1): 82 | self.assertDictEqual(scopes._current_arg_scope(), current_scope1) 83 | with scopes.arg_scope(scope2): 84 | self.assertDictEqual(scopes._current_arg_scope(), current_scope2) 85 | 86 | def testSimpleArgScope(self): 87 | func1_args = (0,) 88 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 89 | with self.test_session(): 90 | with scopes.arg_scope([func1], a=1, b=None, c=[1]): 91 | args, kwargs = func1(0) 92 | self.assertTupleEqual(args, func1_args) 93 | self.assertDictEqual(kwargs, func1_kwargs) 94 | 95 | def testSimpleArgScopeWithTuple(self): 96 | func1_args = (0,) 97 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 98 | with self.test_session(): 99 | with scopes.arg_scope((func1,), a=1, b=None, c=[1]): 100 | args, kwargs = func1(0) 101 | self.assertTupleEqual(args, func1_args) 102 | self.assertDictEqual(kwargs, func1_kwargs) 103 | 104 | def testOverwriteArgScope(self): 105 | func1_args = (0,) 106 | func1_kwargs = {'a': 1, 'b': 2, 'c': [1]} 107 | with scopes.arg_scope([func1], a=1, b=None, c=[1]): 108 | args, kwargs = func1(0, b=2) 109 | self.assertTupleEqual(args, func1_args) 110 | self.assertDictEqual(kwargs, func1_kwargs) 111 | 112 | def testNestedArgScope(self): 113 | func1_args = (0,) 114 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 115 | with scopes.arg_scope([func1], a=1, b=None, c=[1]): 116 | args, kwargs = func1(0) 117 | self.assertTupleEqual(args, func1_args) 118 | self.assertDictEqual(kwargs, func1_kwargs) 119 | func1_kwargs['b'] = 2 120 | with scopes.arg_scope([func1], b=2): 121 | args, kwargs = func1(0) 122 | self.assertTupleEqual(args, func1_args) 123 | self.assertDictEqual(kwargs, func1_kwargs) 124 | 125 | def testSharedArgScope(self): 126 | func1_args = (0,) 127 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 128 | with scopes.arg_scope([func1, func2], a=1, b=None, c=[1]): 129 | args, kwargs = func1(0) 130 | self.assertTupleEqual(args, func1_args) 131 | self.assertDictEqual(kwargs, func1_kwargs) 132 | args, kwargs = func2(0) 133 | self.assertTupleEqual(args, func1_args) 134 | self.assertDictEqual(kwargs, func1_kwargs) 135 | 136 | def testSharedArgScopeTuple(self): 137 | func1_args = (0,) 138 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 139 | with scopes.arg_scope((func1, func2), a=1, b=None, c=[1]): 140 | args, kwargs = func1(0) 141 | self.assertTupleEqual(args, func1_args) 142 | self.assertDictEqual(kwargs, func1_kwargs) 143 | args, kwargs = func2(0) 144 | self.assertTupleEqual(args, func1_args) 145 | self.assertDictEqual(kwargs, func1_kwargs) 146 | 147 | def testPartiallySharedArgScope(self): 148 | func1_args = (0,) 149 | func1_kwargs = {'a': 1, 'b': None, 'c': [1]} 150 | func2_args = (1,) 151 | func2_kwargs = {'a': 1, 'b': None, 'd': [2]} 152 | with scopes.arg_scope([func1, func2], a=1, b=None): 153 | with scopes.arg_scope([func1], c=[1]), scopes.arg_scope([func2], d=[2]): 154 | args, kwargs = func1(0) 155 | self.assertTupleEqual(args, func1_args) 156 | self.assertDictEqual(kwargs, func1_kwargs) 157 | args, kwargs = func2(1) 158 | self.assertTupleEqual(args, func2_args) 159 | self.assertDictEqual(kwargs, func2_kwargs) 160 | 161 | if __name__ == '__main__': 162 | tf.test.main() 163 | -------------------------------------------------------------------------------- /inception/slim/slim.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """TF-Slim grouped API. Please see README.md for details and usage.""" 16 | # pylint: disable=unused-import 17 | 18 | # Collapse tf-slim into a single namespace. 19 | from inception.slim import inception_model as inception 20 | from inception.slim import peta_model as peta 21 | from inception.slim import losses 22 | from inception.slim import ops 23 | from inception.slim import scopes 24 | from inception.slim import variables 25 | from inception.slim.scopes import arg_scope 26 | -------------------------------------------------------------------------------- /inception/slim/variables.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Contains convenience wrappers for creating variables in TF-Slim. 16 | 17 | The variables module is typically used for defining model variables from the 18 | ops routines (see slim.ops). Such variables are used for training, evaluation 19 | and inference of models. 20 | 21 | All the variables created through this module would be added to the 22 | MODEL_VARIABLES collection, if you create a model variable outside slim, it can 23 | be added with slim.variables.add_variable(external_variable, reuse). 24 | 25 | Usage: 26 | weights_initializer = tf.truncated_normal_initializer(stddev=0.01) 27 | l2_regularizer = lambda t: losses.l2_loss(t, weight=0.0005) 28 | weights = variables.variable('weights', 29 | shape=[100, 100], 30 | initializer=weights_initializer, 31 | regularizer=l2_regularizer, 32 | device='/cpu:0') 33 | 34 | biases = variables.variable('biases', 35 | shape=[100], 36 | initializer=tf.zeros_initializer(), 37 | device='/cpu:0') 38 | 39 | # More complex example. 40 | 41 | net = slim.ops.conv2d(input, 32, [3, 3], scope='conv1') 42 | net = slim.ops.conv2d(net, 64, [3, 3], scope='conv2') 43 | with slim.arg_scope([variables.variable], restore=False): 44 | net = slim.ops.conv2d(net, 64, [3, 3], scope='conv3') 45 | 46 | # Get all model variables from all the layers. 47 | model_variables = slim.variables.get_variables() 48 | 49 | # Get all model variables from a specific the layer, i.e 'conv1'. 50 | conv1_variables = slim.variables.get_variables('conv1') 51 | 52 | # Get all weights from all the layers. 53 | weights = slim.variables.get_variables_by_name('weights') 54 | 55 | # Get all bias from all the layers. 56 | biases = slim.variables.get_variables_by_name('biases') 57 | 58 | # Get all variables to restore. 59 | # (i.e. only those created by 'conv1' and 'conv2') 60 | variables_to_restore = slim.variables.get_variables_to_restore() 61 | 62 | ************************************************ 63 | * Initializing model variables from a checkpoint 64 | ************************************************ 65 | 66 | # Create some variables. 67 | v1 = slim.variables.variable(name="v1", ..., restore=False) 68 | v2 = slim.variables.variable(name="v2", ...) # By default restore=True 69 | ... 70 | # The list of variables to restore should only contain 'v2'. 71 | variables_to_restore = slim.variables.get_variables_to_restore() 72 | restorer = tf.train.Saver(variables_to_restore) 73 | with tf.Session() as sess: 74 | # Restore variables from disk. 75 | restorer.restore(sess, "/tmp/model.ckpt") 76 | print("Model restored.") 77 | # Do some work with the model 78 | ... 79 | 80 | """ 81 | from __future__ import absolute_import 82 | from __future__ import division 83 | from __future__ import print_function 84 | 85 | import tensorflow as tf 86 | 87 | from inception.slim import scopes 88 | 89 | # Collection containing all the variables created using slim.variables 90 | MODEL_VARIABLES = '_model_variables_' 91 | 92 | # Collection containing the slim.variables that are created with restore=True. 93 | VARIABLES_TO_RESTORE = '_variables_to_restore_' 94 | 95 | 96 | def add_variable(var, restore=True): 97 | """Adds a variable to the MODEL_VARIABLES collection. 98 | 99 | Optionally it will add the variable to the VARIABLES_TO_RESTORE collection. 100 | Args: 101 | var: a variable. 102 | restore: whether the variable should be added to the 103 | VARIABLES_TO_RESTORE collection. 104 | 105 | """ 106 | collections = [MODEL_VARIABLES] 107 | if restore: 108 | collections.append(VARIABLES_TO_RESTORE) 109 | for collection in collections: 110 | if var not in tf.get_collection(collection): 111 | tf.add_to_collection(collection, var) 112 | 113 | 114 | def get_variables(scope=None, suffix=None): 115 | """Gets the list of variables, filtered by scope and/or suffix. 116 | 117 | Args: 118 | scope: an optional scope for filtering the variables to return. 119 | suffix: an optional suffix for filtering the variables to return. 120 | 121 | Returns: 122 | a copied list of variables with scope and suffix. 123 | """ 124 | candidates = tf.get_collection(MODEL_VARIABLES, scope)[:] 125 | if suffix is not None: 126 | candidates = [var for var in candidates if var.op.name.endswith(suffix)] 127 | return candidates 128 | 129 | 130 | def get_variables_to_restore(): 131 | """Gets the list of variables to restore. 132 | 133 | Returns: 134 | a copied list of variables. 135 | """ 136 | return tf.get_collection(VARIABLES_TO_RESTORE)[:] 137 | 138 | 139 | def get_variables_by_name(given_name, scope=None): 140 | """Gets the list of variables that were given that name. 141 | 142 | Args: 143 | given_name: name given to the variable without scope. 144 | scope: an optional scope for filtering the variables to return. 145 | 146 | Returns: 147 | a copied list of variables with the given name and prefix. 148 | """ 149 | return get_variables(scope=scope, suffix=given_name) 150 | 151 | 152 | def get_unique_variable(name): 153 | """Gets the variable uniquely identified by that name. 154 | 155 | Args: 156 | name: a name that uniquely identifies the variable. 157 | 158 | Returns: 159 | a tensorflow variable. 160 | 161 | Raises: 162 | ValueError: if no variable uniquely identified by the name exists. 163 | """ 164 | candidates = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, name) 165 | if not candidates: 166 | raise ValueError('Couldnt find variable %s' % name) 167 | 168 | for candidate in candidates: 169 | if candidate.op.name == name: 170 | return candidate 171 | raise ValueError('Variable %s does not uniquely identify a variable', name) 172 | 173 | 174 | class VariableDeviceChooser(object): 175 | """Slim device chooser for variables. 176 | 177 | When using a parameter server it will assign them in a round-robin fashion. 178 | When not using a parameter server it allows GPU:0 placement otherwise CPU:0. 179 | """ 180 | 181 | def __init__(self, 182 | num_parameter_servers=0, 183 | ps_device='/job:ps', 184 | placement='CPU:0'): 185 | """Initialize VariableDeviceChooser. 186 | 187 | Args: 188 | num_parameter_servers: number of parameter servers. 189 | ps_device: string representing the parameter server device. 190 | placement: string representing the placement of the variable either CPU:0 191 | or GPU:0. When using parameter servers forced to CPU:0. 192 | """ 193 | self._num_ps = num_parameter_servers 194 | self._ps_device = ps_device 195 | self._placement = placement if num_parameter_servers == 0 else 'CPU:0' 196 | self._next_task_id = 0 197 | 198 | def __call__(self, op): 199 | device_string = '' 200 | if self._num_ps > 0: 201 | task_id = self._next_task_id 202 | self._next_task_id = (self._next_task_id + 1) % self._num_ps 203 | device_string = '%s/task:%d' % (self._ps_device, task_id) 204 | device_string += '/%s' % self._placement 205 | return device_string 206 | 207 | 208 | # TODO(sguada) Remove once get_variable is able to colocate op.devices. 209 | def variable_device(device, name): 210 | """Fix the variable device to colocate its ops.""" 211 | if callable(device): 212 | var_name = tf.get_variable_scope().name + '/' + name 213 | var_def = tf.NodeDef(name=var_name, op='Variable') 214 | device = device(var_def) 215 | if device is None: 216 | device = '' 217 | return device 218 | 219 | 220 | @scopes.add_arg_scope 221 | def global_step(device=''): 222 | """Returns the global step variable. 223 | 224 | Args: 225 | device: Optional device to place the variable. It can be an string or a 226 | function that is called to get the device for the variable. 227 | 228 | Returns: 229 | the tensor representing the global step variable. 230 | """ 231 | global_step_ref = tf.get_collection(tf.GraphKeys.GLOBAL_STEP) 232 | if global_step_ref: 233 | return global_step_ref[0] 234 | else: 235 | collections = [ 236 | VARIABLES_TO_RESTORE, 237 | tf.GraphKeys.GLOBAL_VARIABLES, 238 | tf.GraphKeys.GLOBAL_STEP, 239 | ] 240 | # Get the device for the variable. 241 | with tf.device(variable_device(device, 'global_step')): 242 | return tf.get_variable('global_step', shape=[], dtype=tf.int64, 243 | initializer=tf.zeros_initializer(), 244 | trainable=False, collections=collections) 245 | 246 | 247 | @scopes.add_arg_scope 248 | def variable(name, shape=None, dtype=tf.float32, initializer=None, 249 | regularizer=None, trainable=True, collections=None, device='', 250 | restore=True): 251 | """Gets an existing variable with these parameters or creates a new one. 252 | 253 | It also add itself to a group with its name. 254 | 255 | Args: 256 | name: the name of the new or existing variable. 257 | shape: shape of the new or existing variable. 258 | dtype: type of the new or existing variable (defaults to `DT_FLOAT`). 259 | initializer: initializer for the variable if one is created. 260 | regularizer: a (Tensor -> Tensor or None) function; the result of 261 | applying it on a newly created variable will be added to the collection 262 | GraphKeys.REGULARIZATION_LOSSES and can be used for regularization. 263 | trainable: If `True` also add the variable to the graph collection 264 | `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable). 265 | collections: A list of collection names to which the Variable will be added. 266 | Note that the variable is always also added to the tf.GraphKeys.GLOBAL_VARIABLES 267 | and MODEL_VARIABLES collections. 268 | device: Optional device to place the variable. It can be an string or a 269 | function that is called to get the device for the variable. 270 | restore: whether the variable should be added to the 271 | VARIABLES_TO_RESTORE collection. 272 | 273 | Returns: 274 | The created or existing variable. 275 | """ 276 | collections = list(collections or []) 277 | 278 | # Make sure variables are added to tf.GraphKeys.GLOBAL_VARIABLES and MODEL_VARIABLES 279 | collections += [tf.GraphKeys.GLOBAL_VARIABLES, MODEL_VARIABLES] 280 | # Add to VARIABLES_TO_RESTORE if necessary 281 | if restore: 282 | collections.append(VARIABLES_TO_RESTORE) 283 | # Remove duplicates 284 | collections = set(collections) 285 | # Get the device for the variable. 286 | with tf.device(variable_device(device, name)): 287 | return tf.get_variable(name, shape=shape, dtype=dtype, 288 | initializer=initializer, regularizer=regularizer, 289 | trainable=trainable, collections=collections) 290 | -------------------------------------------------------------------------------- /inception/slim/variables_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ============================================================================== 15 | """Tests for slim.variables.""" 16 | from __future__ import absolute_import 17 | from __future__ import division 18 | from __future__ import print_function 19 | 20 | import tensorflow as tf 21 | 22 | from inception.slim import scopes 23 | from inception.slim import variables 24 | 25 | 26 | class VariablesTest(tf.test.TestCase): 27 | 28 | def testCreateVariable(self): 29 | with self.test_session(): 30 | with tf.variable_scope('A'): 31 | a = variables.variable('a', [5]) 32 | self.assertEquals(a.op.name, 'A/a') 33 | self.assertListEqual(a.get_shape().as_list(), [5]) 34 | 35 | def testGetVariables(self): 36 | with self.test_session(): 37 | with tf.variable_scope('A'): 38 | a = variables.variable('a', [5]) 39 | with tf.variable_scope('B'): 40 | b = variables.variable('a', [5]) 41 | self.assertEquals([a, b], variables.get_variables()) 42 | self.assertEquals([a], variables.get_variables('A')) 43 | self.assertEquals([b], variables.get_variables('B')) 44 | 45 | def testGetVariablesSuffix(self): 46 | with self.test_session(): 47 | with tf.variable_scope('A'): 48 | a = variables.variable('a', [5]) 49 | with tf.variable_scope('A'): 50 | b = variables.variable('b', [5]) 51 | self.assertEquals([a], variables.get_variables(suffix='a')) 52 | self.assertEquals([b], variables.get_variables(suffix='b')) 53 | 54 | def testGetVariableWithSingleVar(self): 55 | with self.test_session(): 56 | with tf.variable_scope('parent'): 57 | a = variables.variable('child', [5]) 58 | self.assertEquals(a, variables.get_unique_variable('parent/child')) 59 | 60 | def testGetVariableWithDistractors(self): 61 | with self.test_session(): 62 | with tf.variable_scope('parent'): 63 | a = variables.variable('child', [5]) 64 | with tf.variable_scope('child'): 65 | variables.variable('grandchild1', [7]) 66 | variables.variable('grandchild2', [9]) 67 | self.assertEquals(a, variables.get_unique_variable('parent/child')) 68 | 69 | def testGetVariableThrowsExceptionWithNoMatch(self): 70 | var_name = 'cant_find_me' 71 | with self.test_session(): 72 | with self.assertRaises(ValueError): 73 | variables.get_unique_variable(var_name) 74 | 75 | def testGetThrowsExceptionWithChildrenButNoMatch(self): 76 | var_name = 'parent/child' 77 | with self.test_session(): 78 | with tf.variable_scope(var_name): 79 | variables.variable('grandchild1', [7]) 80 | variables.variable('grandchild2', [9]) 81 | with self.assertRaises(ValueError): 82 | variables.get_unique_variable(var_name) 83 | 84 | def testGetVariablesToRestore(self): 85 | with self.test_session(): 86 | with tf.variable_scope('A'): 87 | a = variables.variable('a', [5]) 88 | with tf.variable_scope('B'): 89 | b = variables.variable('a', [5]) 90 | self.assertEquals([a, b], variables.get_variables_to_restore()) 91 | 92 | def testNoneGetVariablesToRestore(self): 93 | with self.test_session(): 94 | with tf.variable_scope('A'): 95 | a = variables.variable('a', [5], restore=False) 96 | with tf.variable_scope('B'): 97 | b = variables.variable('a', [5], restore=False) 98 | self.assertEquals([], variables.get_variables_to_restore()) 99 | self.assertEquals([a, b], variables.get_variables()) 100 | 101 | def testGetMixedVariablesToRestore(self): 102 | with self.test_session(): 103 | with tf.variable_scope('A'): 104 | a = variables.variable('a', [5]) 105 | b = variables.variable('b', [5], restore=False) 106 | with tf.variable_scope('B'): 107 | c = variables.variable('c', [5]) 108 | d = variables.variable('d', [5], restore=False) 109 | self.assertEquals([a, b, c, d], variables.get_variables()) 110 | self.assertEquals([a, c], variables.get_variables_to_restore()) 111 | 112 | def testReuseVariable(self): 113 | with self.test_session(): 114 | with tf.variable_scope('A'): 115 | a = variables.variable('a', []) 116 | with tf.variable_scope('A', reuse=True): 117 | b = variables.variable('a', []) 118 | self.assertEquals(a, b) 119 | self.assertListEqual([a], variables.get_variables()) 120 | 121 | def testVariableWithDevice(self): 122 | with self.test_session(): 123 | with tf.variable_scope('A'): 124 | a = variables.variable('a', [], device='cpu:0') 125 | b = variables.variable('b', [], device='cpu:1') 126 | self.assertDeviceEqual(a.device, 'cpu:0') 127 | self.assertDeviceEqual(b.device, 'cpu:1') 128 | 129 | def testVariableWithDeviceFromScope(self): 130 | with self.test_session(): 131 | with tf.device('/cpu:0'): 132 | a = variables.variable('a', []) 133 | b = variables.variable('b', [], device='cpu:1') 134 | self.assertDeviceEqual(a.device, 'cpu:0') 135 | self.assertDeviceEqual(b.device, 'cpu:1') 136 | 137 | def testVariableWithDeviceFunction(self): 138 | class DevFn(object): 139 | 140 | def __init__(self): 141 | self.counter = -1 142 | 143 | def __call__(self, op): 144 | self.counter += 1 145 | return 'cpu:%d' % self.counter 146 | 147 | with self.test_session(): 148 | with scopes.arg_scope([variables.variable], device=DevFn()): 149 | a = variables.variable('a', []) 150 | b = variables.variable('b', []) 151 | c = variables.variable('c', [], device='cpu:12') 152 | d = variables.variable('d', []) 153 | with tf.device('cpu:99'): 154 | e_init = tf.constant(12) 155 | e = variables.variable('e', initializer=e_init) 156 | self.assertDeviceEqual(a.device, 'cpu:0') 157 | self.assertDeviceEqual(a.initial_value.device, 'cpu:0') 158 | self.assertDeviceEqual(b.device, 'cpu:1') 159 | self.assertDeviceEqual(b.initial_value.device, 'cpu:1') 160 | self.assertDeviceEqual(c.device, 'cpu:12') 161 | self.assertDeviceEqual(c.initial_value.device, 'cpu:12') 162 | self.assertDeviceEqual(d.device, 'cpu:2') 163 | self.assertDeviceEqual(d.initial_value.device, 'cpu:2') 164 | self.assertDeviceEqual(e.device, 'cpu:3') 165 | self.assertDeviceEqual(e.initial_value.device, 'cpu:99') 166 | 167 | def testVariableWithReplicaDeviceSetter(self): 168 | with self.test_session(): 169 | with tf.device(tf.train.replica_device_setter(ps_tasks=2)): 170 | a = variables.variable('a', []) 171 | b = variables.variable('b', []) 172 | c = variables.variable('c', [], device='cpu:12') 173 | d = variables.variable('d', []) 174 | with tf.device('cpu:99'): 175 | e_init = tf.constant(12) 176 | e = variables.variable('e', initializer=e_init) 177 | # The values below highlight how the replica_device_setter puts initial 178 | # values on the worker job, and how it merges explicit devices. 179 | self.assertDeviceEqual(a.device, '/job:ps/task:0/cpu:0') 180 | self.assertDeviceEqual(a.initial_value.device, '/job:worker/cpu:0') 181 | self.assertDeviceEqual(b.device, '/job:ps/task:1/cpu:0') 182 | self.assertDeviceEqual(b.initial_value.device, '/job:worker/cpu:0') 183 | self.assertDeviceEqual(c.device, '/job:ps/task:0/cpu:12') 184 | self.assertDeviceEqual(c.initial_value.device, '/job:worker/cpu:12') 185 | self.assertDeviceEqual(d.device, '/job:ps/task:1/cpu:0') 186 | self.assertDeviceEqual(d.initial_value.device, '/job:worker/cpu:0') 187 | self.assertDeviceEqual(e.device, '/job:ps/task:0/cpu:0') 188 | self.assertDeviceEqual(e.initial_value.device, '/job:worker/cpu:99') 189 | 190 | def testVariableWithVariableDeviceChooser(self): 191 | 192 | with tf.Graph().as_default(): 193 | device_fn = variables.VariableDeviceChooser(num_parameter_servers=2) 194 | with scopes.arg_scope([variables.variable], device=device_fn): 195 | a = variables.variable('a', []) 196 | b = variables.variable('b', []) 197 | c = variables.variable('c', [], device='cpu:12') 198 | d = variables.variable('d', []) 199 | with tf.device('cpu:99'): 200 | e_init = tf.constant(12) 201 | e = variables.variable('e', initializer=e_init) 202 | # The values below highlight how the VariableDeviceChooser puts initial 203 | # values on the same device as the variable job. 204 | self.assertDeviceEqual(a.device, '/job:ps/task:0/cpu:0') 205 | self.assertDeviceEqual(a.initial_value.device, a.device) 206 | self.assertDeviceEqual(b.device, '/job:ps/task:1/cpu:0') 207 | self.assertDeviceEqual(b.initial_value.device, b.device) 208 | self.assertDeviceEqual(c.device, '/cpu:12') 209 | self.assertDeviceEqual(c.initial_value.device, c.device) 210 | self.assertDeviceEqual(d.device, '/job:ps/task:0/cpu:0') 211 | self.assertDeviceEqual(d.initial_value.device, d.device) 212 | self.assertDeviceEqual(e.device, '/job:ps/task:1/cpu:0') 213 | self.assertDeviceEqual(e.initial_value.device, '/cpu:99') 214 | 215 | def testVariableGPUPlacement(self): 216 | 217 | with tf.Graph().as_default(): 218 | device_fn = variables.VariableDeviceChooser(placement='gpu:0') 219 | with scopes.arg_scope([variables.variable], device=device_fn): 220 | a = variables.variable('a', []) 221 | b = variables.variable('b', []) 222 | c = variables.variable('c', [], device='cpu:12') 223 | d = variables.variable('d', []) 224 | with tf.device('cpu:99'): 225 | e_init = tf.constant(12) 226 | e = variables.variable('e', initializer=e_init) 227 | # The values below highlight how the VariableDeviceChooser puts initial 228 | # values on the same device as the variable job. 229 | self.assertDeviceEqual(a.device, '/gpu:0') 230 | self.assertDeviceEqual(a.initial_value.device, a.device) 231 | self.assertDeviceEqual(b.device, '/gpu:0') 232 | self.assertDeviceEqual(b.initial_value.device, b.device) 233 | self.assertDeviceEqual(c.device, '/cpu:12') 234 | self.assertDeviceEqual(c.initial_value.device, c.device) 235 | self.assertDeviceEqual(d.device, '/gpu:0') 236 | self.assertDeviceEqual(d.initial_value.device, d.device) 237 | self.assertDeviceEqual(e.device, '/gpu:0') 238 | self.assertDeviceEqual(e.initial_value.device, '/cpu:99') 239 | 240 | def testVariableCollection(self): 241 | with self.test_session(): 242 | a = variables.variable('a', [], collections='A') 243 | b = variables.variable('b', [], collections='B') 244 | self.assertEquals(a, tf.get_collection('A')[0]) 245 | self.assertEquals(b, tf.get_collection('B')[0]) 246 | 247 | def testVariableCollections(self): 248 | with self.test_session(): 249 | a = variables.variable('a', [], collections=['A', 'C']) 250 | b = variables.variable('b', [], collections=['B', 'C']) 251 | self.assertEquals(a, tf.get_collection('A')[0]) 252 | self.assertEquals(b, tf.get_collection('B')[0]) 253 | 254 | def testVariableCollectionsWithArgScope(self): 255 | with self.test_session(): 256 | with scopes.arg_scope([variables.variable], collections='A'): 257 | a = variables.variable('a', []) 258 | b = variables.variable('b', []) 259 | self.assertListEqual([a, b], tf.get_collection('A')) 260 | 261 | def testVariableCollectionsWithArgScopeNested(self): 262 | with self.test_session(): 263 | with scopes.arg_scope([variables.variable], collections='A'): 264 | a = variables.variable('a', []) 265 | with scopes.arg_scope([variables.variable], collections='B'): 266 | b = variables.variable('b', []) 267 | self.assertEquals(a, tf.get_collection('A')[0]) 268 | self.assertEquals(b, tf.get_collection('B')[0]) 269 | 270 | def testVariableCollectionsWithArgScopeNonNested(self): 271 | with self.test_session(): 272 | with scopes.arg_scope([variables.variable], collections='A'): 273 | a = variables.variable('a', []) 274 | with scopes.arg_scope([variables.variable], collections='B'): 275 | b = variables.variable('b', []) 276 | variables.variable('c', []) 277 | self.assertListEqual([a], tf.get_collection('A')) 278 | self.assertListEqual([b], tf.get_collection('B')) 279 | 280 | def testVariableRestoreWithArgScopeNested(self): 281 | with self.test_session(): 282 | with scopes.arg_scope([variables.variable], restore=True): 283 | a = variables.variable('a', []) 284 | with scopes.arg_scope([variables.variable], 285 | trainable=False, 286 | collections=['A', 'B']): 287 | b = variables.variable('b', []) 288 | c = variables.variable('c', []) 289 | self.assertListEqual([a, b, c], variables.get_variables_to_restore()) 290 | self.assertListEqual([a, c], tf.trainable_variables()) 291 | self.assertListEqual([b], tf.get_collection('A')) 292 | self.assertListEqual([b], tf.get_collection('B')) 293 | 294 | 295 | class GetVariablesByNameTest(tf.test.TestCase): 296 | 297 | def testGetVariableGivenNameScoped(self): 298 | with self.test_session(): 299 | with tf.variable_scope('A'): 300 | a = variables.variable('a', [5]) 301 | b = variables.variable('b', [5]) 302 | self.assertEquals([a], variables.get_variables_by_name('a')) 303 | self.assertEquals([b], variables.get_variables_by_name('b')) 304 | 305 | def testGetVariablesByNameReturnsByValueWithScope(self): 306 | with self.test_session(): 307 | with tf.variable_scope('A'): 308 | a = variables.variable('a', [5]) 309 | matched_variables = variables.get_variables_by_name('a') 310 | 311 | # If variables.get_variables_by_name returns the list by reference, the 312 | # following append should persist, and be returned, in subsequent calls 313 | # to variables.get_variables_by_name('a'). 314 | matched_variables.append(4) 315 | 316 | matched_variables = variables.get_variables_by_name('a') 317 | self.assertEquals([a], matched_variables) 318 | 319 | def testGetVariablesByNameReturnsByValueWithoutScope(self): 320 | with self.test_session(): 321 | a = variables.variable('a', [5]) 322 | matched_variables = variables.get_variables_by_name('a') 323 | 324 | # If variables.get_variables_by_name returns the list by reference, the 325 | # following append should persist, and be returned, in subsequent calls 326 | # to variables.get_variables_by_name('a'). 327 | matched_variables.append(4) 328 | 329 | matched_variables = variables.get_variables_by_name('a') 330 | self.assertEquals([a], matched_variables) 331 | 332 | 333 | class GlobalStepTest(tf.test.TestCase): 334 | 335 | def testStable(self): 336 | with tf.Graph().as_default(): 337 | gs = variables.global_step() 338 | gs2 = variables.global_step() 339 | self.assertTrue(gs is gs2) 340 | 341 | def testDevice(self): 342 | with tf.Graph().as_default(): 343 | with scopes.arg_scope([variables.global_step], device='/gpu:0'): 344 | gs = variables.global_step() 345 | self.assertDeviceEqual(gs.device, '/gpu:0') 346 | 347 | def testDeviceFn(self): 348 | class DevFn(object): 349 | 350 | def __init__(self): 351 | self.counter = -1 352 | 353 | def __call__(self, op): 354 | self.counter += 1 355 | return '/cpu:%d' % self.counter 356 | 357 | with tf.Graph().as_default(): 358 | with scopes.arg_scope([variables.global_step], device=DevFn()): 359 | gs = variables.global_step() 360 | gs2 = variables.global_step() 361 | self.assertDeviceEqual(gs.device, '/cpu:0') 362 | self.assertEquals(gs, gs2) 363 | self.assertDeviceEqual(gs2.device, '/cpu:0') 364 | 365 | def testReplicaDeviceSetter(self): 366 | device_fn = tf.train.replica_device_setter(2) 367 | with tf.Graph().as_default(): 368 | with scopes.arg_scope([variables.global_step], device=device_fn): 369 | gs = variables.global_step() 370 | gs2 = variables.global_step() 371 | self.assertEquals(gs, gs2) 372 | self.assertDeviceEqual(gs.device, '/job:ps/task:0') 373 | self.assertDeviceEqual(gs.initial_value.device, '/job:ps/task:0') 374 | self.assertDeviceEqual(gs2.device, '/job:ps/task:0') 375 | self.assertDeviceEqual(gs2.initial_value.device, '/job:ps/task:0') 376 | 377 | def testVariableWithVariableDeviceChooser(self): 378 | 379 | with tf.Graph().as_default(): 380 | device_fn = variables.VariableDeviceChooser() 381 | with scopes.arg_scope([variables.global_step], device=device_fn): 382 | gs = variables.global_step() 383 | gs2 = variables.global_step() 384 | self.assertEquals(gs, gs2) 385 | self.assertDeviceEqual(gs.device, 'cpu:0') 386 | self.assertDeviceEqual(gs.initial_value.device, gs.device) 387 | self.assertDeviceEqual(gs2.device, 'cpu:0') 388 | self.assertDeviceEqual(gs2.initial_value.device, gs2.device) 389 | 390 | 391 | if __name__ == '__main__': 392 | tf.test.main() 393 | --------------------------------------------------------------------------------