When you start your deep learning journey, the first major choice you'll face is which framework to use. The two dominant players are TensorFlow (usually via its high-level API, Keras) and PyTorch.

FeatureKeras (TensorFlow)PyTorchPhilosophyDeclarative & User-Friendly. High-level, modular, and easy to use. Great for rapid prototyping and production.Imperative & Flexible. Lower-level, more Pythonic, and offers fine-grained control. A favorite in research.API Style"Lego-like." You define a Sequential or Functional model by stacking layers.Object-oriented. You define your model as a Python class that inherits from nn.Module.Training LoopAbstracted away. The powerful model.fit() method handles the entire training process for you.Explicit & Manual. You must write the training loop yourself (iterate over data, zero gradients, backpropagate, update weights).EcosystemExcellent production tools like TensorFlow Serving, TensorFlow Lite (for mobile), and TensorFlow.js (for browsers).Strong and growing ecosystem, particularly in the research community. Integrates well with the Python scientific stack.

Export to Sheets

Let's build the same simple neural network for classifying MNIST handwritten digits in both frameworks to see the difference in practice.

1. Keras (TensorFlow) Quickstart

Keras is all about simplicity and speed of development. The code is concise and readable.

Python


import tensorflow as tf
from tensorflow import keras

# 1. Load Data
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Normalize pixel values to be between 0 and 1
x_train, x_test = x_train / 255.0, x_test / 255.0


# 2. Define the Model
# The Sequential model is a linear stack of layers.
model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)), # Flattens the 28x28 image into a 784 vector
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dropout(0.2),
    keras.layers.Dense(10, activation='softmax') # Output layer for 10 classes
])

# 3. Compile the Model
# This step configures the model for training.
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 4. Train the Model
# The .fit() method handles the entire training loop.
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))

# 5. Evaluate the Model
print("\nEvaluating model on test data:")
model.evaluate(x_test, y_test, verbose=2)

2. PyTorch Quickstart

PyTorch gives you more explicit control. You define the model architecture and the training process step-by-step.

Python


import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 1. Load Data
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 2. Define the Model
# The model is a class that inherits from nn.Module.
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(28*28, 128)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(0.2)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x): # The forward pass logic
        x = self.flatten(x)
        x = self.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

model = Net()

# 3. Define Loss and Optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 4. Train the Model (The Manual Loop)
epochs = 5
for epoch in range(epochs):
    for images, labels in train_loader:
        optimizer.zero_grad()      # Clear previous gradients
        outputs = model(images)    # Forward pass
        loss = criterion(outputs, labels) # Calculate loss
        loss.backward()            # Backpropagation
        optimizer.step()           # Update weights
    print(f"Epoch {epoch+1}/{epochs}, Loss: {loss.item():.4f}")

# 5. Evaluate the Model (Also a manual loop)
# ... code to iterate through test_l