# Getting started with artificial intelligence in Python: a first project

> Get started with AI in Python: set up Python 3.14 and a virtual environment, train and test a scikit-learn model, try PyTorch, and call an LLM API safely.

- URL: https://computese.com/artificial-intelligence-with-python/
- Author: Duong Quan Nguyen, CEO, Computese
- Published: 2024-05-30
- Updated: 2026-09-25
- Topics: AI & automation, Custom software

## In short
- Getting started with AI in Python means one small project end to end: a virtual environment, a built-in dataset, a model trained on part of the data and scored once on rows it never saw.
- As of September 2026, use Python 3.14 with scikit-learn 1.9 and PyTorch 2.14. Python 3.15 is due on October 1, 2026, but PyTorch 2.14 publishes packages only up to Python 3.14.
- Split the data before any preprocessing and keep scaling inside a scikit-learn pipeline. Fitting anything on the test rows is data leakage, and it makes a model look better than it is.
- Start simple and measure against a baseline. In this guide, logistic regression scored 98% on held-out data against 63% for always guessing the common class, and a small neural network did not beat it.
- Call hosted language models through the provider's SDK with the API key in an environment variable or an ignored .env file, never in code or a notebook.

To get started with artificial intelligence in Python, install a current Python, create a virtual environment, add scikit-learn and Jupyter, and build one small project end to end: load a dataset, split off a test set, train a model inside a pipeline and score it once on data it has never seen. PyTorch and hosted model APIs come after that.

This guide walks that path with code that runs as written: every sample was run with Python 3.14, scikit-learn 1.9.1 and PyTorch 2.14.0 in September 2026. You will train a classifier on a medical dataset that ships with scikit-learn, see how a mistake called data leakage makes a model look better than it is, rebuild the classifier as a small neural network, and call a hosted large language model without putting the API key in your code. It ends with the errors beginners hit most and what to learn next. If programming itself is new to you, our [tips for new coders](https://computese.com/essential-tips-for-new-coders/) cover the path from a first language to a first code review.

## Why Python is where most AI work starts

Python is not fast on its own, and for AI work it does not need to be. The arithmetic runs in compiled code underneath: [NumPy](https://numpy.org/), the array library that scikit-learn and pandas install as a dependency, describes its core as well-optimized C code. Python is the readable layer you write on top, which is why a few lines can load data, train a model and score it.

The other reason is the ecosystem. Data handling, classic machine learning, deep learning, notebooks and the SDKs for hosted models are all Python-first, and the numbers show it:

- In the [Stack Overflow 2025 Developer Survey](https://survey.stackoverflow.co/2025/technology), 57.9% of respondents had done extensive development work in Python, up 7 percentage points from 2024. Among people learning to code, Python was the most used language, at 71.8%.
- GitHub's [Octoverse 2025](https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/) found that TypeScript overtook Python as the most used language on GitHub in August 2025, but that Python remains dominant for AI and data science, with 2.6 million contributors, and powers nearly half of all new AI repositories.

In practice, most AI work you can do on a laptop is machine learning: instead of writing the rule yourself, you give the program labelled examples and it learns the rule. Your first project below is supervised classification, 30 measurements in and one of two labels out. These are the libraries it uses:

| Library       | What it does in this guide                                          | Install name                          |
| ------------- | ------------------------------------------------------------------- | ------------------------------------- |
| NumPy         | Arrays and fast numerical math under the other libraries            | `numpy` (installed automatically)     |
| pandas        | Tables of data: load, inspect, clean                                | `pandas`                              |
| scikit-learn  | Classic machine learning: splitting, preprocessing, models, metrics | `scikit-learn`, imported as `sklearn` |
| PyTorch       | Neural networks, with GPU support when you need it                  | `torch`                               |
| JupyterLab    | Notebooks for exploring data and results                            | `jupyterlab`                          |
| Provider SDKs | Calling hosted language models                                      | `anthropic`, `openai`, `google-genai` |

Choosing between competing frameworks is a separate question, covered in our [AI frameworks comparison](https://computese.com/latest-ai-tools-and-frameworks-a-comparative-analysis/). For a first project, these defaults are enough, and the skills carry over to whichever tools you pick later.

## Set up Python, a virtual environment and Jupyter

You need basic Python (variables, functions, imports), a terminal, and any recent Windows, macOS or Linux computer. You do not need a GPU: everything in this guide runs on a laptop CPU in seconds.

### Choose the Python version

As of September 2026, use Python 3.14. The [current release is 3.14.7](https://www.python.org/downloads/), and the 3.14 series is supported until October 2030. Python 3.15 is planned for October 1, 2026, but wait before switching: [PyTorch 2.14.0](https://pypi.org/project/torch/) publishes packages for Python 3.10 to 3.14 only, so on a 3.15 pre-release `pip install torch` stops with "No matching distribution found". [scikit-learn 1.9](https://pypi.org/project/scikit-learn/) needs Python 3.11 or later, so anything from 3.11 to 3.14 runs this guide, and 3.14 is the sensible default.

Where to get it:

- **Windows:** install the [Python install manager](https://docs.python.org/3/using/windows.html) from python.org or the Microsoft Store, then run `py install 3.14`.
- **macOS:** the installer from python.org, Homebrew, or uv (below).
- **Linux:** your distribution's package, or uv.

### Option 1: venv and pip, built into Python

On macOS or Linux:

```bash
mkdir ai-first-project
cd ai-first-project
python3.14 -m venv .venv
source .venv/bin/activate
python -m pip install scikit-learn pandas jupyterlab
jupyter lab
```

On Windows, in PowerShell:

```powershell
mkdir ai-first-project
cd ai-first-project
py -3.14 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install scikit-learn pandas jupyterlab
jupyter lab
```

A [virtual environment](https://docs.python.org/3/library/venv.html) is a folder, here `.venv`, with its own set of packages, isolated from the Python it was created from. Activating it puts its `bin` folder (`Scripts` on Windows) first on your `PATH`, so `python` and `jupyter` mean the project's copies. Treat it as disposable: it is not committed to Git and not copied between machines; you recreate it instead. Since Python 3.13, `venv` writes a `.gitignore` inside the folder so Git skips it automatically.

Installing into the system Python instead is not only untidy, it is often refused. On Homebrew's Python, and on Linux distributions that follow the same standard, pip stops with `error: externally-managed-environment`, because another package manager owns that installation. The [packaging standard behind that error](https://packaging.python.org/en/latest/specifications/externally-managed-environments/) points users to virtual environments, which is the fix rather than a workaround.

### Option 2: uv, one tool for Python versions, environments and lockfiles

```bash
uv init -p 3.14 ai-first-project
cd ai-first-project
uv add scikit-learn pandas jupyterlab
uv run jupyter lab
```

[uv](https://docs.astral.sh/uv/) is a package and project manager from Astral, written in Rust, that replaces pip, virtualenv, pyenv and several other tools. It can install Python itself (`uv python install 3.14`). In a project, it [creates the `.venv` folder and a `uv.lock` file](https://docs.astral.sh/uv/guides/projects/) the first time you add a package or run a project command, and `uv run` runs a command inside that environment without activating it.

|                          | venv and pip                         | uv                               |
| ------------------------ | ------------------------------------ | -------------------------------- |
| Comes with Python        | Yes                                  | No, one extra install            |
| Installs Python versions | No                                   | Yes                              |
| Records exact versions   | Only if you run `pip freeze` by hand | Yes, in `uv.lock`                |
| Good for                 | Following any tutorial as written    | Projects you will keep and share |

### Notebook or script

`jupyter lab` opens JupyterLab in your browser. A notebook is a file of code cells with the output of each shown below it, which makes it the natural place to explore data. Anything you will run again belongs in a script. [JupyterLab installs with pip](https://jupyter.org/install) like any other package, and the one rule is that it must run your environment's Python: start it from the activated environment, or with `uv run`.

## Build your first machine learning model with scikit-learn

The project: classify breast tumour samples as malignant or benign. The [Breast Cancer Wisconsin (Diagnostic) dataset](https://scikit-learn.org/stable/datasets/toy_dataset.html) ships with scikit-learn, so there is nothing to download. It holds 569 samples, each with 30 measurements computed from a digitized image of a fine needle aspirate of a breast mass, labelled 212 malignant and 357 benign.

> [!NOTE]
> This is a teaching dataset. scikit-learn's [reference for `load_breast_cancer`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_breast_cancer.html) describes it as a classic and very easy classification problem, and the dataset guide adds that these bundled datasets are often too small to represent real-world machine learning. The workflow transfers to real data; the score does not, and nothing here is a diagnostic tool.

Run each block below as a notebook cell, in order, or save them together as `first_model.py` and run `python first_model.py`.

### Step 1: Load the data and look at it

```python
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer(as_frame=True)
X, y = data.data, data.target

print(X.shape)
print(data.target_names)
print(y.value_counts())
print(X[["mean area", "mean smoothness"]].agg(["min", "max"]))
```

```text
(569, 30)
['malignant' 'benign']
target
1    357
0    212
Name: count, dtype: int64
     mean area  mean smoothness
min      143.5          0.05263
max     2501.0          0.16340
```

`X` is a pandas table of 569 rows and 30 columns; `y` holds the labels, where 0 means malignant and 1 means benign. Two things matter already. The classes are unbalanced (357 against 212), which will set the bar for a useful score. And the columns sit on very different scales: mean area runs from 143.5 to 2,501, mean smoothness from 0.05 to 0.16. The [scikit-learn documentation on preprocessing](https://scikit-learn.org/stable/modules/preprocessing.html) warns that many of its models behave badly when features are not standardized, so scaling will be part of the model.

### Step 2: Split before anything learns

```python
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)
print(X_train.shape, X_test.shape)
```

```text
(455, 30) (114, 30)
```

`test_size=0.2` holds back 20% of the rows, 114 of them, as the test set. `stratify=y` keeps the share of malignant and benign samples the same on both sides, and `random_state=42` makes the split repeatable, so you get the numbers shown here. From this line on, the test rows are off limits until the last step. The [scikit-learn guide to cross-validation](https://scikit-learn.org/stable/modules/cross_validation.html) calls training and testing on the same data a methodological mistake: a model that simply memorized the labels would score perfectly and predict nothing.

![A stack of data rows is cut in two. The larger part moves into a gear that learns, while the smaller part waits in a box closed with an orange padlock until a final gauge at the end.](https://computese.com/images/blog/artificial-intelligence-with-python/split.be61e820cd-1536.webp)

*The held-back rows stay sealed until the end: a score on rows the model has already seen proves nothing.*

### Step 3: Set a baseline

```python
from sklearn.dummy import DummyClassifier

baseline = DummyClassifier(strategy="most_frequent")
baseline.fit(X_train, y_train)
print(f"Baseline accuracy: {baseline.score(X_test, y_test):.3f}")
```

```text
Baseline accuracy: 0.632
```

A [`DummyClassifier`](https://scikit-learn.org/stable/modules/generated/sklearn.dummy.DummyClassifier.html) ignores the measurements entirely. This one always answers "benign" and is right 63.2% of the time, 72 of 114. Every model you build has to beat that number, and it is a useful reminder that accuracy alone can flatter a model when one class is more common.

### Step 4: Build a pipeline and cross-validate it

```python
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

model = make_pipeline(StandardScaler(), LogisticRegression())
scores = cross_val_score(model, X_train, y_train, cv=5)
print(f"Cross-validation accuracy: {scores.mean():.3f} (+/- {scores.std():.3f})")
```

```text
Cross-validation accuracy: 0.980 (+/- 0.013)
```

The pipeline chains two steps into one model: `StandardScaler` rescales each column to mean 0 and standard deviation 1, and `LogisticRegression` learns a weight for each column. Because they are fitted together, the scaler only ever learns its means and deviations from the rows the pipeline is trained on.

`cross_val_score` with `cv=5` splits the training set into five folds, trains on four and scores on the fifth, five times over, and reports the scores. The average, 98.0% with little spread between folds, is your estimate of how the model will do on new data. Compare models and settings here, never on the test set.

### Step 5: Train once and test once

```python
from sklearn.metrics import classification_report, confusion_matrix

model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred, target_names=data.target_names))
```

```text
[[41  1]
 [ 1 71]]
              precision    recall  f1-score   support

   malignant       0.98      0.98      0.98        42
      benign       0.99      0.99      0.99        72

    accuracy                           0.98       114
   macro avg       0.98      0.98      0.98       114
weighted avg       0.98      0.98      0.98       114
```

In a scikit-learn [confusion matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html), rows are the true classes and columns the predictions. Of 42 malignant test samples, 41 were caught and 1 was called benign; of 72 benign samples, 71 were right and 1 was flagged as malignant. Accuracy is 98%, against 63.2% for the baseline, and it agrees with the cross-validation estimate of 98.0%.

Accuracy hides which mistakes a model makes, so read the other columns too. **Precision** is the share of samples predicted malignant that really were; **recall** is the share of malignant samples the model found. Which one matters more depends on the use. In screening, a missed malignant sample is the expensive error, so you would watch malignant recall and accept more false alarms to raise it.

## Data leakage: the mistake that makes models look better than they are

scikit-learn's page of [common pitfalls](https://scikit-learn.org/stable/common_pitfalls.html) defines data leakage as information that would not be available at prediction time being used to build the model. It produces optimistic scores in testing and poorer results on genuinely new data. A common cause is letting test rows into any step that learns from data, preprocessing included, and the rule that prevents it is short: never call `fit` on the test data.

The same page demonstrates how large the effect can be, using pure noise: 200 samples with 10,000 random features and random labels. Selecting the 25 "best" features on all the data before splitting produced 76% test accuracy on labels that cannot be predicted at all. Selecting them on the training rows only gave 50%, exactly what chance should give.

That is why the scaler in step 4 lives inside the pipeline. When `cross_val_score` trains on four folds, the pipeline refits the scaler on those four folds only, so the fold being scored never influences its own preprocessing. The same holds for every transformer you add later.

| Leak                                                                     | Why it inflates the score                             | Fix                                                          |
| ------------------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------ |
| Scaling, filling gaps or selecting features on all rows before the split | Statistics from the test rows shape the training      | Split first, and put every preprocessing step in a pipeline  |
| Trying models and settings against the test set                          | The test set turns into training data by another name | Compare with cross-validation on the training set; test once |
| Rows from the same patient, customer or device on both sides             | The model recognizes the individual, not the pattern  | Split by group with `GroupKFold`                             |
| Shuffling data that is ordered in time                                   | The model learns from the future to predict the past  | Split with `TimeSeriesSplit`                                 |
| A column recorded after the outcome                                      | It encodes the answer                                 | Drop anything that will not exist at prediction time         |

## Take a first step into deep learning with PyTorch

Deep learning uses neural networks: layers of learned weights joined by simple non-linear functions. They earn their complexity on images, audio, text and very large datasets. Building the same classifier as a small network is still the clearest way to see the moving parts. For the ideas behind the code, weights, backpropagation and the main architectures, see [deep learning and NLP explained](https://computese.com/the-ai-and-machine-learning-revolution/).

Install PyTorch into the same environment with `python -m pip install torch`, or `uv add torch`. Version 2.14.0, released on September 2, 2026, needs [Python 3.10 or later](https://pytorch.org/get-started/locally/). According to [uv's PyTorch guide](https://docs.astral.sh/uv/guides/integration/pytorch/), the package on PyPI is built with CUDA for NVIDIA GPUs on Linux and is CPU-only on Windows; for a CPU-only Linux build or a CUDA build on Windows, copy the command from the selector on pytorch.org. This example runs on any CPU.

```python
import torch
from torch import nn
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)

# Learn the scaling from the training rows only, then apply it to both sets.
scaler = StandardScaler().fit(X_train)
X_train = torch.tensor(scaler.transform(X_train), dtype=torch.float32)
X_test = torch.tensor(scaler.transform(X_test), dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1)
y_test = torch.tensor(y_test, dtype=torch.float32).unsqueeze(1)

torch.manual_seed(42)
model = nn.Sequential(
    nn.Linear(30, 16),  # 30 measurements in, 16 hidden units
    nn.ReLU(),
    nn.Linear(16, 1),   # one score out: above 0 means "benign"
)
loss_fn = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

for epoch in range(100):
    model.train()
    optimizer.zero_grad()                      # clear the previous gradients
    loss = loss_fn(model(X_train), y_train)    # forward pass and loss
    loss.backward()                            # gradients for every weight
    optimizer.step()                           # nudge the weights
    if epoch % 25 == 0:
        print(f"epoch {epoch:3d}  loss {loss.item():.4f}")

model.eval()
with torch.no_grad():
    predicted = (model(X_test) > 0).float()
accuracy = (predicted == y_test).float().mean().item()
print(f"Test accuracy: {accuracy:.3f}")
```

```text
epoch   0  loss 0.7288
epoch  25  loss 0.0895
epoch  50  loss 0.0500
epoch  75  loss 0.0378
Test accuracy: 0.956
```

The split and the scaling are the same as before, done by hand this time, with the scaler fitted on the training rows only. The model has 513 parameters (weights and biases) in two linear layers with a ReLU between them. Each pass of the loop is one epoch over the training rows, and the [PyTorch tutorial on optimization](https://docs.pytorch.org/tutorials/beginner/basics/optimization_tutorial.html) describes its three steps: `optimizer.zero_grad()` resets the gradients, which otherwise add up from one pass to the next; `loss.backward()` computes how the loss changes with every weight; and `optimizer.step()` adjusts each weight using those gradients. The loss function, `BCEWithLogitsLoss`, measures how far the raw scores are from the 0 and 1 labels.

![Rows of data flow through three columns of connected circles to a single output circle and a gauge. An orange arrow runs back under the network, carrying corrections to every layer.](https://computese.com/images/blog/artificial-intelligence-with-python/loop.b017f50389-1536.webp)

*Each epoch runs forward to a loss, then backward to adjust every weight a little; training is that loop, repeated.*

The result is the lesson. The training loss fell from 0.73 to below 0.04 by epoch 75, yet the network scored 95.6% on the test set, below the 98% of the two-step logistic regression. On a few hundred rows of clean numbers, more capacity is not what the problem needs. Keep the simplest model that works as your baseline, and reach for neural networks when the data is images, sound or text, or when there is far more of it.

Two notes for later. On a machine with a supported GPU, the [PyTorch tutorials](https://docs.pytorch.org/tutorials/beginner/basics/buildmodel_tutorial.html) select it with `torch.accelerator` (CUDA, MPS and others) and move the model and data to it. And if you prefer a higher-level API, [Keras 3](https://keras.io/getting_started/) builds the same kind of model on a backend you choose: JAX, TensorFlow or PyTorch.

## Call a hosted language model from Python without leaking your key

Much of what people now mean by AI is a large language model that you call over an API rather than train. Each provider publishes a Python SDK, and each reads its key from an environment variable by default: `ANTHROPIC_API_KEY` for Anthropic's `anthropic` package, `OPENAI_API_KEY` for [OpenAI's `openai` package](https://github.com/openai/openai-python), and `GEMINI_API_KEY` or `GOOGLE_API_KEY` for [Google's `google-genai` package](https://github.com/googleapis/python-genai), which calls models such as [Gemini](https://computese.com/google-unveils-gemini-the-most-advanced-and-versatile-ai-model-yet/). The example uses Anthropic's SDK; the pattern is the same with the others.

1. **Create an API key** in the provider's console, and set a monthly spend limit before you write any code. On Anthropic's console, [spend limits](https://platform.claude.com/docs/en/api/rate-limits) sit under Settings, then Billing.
2. **Put the key in the environment** of the terminal that will run Python. On macOS or Linux, `export ANTHROPIC_API_KEY="paste-your-key-here"`. In PowerShell, `$Env:ANTHROPIC_API_KEY = "paste-your-key-here"`, which [lasts for the current session only](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables).
3. **Install the SDK** into your environment: `python -m pip install anthropic`. [Anthropic's Python SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/python) needs Python 3.10 or later.
4. **Run the script** below as `ask_model.py`.

```python
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "In two sentences, what is data leakage in machine learning?",
        }
    ],
)

for block in response.content:
    if block.type == "text":
        print(block.text)
print(f"Stop reason: {response.stop_reason}")
print(f"Tokens: {response.usage.input_tokens} in, {response.usage.output_tokens} out")
```

The client finds the key itself, as Anthropic's [getting started guide](https://platform.claude.com/docs/en/get-started) describes, so the key never appears in the file. `claude-opus-5-5` is the model Anthropic's [models overview](https://platform.claude.com/docs/en/models/overview) suggests starting with as of September 2026, priced at $4 per million input tokens and $20 per million output tokens. `max_tokens` is the [most tokens the model may generate](https://platform.claude.com/docs/en/api/messages/create) before it stops, which caps the length and cost of the reply. The response is a list of content blocks, so the loop prints only the text ones, and `usage` reports the tokens you are billed for. The SDK retries connection errors, rate limits (HTTP 429) and server errors twice by default before raising an exception.

Typing the key into every new terminal gets old quickly. The usual alternative is a `.env` file read by [python-dotenv](https://pypi.org/project/python-dotenv/), which Anthropic's SDK documentation also suggests. Install it with `python -m pip install python-dotenv`, put one line in `.env` in the project folder (`ANTHROPIC_API_KEY=paste-your-key-here`), add `.env` to `.gitignore`, and call `load_dotenv()` before creating the client:

```python
from dotenv import load_dotenv

load_dotenv()  # copies ANTHROPIC_API_KEY from .env into the environment
```

Before your first commit, `git check-ignore -v .env` should print the `.gitignore` rule that excludes the file. If it prints nothing, the file is not ignored, and the next `git add` will pick up the key.

![A laptop runs a script while an orange key sits in a locked safe beside it. The key joins the request only at run time, and the code repository below receives the script but never the key.](https://computese.com/images/blog/artificial-intelligence-with-python/key.c68431c7b0-1536.webp)

*The key lives beside the code, never in it: the script reads it at run time, and the repository never sees it.*

> [!WARNING]
> Never paste an API key into a notebook cell. Notebooks save their code and output inside the `.ipynb` file, and that file is what gets committed, emailed and shared. If a key does leak, the [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html) says to revoke it immediately, issue a new one and remove the old one wherever it was exposed.

Environment variables are the right tool on your own computer. On servers, OWASP notes that they are readable by other processes and can end up in logs, so production systems load keys from a secrets manager instead. The same rules apply to every credential in your code; our guide to [secure coding best practices](https://computese.com/best-practices-for-secure-coding/) covers the rest. Finally, treat each prompt as data leaving your machine: do not send personal or confidential information until you know what the provider does with it and what your organization allows.

## Common errors when getting started, and how to fix them

| Symptom                                                                 | Likely cause                                                                            | Fix                                                                             |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `error: externally-managed-environment` from pip                        | You are installing into a Python that the operating system or Homebrew manages          | Create and activate a virtual environment, then install                         |
| `ModuleNotFoundError: No module named 'sklearn'` right after installing | The terminal or notebook is running a different Python                                  | Activate `.venv` (or use `uv run`) and start Jupyter from there                 |
| `pip install sklearn` fails                                             | `sklearn` on PyPI is a [deprecated placeholder](https://pypi.org/project/sklearn/)      | Install `scikit-learn`, then import it as `sklearn`                             |
| `No matching distribution found for torch`                              | Your Python is newer than PyTorch's packages (a 3.15 pre-release, as of September 2026) | Use Python 3.14                                                                 |
| PowerShell refuses to run `Activate.ps1`                                | The script execution policy blocks it                                                   | Run `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` once |
| `Could not resolve authentication method` from the SDK                  | `ANTHROPIC_API_KEY` is not set in the terminal that runs Python                         | Set it in that terminal, or call `load_dotenv()` before creating the client     |
| Scores that look too good in testing, then fall apart on new data       | Leakage, or a test set that has been used for tuning                                    | Put every preprocessing step in a pipeline and score a fresh test set once      |

The PowerShell fix is the one the [`venv` documentation](https://docs.python.org/3/library/venv.html) gives; it applies to your user account only.

## What to learn next

You now have the loop every machine learning project follows: set up, look, split, baseline, train with cross-validation, test once. The next steps build on it in roughly this order:

1. **Your own data.** Load a CSV with pandas and check it before training: missing values, duplicate rows, and columns recorded after the outcome you want to predict.
2. **More of scikit-learn.** Try tree ensembles such as `HistGradientBoostingClassifier` on tabular data, search settings with `GridSearchCV` inside cross-validation, and choose metrics that match the cost of each error. The scikit-learn [Getting Started](https://scikit-learn.org/stable/getting_started.html) page leads into the user guide.
3. **PyTorch properly.** The [Learn the Basics](https://docs.pytorch.org/tutorials/beginner/basics/intro.html) tutorials cover tensors, datasets and data loaders, automatic differentiation, training and saving models, on image data where neural networks earn their keep.
4. **Building with hosted models.** Ask for structured output instead of free text, ground answers in your own documents, and keep a set of real test questions that every prompt or model change must pass before it ships.
5. **The math, as you need it.** Linear algebra explains what a layer computes, probability what a score means, and derivatives how training moves the weights.

When a notebook result needs to become something a team relies on, most of the work moves from the model to everything around it. Our [AI and automation service](https://computese.com/services/ai-automation/) uses a language model only where a step needs judgment, tests every model or prompt change against an evaluation set built from your real cases, and removes personal data before the model reads it. [Custom software development](https://computese.com/services/custom-software-development/) covers the platform, APIs and back end that the model plugs into.

## Key terms
- **Machine learning**: Software that learns a rule from examples instead of having the rule written by hand. It is where most hands-on artificial intelligence work starts.
- **Virtual environment**: A folder, usually .venv, with its own Python packages, isolated from the system Python and from other projects. Created with venv or uv, and never committed to Git.
- **Jupyter notebook**: A file of runnable code cells, each with its output shown below it, opened in JupyterLab. The usual place to explore data before code moves into scripts.
- **Training set and test set**: The rows a model learns from, and the rows held back to measure it once at the end. A score on rows the model has seen says little about new data.
- **Cross-validation**: Splitting the training set into k folds, training on k minus 1 of them and scoring on the one left out, k times, then averaging. Used to compare models without touching the test set.
- **Data leakage**: Information that would not exist at prediction time reaching the model during training, for example scaling fitted on the test rows. It produces scores that real data will not repeat.
- **Pipeline**: A scikit-learn object that chains preprocessing steps and a model, so that every step is fitted only on the data the pipeline is trained on.
- **Baseline**: The score of a model that ignores the inputs, such as always predicting the most common class. Any real model has to beat it.
- **Neural network**: Layers of weighted sums joined by simple non-linear functions, trained by repeatedly measuring the error and adjusting the weights. The basis of deep learning.
- **API key**: A secret string that identifies your account to a hosted model provider. Every call made with it is billed to you, so it is handled like a password.

## Common questions

### How do I get started with artificial intelligence in Python?

Install Python 3.14, create a virtual environment, install scikit-learn, pandas and JupyterLab, and train a classifier on a dataset that ships with scikit-learn. Split off a test set first, compare against a baseline, and score on the test set once. Then try a small PyTorch network and a hosted model API.

### Do I need a GPU to learn AI with Python?

No. Every example in this guide runs on a laptop CPU in a few seconds. A GPU starts to matter when you train neural networks on images, audio, text or large datasets; the install selector on pytorch.org then gives the right build for your hardware.

### Should I learn scikit-learn or PyTorch first?

scikit-learn. It teaches the workflow every project needs (splitting, pipelines, cross-validation, baselines and metrics) on problems where simple models do well. Move to PyTorch when your data is images, sound or text, or when a simple model stops being good enough.

### Is Python fast enough for machine learning?

Yes, because the heavy arithmetic does not run in Python. Libraries such as NumPy do their numerical work in compiled C code, and Python is the readable layer that calls them. Work on whole arrays rather than looping over single values in Python, and the speed of that compiled code is yours.

### How much math do I need to start?

Less than you might expect for a first project: averages, percentages and reading a table of results. Linear algebra, probability and derivatives become useful when you want to understand why models behave as they do, especially neural networks, and are easier to learn with working code in front of you.

### Can I use models from OpenAI, Anthropic or Google in Python?

Yes. Each provider publishes a Python SDK (openai, anthropic and google-genai) that reads an API key from an environment variable. The call itself is a few lines; the care goes into keeping the key out of your code, limiting spend and deciding what data you send.

## Sources
1. [NumPy](https://numpy.org/), NumPy project
2. [Stack Overflow 2025 Developer Survey: Technology](https://survey.stackoverflow.co/2025/technology), Stack Overflow
3. [Octoverse: A new developer joins GitHub every second as AI leads TypeScript to #1](https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/), GitHub
4. [Download Python](https://www.python.org/downloads/), Python Software Foundation
5. [torch](https://pypi.org/project/torch/), PyPI
6. [scikit-learn](https://pypi.org/project/scikit-learn/), PyPI
7. [Using Python on Windows](https://docs.python.org/3/using/windows.html), Python documentation
8. [venv: Creation of virtual environments](https://docs.python.org/3/library/venv.html), Python documentation
9. [Externally Managed Environments](https://packaging.python.org/en/latest/specifications/externally-managed-environments/), Python Packaging Authority
10. [uv: An extremely fast Python package and project manager](https://docs.astral.sh/uv/), Astral
11. [Working on projects](https://docs.astral.sh/uv/guides/projects/), Astral (uv documentation)
12. [Installing Jupyter](https://jupyter.org/install), Project Jupyter
13. [Toy datasets: Breast cancer Wisconsin (diagnostic) dataset](https://scikit-learn.org/stable/datasets/toy_dataset.html), scikit-learn
14. [load_breast_cancer](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_breast_cancer.html), scikit-learn
15. [Preprocessing data](https://scikit-learn.org/stable/modules/preprocessing.html), scikit-learn
16. [Cross-validation: evaluating estimator performance](https://scikit-learn.org/stable/modules/cross_validation.html), scikit-learn
17. [DummyClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.dummy.DummyClassifier.html), scikit-learn
18. [confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html), scikit-learn
19. [Common pitfalls and recommended practices](https://scikit-learn.org/stable/common_pitfalls.html), scikit-learn
20. [Get Started: Start Locally](https://pytorch.org/get-started/locally/), PyTorch
21. [Using uv with PyTorch](https://docs.astral.sh/uv/guides/integration/pytorch/), Astral (uv documentation)
22. [Optimizing Model Parameters](https://docs.pytorch.org/tutorials/beginner/basics/optimization_tutorial.html), PyTorch Tutorials
23. [Build the Neural Network](https://docs.pytorch.org/tutorials/beginner/basics/buildmodel_tutorial.html), PyTorch Tutorials
24. [Getting started with Keras](https://keras.io/getting_started/), Keras
25. [OpenAI Python API library](https://github.com/openai/openai-python), OpenAI (GitHub)
26. [Google Gen AI Python SDK](https://github.com/googleapis/python-genai), Google (GitHub)
27. [Rate limits: spend limits](https://platform.claude.com/docs/en/api/rate-limits), Anthropic
28. [about_Environment_Variables](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables), Microsoft Learn
29. [Python SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/python), Anthropic
30. [Get started with Claude](https://platform.claude.com/docs/en/get-started), Anthropic
31. [Models overview](https://platform.claude.com/docs/en/models/overview), Anthropic
32. [Create a Message](https://platform.claude.com/docs/en/api/messages/create), Anthropic (API reference)
33. [python-dotenv](https://pypi.org/project/python-dotenv/), PyPI
34. [Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html), OWASP Cheat Sheet Series
35. [sklearn (deprecated package)](https://pypi.org/project/sklearn/), PyPI
36. [Getting Started](https://scikit-learn.org/stable/getting_started.html), scikit-learn
37. [Learn the Basics](https://docs.pytorch.org/tutorials/beginner/basics/intro.html), PyTorch Tutorials
