-
Notifications
You must be signed in to change notification settings - Fork 9
TensorFlow 2x Migration Notes
This project has been migrated from TensorFlow 1.x to TensorFlow 2.x. This document explains the changes made and provides guidance for understanding the modernized codebase.
TensorFlow 1.x (Old):
import tensorflow as tf
# Low-level API
conv1 = tf.layers.conv2d(inputs, filters=64, kernel_size=11)
pool1 = tf.layers.max_pooling2d(conv1, pool_size=3)TensorFlow 2.x (Current):
import tensorflow as tf
# Keras API (integrated)
conv1 = tf.keras.layers.Conv2D(64, (11, 11))
pool1 = tf.keras.layers.MaxPooling2D(pool_size=(3, 3))Benefits:
- More intuitive, object-oriented API
- Better documentation and community support
- Easier to build complex models
- Consistent with Keras best practices
TensorFlow 1.x:
- Graph-based execution
- Requires session management
- Placeholders for inputs
- Difficult debugging
TensorFlow 2.x:
- Eager execution by default
- Immediate evaluation
- No sessions needed
- Easy debugging with Python debugger
Example:
# TensorFlow 2.x - immediate execution
x = tf.constant([1, 2, 3])
print(x) # Prints immediately, no session neededTensorFlow 1.x Pattern:
def alexnet(x, dropout):
conv1 = tf.layers.conv2d(x, filters=64, kernel_size=11)
# ... more layers
return outputTensorFlow 2.x Pattern (Current):
class AlexNetModel(tf.keras.Model):
def __init__(self):
super(AlexNetModel, self).__init__()
self.conv1 = tf.keras.layers.Conv2D(64, (11, 11))
# ... more layers
def call(self, inputs, training=False):
x = self.conv1(inputs)
# ... forward pass
return xBenefits:
- Encapsulation of model logic
- Automatic variable tracking
- Easy to save/load models
- Support for training/inference modes
TensorFlow 1.x:
x = tf.placeholder(tf.float32, shape=[None, 224, 224, 3])
y = tf.placeholder(tf.float32, shape=[None, 4])TensorFlow 2.x:
# Data passed directly to model
predictions = model(batch_images, training=True)Benefits:
- Simpler code
- No placeholder management
- Direct Python values
TensorFlow 1.x:
loss = tf.losses.categorical_crossentropy(labels, predictions)
optimizer = tf.train.AdamOptimizer(learning_rate)
train_op = optimizer.minimize(loss)TensorFlow 2.x:
with tf.GradientTape() as tape:
predictions = model(images, training=True)
loss = loss_fn(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))In this project:
- Uses
model.compile()andmodel.fit()for simplified training - Automatic gradient computation under the hood
Current implementation uses high-level API:
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.fit(train_dataset, epochs=100, validation_data=val_dataset)Benefits:
- Less boilerplate code
- Automatic metric tracking
- Built-in callbacks support
- TensorBoard integration
TensorFlow 1.x:
saver = tf.train.Saver()
saver.save(sess, 'model.ckpt')
saver.restore(sess, 'model.ckpt')TensorFlow 2.x:
# Save
model.save_weights('model.ckpt')
# Restore
model.load_weights('model.ckpt')In this project:
- Checkpoints saved in TensorFlow format
- Compatible with TensorFlow 2.x checkpoint system
- Extension:
.ckpt(not.cktp)
TensorFlow 1.x:
# Required session.run()
img = tf.image.decode_jpeg(img_bytes)
img_resized = tf.image.resize_image_with_crop_or_pad(img, 224, 224)
img_array = sess.run(img_resized)TensorFlow 2.x:
# Eager execution - immediate evaluation
img_bytes = tf.io.read_file(img_path)
img = tf.image.decode_jpeg(img_bytes, channels=3)
img = tf.image.convert_image_dtype(img, tf.float32)
img_resized = tf.image.resize_with_crop_or_pad(img, 224, 224)
img_array = img_resized.numpy() # Direct conversionChanges in Dataset.py:
-
tf.io.read_file()instead oftf.gfile.FastGFile() -
tf.image.resize_with_crop_or_pad()instead ofresize_image_with_crop_or_pad() - Direct
.numpy()conversion
TensorFlow 1.x:
bn = tf.layers.batch_normalization(conv, training=is_training)TensorFlow 2.x:
self.bn = tf.keras.layers.BatchNormalization()
# In call method:
x = self.bn(x, training=training)Important:
- Must pass
trainingargument - Different behavior in training vs. inference
- Affects moving average statistics
TensorFlow 1.x:
dropout = tf.layers.dropout(inputs, rate=0.5, training=is_training)TensorFlow 2.x:
self.dropout = tf.keras.layers.Dropout(0.5)
# In call method:
x = self.dropout(x, training=training)Note:
- Rate parameter is proportion to drop (not keep)
- Must pass
trainingflag for proper behavior
DO:
- Use
tf.keras.layers.*for layers - Use
tf.keras.Modelfor model classes - Pass
trainingargument to BatchNorm and Dropout - Use
model.compile()andmodel.fit()for training - Use eager execution debugging
DON'T:
- Use deprecated
tf.layers.* - Use
tf.Session() - Use
tf.placeholder() - Use
tf.train.Saver()(usemodel.save_weights()) - Use
feed_dict
Not maintained:
- Code will NOT work with TensorFlow 1.x
- Requires TensorFlow 2.0 or later
- Tested with TensorFlow 2.10+
To use TensorFlow 1.x code:
- Check git history for older versions
- Or use compatibility module:
tf.compat.v1(not recommended)
TensorFlow 2.x vs 1.x:
- Similar performance for most operations
- Eager execution slightly slower than graph mode
- Can use
@tf.functiondecorator for graph compilation
Current implementation:
- Uses Keras high-level API
- Performance is comparable to TF 1.x version
- GPU acceleration works as expected
TensorFlow 2.x:
- More aggressive garbage collection
- Better memory management
- Allow GPU memory growth by default
Error:
AttributeError: module 'tensorflow' has no attribute 'placeholder'
Cause: TF 1.x code in TF 2.x environment
Solution: Update to TF 2.x patterns shown above
Error:
AttributeError: module 'tensorflow' has no attribute 'Session'
Cause: Trying to use TF 1.x session
Solution: Remove session code, use eager execution
Error:
ValueError: Input 0 of layer is incompatible with the layer
Cause: Shape mismatches, different shape handling in TF 2.x
Solution:
- Use
model.build(input_shape=...)to define shapes - Verify input dimensions match expected format
# Good
model = tf.keras.Model(...)
layer = tf.keras.layers.Dense(128)
# Avoid
# TF 1.x style low-level operations# Good
model.compile(optimizer='adam', loss='categorical_crossentropy')
model.fit(train_data, epochs=10)
# Acceptable for custom training
with tf.GradientTape() as tape:
# custom training loopcallbacks = [
tf.keras.callbacks.ModelCheckpoint('model.ckpt'),
tf.keras.callbacks.TensorBoard(log_dir='logs'),
tf.keras.callbacks.EarlyStopping(patience=10)
]
model.fit(train_data, epochs=100, callbacks=callbacks)from tensorflow.keras import mixed_precision
policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_global_policy(policy)@tf.function
def train_step(images, labels):
with tf.GradientTape() as tape:
predictions = model(images, training=True)
loss = loss_fn(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss- TensorFlow: 2.10, 2.11, 2.12+
- Python: 3.7, 3.8, 3.9, 3.10
- NumPy: 1.21+
- scikit-learn: 1.0+
# Recommended installation
pip install tensorflow>=2.10.0
pip install numpy>=1.21.0
pip install scikit-learn>=1.0.0
pip install matplotlib>=3.3.0-
Modern Keras API: Uses
tf.kerasfor all layers and models - Eager Execution: No more sessions or placeholders
-
Model Subclassing:
tf.keras.Modelfor custom architectures -
Simplified Training:
compile()andfit()methods - Better Debugging: Python-native debugging support
- Performance: Comparable to TF 1.x with better usability
- Replaced
tf.layerswithtf.keras.layers - Removed sessions and placeholders
- Updated to
tf.keras.Modelsubclassing - Modified image processing to use eager execution
- Updated checkpoint saving/loading
- Ensured batch normalization has training flag
- Updated dropout to use rate (not keep_prob)
- Tested with TensorFlow 2.10+
- Verified GPU compatibility
- Updated documentation
The migration is complete and the code is fully compatible with TensorFlow 2.x!