Skip to content

Commit d10a0f2

Browse files
authored
Merge pull request tensorflow#47 from tensorflow/internal-to-github-sync
Merge internal changes into public repository (change 181251654)
2 parents 1dfee59 + a2a75e0 commit d10a0f2

18 files changed

+3422
-155
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Copyright 2018 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+
r"""Script to create a fake dataset to test out ResNet-50 and related models.
16+
17+
To run the script setup a virtualenv with the following libraries installed.
18+
- `gcloud`: Follow the instructions on
19+
[cloud SDK docs](https://cloud.google.com/sdk/downloads) followed by
20+
installing the python api using `pip install google-cloud`.
21+
- `tensorflow`: Install with `pip install tensorflow`
22+
- `Pillow`: Install with `pip install pillow`
23+
24+
You can run the script using the following command.
25+
```
26+
python fake_data_generator.py \
27+
--project="TEST_PROJECT" \
28+
--gcs_output_path="gs://TEST_BUCKET/DATA_DIR"
29+
```
30+
"""
31+
32+
import os
33+
import StringIO
34+
import numpy as np
35+
from PIL import Image
36+
import tensorflow as tf
37+
38+
tf.flags.DEFINE_string('project', None,
39+
'Google cloud project id for uploading the dataset.')
40+
tf.flags.DEFINE_string('gcs_output_path', None,
41+
'GCS path for uploading the dataset.')
42+
tf.flags.DEFINE_integer('examples_per_shard', 5000, '')
43+
tf.flags.DEFINE_integer('num_label_classes', 1000, '')
44+
tf.flags.DEFINE_integer('training_shards', 260, '')
45+
tf.flags.DEFINE_integer('validation_shards', 10, '')
46+
47+
FLAGS = tf.flags.FLAGS
48+
49+
TRAINING_PREFIX = 'train'
50+
VALIDATION_PREFIX = 'validation'
51+
52+
53+
def _int64_feature(value):
54+
"""Wrapper for inserting int64 features into Example proto."""
55+
if not isinstance(value, list):
56+
value = [value]
57+
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
58+
59+
60+
def _bytes_feature(value):
61+
"""Wrapper for inserting bytes features into Example proto."""
62+
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
63+
64+
65+
def _create_example(label):
66+
"""Build an Example proto for a single randomly generated image."""
67+
colorspace = 'RGB'
68+
channels = 3
69+
image_format = 'JPEG'
70+
height = 224
71+
width = 224
72+
73+
# Create a random image
74+
image = (np.random.rand(height, width, channels) * 255).astype('uint8')
75+
image = Image.fromarray(image)
76+
image_buffer = StringIO.StringIO()
77+
image.save(image_buffer, format=image_format)
78+
79+
example = tf.train.Example(
80+
features=tf.train.Features(
81+
feature={
82+
'image/height': _int64_feature(height),
83+
'image/width': _int64_feature(width),
84+
'image/colorspace': _bytes_feature(colorspace),
85+
'image/channels': _int64_feature(channels),
86+
'image/class/label': _int64_feature(label),
87+
'image/format': _bytes_feature(image_format),
88+
'image/encoded': _bytes_feature(image_buffer.getvalue())
89+
}))
90+
return example
91+
92+
93+
def _create_random_file(output_file):
94+
"""Create a single tf-record file with multiple examples for each class."""
95+
writer = tf.python_io.TFRecordWriter(output_file)
96+
examples_per_class = int(FLAGS.examples_per_shard / FLAGS.num_label_classes)
97+
98+
assert examples_per_class > 0, 'Number of examples per class should be >= 1'
99+
100+
for label in range(FLAGS.num_label_classes):
101+
for _ in range(examples_per_class):
102+
example = _create_example(label)
103+
writer.write(example.SerializeToString())
104+
writer.close()
105+
106+
107+
def create_tf_records(data_dir):
108+
"""Create random data and write it to tf-record files."""
109+
def _create_records(prefix, num_shards):
110+
"""Create records in a given directory."""
111+
for shard in range(num_shards):
112+
filename = os.path.join(data_dir, '%s-%.5d-of-%.5d' % (prefix, shard,
113+
num_shards))
114+
_create_random_file(filename)
115+
116+
tf.logging.info('Processing the training data.')
117+
_create_records(TRAINING_PREFIX, FLAGS.training_shards)
118+
119+
tf.logging.info('Processing the validation data.')
120+
_create_records(VALIDATION_PREFIX, FLAGS.validation_shards)
121+
122+
123+
def main(argv): # pylint: disable=unused-argument
124+
tf.logging.set_verbosity(tf.logging.INFO)
125+
126+
if FLAGS.project is None:
127+
raise ValueError('GCS Project must be provided.')
128+
129+
if FLAGS.gcs_output_path is None:
130+
raise ValueError('GCS output path must be provided.')
131+
elif not FLAGS.gcs_output_path.startswith('gs://'):
132+
raise ValueError('GCS output path must start with gs://')
133+
134+
# Create fake tf-records
135+
create_tf_records(FLAGS.gcs_output_path)
136+
137+
138+
if __name__ == '__main__':
139+
tf.app.run()

cloud_tpu/datasets/imagenet_to_gcs.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,22 +410,21 @@ def upload_to_gcs(training_records, validation_records):
410410
client = storage.Client(project=FLAGS.project)
411411
bucket = client.get_bucket(bucket_name)
412412

413-
def _upload_files(filenames, subdirectory):
413+
def _upload_files(filenames):
414414
"""Upload a list of files into a specifc subdirectory."""
415415
for i, filename in enumerate(sorted(filenames)):
416-
blob = bucket.blob(key_prefix + subdirectory + '/' +
417-
os.path.basename(filename))
416+
blob = bucket.blob(key_prefix + os.path.basename(filename))
418417
blob.upload_from_filename(filename)
419418
if not i % 20:
420419
tf.logging.info('Finished uploading file: %s' % filename)
421420

422421
# Upload training dataset
423422
tf.logging.info('Uploading the training data.')
424-
_upload_files(training_records, TRAINING_DIRECTORY)
423+
_upload_files(training_records)
425424

426425
# Upload validation dataset
427426
tf.logging.info('Uploading the validation data.')
428-
_upload_files(validation_records, VALIDATION_DIRECTORY)
427+
_upload_files(validation_records)
429428

430429

431430
def main(argv): # pylint: disable=unused-argument

cloud_tpu/jupyterhub/launch.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/bin/bash
2+
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ==============================================================================
16+
#
17+
# This script tries to launch the Jupyterhub notebook in this directory if it
18+
# is running in a GCE instance.
19+
#
20+
# 1. Verifies that Jupyterhub, TensorFlow, and gcloud are installed properly
21+
# 2. Tags the current instance with `cloud-tpu-demo-notebook`.
22+
# 3. Creates a firewall rule that opens port 8888 (for Jupyterhub) and port
23+
# 6006 (for TensorBoard) for all instances tagged `cloud-tpu-demo-notebook`.
24+
# 4. Starts Jupyterhub.
25+
26+
version_lte() {
27+
[ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]
28+
}
29+
30+
# Ensure that pip is installed
31+
command -v pip >/dev/null 2>&1 || { echo "To run this tutorial, we need pip to be installed. You can install pip by running `sudo apt-get install python-pip`."; exit 1; }
32+
33+
# Ensure that gcloud is installed
34+
command -v gcloud >/dev/null 2>&1 || { echo "To run this tutorial, we need the Google Cloud SDK. Please see https://cloud.google.com/sdk/downloads for instructions."; exit 1; }
35+
36+
# Ensure that TensorFlow is installed
37+
TF_VERSION=`python -c "import tensorflow; print tensorflow.__version__" 2>/dev/null`
38+
version_lte $TF_VERSION 1.5 && (echo "Your version of TensorFlow is too low. You must install at least version 1.5.0."; exit 1;)
39+
40+
# Ensure that Jupyter is installed
41+
command -v jupyter >/dev/null 2>&1 || { sudo pip install jupyter; }
42+
43+
# Retrieve the instance name and zone of the current instance
44+
INSTANCE_NAME=`curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/name 2>/dev/null`
45+
INSTANCE_ZONE=`curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone 2>/dev/null`
46+
47+
# Add `cloud-tpu-demo-notebook` tag to current instance
48+
gcloud compute instances add-tags $INSTANCE_NAME --tags cloud-tpu-demo-notebook --zone $INSTANCE_ZONE
49+
50+
# Add firewall rule to open tcp:6006,8888 for `cloud-tpu-demo-notebook`
51+
gcloud compute firewall-rules create cloud-tpu-demo-notebook --target-tags=cloud-tpu-demo-notebook --allow=tcp:6006,tcp:8888
52+
53+
# Print out JupyterHub URL
54+
echo
55+
echo The Jupyterhub is at: http://`curl -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip 2> /dev/null`:8888/
56+
echo
57+
58+
# Launch JupyterHub
59+
jupyter notebook --no-browser --ip=0.0.0.0
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Copyright 2017 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+
"""Cifar example using Keras for model definition."""
16+
17+
from __future__ import absolute_import
18+
from __future__ import division
19+
from __future__ import print_function
20+
21+
import tensorflow as tf
22+
23+
from tensorflow.contrib.tpu.python.tpu import tpu_config
24+
from tensorflow.contrib.tpu.python.tpu import tpu_estimator
25+
from tensorflow.contrib.tpu.python.tpu import tpu_optimizer
26+
27+
tf.flags.DEFINE_integer("batch_size", 128,
28+
"Mini-batch size for the computation. Note that this "
29+
"is the global batch size and not the per-shard batch.")
30+
tf.flags.DEFINE_float("learning_rate", 0.05, "Learning rate.")
31+
tf.flags.DEFINE_string("train_file", "", "Path to cifar10 training data.")
32+
tf.flags.DEFINE_integer("train_steps", 100000,
33+
"Total number of steps. Note that the actual number of "
34+
"steps is the next multiple of --iterations greater "
35+
"than this value.")
36+
tf.flags.DEFINE_bool("use_tpu", True, "Use TPUs rather than plain CPUs")
37+
tf.flags.DEFINE_string("master", "",
38+
"BNS name of the TensorFlow master to use.")
39+
tf.flags.DEFINE_string("model_dir", None, "Estimator model_dir")
40+
tf.flags.DEFINE_integer("iterations", 100,
41+
"Number of iterations per TPU training loop.")
42+
tf.flags.DEFINE_integer("num_shards", 8, "Number of shards (TPU chips).")
43+
44+
45+
FLAGS = tf.flags.FLAGS
46+
47+
48+
def model_fn(features, labels, mode, params):
49+
"""Define a CIFAR model in Keras."""
50+
del params # unused
51+
layers = tf.contrib.keras.layers
52+
53+
# Pass our input tensor to initialize the Keras input layer.
54+
v = layers.Input(tensor=features)
55+
v = layers.Conv2D(filters=32, kernel_size=5,
56+
activation="relu", padding="same")(v)
57+
v = layers.MaxPool2D(pool_size=2)(v)
58+
v = layers.Conv2D(filters=64, kernel_size=5,
59+
activation="relu", padding="same")(v)
60+
v = layers.MaxPool2D(pool_size=2)(v)
61+
v = layers.Flatten()(v)
62+
fc1 = layers.Dense(units=512, activation="relu")(v)
63+
logits = layers.Dense(units=10)(fc1)
64+
65+
# Instead of constructing a Keras model for training, build our loss function
66+
# and optimizer in Tensorflow.
67+
#
68+
# N.B. This construction omits some features that are important for more
69+
# complex models (e.g. regularization, batch-norm). Once
70+
# `model_to_estimator` support is added for TPUs, it should be used instead.
71+
loss = tf.reduce_mean(
72+
tf.nn.sparse_softmax_cross_entropy_with_logits(
73+
logits=logits, labels=labels
74+
)
75+
)
76+
optimizer = tf.train.AdamOptimizer()
77+
if FLAGS.use_tpu:
78+
optimizer = tpu_optimizer.CrossShardOptimizer(optimizer)
79+
80+
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
81+
82+
return tpu_estimator.TPUEstimatorSpec(
83+
mode=mode,
84+
loss=loss,
85+
train_op=train_op,
86+
predictions={
87+
"classes": tf.argmax(input=logits, axis=1),
88+
"probabilities": tf.nn.softmax(logits, name="softmax_tensor")
89+
}
90+
)
91+
92+
93+
def input_fn(params):
94+
"""Read CIFAR input data from a TFRecord dataset."""
95+
del params
96+
batch_size = FLAGS.batch_size
97+
def parser(serialized_example):
98+
"""Parses a single tf.Example into image and label tensors."""
99+
features = tf.parse_single_example(
100+
serialized_example,
101+
features={
102+
"image": tf.FixedLenFeature([], tf.string),
103+
"label": tf.FixedLenFeature([], tf.int64),
104+
})
105+
image = tf.decode_raw(features["image"], tf.uint8)
106+
image.set_shape([3*32*32])
107+
image = tf.cast(image, tf.float32) * (1. / 255) - 0.5
108+
image = tf.transpose(tf.reshape(image, [3, 32, 32]))
109+
label = tf.cast(features["label"], tf.int32)
110+
return image, label
111+
112+
dataset = tf.data.TFRecordDataset([FLAGS.train_file])
113+
dataset = dataset.map(parser, num_parallel_calls=batch_size)
114+
dataset = dataset.prefetch(4 * batch_size).cache().repeat()
115+
dataset = dataset.apply(
116+
tf.contrib.data.batch_and_drop_remainder(FLAGS.batch_size)
117+
)
118+
dataset = dataset.prefetch(1)
119+
images, labels = dataset.make_one_shot_iterator().get_next()
120+
return images, labels
121+
122+
123+
def main(argv):
124+
del argv # Unused.
125+
126+
run_config = tpu_config.RunConfig(
127+
master=FLAGS.master,
128+
model_dir=FLAGS.model_dir,
129+
save_checkpoints_secs=3600,
130+
session_config=tf.ConfigProto(
131+
allow_soft_placement=True, log_device_placement=True),
132+
tpu_config=tpu_config.TPUConfig(
133+
iterations_per_loop=FLAGS.iterations, num_shards=FLAGS.num_shards),
134+
)
135+
136+
estimator = tpu_estimator.TPUEstimator(
137+
model_fn=model_fn,
138+
use_tpu=FLAGS.use_tpu,
139+
config=run_config,
140+
train_batch_size=FLAGS.batch_size)
141+
estimator.train(input_fn=input_fn, max_steps=FLAGS.train_steps)
142+
143+
144+
if __name__ == "__main__":
145+
tf.logging.set_verbosity(tf.logging.INFO)
146+
tf.app.run(main)

0 commit comments

Comments
 (0)