To get started with machine learning with Python, choose a small task, separate the training and test data, and compare a simple model with a basic baseline. You do not need to rent a GPU for your first exercise. In this guide, we will build a complete classifier on a CPU, interpret its errors, and decide when it makes sense to change the infrastructure.
The goal is to finish with an experiment that you can repeat and explain. Getting a single prediction right is less useful than knowing which data the model saw, how it was evaluated, and where it fails.
What to learn first in machine learning with Python
A supervised learning project has inputs, called features, and a known answer, called the target. In this article's example, the features are flower measurements and the target is the species. The model learns a relationship using the training set and then tries to classify examples that were kept separate.
Before choosing a library, write down the question you want to answer:
| Task | Response type | Possible first experiment |
|---|---|---|
| Classify an observation | A category | Logistic regression or a decision tree |
| Estimate a quantity | A number | Linear regression and error analysis |
| Find groups without labels | Clusters | A clustering method and inspection of the groups |
| Work with images or language at scale | More complex representations and predictions | An appropriate deep learning library, after defining the evaluation |
Do not choose a neural network just because it seems more advanced. If a simple solution solves the task within the required cost and timeframe, it is an important baseline for any later alternative.
Set up an isolated environment
You need a Python installation compatible with scikit-learn and access to a terminal. Create a working folder and a virtual environment to avoid conflicts with other projects:
python -m venv .venv
On macOS or Linux, activate it with source .venv/bin/activate. In Windows PowerShell, use .venv\Scripts\Activate.ps1, according to local terminal policies. Then install the library and record the versions:
python -m pip install scikit-learn
python -m pip freeze > requirements.txt
Use python3 instead of python if that is the name of the executable on your computer. The dependency file helps recreate the environment; also keep the Python version, the code, and the experiment configuration.
A first complete model: flower classification
The scikit-learn Iris dataset contains 150 observations, four numerical features, and three classes. It is small and suitable for learning the workflow, but it does not demonstrate that a system is ready for real-world data.
Save the code below as exemplo_iris.py and run python exemplo_iris.py. It uses 120 observations for training and 30 for testing. The stratified split maintains class representation; the fixed seed makes it possible to repeat the same split.
import platform
from time import perf_counter
import sklearn
from sklearn.datasets import load_iris
from sklearn.dummy import DummyClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, random_state=42, stratify=y
)
models = {
"baseline": DummyClassifier(strategy="most_frequent"),
"logistica": make_pipeline(
StandardScaler(), LogisticRegression(max_iter=1000)
),
}
for name, model in models.items():
start = perf_counter()
model.fit(X_train, y_train)
train_seconds = perf_counter() - start
pred = model.predict(X_test)
print(name, "acuracia=", round(accuracy_score(y_test, pred), 3),
"f1_macro=", round(f1_score(
y_test, pred, average="macro", zero_division=0
), 3))
print("matriz de confusao:", confusion_matrix(y_test, pred).tolist())
print("tempo de treino (s):", round(train_seconds, 6))
print("Python:", platform.python_version(),
"scikit-learn:", sklearn.__version__)
The DummyClassifier provides a comparison that does not learn a relationship between the features and the class. With the strategy used here, it predicts the most frequent class in the training data. If a more elaborate model does not improve on such a baseline, investigate the data, objective, and evaluation before spending more resources. See the strategies in the DummyClassifier documentation.
Logistic regression receives the data through a Pipeline: first standardization, then the classifier. The transformations are fitted on the training data and reapplied to the test data. This prevents calculating the scale using information that should be reserved for evaluation, a common form of data leakage. The scikit-learn best practices documentation explains this precaution.
How to interpret the output without misleading yourself
When running this example on CPU, with Python 3.14.4 and scikit-learn 1.9.1, we obtained the results below. They are results from this exercise and this data split, not a promise for another dataset.
| Model | Test accuracy | Macro F1 |
|---|---|---|
| Most frequent class baseline | 0.333 | 0.167 |
| Standardization + logistic regression | 0.933 | 0.933 |
The matrix for the second model was [[10, 0, 0], [0, 9, 1], [0, 1, 9]]: two of the 30 test flowers were confused between the last two classes. This is more informative than simply saying that the model got about 93% correct.
Accuracy indicates the proportion of correct predictions in the evaluated set. Macro F1 calculates the F1 score for each class and averages them without giving greater weight to the most frequent class. The confusion matrix shows which classes were confused. Use all three views to understand the behavior, rather than looking only for the largest number.
The printed time is only the training time for that run on your computer. On such a small dataset, it varies with the machine and measurement noise. Do not use this number to promise cloud savings or compare CPU and GPU.
The Iris result should not become an expectation of accuracy for your product either. With your own data, the distribution, label quality, and cost of errors may be completely different. A rare failure can matter more than dozens of easy successes.
Before changing the algorithm, answer:
- Did the model outperform the basic baseline using exactly the same test set?
- Which class accounts for the errors, and what is their impact on the task?
- Is there information in the inputs that would only be available after the prediction?
- Does the test represent new examples, or does it contain duplicates and observations related to the training data?
- Does performance hold across other valid data splits?
From the exercise to a real dataset
A random split is convenient for Iris. It may be unsuitable if you predict future events, have multiple rows per customer, or find copies of the same observation. In those cases, consider a temporal or group-based split, according to how the model will be used. The random_state parameter does not fix a conceptually wrong split. The train_test_split reference describes the controls available for this simple split.
Set aside validation data to choose configurations and keep a separate final test set. If you repeatedly consult the test set to decide the next adjustment, it starts influencing your choices. For a small project, an experiment spreadsheet already helps:
| Record | What to note |
|---|---|
| Data | Source, date, size, columns, and exclusion rule |
| Split | Temporal, group-based, or random; seed when applicable |
| Model | Algorithm, parameters, and dependency versions |
| Evaluation | Main metric, errors by class, and comparison with the baseline |
| Operation | Time, memory, artifact size, and measured cost |
| Decision | What improved and which problem remains open |
When replacing Iris with your own table, validate types, missing fields, and categories before training. Keep transformations together with the model so that prediction uses the same data preparation. A column whose unit has changed can cause problems even if the code continues to run.
When a GPU helps — and when it does not
The example in this guide runs on CPU. Adding a graphics card to the machine does not automatically make all scikit-learn code use it. The project documents GPU support for a limited set of estimators and configurations, including through specific inputs and options. Check the exact path for the chosen algorithm.
A GPU is worth an experiment when there is a compatible implementation and a workload that can take advantage of it, such as certain neural network training tasks or batch processing. Even then, the gain must offset data transfer, environment setup, and infrastructure cost.
| Observed situation | Recommended next action |
|---|---|
| Little data and fast CPU training | Prioritize data quality and evaluation |
| Reading or preparation consumes most of the time | Measure storage, loading, and transformations |
| Algorithm without a GPU-compatible path | Review the library or stay with CPU |
| GPU-compatible training takes up a large part of the cycle | Run a controlled test on the candidate configuration |
| Large model or high inference volume | Measure memory, latency, and concurrency with the real workload |
Compare the total time to a useful result, not just the execution of one operation. Include installation, transfer, training, validation, storage, and idle periods. An alternative that is faster per epoch may be worse if it requires more attempts to reach the required quality.
When the project reaches this stage, Flatkey Cloud GPU lets you evaluate NVIDIA GPU rental options. Confirm the configuration, region, availability, and terms for the intended workload. Bring the dataset size, library, required memory, and test objective; this tutorial does not require renting a GPU to complete.
Before putting the model into use
Define the accepted input format, the behavior for invalid fields, and how to monitor errors after publication. Keep the model version and data preparation together. Test a prediction with representative data outside the notebook before thinking about scale.
If the next step is to serve a language model with your own infrastructure, the vLLM deployment guide covers another type of workload. Do not confuse a small tabular classifier with operating an LLM: memory, evaluation, and server requirements are different.
Frequently asked questions
Do I need a GPU to learn machine learning with Python?
No. The example shown can run on a CPU. Choose larger infrastructure when there is a measured bottleneck and an implementation that can take advantage of it.
Why use a baseline before a more complex model?
It shows what can be achieved with a simple rule. This makes it possible to assess whether the model learned something useful and whether the added complexity is justified.
Does the same seed guarantee the same result in every environment?
It fixes the random choices controlled by that parameter. Also record versions and the environment; implementation and execution differences can affect results. Do not confuse the repeatability of a split with a universal performance guarantee.
What is the next project after Iris?
Choose a small task with data you understand, a verifiable target, and a success criterion. Repeat the process: baseline, correct split, model, error analysis, and measurement. This habit is the foundation for progressing in machine learning with Python without increasing costs before necessary.



