In the two previous lessons you built the same gradient and the same MNIST network in TensorFlow/Keras and in PyTorch, and confirmed that they reach the same result. Now comes the question everyone asks sooner or later — and that the TecnoMarket team has written on their whiteboard: which one should you choose? This lesson answers honestly: no camps, just criteria. We will compare philosophy, learning curve, debugging, ecosystems and real-world adoption; we will put the same mini-model side by side; we will briefly introduce the other players in the landscape (JAX, Hugging Face, ONNX); and we will close with a practical decision guide. Spoiler for the ending: the choice matters less than it seems, because what is valuable — the concepts you have spent five modules learning — is transferable.
Contents
- Two philosophies, one goal
- Learning curve and debugging
- Ecosystems: what surrounds each framework
- Adoption: industry vs. research
- Performance: the practical tie
- Detailed comparison table
- The same model, side by side
- Other players in the landscape
- Decision guide: for you and for TecnoMarket
Two philosophies, one goal
If we had to sum up each framework in one sentence:
- TensorFlow/Keras: "the common case should be trivial". Optimized for the standard path: define, compile, train, deploy. Born at Google (2015) with large-scale production in mind.
- PyTorch: "everything should be visible". Optimized for experimentation: every training step is in your code, ready to modify. Born at Meta (2017) with research in mind.
Neither philosophy is superior; they answer different needs. The course analogy: Keras is the appliance with preset programs; PyTorch is the professional kitchen where you control every burner. For 90% of dishes the result is the same; for the experimental 10% (a GAN with a custom loop like the one in 05-01, an exotic loss, a freshly published paper), the professional kitchen is a blessing — although Keras also lets you drop down to that level with GradientTape, as you saw in 06-01, it is simply not its default path.
Learning curve and debugging
Learning curve. Keras wins in the first hours: your first network in 02-05 was five lines (Sequential, compile, fit). In PyTorch that same network requires understanding nn.Module, DataLoader and the five-step loop before you see a single result. But the curves cross: the PyTorch user understands what is going on sooner (because they wrote it), while the Keras user can take longer to escape the "magic" of fit(). This course deliberately followed that order: first productivity with Keras, then transparency with PyTorch.
Debugging. Here PyTorch has a structural advantage thanks to define-by-run: the forward pass is normal Python code, so you can put print(x.shape) inside forward(), step through with your IDE's debugger, and inspect any intermediate tensor. In TensorFlow, eager mode (the one you used in 06-01) allows the same, but when Keras compiles the model into a graph for speed (tf.function, which fit() applies by default), errors arrive wrapped in long, less readable tracebacks. Practical translation: in Keras you debug mostly by reading messages; in PyTorch you debug by executing line by line.
Ecosystems: what surrounds each framework
A framework is not just its API: it is everything built around it.
The TensorFlow ecosystem: strong at deployment
| Piece | What it is for |
|---|---|
| TFLite (LiteRT) | Running models on phones and embedded devices (Android, iOS, microcontrollers) |
| TF.js | Running and training models in the browser, in JavaScript |
| TF Serving | High-performance model server for production |
| TFX | Complete production ML pipelines (data validation, training, deployment) |
| TensorBoard | Training visualization (you will use it in 06-04; it also works with PyTorch) |
The common thread: bringing the model to where the user is. We will cover deployment in detail in 06-05.
The PyTorch ecosystem: strong at models and research
| Piece | What it is for |
|---|---|
| torchvision / torchaudio / torchtext | Datasets, transforms and pretrained models per domain |
| transformers (Hugging Face) | Thousands of pretrained models (BERT, GPT and family — the ones from 05-05) ready for fine-tuning |
| PyTorch Lightning | Structures the explicit training loop (recovers part of fit()'s convenience) |
| TorchServe | Model server (equivalent to TF Serving) |
The common thread: immediate access to the latest. When a paper comes out, its code is usually PyTorch; when an open language model comes out, it is on Hugging Face. Important note: Hugging Face also supports TensorFlow for many models, but its first-class citizen is PyTorch.
Adoption: industry vs. research
The broad strokes, without percentages that go stale:
- Research: PyTorch has clearly dominated since ~2020. At the major conferences (NeurIPS, ICML, CVPR), the vast majority of published implementations are PyTorch. If your job is reproducing papers, PyTorch is nearly mandatory.
- Industry: much more evenly split. TensorFlow has an enormous installed base (especially at companies that built their infrastructure between 2016 and 2020, and on mobile/edge thanks to TFLite), while PyTorch grows strongly, pushed by the LLM boom and Hugging Face.
- Job postings: most deep learning positions cite both, or "either one". Knowing both — like you now — is the most comfortable position.
Performance: the practical tie
Which trains faster? Honest answer: a practical tie. Both delegate the heavy lifting to the same NVIDIA libraries (cuDNN) for GPUs; both compile graphs to optimize (TF with tf.function, PyTorch with torch.compile); and benchmarks flip back and forth depending on model, hardware and version. The typical differences (±10%) are smaller than the effect of a good data pipeline (the prefetch from 06-01) or a sensible batch size. Conclusion: do not choose a framework for speed; choose for your team, the ecosystem and the model's destination.
Detailed comparison table
| Criterion | TensorFlow / Keras | PyTorch |
|---|---|---|
| Creator and year | Google, 2015 | Meta, 2017 |
| Philosophy | High-level by default, production | Explicit by default, research |
| Model definition | Sequential / functional / subclassing | Subclassing (nn.Module) as the norm |
| Training loop | Automatic fit() (GradientTape if you want control) |
Always explicit (Lightning if you want structure) |
| Initial curve | Very gentle (5 lines and you train) | More demanding (5-step loop) |
| Debugging | Good in eager; harsh tracebacks in graph mode | Excellent: pure Python, standard debugger |
| Data | tf.data (map/shuffle/batch/prefetch) |
Dataset + DataLoader |
| Mobile / browser | TFLite, TF.js (very mature) | ExecuTorch (more recent) |
| Serving in production | TF Serving, TFX | TorchServe, generic servers (FastAPI) |
| Pretrained models | Keras Applications (the MobileNetV2 from 05-03), TF Hub | torchvision, Hugging Face (huge) |
| Research community | A minority today | Dominant |
| Enterprise installed base | Very large | Large and growing |
| Performance | Equivalent | Equivalent |
| What you already did in the course | All of modules 2–5 plus 06-01 | 06-02 (MNIST rewritten) |
The same model, side by side
You already saw the snippets in 06-01 and 06-02; here they are condensed for a single glance. The 784-128-64-10 network from 02-05:
# ---------- KERAS ----------
from tensorflow import keras
model = keras.Sequential([
keras.layers.Dense(128, activation="relu"),
keras.layers.Dense(64, activation="relu"),
keras.layers.Dense(10, activation="softmax"),
])
model.compile(optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
model.fit(x_train, y_train, epochs=5, batch_size=32)# ---------- PYTORCH ----------
import torch
from torch import nn
class MNISTNet(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential( # yes, PyTorch also has Sequential
nn.Linear(784, 128), nn.ReLU(),
nn.Linear(128, 64), nn.ReLU(),
nn.Linear(64, 10)) # logits, no softmax (see 06-02)
def forward(self, x):
return self.net(x)
model = MNISTNet()
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
for epoch in range(5):
for x, y in train_loader:
logits = model(x.view(x.size(0), -1))
loss = loss_fn(logits, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()Reading the side-by-side:
- The model definition is almost a carbon copy (note
nn.Sequential: for linear stacks, PyTorch also offers a shortcut). - The difference is in the training: 3 lines (
compile+fit) versus ~10 (the loop). That is, in essence, the whole framework debate condensed onto one screen. - And the two "detail" differences you already know: softmax on the output (Keras) vs. raw logits (PyTorch), and the explicit flatten.
Other players in the landscape
The world does not end at TF and PyTorch. Three names worth placing on the map:
| Player | What it is | When you will run into it |
|---|---|---|
| JAX | Google library: numpy + automatic differentiation + XLA compilation. Pure functional style | Cutting-edge research and giant models; Keras 3 can use it as a backend |
| Hugging Face | Not a competitor: it is an upper layer with thousands of pretrained models (the transformers from 05-05) and datasets, on top of PyTorch (mainly) and TF | As soon as you want to use a BERT/GPT without training it yourself (you will in 07-05) |
| ONNX | Not a framework: it is a model interchange format. You export from PyTorch, run on any compatible runtime | As a bridge between frameworks and toward production; we will use it in 06-05 |
Final mention: Keras 3 is now multi-backend — the same Keras code can run on TensorFlow, JAX or even PyTorch. The border between frameworks blurs year after year, one more reason not to obsess over the choice.
Decision guide: for you and for TecnoMarket
Questions that actually decide (in order of weight):
- What does your team / your company use? The best framework is the one used by the people who will help you and the code you will inherit.
- Will you start from pretrained models from recent research (LLMs, diffusion, the latest from Hugging Face)? → PyTorch will give you less friction.
- Is the destination mobile, browser or edge? → TensorFlow's TFLite/TF.js ecosystem remains the most mature.
- Do you prioritize fast prototyping of standard workflows (classification, regression, transfer learning like 05-03)? → Keras is hard to beat.
- Do you need custom training loops (GANs like 05-01, multiple losses, research)? → PyTorch's explicit style feels more natural.
TecnoMarket's decision. The data team debates it and decides:
- Keras/TensorFlow as the production base: their current systems (the photo classifier with MobileNetV2 from 05-03, the review classifier from 04-03, the demand forecasting from 04-04) are already written in Keras, they work, and the plan to bring the product classifier to the warehouse staff's mobile app fits TFLite.
- PyTorch as the exploration tool: the project to generate promotional descriptions and images (module 7) will start from Hugging Face models, and there PyTorch is the short path.
- Team rule: every model that goes to production is validated against the same frozen test set, whatever the framework — and ONNX is noted down as the bridge if a model ever needs to move from one world to the other (we will see it in 06-05).
It is a pragmatic decision, not a religious one. And it is the same one we recommend to you: go deep in one, stay functional in the other.
Common Mistakes and Tips
- Choosing by headlines ("X is dead", "everyone uses Y"): both frameworks have active development, enormous communities and years of future ahead. Decide based on your context, not on Twitter.
- Switching frameworks mid-project: the cost of migrating (rewriting, revalidating, retraining the team) almost never pays off against a marginal advantage. Finish with what you started; migrate, if at all, between projects.
- Learning the framework instead of the concepts: whoever understands backprop (02-03), regularization (05-04) or attention (05-05) switches frameworks in days; whoever only memorized APIs starts from scratch. Invest in concepts.
- Comparing performance with other people's benchmarks: if you truly care about speed, measure your model with your data on your hardware. Generic benchmarks do not capture your case.
- Tip: reading code in the "other" framework is a great exercise. With the equivalence tables from 06-02 you can mentally translate almost any example, and that doubles the documentation and tutorials within your reach.
Exercises
Exercise 1: mental translation
Without running anything, match each Keras element with its PyTorch equivalent: (a) model.fit(...), (b) Dense(64, activation="relu"), (c) tf.data.Dataset with shuffle().batch(), (d) model.evaluate(...), (e) compile(optimizer="adam", loss=...).
Exercise 2: reasoned recommendation
Three scenarios; for each, recommend a framework and justify it in 2-3 lines using the decision guide criteria: (1) a startup wants to detect manufacturing defects with an Android tablet camera inside the factory itself, offline; (2) a university group wants to modify the attention mechanism of a transformer published last month; (3) TecnoMarket wants a standard support-ticket classifier in 2 weeks, with a team that has only taken this course.
Exercise 3: reading the other language
This PyTorch snippet reaches you from a paper. Describe it in "Keras language": what model is it and how would you write it with Sequential?
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(20, 8)
self.drop = nn.Dropout(0.3)
self.fc2 = nn.Linear(8, 1)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.drop(x)
return self.fc2(x)Solutions
Solution 1:
- (a)
fit()→ the complete explicit loop:for epoch → forward → loss → zero_grad → backward → step. - (b)
Dense(64, activation="relu")→nn.Linear(in_features, 64)followed bynn.ReLU()(in PyTorch the input is explicit and the activation goes separately). - (c)
tf.datawithshuffle().batch()→DataLoader(dataset, batch_size=..., shuffle=True). - (d)
evaluate()→ a loop withmodel.eval()+torch.no_grad()computing metrics by hand. - (e)
compile(...)→ creatingtorch.optim.Adam(model.parameters())and the loss function (nn.CrossEntropyLoss(), etc.) as standalone objects.
Solution 2:
- TensorFlow/Keras: an offline edge/mobile destination → TFLite is the most mature ecosystem for Android (criterion 3). They would train with Keras (probably transfer learning as in 05-03) and export to TFLite.
- PyTorch: reproducing and modifying a recent paper → the published code will almost surely be PyTorch (criterion 2), and the explicit loop makes it easier to touch the model's internals (criterion 5).
- Keras: standard workflow, short deadline, a team trained in this course where Keras is the main language (criteria 1 and 4).
TextVectorization+ dense network as in 04-03, and off to production.
Solution 3: It is a binary MLP with dropout (like the ones in 05-04): a 20-feature input, a hidden layer of 8 with ReLU, 30% dropout and an output of 1 logit (the loss would be BCEWithLogitsLoss). In Keras:
model = keras.Sequential([
keras.layers.Dense(8, activation="relu", input_shape=(20,)),
keras.layers.Dropout(0.3),
keras.layers.Dense(1, activation="sigmoid"), # or no sigmoid + from_logits=True
])One nuance: the usual Keras version puts a sigmoid on the output and uses plain BinaryCrossentropy; the exact equivalence with the PyTorch snippet (raw logit) would be no final activation plus from_logits=True.
Conclusion
You now have the full comparison: Keras/TensorFlow shines in productivity and deployment (TFLite, TF.js, TF Serving); PyTorch shines in transparency, debugging and research (Hugging Face, papers); performance is a practical tie; and around them orbit JAX, Hugging Face as an upper layer, and ONNX as a bridge format. TecnoMarket chose pragmatically: Keras for their existing production, PyTorch for exploring pretrained models, and shared validation for everything. The underlying lesson is the one that closes the debate: the course's concepts — tensors, gradients, layers, regularization, attention — are transferable; the framework is a tool, and you already handle the two main ones.
Before taking anything to production, the environment you work in needs to be professionalized: in the next lesson we will step out of the notebook — local and cloud GPUs, project structure, reproducibility, version control for ML and monitoring with TensorBoard — so that the TecnoMarket team's work stops living in loose Colab tabs.
Deep Learning Course
Module 1: Introduction to Deep Learning
- What is Deep Learning?
- History and evolution of Deep Learning
- Applications of Deep Learning
- Basic concepts of neural networks
- Setting up the work environment
Module 2: Neural Network Fundamentals
- Perceptron and Multilayer Perceptron
- Activation functions
- Forward and backward propagation
- Optimization and loss functions
- Your first complete neural network
Module 3: Convolutional Neural Networks (CNN)
- Introduction to CNNs
- Convolutional and pooling layers
- Popular CNN architectures
- CNN applications in image recognition
Module 4: Recurrent Neural Networks (RNN)
- Introduction to RNNs
- LSTM and GRU
- RNN applications in natural language processing
- Sequences and time series
Module 5: Advanced Deep Learning Techniques
- Generative Adversarial Networks (GAN)
- Autoencoders
- Transfer Learning
- Regularization and improvement techniques
- Attention mechanisms and Transformers
Module 6: Tools and Frameworks
- Introduction to TensorFlow
- Introduction to PyTorch
- Framework comparison
- Development environments and additional resources
- Saving, loading and deploying models
Module 7: Hands-On Projects
- Image classification with CNNs
- Text generation with RNNs
- Anomaly detection with Autoencoders
- Building a GAN for image generation
- Fine-tuning a pretrained model
