Skip to content

Commit a591478

Browse files
panyx0718martinwicke
authored andcommitted
Add resnet model. (tensorflow#273)
1 parent be7a899 commit a591478

File tree

7 files changed

+759
-0
lines changed

7 files changed

+759
-0
lines changed

resnet/BUILD

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package(default_visibility = [":internal"])
2+
3+
licenses(["notice"]) # Apache 2.0
4+
5+
exports_files(["LICENSE"])
6+
7+
package_group(
8+
name = "internal",
9+
packages = [
10+
"//resnet/...",
11+
],
12+
)
13+
14+
filegroup(
15+
name = "py_srcs",
16+
data = glob([
17+
"**/*.py",
18+
]),
19+
)
20+
21+
py_library(
22+
name = "resnet_model",
23+
srcs = ["resnet_model.py"],
24+
)
25+
26+
py_binary(
27+
name = "resnet_main",
28+
srcs = [
29+
"resnet_main.py",
30+
],
31+
deps = [
32+
":cifar_input",
33+
":resnet_model",
34+
],
35+
)
36+
37+
py_library(
38+
name = "cifar_input",
39+
srcs = ["cifar_input.py"],
40+
)

resnet/README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<font size=4><b>Reproduced ResNet on CIFAR-10 and CIFAR-100 dataset.</b></font>
2+
3+
contact: panyx0718 ([email protected])
4+
5+
<b>Dataset:</b>
6+
7+
https://www.cs.toronto.edu/~kriz/cifar.html
8+
9+
<b>Related papers:</b>
10+
11+
Identity Mappings in Deep Residual Networks
12+
13+
https://arxiv.org/pdf/1603.05027v2.pdf
14+
15+
Deep Residual Learning for Image Recognition
16+
17+
https://arxiv.org/pdf/1512.03385v1.pdf
18+
19+
Wide Residual Networks
20+
21+
https://arxiv.org/pdf/1605.07146v1.pdf
22+
23+
<b>Settings:</b>
24+
25+
* Random split 50k training set into 45k/5k train/eval split.
26+
* Pad to 36x36 and random crop. Horizontal flip. Per-image whitenting.
27+
* Momentum optimizer 0.9.
28+
* Learning rate schedule: 0.1 (40k), 0.01 (60k), 0.001 (>60k).
29+
* L2 weight decay: 0.002.
30+
* Batch size: 128. (28-10 wide and 1001 layer bottleneck use 64)
31+
32+
<b>Results:</b>
33+
34+
<left>
35+
![Precisions](g3doc/cifar_resnet.gif)
36+
</left>
37+
<left>
38+
![Precisions Legends](g3doc/cifar_resnet_legends.gif)
39+
</left>
40+
41+
42+
CIFAR-10 Model|Best Precision|Steps
43+
--------------|--------------|------
44+
32 layer|92.5%|~80k
45+
110 layer|93.6%|~80k
46+
164 layer bottleneck|94.5%|~80k
47+
1001 layer bottleneck|94.9%|~80k
48+
28-10 wide|95%|~90k
49+
50+
CIFAR-100 Model|Best Precision|Steps
51+
---------------|--------------|-----
52+
32 layer|68.1%|~45k
53+
110 layer|71.3%|~60k
54+
164 layer bottleneck|75.7%|~50k
55+
1001 layer bottleneck|78.2%|~70k
56+
28-10 wide|78.3%|~70k
57+
58+
<b>Prerequisite:</b>
59+
60+
1. Install TensorFlow, Bazel.
61+
62+
2. Download CIFAR-10/CIFAR-100 dataset.
63+
64+
```shell
65+
curl -o cifar-10-binary.tar.gz https://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz
66+
curl -o cifar-100-binary.tar.gz https://www.cs.toronto.edu/~kriz/cifar-100-binary.tar.gz
67+
```
68+
69+
<b>How to run:</b>
70+
71+
```shell
72+
# cd to the your workspace.
73+
# It contains an empty WORKSPACE file, resnet codes and cifar10 dataset.
74+
ls -R
75+
.:
76+
cifar10 resnet WORKSPACE
77+
78+
./cifar10:
79+
test.bin train.bin validation.bin
80+
81+
./resnet:
82+
BUILD cifar_input.py g3doc README.md resnet_main.py resnet_model.py
83+
84+
# Build everything for GPU.
85+
bazel build -c opt --config=cuda resnet/...
86+
87+
# Train the model.
88+
bazel-bin/resnet/resnet_main --train_data_path=cifar10/train.bin \
89+
--log_root=/tmp/resnet_model \
90+
--train_dir=/tmp/resnet_model/train \
91+
--dataset='cifar10' \
92+
--num_gpus=1
93+
94+
# Evaluate the model.
95+
# Avoid running on the same GPU as the training job at the same time,
96+
# otherwise, you might run out of memory.
97+
bazel-bin/resnet/resnet_main --eval_data_path=cifar10/test.bin \
98+
--log_root=/tmp/resnet_model \
99+
--eval_dir=/tmp/resnet_model/test \
100+
--mode=eval \
101+
--dataset='cifar10' \
102+
--num_gpus=0
103+
```

resnet/cifar_input.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Copyright 2016 The TensorFlow Authors. 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+
16+
"""CIFAR dataset input module.
17+
"""
18+
19+
import tensorflow as tf
20+
21+
22+
def build_input(dataset, data_path, batch_size, mode):
23+
"""Build CIFAR image and labels.
24+
25+
Args:
26+
dataset: Either 'cifar10' or 'cifar100'.
27+
data_path: Filename for data.
28+
batch_size: Input batch size.
29+
mode: Either 'train' or 'eval'.
30+
Returns:
31+
images: Batches of images. [batch_size, image_size, image_size, 3]
32+
labels: Batches of labels. [batch_size, num_classes]
33+
Raises:
34+
ValueError: when the specified dataset is not supported.
35+
"""
36+
image_size = 32
37+
if dataset == 'cifar10':
38+
label_bytes = 1
39+
label_offset = 0
40+
num_classes = 10
41+
elif dataset == 'cifar100':
42+
label_bytes = 1
43+
label_offset = 1
44+
num_classes = 100
45+
else:
46+
raise ValueError('Not supported dataset %s', dataset)
47+
48+
depth = 3
49+
image_bytes = image_size * image_size * depth
50+
record_bytes = label_bytes + label_offset + image_bytes
51+
52+
file_queue = tf.train.string_input_producer([data_path], shuffle=True)
53+
# Read examples from files in the filename queue.
54+
reader = tf.FixedLengthRecordReader(record_bytes=record_bytes)
55+
_, value = reader.read(file_queue)
56+
57+
# Convert these examples to dense labels and processed images.
58+
record = tf.reshape(tf.decode_raw(value, tf.uint8), [record_bytes])
59+
label = tf.cast(tf.slice(record, [label_offset], [label_bytes]), tf.int32)
60+
# Convert from string to [depth * height * width] to [depth, height, width].
61+
depth_major = tf.reshape(tf.slice(record, [label_bytes], [image_bytes]),
62+
[depth, image_size, image_size])
63+
# Convert from [depth, height, width] to [height, width, depth].
64+
image = tf.cast(tf.transpose(depth_major, [1, 2, 0]), tf.float32)
65+
66+
if mode == 'train':
67+
image = tf.image.resize_image_with_crop_or_pad(
68+
image, image_size+4, image_size+4)
69+
image = tf.random_crop(image, [image_size, image_size, 3])
70+
image = tf.image.random_flip_left_right(image)
71+
# Brightness/saturation/constrast provides small gains .2%~.5% on cifar.
72+
# image = tf.image.random_brightness(image, max_delta=63. / 255.)
73+
# image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
74+
# image = tf.image.random_contrast(image, lower=0.2, upper=1.8)
75+
image = tf.image.per_image_whitening(image)
76+
77+
example_queue = tf.RandomShuffleQueue(
78+
capacity=16 * batch_size,
79+
min_after_dequeue=8 * batch_size,
80+
dtypes=[tf.float32, tf.int32],
81+
shapes=[[image_size, image_size, depth], [1]])
82+
num_threads = 16
83+
else:
84+
image = tf.image.resize_image_with_crop_or_pad(
85+
image, image_size, image_size)
86+
image = tf.image.per_image_whitening(image)
87+
88+
example_queue = tf.FIFOQueue(
89+
3 * batch_size,
90+
dtypes=[tf.float32, tf.int32],
91+
shapes=[[image_size, image_size, depth], [1]])
92+
num_threads = 1
93+
94+
example_enqueue_op = example_queue.enqueue([image, label])
95+
tf.train.add_queue_runner(tf.train.queue_runner.QueueRunner(
96+
example_queue, [example_enqueue_op] * num_threads))
97+
98+
# Read 'batch' labels + images from the example queue.
99+
images, labels = example_queue.dequeue_many(batch_size)
100+
labels = tf.reshape(labels, [batch_size, 1])
101+
indices = tf.reshape(tf.range(0, batch_size, 1), [batch_size, 1])
102+
labels = tf.sparse_to_dense(
103+
tf.concat(1, [indices, labels]),
104+
[batch_size, num_classes], 1.0, 0.0)
105+
106+
assert len(images.get_shape()) == 4
107+
assert images.get_shape()[0] == batch_size
108+
assert images.get_shape()[-1] == 3
109+
assert len(labels.get_shape()) == 2
110+
assert labels.get_shape()[0] == batch_size
111+
assert labels.get_shape()[1] == num_classes
112+
113+
# Display the training images in the visualizer.
114+
tf.image_summary('images', images)
115+
return images, labels

resnet/g3doc/cifar_resnet.gif

14.2 KB
Loading

resnet/g3doc/cifar_resnet_legends.gif

4.49 KB
Loading

0 commit comments

Comments
 (0)