Your Python ML setup does not need to be complicated: this walkthrough gets your machine learning environment running fast. You will install Jupyter Notebook, scikit-learn, and the rest of the essential ML libraries, configure your workspace, and verify everything works by training a real model in 10 lines of code.
“The best notebook is one where the code runs. The second best is one where the code ran last week.”
Joel Grus, JupyterCon 2018
Last Updated: July 2026 | Tested on: Python 3.14.6, scikit-learn 1.9.0, JupyterLab 4.6.0 | Difficulty: Beginner | Reading Time: 12 minutes
So far you have been writing Python in .py files and running the whole thing from the terminal. That works great for building software. Machine learning has a different rhythm, though. You load some data, look at it, change one number, run it again, look again, and keep going until it clicks. Running the entire script from scratch every single time would drive you mad.
Think of a chef’s kitchen counter. You do not cook the whole meal in one shot. You chop a little, taste, add salt, taste again, adjust. A Jupyter notebook is that counter for your code. You run one small chunk, see the result right there, tweak it, and run the next chunk. That is exactly why Jupyter Notebook became the standard tool in data science and ML: it lets you work in small bites, see results instantly, and keep your notes next to your code.
This post gets your ML workspace running in under 15 minutes. By the end you will have Jupyter, scikit-learn, and every supporting library installed, and you will have proved it all works by training a real model.
Table of Contents
Prerequisites
- virtual environments tutorial (creating isolated Python environments)
- package managers tutorial (pip and uv)
- Python 3.13+ installed (this post is tested on Python 3.14.6)
Install & Verify
📄 Terminal: create environment and install the ML stack
# Create a dedicated ML virtual environment
python -m venv ml-env
source ml-env/bin/activate # Windows: ml-env\Scripts\activate
# Install the core ML stack
pip install scikit-learn pandas numpy matplotlib seaborn jupyterlab
# Verify installations
python -c "import sklearn; print(f'scikit-learn: {sklearn.__version__}')"
python -c "import pandas; print(f'pandas: {pandas.__version__}')"
python -c "import numpy; print(f'numpy: {numpy.__version__}')"
python -c "import matplotlib; print(f'matplotlib: {matplotlib.__version__}')"
python -c "import seaborn; print(f'seaborn: {seaborn.__version__}')"
▶ Output
scikit-learn: 1.9.0 pandas: 3.0.3 numpy: 2.4.6 matplotlib: 3.11.0 seaborn: 0.13.2
JupyterLab, Your ML Workbench
Jupyter Notebook (and its newer interface, JupyterLab) runs in your browser. You write code in cells, run them one at a time, and see the output right below each cell, charts and dataframes included. The name comes from Julia, Python, and R, the three languages it first supported. Today it speaks dozens of languages through different kernels.
The setup is simple. Your browser is the front end where you type. A Jupyter server sits in the middle and manages the connection. A Python kernel is the part that actually runs your code. The kernel remembers everything between cells, so a variable you create in cell 1 is still there in cell 10. Think of it like a whiteboard in a meeting room: whatever you write stays up until someone wipes it clean, no matter what order people walked in and added notes.
That memory is what makes notebooks feel alive, and it is also the source of the biggest Jupyter catch: because you can run cells in any order you like, it is easy to end up with leftover values that no longer match the code on screen.
The diagram shows Jupyter’s three parts working together: the browser front end where you write and run cells, the Jupyter server that manages your notebooks and the connection, and the Python kernel that actually runs your code. Each notebook gets its own kernel, and that kernel holds onto your variables and imports between cell runs. This is exactly why running cells out of order can confuse you, and why “Restart Kernel” wipes every variable clean. Once this picture clicks, the most common Jupyter head-scratcher goes away.
📄 Terminal: launch JupyterLab
# Launch JupyterLab (opens browser automatically) jupyter lab # Or classic notebook interface jupyter notebook # Or specify port and no-browser (for remote servers) jupyter lab --port=8888 --no-browser
The Quick Win: Your First ML Model in 10 Lines
Scikit-learn ships with a few small datasets built in, perfect for learning. The Iris dataset is the “hello world” of ML: 150 flowers, 4 measurements each (petal and sepal sizes), and 3 species to tell apart. Let us load it, train a model, and make a prediction. Total time: under 2 minutes.
📄 first_model.py: Iris classification in 10 lines
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# Load built-in dataset
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.2, random_state=42
)
# Train and evaluate
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, predictions):.0%}")
print(f"Features: {iris.feature_names}")
print(f"Classes: {iris.target_names.tolist()}")
print(f"Training samples: {len(X_train)}, Test samples: {len(X_test)}")
▶ Output
Accuracy: 100% Features: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'] Classes: ['setosa', 'versicolor', 'virginica'] Training samples: 120, Test samples: 30
What happened here: In 10 lines you loaded a real dataset, split it into a training set and a test set, trained a Random Forest of 100 trees, and scored 100% accuracy. Do not let that perfect score fool you into thinking ML is always this easy. Iris is tiny and the three flower species barely overlap, so a perfect score is normal here. Real datasets are far messier, and you will fight for every percent. What stays the same on every project, though, is the rhythm: load, split, fit, predict, score. Learn that loop once and you can run any scikit-learn model.
The scikit-learn API: Consistent Across All Algorithms
Here is the single best thing about scikit-learn: every model speaks the same language. Once you know fit(), predict(), and score(), you can swap one algorithm for another by changing a single line. It is a bit like driving a rental car. The engine under the hood is completely different, but the steering wheel, pedals, and gear stick are always in the same place, so you can just drive. Your workflow stays identical whether the model behind it is logistic regression, a random forest, or an SVM (Support Vector Machine).
📄 sklearn_api.py: same API, different algorithms
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.2, random_state=42
)
# Every model: instantiate → fit → score. That's it.
models = {
"Logistic Regression": LogisticRegression(max_iter=200),
"Decision Tree": DecisionTreeClassifier(random_state=42),
"SVM": SVC(),
"KNN (k=5)": KNeighborsClassifier(n_neighbors=5),
"Random Forest": RandomForestClassifier(n_estimators=100, random_state=42),
}
print(f"{'Model':<25} {'Train Acc':>10} {'Test Acc':>10}")
print("-" * 47)
for name, model in models.items():
model.fit(X_train, y_train)
train_acc = model.score(X_train, y_train)
test_acc = model.score(X_test, y_test)
print(f"{name:<25} {train_acc:>9.1%} {test_acc:>9.1%}")
▶ Output
Model Train Acc Test Acc ----------------------------------------------- Logistic Regression 97.5% 100.0% Decision Tree 100.0% 100.0% SVM 97.5% 100.0% KNN (k=5) 96.7% 100.0% Random Forest 100.0% 100.0%
What happened here: Five completely different algorithms, one identical three-step workflow. Look at fit(X_train, y_train): it is the same call whether the model draws boundary lines (SVM), grows trees (Decision Tree), or measures distances between points (K-Nearest Neighbors, KNN). That consistency is scikit-learn’s best design decision, and it is why this library is the place every Python ML journey starts. The next several posts open up each of these algorithms one by one. For now, your numbers may shift by a fraction if your library versions differ slightly, and that is fine.
VS Code as an Alternative to Jupyter
If you would rather stay in your editor, VS Code has solid Jupyter support built in. Install the official “Jupyter” extension, open a .ipynb file, and you get the same cell-by-cell execution right inside VS Code. You keep the best of both worlds: Jupyter’s run-and-tweak workflow plus VS Code’s autocomplete, debugger, and Git integration in one window.
📄 Terminal: VS Code Jupyter setup
# Install the Jupyter extension in VS Code # Extensions panel → search "Jupyter" → Install (by Microsoft) # Create a notebook file touch my_analysis.ipynb # Open in VS Code (it auto-detects the notebook format) code my_analysis.ipynb # Or use Python files with cell markers (# %% creates cells) # This gives you .py files that behave like notebooks
Common Mistakes
❌ Mistake 1: Running Jupyter cells out of order
# Cell 1: (you run this)
data = [1, 2, 3, 4, 5]
# Cell 2: (you run this)
total = sum(data)
print(f"Total: {total}")
# Cell 3: (you change data, run this)
data = [10, 20, 30]
# Problem: Cell 2 still shows total=15, but data is now [10, 20, 30]
# If you re-run Cell 2, total becomes 60
# RULE: Always "Restart Kernel & Run All" before sharing a notebook
# This ensures cells run top-to-bottom with clean state
❌ Mistake 2: Installing packages in wrong environment
# BAD: Installing sklearn in system Python, running Jupyter in venv # Result: ImportError, because the package is in the wrong place # GOOD: Always install inside your activated virtual environment # 1. Activate venv: source ml-env/bin/activate # 2. Install: pip install scikit-learn # 3. Install Jupyter IN the venv: pip install jupyterlab # 4. Launch: jupyter lab # Now Jupyter uses the venv's Python and packages # Verify you're in the right environment: import sys print(sys.executable) # Should show your venv path
Practice Exercises
- Exercise 1: Swap the Iris dataset for
load_wine()(also built into scikit-learn) and re-runfirst_model.py. Print how many samples and classes it has, then check the accuracy. Does Random Forest still ace it? - Exercise 2: In
sklearn_api.py, changetest_sizefrom0.2to0.5. With half the data held back for testing, watch how the test accuracy moves. Write one sentence on why a bigger test set can change the score. - Exercise 3: Add a sixth model,
GaussianNBfromsklearn.naive_bayes, to the comparison loop. It needs no settings at all. Slot it into the table next to the other five and compare its train and test accuracy.
Conclusion
You now have a complete Python ML setup: a dedicated virtual environment, JupyterLab as your run-and-tweak workbench, and the full scikit-learn stack verified by training a real model on the Iris dataset. More importantly, you learned the rhythm that never changes: load, split, fit, predict, score. You also saw that every scikit-learn algorithm speaks the same fit/predict/score language, so swapping a random forest for an SVM is a one-line change.
Next up we go deeper on train/test split and cross-validation, so you can measure a model honestly instead of trusting one lucky split. That is where the perfect-score honeymoon of Iris really ends. To follow the full path from setup to deployment, start at the Python + AI/ML tutorial series home.
Frequently Asked Questions
Should I use JupyterLab or classic Jupyter Notebook?
Use JupyterLab. It is the next-generation interface with file browser, multiple tabs, terminal access, and extensions. Classic Notebook still works but is in maintenance mode. JupyterLab does everything Notebook does and more.
Do I need a GPU for machine learning?
Not for this series. Traditional ML (scikit-learn, XGBoost) runs on CPU and handles datasets up to millions of rows. GPUs become essential for deep learning (Part 6) where you train neural networks. For Part 5, a modern laptop CPU is more than sufficient.
What is the difference between scikit-learn and TensorFlow?
scikit-learn is for traditional ML: linear regression, decision trees, SVMs, clustering, preprocessing. TensorFlow (and PyTorch) are for deep learning: neural networks, CNNs (Convolutional Neural Networks), RNNs (Recurrent Neural Networks), transformers. Use scikit-learn for tabular data and classical algorithms. Use TensorFlow/PyTorch when you need neural networks.
Can I use Google Colab instead of a local scikit-learn setup?
Yes. Google Colab is a free cloud-hosted Jupyter environment with scikit-learn, pandas, and matplotlib pre-installed. It even provides free GPU access for deep learning. The tradeoff: slower startup, depends on internet, and files are not local. For learning, Colab is excellent. For production work, a local scikit-learn setup is faster and fully under your control.
How do I export a Jupyter notebook to a Python script?
In JupyterLab: File → Export Notebook As → Executable Script. Or from the terminal: jupyter nbconvert –to script my_notebook.ipynb. This strips cell boundaries and markdown, leaving clean Python code.
Interview Questions on Python ML Setup
Try each one aloud first. The phrasing you produce under mild pressure is what interviews measure.
Q: What are the three moving parts of a running Jupyter notebook?
The browser front end where you write and run cells, the Jupyter server that manages sessions and the connection, and the Python kernel that actually executes your code. The kernel is the piece that holds your variables and imports in memory between cell runs. Understanding this split explains why “Restart Kernel” wipes every variable and why cells can run in any order.
Q: What does train_test_split do, and why hold back a test set at all?
It randomly divides your data into a training portion the model learns from and a test portion it never sees during training. You hold back the test set to measure how the model performs on unseen data, which is the only honest estimate of real-world accuracy. Without it, a model can simply memorize the training rows and look far better than it actually is.
Q: What is the shared scikit-learn Application Programming Interface (API), and why does it matter?
Almost every scikit-learn estimator exposes the same methods: fit() to train, predict() to make predictions, and score() to evaluate. Because the interface is identical, you can swap logistic regression for a random forest or an SVM by changing a single line, with the rest of your workflow untouched. This consistency is what makes scikit-learn easy to learn and quick to experiment in.
Q: What is the point of random_state in a split or a model?
random_state fixes the seed for any randomness, such as how the data is shuffled before splitting or how a random forest samples rows. Setting it to a constant like 42 makes your results reproducible, so you and anyone else get the exact same numbers on every run. Without it, the split changes each time and your accuracy will wobble between runs.
Q: You install scikit-learn with pip, but importing it in JupyterLab raises ModuleNotFoundError. What do you check first?
Almost always the kernel is running a different Python than the one you installed into. Run import sys; print(sys.executable) in a cell to see which interpreter the kernel uses, and confirm it points to your activated virtual environment. The fix is to install Jupyter and the packages inside the same activated venv, then relaunch jupyter lab from there so the kernel and the packages line up.
Q: A teammate says your notebook fails when they run it top to bottom, even though it works perfectly for you. What likely happened?
You probably ran cells out of order, so the kernel holds a variable or import that no longer exists in a clean top-to-bottom run. Your live kernel remembers that leftover state, but a fresh run does not. Reproduce it yourself with “Restart Kernel and Run All”: if it breaks for you too, fix the cell order or missing definitions before sharing.
Series: Python + AI/ML Cookbook, Part 5: Machine Learning
Further reading: the official Python documentation is the authoritative source on this.
Related Posts
Previous: ML: What is Machine Learning? Teaching Computers to Learn from Data
Next: ML: Train/Test Split & Cross-Validation
Series Home: Python + AI/ML Tutorial Series

No comment