Skip to content

Commit 73055fc

Browse files
ratgrtensorflower-gardener
authored andcommitted
This commit addresses an issue where several scripts hardcoded predictable file paths in world-writable shared locations like /tmp/logs, in some examples.
This is a bad example and someone might base their application on these examples PiperOrigin-RevId: 918000013
1 parent cc21433 commit 73055fc

5 files changed

Lines changed: 183 additions & 89 deletions

File tree

tensorflow_model_optimization/python/examples/sparsity/keras/mnist/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ py_strict_binary(
5252
srcs = ["mnist_e2e_sparsity2x4.py"],
5353
deps = [
5454
# absl:app dep1,
55+
# absl/flags dep1,
5556
# tensorflow dep1,
5657
"//tensorflow_model_optimization/python/core/keras:compat",
5758
"//tensorflow_model_optimization/python/core/keras:test_utils",

tensorflow_model_optimization/python/examples/sparsity/keras/mnist/mnist_cnn.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"""Train a simple convnet on the MNIST dataset."""
1717
from __future__ import print_function
1818

19+
import datetime
20+
import os
21+
import tempfile
22+
1923
from absl import app as absl_app
2024
from absl import flags
2125
import tensorflow as tf
@@ -35,8 +39,12 @@
3539
num_classes = 10
3640
epochs = 12
3741

38-
flags.DEFINE_string('output_dir', '/tmp/mnist_train/',
39-
'Output directory to hold tensorboard events')
42+
flags.DEFINE_string(
43+
'output_dir',
44+
None,
45+
'Output directory to hold tensorboard events and models. If None, a'
46+
' temporary directory is used.',
47+
)
4048

4149

4250
def build_sequential_model(input_shape):
@@ -94,7 +102,7 @@ def build_layerwise_model(input_shape, **pruning_params):
94102
])
95103

96104

97-
def train_and_save(models, x_train, y_train, x_test, y_test):
105+
def train_and_save(models, x_train, y_train, x_test, y_test, output_dir):
98106
for model in models:
99107
model.compile(
100108
loss=keras.losses.categorical_crossentropy,
@@ -109,7 +117,7 @@ def train_and_save(models, x_train, y_train, x_test, y_test):
109117
# step. Also add a callback to add pruning summaries to tensorboard
110118
callbacks = [
111119
pruning_callbacks.UpdatePruningStep(),
112-
pruning_callbacks.PruningSummaries(log_dir=FLAGS.output_dir)
120+
pruning_callbacks.PruningSummaries(log_dir=output_dir)
113121
]
114122

115123
model.fit(
@@ -125,7 +133,7 @@ def train_and_save(models, x_train, y_train, x_test, y_test):
125133
print('Test accuracy:', score[1])
126134

127135
# Export and import the model. Check that accuracy persists.
128-
saved_model_dir = '/tmp/saved_model'
136+
saved_model_dir = os.path.join(output_dir, 'saved_model')
129137
print('Saving model to: ', saved_model_dir)
130138
keras.models.save_model(model, saved_model_dir, save_format='tf')
131139
print('Loading model from: ', saved_model_dir)
@@ -182,8 +190,18 @@ def main(unused_argv):
182190
functional_model = prune.prune_low_magnitude(
183191
functional_model, **pruning_params)
184192

193+
if FLAGS.output_dir and not os.path.exists(FLAGS.output_dir):
194+
os.makedirs(FLAGS.output_dir)
195+
output_dir = tempfile.mkdtemp(
196+
dir=FLAGS.output_dir,
197+
prefix=datetime.datetime.now().strftime('tmp_%Y%m%d%H%M_'),
198+
)
199+
print('All models and logs will be saved to: {}'.format(output_dir))
200+
185201
models = [layerwise_model, sequential_model, functional_model]
186-
train_and_save(models, x_train, y_train, x_test, y_test)
202+
train_and_save(
203+
models, x_train, y_train, x_test, y_test, output_dir=output_dir
204+
)
187205

188206

189207
if __name__ == '__main__':

tensorflow_model_optimization/python/examples/sparsity/keras/mnist/mnist_e2e.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"""Train a simple convnet on the MNIST dataset."""
1717
from __future__ import print_function
1818

19+
import datetime
20+
import os
21+
import tempfile
22+
1923
from absl import app as absl_app
2024
from absl import flags
2125
import tensorflow as tf
@@ -37,6 +41,12 @@
3741
epochs = 1
3842

3943
flags.DEFINE_float('sparsity', '0.0', 'Target sparsity level.')
44+
flags.DEFINE_string(
45+
'output_dir',
46+
None,
47+
'Output directory for models and logs. If not set, a temporary directory'
48+
' is used.',
49+
)
4050

4151

4252
def build_layerwise_model(input_shape, **pruning_params):
@@ -60,7 +70,7 @@ def build_layerwise_model(input_shape, **pruning_params):
6070
])
6171

6272

63-
def train(model, x_train, y_train, x_test, y_test):
73+
def train(model, x_train, y_train, x_test, y_test, output_dir):
6474
model.compile(
6575
loss=keras.losses.categorical_crossentropy,
6676
optimizer='adam',
@@ -74,7 +84,7 @@ def train(model, x_train, y_train, x_test, y_test):
7484
# step. Also add a callback to add pruning summaries to tensorboard
7585
callbacks = [
7686
pruning_callbacks.UpdatePruningStep(),
77-
pruning_callbacks.PruningSummaries(log_dir='/tmp/logs')
87+
pruning_callbacks.PruningSummaries(log_dir=output_dir)
7888
]
7989

8090
model.fit(
@@ -101,6 +111,14 @@ def main(unused_argv):
101111
x_test,
102112
y_test), input_shape = keras_test_utils.get_preprocessed_mnist_data()
103113

114+
if FLAGS.output_dir and not os.path.exists(FLAGS.output_dir):
115+
os.makedirs(FLAGS.output_dir)
116+
temp_dir = tempfile.mkdtemp(
117+
dir=FLAGS.output_dir,
118+
prefix=datetime.datetime.now().strftime('tmp_%Y%m%d%H%M_'),
119+
)
120+
print('All models and logs will be saved to: {}'.format(temp_dir))
121+
104122
##############################################################################
105123
# Train and convert a model with 2x2 block config. There's no kernel in tflite
106124
# supporting this block configuration, so the sparse tensor is densified and
@@ -113,13 +131,13 @@ def main(unused_argv):
113131
}
114132

115133
model = build_layerwise_model(input_shape, **pruning_params)
116-
model = train(model, x_train, y_train, x_test, y_test)
134+
model = train(model, x_train, y_train, x_test, y_test, output_dir=temp_dir)
117135

118136
converter = tf.lite.TFLiteConverter.from_keras_model(model)
119137

120138
# Get a dense model as baseline
121139
tflite_model_dense = converter.convert()
122-
tflite_model_path = '/tmp/dense_mnist.tflite'
140+
tflite_model_path = os.path.join(temp_dir, 'dense_mnist.tflite')
123141
with open(tflite_model_path, 'wb') as f:
124142
f.write(tflite_model_dense)
125143

@@ -131,7 +149,9 @@ def main(unused_argv):
131149
# Check the model is compressed
132150
print('Compression ratio: ', len(tflite_model) / len(tflite_model_dense))
133151

134-
tflite_model_path = '/tmp/sparse_mnist_%s_2x2.tflite' % FLAGS.sparsity
152+
tflite_model_path = os.path.join(
153+
temp_dir, 'sparse_mnist_%s_2x2.tflite' % FLAGS.sparsity
154+
)
135155
with open(tflite_model_path, 'wb') as f:
136156
f.write(tflite_model)
137157

@@ -152,7 +172,7 @@ def main(unused_argv):
152172
}
153173

154174
model = build_layerwise_model(input_shape, **pruning_params)
155-
model = train(model, x_train, y_train, x_test, y_test)
175+
model = train(model, x_train, y_train, x_test, y_test, output_dir=temp_dir)
156176

157177
converter = tf.lite.TFLiteConverter.from_keras_model(model)
158178
converter.optimizations = {tf.lite.Optimize.EXPERIMENTAL_SPARSITY}
@@ -161,7 +181,9 @@ def main(unused_argv):
161181
# Check the model is compressed
162182
print('Compression ratio: ', len(tflite_model) / len(tflite_model_dense))
163183

164-
tflite_model_path = '/tmp/sparse_mnist_%s_1x4.tflite' % FLAGS.sparsity
184+
tflite_model_path = os.path.join(
185+
temp_dir, 'sparse_mnist_%s_1x4.tflite' % FLAGS.sparsity
186+
)
165187
with open(tflite_model_path, 'wb') as f:
166188
f.write(tflite_model)
167189

@@ -181,7 +203,7 @@ def main(unused_argv):
181203
}
182204

183205
model = build_layerwise_model(input_shape, **pruning_params)
184-
model = train(model, x_train, y_train, x_test, y_test)
206+
model = train(model, x_train, y_train, x_test, y_test, output_dir=temp_dir)
185207

186208
converter = tf.lite.TFLiteConverter.from_keras_model(model)
187209
converter.optimizations = {
@@ -192,7 +214,9 @@ def main(unused_argv):
192214
# Check the model is compressed
193215
print('Compression ratio: ', len(tflite_model) / len(tflite_model_dense))
194216

195-
tflite_model_path = '/tmp/sparse_mnist_%s_1x16.tflite' % FLAGS.sparsity
217+
tflite_model_path = os.path.join(
218+
temp_dir, 'sparse_mnist_%s_1x16.tflite' % FLAGS.sparsity
219+
)
196220
with open(tflite_model_path, 'wb') as f:
197221
f.write(tflite_model)
198222

tensorflow_model_optimization/python/examples/sparsity/keras/mnist/mnist_e2e_sparsity2x4.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
"""
2020
from __future__ import print_function
2121

22+
import datetime
23+
import os
24+
import tempfile
25+
2226
from absl import app as absl_app
27+
from absl import flags
2328
import tensorflow as tf
2429

2530
from tensorflow_model_optimization.python.core.keras import test_utils as keras_test_utils
@@ -40,6 +45,14 @@
4045
num_classes = 10
4146
epochs = 1
4247

48+
FLAGS = flags.FLAGS
49+
flags.DEFINE_string(
50+
'output_dir',
51+
None,
52+
'Output directory for models and logs. If not set, a temporary directory'
53+
' is used.',
54+
)
55+
4356
PRUNABLE_2x4_LAYERS = (keras.layers.Conv2D, keras.layers.Dense)
4457

4558

@@ -77,7 +90,7 @@ def build_layerwise_model(input_shape, **pruning_params):
7790
])
7891

7992

80-
def train(model, x_train, y_train, x_test, y_test):
93+
def train(model, x_train, y_train, x_test, y_test, output_dir):
8194
model.compile(
8295
loss=keras.losses.categorical_crossentropy,
8396
optimizer='adam',
@@ -92,7 +105,7 @@ def train(model, x_train, y_train, x_test, y_test):
92105
# step. Also add a callback to add pruning summaries to tensorboard
93106
callbacks = [
94107
pruning_callbacks.UpdatePruningStep(),
95-
pruning_callbacks.PruningSummaries(log_dir='/tmp/logs')
108+
pruning_callbacks.PruningSummaries(log_dir=output_dir)
96109
]
97110

98111
model.fit(
@@ -131,14 +144,25 @@ def main(unused_argv):
131144
'sparsity_m_by_n': (2, 4),
132145
}
133146

147+
if FLAGS.output_dir and not os.path.exists(FLAGS.output_dir):
148+
os.makedirs(FLAGS.output_dir)
149+
temp_dir = tempfile.mkdtemp(
150+
dir=FLAGS.output_dir,
151+
prefix=datetime.datetime.now().strftime('tmp_%Y%m%d%H%M_'),
152+
)
153+
print('All models and logs will be saved to: {}'.format(temp_dir))
154+
134155
model = build_layerwise_model(input_shape, **pruning_params)
135-
pruned_model = train(model, x_train, y_train, x_test, y_test)
156+
pruned_model = train(
157+
model, x_train, y_train, x_test, y_test, output_dir=temp_dir
158+
)
136159

137160
# Write a model that has been pruned with 2x4 sparsity.
138161
converter = tf.lite.TFLiteConverter.from_keras_model(pruned_model)
139162
tflite_model = converter.convert()
140163

141-
tflite_model_path = '/tmp/mnist_2x4.tflite'
164+
tflite_model_dir = temp_dir
165+
tflite_model_path = os.path.join(tflite_model_dir, 'mnist_2x4.tflite')
142166
print('model is saved to {}'.format(tflite_model_path))
143167
with open(tflite_model_path, 'wb') as f:
144168
f.write(tflite_model)

0 commit comments

Comments
 (0)