TensorFlow Fundamentals · lesson 03/27
Pretty Tensor
Pretty Tensor was a Google library released around 2016 that let you write a network as a chain of method calls, with tensor shapes and variable scopes handled for you. It predates tf.keras and targets TensorFlow 1.x graph construction. It is unmaintained, and everything it did is now a first-class part of tf.keras — this lesson teaches the idea so you can read old code.
The idea
In TensorFlow 1.x you built a graph by hand: create variables with tf.get_variable, apply ops, and track names so that weights could be reused or restored. Pretty Tensor wrapped a tensor in an object and turned each layer into a method. The snippet below is TF 1.x only and does not run on TensorFlow 2:
import prettytensor as pt # legacy TF 1.x only; not compatible with TF 2.x
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
y = (pt.wrap(x)
.reshape([-1, 28, 28, 1])
.conv2d(5, 16, stride=1, activation_fn=tf.nn.relu)
.max_pool(2, 2)
.flatten()
.fully_connected(128, activation_fn=tf.nn.relu)
.softmax_classifier(10))The abstraction solved a real problem: no manual variable_scope juggling, no hand-written initializers, and shapes chained cleanly from one call to the next. Its weakness was leakage — anything unusual still needed raw graph code — and it never gained enough adoption to justify maintenance.
Worked example
That last line, softmax_classifier(10), does three jobs at once: it adds a fully connected layer with 10 outputs, applies a softmax, and computes the cross-entropy loss against supplied labels. The explicit TF 1.x equivalent was tf.nn.softmax_cross_entropy_with_logits plus a tf.reduce_mean. Fusing layer, activation, and loss into one call saved typing but hid which tensor was a logit and which was a probability — a persistent bug source the moment you wanted a different loss function.
In code
The modern replacement is a Keras model, which is what Pretty Tensor was reaching for:
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(28, 28, 1)),
tf.keras.layers.Conv2D(16, 5, activation="relu"),
tf.keras.layers.MaxPool2D(2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation="relu"),
tf.keras.layers.Dense(10),
])
model.compile(optimizer="adam",
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=["accuracy"])Status: Pretty Tensor is deprecated and unmaintained. The tensorflow.contrib namespace it lived alongside was removed in TensorFlow 2.0, and the prettytensor package is not compatible with TF 2.x. Do not start new work with it.
Check yourself
- What two problems did Pretty Tensor's chained API remove from TF 1.x graph code?
- Why does
softmax_classifier(layer plus softmax plus loss in one call) make debugging harder thanDense(10)withfrom_logits=True? - Name one thing
tf.kerasprovides that Pretty Tensor could not, and say why it matters.
Key takeaways
- Pretty Tensor was an early "layers as method calls" API and did not survive TF 2.0.
- Its design idea — composable layer objects that own their variables — lives on in
tf.keras.layers. - Legacy TF 1.x code is readable, but port it to Keras rather than run it.