---
title: "Build Your First Model"
description: "Building a machine learning model is not rocket science. In this article, I'll guide you through the essential steps to create your first model from scratch by understanding every magic behind it with simple language."
canonical_url: "https://otabek.io/blogs/build-your-first-model"
md_url: "https://otabek.io/blogs/build-your-first-model.md"
language: "en"
last_updated: "2025-11-20"
tags: ["Life"]
---

# Build Your First Model

Building a machine learning model isn’t rocket science. I want to show you that it’s fundamentally simple math, even if it looks intimidating from the outside. We’ll start by building a basic **House Price Predictor** entirely from scratch, just math and pure Python, no third-party libraries. After that, we’ll switch to the standard tools, and you’ll actually understand the “magic” happening under the hood because you’ve built it yourself first.

### Features (_x_) and Targets (_y_)

Before jumping into code, it’s important to understand how a machine “sees” a problem. Think like a real estate agent: if I ask, _“How much is this house?”_ your first question will be, _“How big is it?”_. In machine learning terms, we call these:

1. **Feature (_x_):** The input data — the information you _know_.
   _(Example: the size of the house.)_

2. **Target (_y_):** The output data — the value you want to _predict_.
   _(Example: the price of the house.)_

The goal of our model is simple: look at _x_ and discover the mathematical relationship that leads to _y_. To teach a computer anything, we need examples. So let’s imagine we have historical data for three houses:

1. **House A:** 600 sq ft → sold for 150,000
2. **House B:** 1000 sq ft → sold for 250,000
3. **House C:** 1500 sq ft → sold for 375,000

In most programming languages, we can store this data using **arrays (lists)**. For example:

```python-run
house_sizes = [600, 1000, 1500]
house_prices = [150000, 250000, 375000]
print("House sizes:", house_sizes)
print("House prices:", house_prices)
```

### The “Magic Number” (Weights)

Now we have data, but no intelligence yet not in us, in our program. In machine learning, that “intelligence” is simply a mathematical relationship. You might wonder how that’s possible, but hold that thought for a moment. First, focus on finding a relationship of the form:

$price = weight * size$

This multiplier is called **w** (the _weight_). It tells us how strongly the input affects the output. A higher weight means even a small increase in size leads to a large jump in price, and vice versa.

Let’s build a simple **prediction function** using the sizes and prices from earlier. Look at the numbers: what is the “magic number” _w_ that converts size into price? Multiply each size by the same value and you get the corresponding price. Even a kindergartener would spot it. The number is **250**.

How did we find it? Straightforward math:

$weight = price / size$

```python-run
def find_weight(price, size):
    return price / size

def predict_price(size, weight):
    return size * weight

size = 600
price = 150000
weight = find_weight(price, size)
print("The weight is:", weight)

predicted_price = predict_price(1000, weight)
print("Our prediction for size 1000 sq ft is:", predicted_price)
```

Now the model can predict house prices based purely on size. A simple start, but a solid one.

### The “Loss” (How wrong are we?)

In the earlier example, everything lined up perfectly. Every house followed the rule `size * 250` without a single mistake. **Real-world data never behaves this cleanly.**
Imagine a new house hits the market:

- **Size:** 1200 sq ft
- **Actual Price:** $330,000 (maybe it has a great view)

Using our model (`w = 250`), the prediction becomes:

$1200 * 250 = 300,000$

Our model says 300,000. The real price is 330,000. We’re off by 30,000. This difference is the **Loss** (or **Error**). To compute it:

$Loss = |Predicted_Price - Actual_Price|$

The absolute value ensures the loss is never negative. The entire purpose of machine learning is essentially: **Reduce the loss as close to zero as possible.**

```python-run
def calculate_loss(predicted_price, actual_price):
    return abs(predicted_price - actual_price)

def find_weight(price, size):
    return price / size

def predict_price(size, weight):
    return size * weight

size = 600
price = 150000
weight = find_weight(price, size)
print("The weight is:", weight)

# Test with a new house
house_size = 1200
actual_price = 330000
predicted_price = predict_price(house_size, weight)
print("Our prediction for size 1200 sq ft is:", predicted_price)

loss = calculate_loss(predicted_price, actual_price)
print("The loss here is:", loss)
```

### Hot or Cold

Now comes the interesting part. We have a **model** and a way to measure **loss**, but we still need an **optimizer** logic that automatically adjusts the weight to reduce the error. Think of it like tuning an old radio: you twist the knob, hear static (high error), adjust again, and keep going until the signal becomes clear.

**The process:**

1. Start with a random guess for the weight (say, 0).
2. Make a prediction.
3. Compute the loss.
4. **Update:** If the loss is high, adjust the weight.
5. Repeat until the mistake shrinks.

```python-run
house_size = 1000
actual_price = 250_000

def calculate_loss(predicted_price, actual_price):
    return abs(predicted_price - actual_price)

def find_weight(price, size):
    return price / size

def predict_price(size, weight):
    return size * weight

# Using old data: 600 sq ft -> $150,000
weight = find_weight(600, 150000)

for weight in range(0, 500):
    prediction = predict_price(house_size, weight)
    loss = calculate_loss(prediction, actual_price)

    if loss == 0:
        print(f"Found it! The best weight is: {weight}")
        break
```

### Gradient Descent (The “Step”)

Brute force worked only because the correct answer `250` was small and clean. If the correct weight were `250.4217` or `1,000,000`, counting one by one would be useless. Real machine learning moves **intelligently**, following the slope of the error toward the minimum. This method is called **Gradient Descent**.

Picture yourself on a foggy mountain:

- If the ground slopes _down_, you walk that way.
- If it slopes _up_, you turn around.

The same idea applies here. **Logic:**

1. Make a prediction.
2. If the prediction is **too low**, increase the weight (`+ step`).
3. If the prediction is **too high**, decrease the weight (`– step`).

```python-run
def calculate_loss(predicted_price, actual_price):
    return abs(predicted_price - actual_price)

def find_weight(price, size):
    return price / size

def predict_price(size, weight):
    return size * weight

house_size = 1000
actual_price = 250_000

# Using old data: 600 sq ft -> $150,000
weight = find_weight(600, 150000)
step = 10

while True:
    prediction = predict_price(house_size, weight)

    if prediction == actual_price:
        print(f"Found it! Weight: {weight}")
        break
    elif prediction > actual_price:
        print("Overshot!")
        break
    else:
        print(f"Prediction {prediction} too low, stepping up.")
        weight += step
```

### The “Best Fit”

So far, we’ve matched **one** house perfectly. Real datasets contain thousands of houses, each with noise, quirks, and outliers. Consider these two:

1. **House A:** 1000 sq ft → $200,000 (ratio: 200)
2. **House B:** 1000 sq ft → $300,000 (ratio: 300)

Maybe House B has a gold-plated bathroom; maybe House A has termites. Either way, **no single weight can satisfy both perfectly.**

- If weight is 200, House A is perfect and House B is wrong.
- If weight is 300, House B is perfect and House A is wrong.

When perfection is impossible, we aim to be **“the least wrong.”** We search for the line that best threads through the middle. This is the **Line of Best Fit**. To find it, we compute the **Total Error**:

$Total Error = Error(House A) + Error(House B)$

The best weight is the one that produces the smallest total. **Data:**

- House A: size = 1000, price = 200,000
- House B: size = 1000, price = 300,000

```python-run
# Manual version for clarity
size_a = 1000
price_a = 200_000

size_b = 1000
price_b = 300_000

def calculate_total_error(weight):
    predict_a = size_a * weight
    predict_b = size_b * weight

    error_a = abs(predict_a - price_a)
    error_b = abs(predict_b - price_b)

    return error_a + error_b

print(f"Total Error for 200: {calculate_total_error(200)}")
print(f"Total Error for 250: {calculate_total_error(250)}")
```

### The Missing Piece (The Bias)

There’s a flaw in our current formula (`Price = Size * Weight`).
If a house has a size of **0**, the predicted price becomes **0**.
**That’s obviously wrong.** Even a tiny house sits on land, and land alone has value. In school, you saw this in the familiar line equation:

$y = mx + c$

Machine learning uses the same structure with different symbols:

$y = wx + b$

- **w (Weight):** How strongly the input affects the output (the slope).
- **b (Bias):** The baseline value, the price even when the size is zero (the y-intercept).

![Image of linear regression with y-intercept](https://encrypted-tbn3.gstatic.com/licensed-image?q=tbn:ANd9GcT5ZlycCJIZ1wf5TAvZFIFUZfQAdlDhJRxqPJhQq0H-kTXf0UiyxGxr_Vwd0RCJIskWhoIuadS8hBQUzhFUzswb10T4NqhaTYVbkxrkgQgsJb_pyW0)

With this addition, our prediction formula becomes:

$[\text{Price} = ( \text{Size} \cdot \text{Weight} ) + \text{Bias}]$

```python-run
bias = 50000  # base price of land
weight = 250  # learned weight
size = 1000

prediction = (size * weight) + bias
print(f"prediction is {prediction}")
```

The prediction comes out to **300,000**.

This piece completes the fundamental unit of modern AI: **the linear neuron.**

- **Deep Learning** is thousands of these (wx + b) units stacked and connected.
- **Models like ChatGPT** are billions of them working together.

![Image of single neuron diagram vs neural network](https://encrypted-tbn3.gstatic.com/licensed-image?q=tbn:ANd9GcSEBNjHQvGdnTo1h6IgfBKKU4W6PWvgQJnpUKb9v0l_lr1iK_LJxOley0FnrbX_7hR_-KEjsYbCQvyELVGbrtQiYVmxb8KSP9zWf-5h1o2iqkF5KMM)

At this point, the core idea is clear:
**Guess a weight, measure the loss, adjust the weight.**
Manually coding this teaches the fundamentals, but real-world projects rely on optimized libraries that perform these steps instantly for millions of items.

Next, we move to **Scikit-Learn** (`sklearn`), a widely used machine learning toolkit. Instead of writing `predict` or `train` functions by hand, we hand the data to a model object that learns the best weight and bias automatically.

1. `model = LinearRegression()` — create an empty model.
2. `model.fit(x, y)` — run the training loop internally.
3. `model.predict(x)` — apply the learned formula ((x \times w) + b).

One detail: libraries expect data in **2D form**, not plain lists like `[600, 1000]`.
Why? Because real houses usually have **multiple** features (size, rooms, age, etc.). So the expected format is:

```
[[600], [1000], [1500]]
```

Here’s the full working example. Try it on your own cuz in our environment `scikit-learn` is not installed

```python
from sklearn.linear_model import LinearRegression

def train(x, y) -> LinearRegression:
    model = LinearRegression()
    model.fit(x, y)
    print("Model trained!")
    return model

sizes = [[600], [1000], [1500]]
prices = [150000, 250000, 375000]

model = train(sizes, prices)
new_house = [[2000]]
predicted = model.predict(new_house)
print(predicted)
```

---

```quiz
{
  "quiz": {
    "id": "ml-basics-quiz",
    "title": "Machine Learning Basics Quiz",
    "description": "Test your understanding of ML fundamentals",
    "questions": [
      {
        "id": "q1",
        "type": "single-choice",
        "question": "In machine learning, what is a 'Feature'?",
        "options": [
          { "id": "a", "text": "The input data you know", "description": "" },
          { "id": "b", "text": "The output you want to predict", "description": "That's the Target. Features are the inputs." },
          { "id": "c", "text": "The error in your model", "description": "That's the Loss. Features are input data." },
          { "id": "d", "text": "The type of algorithm", "description": "Features are data, not algorithm types." }
        ]
      },
      {
        "id": "q2",
        "type": "single-choice",
        "question": "What is the 'Weight' in a linear model?",
        "options": [
          { "id": "a", "text": "The multiplier that converts input to output", "description": "" },
          { "id": "b", "text": "How heavy the model file is", "description": "Weight is a mathematical concept, not file size." },
          { "id": "c", "text": "The number of training examples", "description": "Weight is the multiplier in the model equation." },
          { "id": "d", "text": "The speed of training", "description": "Weight is the learned parameter, not speed." }
        ]
      },
      {
        "id": "q3",
        "type": "drag-fill",
        "question": "Complete the linear model formula:",
        "template": "price = (size * {{b1}}) + {{b2}}",
        "options": [
          { "id": "opt1", "content": "weight" },
          { "id": "opt2", "content": "bias" }
        ],
        "blanks": [
          { "id": "b1" },
          { "id": "b2" }
        ]
      },
      {
        "id": "q4",
        "type": "single-choice",
        "question": "What is the purpose of the 'Loss' function?",
        "options": [
          { "id": "a", "text": "To measure how wrong the prediction is", "description": "" },
          { "id": "b", "text": "To delete bad data", "description": "Loss measures error, it doesn't delete data." },
          { "id": "c", "text": "To speed up training", "description": "Loss measures accuracy, not speed." },
          { "id": "d", "text": "To store the model", "description": "Loss is for measuring error, not storage." }
        ]
      },
      {
        "id": "q5",
        "type": "single-choice",
        "question": "What is Gradient Descent?",
        "options": [
          { "id": "a", "text": "A method to intelligently adjust weights to reduce error", "description": "" },
          { "id": "b", "text": "A way to sort data", "description": "Gradient Descent optimizes weights, not sorts data." },
          { "id": "c", "text": "A type of neural network", "description": "Gradient Descent is an optimization method used in neural networks." },
          { "id": "d", "text": "A database query", "description": "Gradient Descent is a machine learning concept." }
        ]
      },
      {
        "id": "q6",
        "type": "drag-drop",
        "question": "Arrange the machine learning training steps:",
        "items": [
          { "id": "guess", "content": "Start with a guess for weight" },
          { "id": "predict", "content": "Make a prediction" },
          { "id": "loss", "content": "Calculate the loss" },
          { "id": "adjust", "content": "Adjust the weight" },
          { "id": "repeat", "content": "Repeat until loss is minimized" }
        ]
      }
    ]
  },
  "answers": {
    "q1": { "correctOptionIds": ["a"] },
    "q2": { "correctOptionIds": ["a"] },
    "q3": { "correctPlacements": { "b1": "opt1", "b2": "opt2" } },
    "q4": { "correctOptionIds": ["a"] },
    "q5": { "correctOptionIds": ["a"] },
    "q6": { "correctOrder": ["guess", "predict", "loss", "adjust", "repeat"] }
  }
}
```


## Sitemap

See the full [Markdown sitemap](/sitemap.md) for all pages.
