Machine Learning with Python and TensorFlow - Practical Guide
Machine Learning with
ai-mlMachine Learning with Python and TensorFlow - Practical Guide
Machine Learning (ML) is revolutionizing the way we build software. Instead of programming explicit rules, we train models to recognize patterns in data. TensorFlow, created by Google, is one of the most powerful frameworks for building and deploying ML models. In this guide, we will walk through the theoretical foundations, TensorFlow architecture, practical implementations, and production deployment strategies.
Machine Learning Fundamentals#
Before diving into TensorFlow, it is essential to understand the three main paradigms of machine learning.
Supervised Learning#
In supervised learning, a model is trained on pairs of (input data, expected output). Based on these examples, it learns a function that maps inputs to outputs.
Common applications:
- Classification - image recognition, sentiment analysis, spam detection
- Regression - price prediction, weather forecasting, delivery time estimation
# Simple example: binary classification
import tensorflow as tf
from tensorflow import keras
# Training data: features and labels
X_train = [[0.1, 0.2], [0.4, 0.6], [0.8, 0.9], [0.3, 0.1]]
y_train = [0, 0, 1, 0] # 0 = class A, 1 = class B
model = keras.Sequential([
keras.layers.Dense(16, activation='relu', input_shape=(2,)),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=50, verbose=0)
Unsupervised Learning#
The model analyzes data without labels, searching for hidden patterns and structures.
Common applications:
- Clustering - customer segmentation, image segmentation
- Dimensionality reduction - visualizing high-dimensional data (PCA, t-SNE)
- Anomaly detection - fraud identification, system monitoring
# Autoencoder for anomaly detection
encoder = keras.Sequential([
keras.layers.Dense(64, activation='relu', input_shape=(100,)),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(16, activation='relu') # Bottleneck
])
decoder = keras.Sequential([
keras.layers.Dense(32, activation='relu', input_shape=(16,)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(100, activation='sigmoid')
])
autoencoder_input = keras.layers.Input(shape=(100,))
encoded = encoder(autoencoder_input)
decoded = decoder(encoded)
autoencoder = keras.Model(autoencoder_input, decoded)
autoencoder.compile(optimizer='adam', loss='mse')
Reinforcement Learning#
An agent learns to make decisions in an environment by receiving rewards for good actions and penalties for bad ones. This paradigm is behind the success of AlphaGo, robotics, and autonomous vehicles.
Key concepts:
- Agent - the decision-making entity
- Environment - the world in which the agent operates
- Policy - the agent's decision-making strategy
- Reward - feedback signal from the environment
TensorFlow and Keras Architecture#
TensorFlow is a comprehensive ecosystem for machine learning. Keras, the high-level API of TensorFlow, significantly simplifies model construction.
Tensors - The Core Data Structure#
A tensor is a multi-dimensional numerical array. The name TensorFlow comes from the flow of tensors through a computational graph.
import tensorflow as tf
# Scalar (0-dimensional tensor)
scalar = tf.constant(42)
print(scalar.shape) # ()
# Vector (1-dimensional tensor)
vector = tf.constant([1.0, 2.0, 3.0])
print(vector.shape) # (3,)
# Matrix (2-dimensional tensor)
matrix = tf.constant([[1, 2], [3, 4], [5, 6]])
print(matrix.shape) # (3, 2)
# 3-dimensional tensor (e.g., batch of RGB images)
images = tf.random.normal([32, 224, 224, 3])
print(images.shape) # (32, 224, 224, 3)
# Tensor operations
a = tf.constant([[1, 2], [3, 4]])
b = tf.constant([[5, 6], [7, 8]])
print(tf.add(a, b)) # Element-wise addition
print(tf.matmul(a, b)) # Matrix multiplication
print(tf.reduce_mean(a)) # Mean
Layers#
Layers are the fundamental building blocks of models. Each layer performs a transformation on the input data.
# Most common layers in Keras
# Dense - fully connected layer
dense = keras.layers.Dense(128, activation='relu')
# Conv2D - 2D convolutional layer
conv = keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu', padding='same')
# LSTM - Long Short-Term Memory
lstm = keras.layers.LSTM(256, return_sequences=True)
# Dropout - regularization (prevents overfitting)
dropout = keras.layers.Dropout(0.3)
# BatchNormalization - batch normalization
bn = keras.layers.BatchNormalization()
# Embedding - maps indices to dense vectors
embedding = keras.layers.Embedding(input_dim=10000, output_dim=128)
Models - Sequential vs Functional API#
Keras offers two main approaches to building models.
# 1. Sequential API - simple stack of layers
model_sequential = keras.Sequential([
keras.layers.Dense(256, activation='relu', input_shape=(784,)),
keras.layers.Dropout(0.3),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
# 2. Functional API - flexible graphs (multiple inputs/outputs, skip connections)
inputs = keras.layers.Input(shape=(784,))
x = keras.layers.Dense(256, activation='relu')(inputs)
x = keras.layers.Dropout(0.3)(x)
# Skip connection (residual)
skip = keras.layers.Dense(128)(inputs)
x = keras.layers.Dense(128, activation='relu')(x)
x = keras.layers.Add()([x, skip])
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(10, activation='softmax')(x)
model_functional = keras.Model(inputs=inputs, outputs=outputs)
The Training Loop#
The model training process consists of several stages: compilation, training, and evaluation.
# Model compilation
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# Callbacks - monitoring and controlling training
callbacks = [
keras.callbacks.EarlyStopping(
monitor='val_loss',
patience=5,
restore_best_weights=True
),
keras.callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.5,
patience=3
),
keras.callbacks.ModelCheckpoint(
filepath='best_model.keras',
monitor='val_accuracy',
save_best_only=True
),
keras.callbacks.TensorBoard(log_dir='./logs')
]
# Training
history = model.fit(
X_train, y_train,
epochs=100,
batch_size=32,
validation_split=0.2,
callbacks=callbacks
)
# Evaluation on test data
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"Test accuracy: {test_acc:.4f}")
Common Neural Network Architectures#
CNN - Convolutional Neural Networks#
Convolutional networks dominate image processing. Convolutional filters automatically learn to detect visual features at different levels of abstraction.
def build_cnn_classifier(input_shape=(224, 224, 3), num_classes=10):
"""Build a CNN image classifier."""
model = keras.Sequential([
# Convolutional block 1
keras.layers.Conv2D(32, (3, 3), activation='relu',
padding='same', input_shape=input_shape),
keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
# Convolutional block 2
keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
# Convolutional block 3
keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.3),
# Classifier head
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Usage
cnn_model = build_cnn_classifier(num_classes=10)
cnn_model.summary()
Key CNN layers:
- Conv2D - detects local features (edges, textures, shapes)
- MaxPooling2D - reduces spatial dimensions, increases receptive field
- GlobalAveragePooling2D - aggregates feature maps into a vector
- BatchNormalization - stabilizes training, faster convergence
RNN - Recurrent Neural Networks#
Recurrent networks process sequential data such as text, time series, and audio. LSTM and GRU architectures solve the vanishing gradient problem.
def build_text_classifier(vocab_size=20000, max_length=200, num_classes=5):
"""Text classifier with bidirectional LSTM."""
model = keras.Sequential([
keras.layers.Embedding(vocab_size, 128, input_length=max_length),
keras.layers.Bidirectional(
keras.layers.LSTM(64, return_sequences=True)
),
keras.layers.Bidirectional(keras.layers.LSTM(32)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Text generation with RNN
def build_text_generator(vocab_size, seq_length):
"""Character-level text generation model."""
model = keras.Sequential([
keras.layers.Embedding(vocab_size, 256, input_length=seq_length),
keras.layers.LSTM(512, return_sequences=True),
keras.layers.LSTM(512),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dense(vocab_size, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
return model
Transformer - A Revolution in NLP and Beyond#
The Transformer architecture, based on the self-attention mechanism, has revolutionized NLP and is increasingly being adopted in computer vision as well.
class TransformerBlock(keras.layers.Layer):
"""Transformer block with Multi-Head Attention."""
def __init__(self, embed_dim, num_heads, ff_dim, dropout_rate=0.1):
super().__init__()
self.attention = keras.layers.MultiHeadAttention(
num_heads=num_heads,
key_dim=embed_dim // num_heads
)
self.ffn = keras.Sequential([
keras.layers.Dense(ff_dim, activation='gelu'),
keras.layers.Dense(embed_dim)
])
self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)
self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)
self.dropout1 = keras.layers.Dropout(dropout_rate)
self.dropout2 = keras.layers.Dropout(dropout_rate)
def call(self, inputs, training=False):
# Multi-Head Self-Attention + Residual
attn_output = self.attention(inputs, inputs)
attn_output = self.dropout1(attn_output, training=training)
out1 = self.layernorm1(inputs + attn_output)
# Feed-Forward Network + Residual
ffn_output = self.ffn(out1)
ffn_output = self.dropout2(ffn_output, training=training)
return self.layernorm2(out1 + ffn_output)
def build_transformer_classifier(
vocab_size=20000, max_length=200, embed_dim=128,
num_heads=4, ff_dim=256, num_blocks=2, num_classes=5
):
"""Transformer-based text classifier."""
inputs = keras.layers.Input(shape=(max_length,))
x = keras.layers.Embedding(vocab_size, embed_dim)(inputs)
# Positional encoding (simple - learned)
positions = keras.layers.Embedding(max_length, embed_dim)(
tf.range(max_length)
)
x = x + positions
for _ in range(num_blocks):
x = TransformerBlock(embed_dim, num_heads, ff_dim)(x)
x = keras.layers.GlobalAveragePooling1D()(x)
x = keras.layers.Dense(64, activation='relu')(x)
x = keras.layers.Dropout(0.3)(x)
outputs = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-4),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
Transfer Learning - The Power of Pretrained Models#
Transfer learning allows you to leverage knowledge from models trained on massive datasets. Instead of training from scratch, you fine-tune a pretrained model for your specific task.
def build_transfer_learning_model(num_classes, fine_tune_at=100):
"""
Image classifier with transfer learning (EfficientNetV2).
Only the top layers are trained while the base is frozen.
"""
# Pretrained model as feature extractor
base_model = keras.applications.EfficientNetV2B0(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# Freeze base layers
base_model.trainable = False
# Build model
model = keras.Sequential([
base_model,
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dropout(0.3),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-3),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model, base_model
def fine_tune_model(model, base_model, fine_tune_at=100):
"""
Stage 2: Fine-tuning - unfreeze top layers of the base model.
Use a lower learning rate to avoid destroying pretrained weights.
"""
base_model.trainable = True
for layer in base_model.layers[:fine_tune_at]:
layer.trainable = False
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Usage
model, base_model = build_transfer_learning_model(num_classes=5)
# Stage 1: Train classifier (frozen base)
model.fit(train_ds, epochs=10, validation_data=val_ds)
# Stage 2: Fine-tuning (unfrozen top layers)
model = fine_tune_model(model, base_model, fine_tune_at=100)
model.fit(train_ds, epochs=10, validation_data=val_ds)
Popular pretrained models in TensorFlow:
- EfficientNetV2 - best accuracy-efficiency trade-off for images
- ResNet50/101 - classic architecture with residual connections
- MobileNetV3 - optimized for mobile devices
- BERT/DistilBERT - pretrained language models (via TF Hub or Hugging Face)
Practical Example: Image Classification#
Let us build a complete image classification pipeline with data augmentation and transfer learning.
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
# 1. Loading and preparing data
BATCH_SIZE = 32
IMG_SIZE = (224, 224)
train_ds = keras.utils.image_dataset_from_directory(
'dataset/train',
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int',
shuffle=True,
seed=42
)
val_ds = keras.utils.image_dataset_from_directory(
'dataset/validation',
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int'
)
class_names = train_ds.class_names
num_classes = len(class_names)
# 2. Data augmentation
data_augmentation = keras.Sequential([
keras.layers.RandomFlip('horizontal'),
keras.layers.RandomRotation(0.2),
keras.layers.RandomZoom(0.2),
keras.layers.RandomContrast(0.2),
keras.layers.RandomTranslation(0.1, 0.1)
])
# 3. Data pipeline optimization
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 4. Building the model with transfer learning
base_model = keras.applications.EfficientNetV2B0(
weights='imagenet', include_top=False, input_shape=(*IMG_SIZE, 3)
)
base_model.trainable = False
inputs = keras.layers.Input(shape=(*IMG_SIZE, 3))
x = data_augmentation(inputs)
x = keras.applications.efficientnet_v2.preprocess_input(x)
x = base_model(x, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(256, activation='relu')(x)
x = keras.layers.Dropout(0.3)(x)
outputs = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs, outputs)
# 5. Training
model.compile(
optimizer=keras.optimizers.Adam(1e-3),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
train_ds, epochs=20, validation_data=val_ds,
callbacks=[
keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),
keras.callbacks.ReduceLROnPlateau(patience=3, factor=0.5)
]
)
# 6. Visualizing results
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(history.history['accuracy'], label='Train')
ax1.plot(history.history['val_accuracy'], label='Val')
ax1.set_title('Accuracy')
ax1.legend()
ax2.plot(history.history['loss'], label='Train')
ax2.plot(history.history['val_loss'], label='Val')
ax2.set_title('Loss')
ax2.legend()
plt.savefig('training_history.png', dpi=150)
plt.show()
Practical Example: Sentiment Analysis (NLP)#
import tensorflow as tf
from tensorflow import keras
import tensorflow_datasets as tfds
# 1. Loading the IMDB Reviews dataset
(train_data, test_data), info = tfds.load(
'imdb_reviews',
split=['train', 'test'],
as_supervised=True,
with_info=True
)
# 2. Tokenization and data preparation
VOCAB_SIZE = 20000
MAX_LENGTH = 300
# TextVectorization - built-in tokenization layer
text_vectorizer = keras.layers.TextVectorization(
max_tokens=VOCAB_SIZE,
output_mode='int',
output_sequence_length=MAX_LENGTH
)
# Adapt to training data
train_texts = train_data.map(lambda text, label: text)
text_vectorizer.adapt(train_texts)
# 3. Preparing datasets
def preprocess(text, label):
text = text_vectorizer(tf.expand_dims(text, -1))
text = tf.squeeze(text, axis=0)
return text, label
BATCH_SIZE = 64
AUTOTUNE = tf.data.AUTOTUNE
train_ds = (train_data
.map(preprocess, num_parallel_calls=AUTOTUNE)
.shuffle(10000)
.batch(BATCH_SIZE)
.prefetch(AUTOTUNE))
test_ds = (test_data
.map(preprocess, num_parallel_calls=AUTOTUNE)
.batch(BATCH_SIZE)
.prefetch(AUTOTUNE))
# 4. Model: 1D CNN + Bidirectional LSTM
model = keras.Sequential([
keras.layers.Embedding(VOCAB_SIZE, 128, input_length=MAX_LENGTH),
keras.layers.Conv1D(128, 5, activation='relu', padding='same'),
keras.layers.MaxPooling1D(2),
keras.layers.Bidirectional(keras.layers.LSTM(64)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
# 5. Training
history = model.fit(
train_ds, epochs=10, validation_data=test_ds,
callbacks=[keras.callbacks.EarlyStopping(patience=3)]
)
# 6. Prediction
def predict_sentiment(texts):
"""Predict sentiment for a list of texts."""
vectorized = text_vectorizer(tf.constant(texts))
predictions = model.predict(vectorized)
for text, pred in zip(texts, predictions):
sentiment = "Positive" if pred[0] > 0.5 else "Negative"
print(f"{sentiment} ({pred[0]:.2%}): {text[:80]}...")
predict_sentiment([
"This movie was absolutely fantastic! Great acting and storyline.",
"Terrible film. Waste of time. The plot made no sense at all."
])
TensorFlow.js - Machine Learning in the Browser#
TensorFlow.js allows you to run ML models directly in the browser or in Node.js, enabling client-side inference without server communication.
// Installation: npm install @tensorflow/tfjs
import * as tf from '@tensorflow/tfjs';
// Loading a pretrained image classification model
async function classifyImage(imageElement) {
// Load MobileNet model
const model = await tf.loadGraphModel(
'https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/classification/5/default/1',
{ fromTFHub: true }
);
// Process image into a tensor
const tensor = tf.browser.fromPixels(imageElement)
.resizeBilinear([224, 224])
.expandDims(0)
.div(255.0);
// Inference
const predictions = model.predict(tensor);
const topK = tf.topk(predictions, 5);
const indices = await topK.indices.data();
const values = await topK.values.data();
// Free memory
tensor.dispose();
predictions.dispose();
return indices.map((idx, i) => ({
classIndex: idx,
confidence: values[i]
}));
}
// Converting a Keras model to TensorFlow.js
// In Python:
// import tensorflowjs as tfjs
// tfjs.converters.save_keras_model(model, 'tfjs_model/')
Advantages of TensorFlow.js:
- Privacy - data never leaves the user's device
- Low latency - no round-trip to the server
- Offline - the model works without internet
- Scaling - inference on user devices instead of expensive GPU servers
Production Model Deployment#
TensorFlow Serving#
TensorFlow Serving is a high-performance system for serving models in production.
# Save model in SavedModel format
model.save('saved_model/image_classifier/1')
# Directory structure:
# saved_model/
# image_classifier/
# 1/ <- model version
# saved_model.pb
# variables/
# docker-compose.yml - TensorFlow Serving
version: "3.8"
services:
tf-serving:
image: tensorflow/serving:latest
ports:
- "8501:8501" # REST API
- "8500:8500" # gRPC
volumes:
- ./saved_model:/models
environment:
MODEL_NAME: image_classifier
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# Calling the REST API
import requests
import numpy as np
import json
def predict_via_serving(image_array):
"""Send a prediction request to TensorFlow Serving."""
url = "http://localhost:8501/v1/models/image_classifier:predict"
payload = {
"instances": image_array.tolist()
}
response = requests.post(url, json=payload)
predictions = response.json()['predictions']
return np.array(predictions)
# Batch prediction
images = np.random.rand(8, 224, 224, 3).astype(np.float32)
results = predict_via_serving(images)
print(f"Predictions shape: {results.shape}")
Exporting to ONNX#
ONNX (Open Neural Network Exchange) is an open format that allows running models across different runtimes.
# TensorFlow -> ONNX conversion
# pip install tf2onnx
import tf2onnx
import onnxruntime as ort
# Conversion
spec = (tf.TensorSpec((None, 224, 224, 3), tf.float32, name="input"),)
model_proto, _ = tf2onnx.convert.from_keras(
model, input_signature=spec, output_path="model.onnx"
)
# Inference with ONNX Runtime (faster than TF for CPU)
session = ort.InferenceSession("model.onnx")
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
result = session.run(
[output_name],
{input_name: np.random.rand(1, 224, 224, 3).astype(np.float32)}
)
print(f"ONNX prediction: {result[0]}")
TensorFlow Lite - Models on Mobile Devices#
# Conversion to TFLite with quantization
converter = tf.lite.TFLiteConverter.from_saved_model('saved_model/image_classifier/1')
# Post-training quantization (reduces model size by 4x)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# Optional: full int8 quantization (requires calibration)
def representative_dataset():
for i in range(100):
yield [np.random.rand(1, 224, 224, 3).astype(np.float32)]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_types = [tf.float16]
tflite_model = converter.convert()
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
print(f"TFLite model size: {len(tflite_model) / 1024 / 1024:.2f} MB")
TensorFlow vs PyTorch - Comparison#
The choice of framework depends on the project context. Here are the key differences:
| Aspect | TensorFlow | PyTorch | |--------|-----------|---------| | Execution mode | Eager + Graph (tf.function) | Eager by default, TorchScript for graph | | High-level API | Keras (built-in) | torch.nn (built-in), Lightning | | Deployment | TF Serving, TFLite, TF.js | TorchServe, ONNX, ExecuTorch | | Mobile/Edge | TFLite (mature) | ExecuTorch (newer) | | Browser | TensorFlow.js (mature) | ONNX.js / Transformers.js | | Ecosystem | TFX, TF Hub, TF Data | Hugging Face, PyTorch Ecosystem | | Research popularity | Declining | Dominant | | Production popularity | Still strong | Growing | | Debugging | Harder (graph mode) | Easier (Pythonic) | | Documentation | Extensive but scattered | Consistent, well-organized |
When to choose TensorFlow:
- Multi-platform deployment (web, mobile, embedded)
- Existing TFX infrastructure in the organization
- Need for TensorFlow.js for browser inference
- Production projects requiring TF Serving
When to choose PyTorch:
- Scientific research and prototyping
- Working with Hugging Face models
- Preference for Pythonic API and easy debugging
- Projects requiring latest architectures from research papers
Best Practices in ML Projects#
1. Experiment Management#
import mlflow
# Logging experiments with MLflow
mlflow.set_experiment("image-classification")
with mlflow.start_run(run_name="efficientnet-v2-finetune"):
# Log hyperparameters
mlflow.log_params({
"learning_rate": 1e-3,
"batch_size": 32,
"epochs": 20,
"model": "EfficientNetV2B0",
"fine_tune_layers": 50
})
# Training
history = model.fit(train_ds, epochs=20, validation_data=val_ds)
# Log metrics
mlflow.log_metrics({
"final_accuracy": history.history['accuracy'][-1],
"final_val_accuracy": history.history['val_accuracy'][-1],
"final_loss": history.history['loss'][-1]
})
# Log model
mlflow.keras.log_model(model, "model")
2. Data Versioning#
# DVC (Data Version Control) - tracking data changes
# dvc init
# dvc add dataset/
# git add dataset.dvc .gitignore
# git commit -m "Add training dataset v1"
# dvc push
3. Reproducibility#
import random
import numpy as np
def set_seeds(seed=42):
"""Set seeds for reproducibility."""
random.seed(seed)
np.random.seed(seed)
tf.random.set_seed(seed)
# Deterministic operations (slower but reproducible)
tf.config.experimental.enable_op_determinism()
set_seeds(42)
Conclusion#
TensorFlow combined with Keras provides a complete ecosystem for building, training, and deploying Machine Learning models. From simple Dense networks, through advanced CNN, RNN, and Transformer architectures, to deployment on servers, mobile devices, and in browsers, TensorFlow delivers tools at every stage of the ML model lifecycle.
Key takeaways:
- Start with transfer learning - pretrained models deliver excellent results with minimal data
- Optimize data pipelines -
tf.datawith prefetch and cache significantly accelerates training - Track experiments - MLflow or TensorBoard is a necessity in serious projects
- Test deployment early - TF Serving, TFLite, and TF.js each have different constraints
Need to integrate Machine Learning into your application? The MDS Software Solutions Group team specializes in building intelligent solutions powered by AI and ML. From image classification, through text analysis, to recommendation systems - we will help you go from prototype to production. Contact us and let's discuss your project!
Team of programming experts specializing in modern web technologies.