Practical Regression

Знайомство з scikit-learn

Вступ до бібліотеки scikit-learn — стандарту машинного навчання в Python. Універсальний API, перша модель та базові метрики якості.

У попередній статті ми розглянули теоретичні основи лінійної регресії: формули, градієнтний спуск, функцію втрат. Тепер настав час перейти від теорії до практики та навчитися будувати моделі машинного навчання за допомогою найпопулярнішої бібліотеки Python — scikit-learn.

Excel + калькулятор vs scikit-learn

Уявіть, що вам потрібно обчислити лінійну регресію для датасету з 1000 рядків та 10 ознак. Якби ви робили це "вручну", код виглядав би приблизно так:

import numpy as np

def fit_linear_regression(X, y, learning_rate=0.01, epochs=1000):
    """Навчання лінійної регресії через градієнтний спуск"""
    n_samples, n_features = X.shape
    
    # Ініціалізація параметрів
    weights = np.zeros(n_features)
    bias = 0
    
    # Градієнтний спуск
    for epoch in range(epochs):
        # Передбачення
        y_pred = np.dot(X, weights) + bias
        
        # Обчислення градієнтів
        dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
        db = (1 / n_samples) * np.sum(y_pred - y)
        
        # Оновлення параметрів
        weights -= learning_rate * dw
        bias -= learning_rate * db
    
    return weights, bias

def predict(X, weights, bias):
    """Передбачення"""
    return np.dot(X, weights) + bias

# Використання
X_train = np.array([[1], [2], [3], [4], [5]])
y_train = np.array([2, 4, 6, 8, 10])

weights, bias = fit_linear_regression(X_train, y_train)
predictions = predict(np.array([[6], [7]]), weights, bias)

Різниця очевидна: 3 рядки замість 50! При цьому scikit-learn працює швидше (оптимізований C-код), надійніше (перевірений мільйонами користувачів) і зручніше (єдиний інтерфейс для всіх алгоритмів).

Аналогія: scikit-learn — це як кухонний комбайн для машинного навчання. Замість того, щоб різати, місити та збивати вручну (писати алгоритми з нуля), ви просто натискаєте кнопку .fit(). Усередині — та сама математика, але упакована у зручний інструмент.


Що таке scikit-learn?

scikit-learn (sklearn) — найпопулярніша бібліотека машинного навчання для Python. Вона надає простий та ефективний інструментарій для аналізу даних та побудови прогнозних моделей.

🎯 Основні переваги

  • Єдиний API для всіх алгоритмів
  • Open-source з активною спільнотою
  • Відмінна документація з прикладами
  • Швидкість (оптимізований C/Cython код)
  • Стабільність (v1.0+ — зворотна сумісність)

🔧 Що входить у scikit-learn?

  • Алгоритми регресії та класифікації
  • Методи кластеризації
  • Інструменти preprocessing (масштабування, кодування)
  • Метрики оцінки моделей
  • Cross-validation та підбір гіперпараметрів
  • Інтеграція з NumPy, pandas, matplotlib
scikit-learn не включає глибоке навчання (deep learning). Для нейронних мереж використовуються інші бібліотеки: TensorFlow, PyTorch, Keras. Але для класичного ML (регресія, дерева рішень, SVM, тощо) scikit-learn — це стандарт індустрії.

Встановлення scikit-learn

pip install scikit-learn

Після встановлення перевірте версію:

In [1]:
import sklearn

print(f"scikit-learn version: {sklearn.__version__}")
Out[1]:
scikit-learn version: 1.5.2
Рекомендується версія 1.5.0 або новіша. У цій версії покращено API (наприклад, sparse_output=False замість застарілого sparse=False у OneHotEncoder), додано нові алгоритми та виправлено помилки.

Філософія scikit-learn — універсальний API

Ключова ідея scikit-learn — єдиний інтерфейс для всіх моделей. Будь-яка модель машинного навчання (від простої лінійної регресії до складного градієнтного бустингу) має три основні методи:

.fit(X, y)

Навчити модель на даних. Модель знаходить оптимальні параметри на основі тренувальних даних.

.predict(X)

Передбачити значення для нових даних. Використовує навчені параметри для генерації прогнозів.

.score(X, y)

Оцінити якість моделі. Для регресії повертає R² (коефіцієнт детермінації).

Це означає, що навчившись працювати з LinearRegression, ви автоматично знаєте, як працювати з Ridge, RandomForest, GradientBoosting та іншими моделями — API однаковий!

Аналогія: всі автомобілі мають руль, педалі газу та гальма, коробку передач — незалежно від марки. Так само всі моделі scikit-learn мають .fit(), .predict(), .score() — незалежно від алгоритму.

Додатково для трансформерів (preprocessing: scaler, encoder) є методи:

  • .transform(X) — перетворити дані (після навчання)
  • .fit_transform(X) — навчити + перетворити за один виклик

Перша модель — ідеальні дані

Почнемо з найпростішого прикладу: ідеальна лінійна залежність y = 2x. Створимо дані вручну та навчимо модель їх розпізнати.

Формат даних у scikit-learn

Важливо! scikit-learn очікує, що X (ознаки) буде двовимірним масивом (матрицею), навіть якщо у вас лише одна ознака. Це пов'язано з тим, що scikit-learn розроблений для роботи з багатовимірними даними.
  • ✅ Правильно: X = [[1], [2], [3]] — двовимірний масив (3 рядки, 1 стовпець)
  • ❌ Неправильно: X = [1, 2, 3] — одновимірний масив (викличе помилку)
first_model.ipynb
Python 3.11
Code
In [1]:
from sklearn.linear_model import LinearRegression
import numpy as np

# Створення даних: y = 2x
X = np.array([[1], [2], [3], [4], [5]])
y = np.array([2, 4, 6, 8, 10])

print("X (ознаки):")
print(X)
print(f"\nФорма X: {X.shape}")  # (5, 1) — 5 рядків, 1 стовпець
print(f"\ny (цільова змінна): {y}")
Out[1]:
X (ознаки):
[[1]
[2]
[3]
[4]
[5]]
Форма X: (5, 1)
y (цільова змінна): [2 4 6 8 10]
In [2]:
# Створити модель
model = LinearRegression()

# Навчити модель (знайти оптимальні w та b)
model.fit(X, y)

print("Модель навчена!")
print(f"Коефіцієнт (w): {model.coef_}")      # Очікуємо [2.]
print(f"Зсув (b): {model.intercept_}")       # Очікуємо 0.0
Out[2]:
Модель навчена!
Коефіцієнт (w): [2.]
Зсув (b): 0.0
Модель ідеально знайшла закономірність: y = 2 * x + 0. Коефіцієнт w = 2 означає, що при збільшенні x на 1, значення y збільшується на 2. Зсув b = 0, тому що пряма проходить через початок координат.

Крок 3: Передбачення для нових даних

Тепер використаємо навчену модель для передбачення значень y для нових x:

In [3]:
# Передбачити значення для x = 6 та x = 7
X_new = np.array([[6], [7]])
predictions = model.predict(X_new)

print("Передбачення:")
for x_val, y_pred in zip(X_new, predictions):
    print(f"  x = {x_val[0]} → y = {y_pred:.1f}")
Out[3]:
Передбачення:
x = 6 → y = 12.0
x = 7 → y = 14.0

Модель правильно передбачила: 6 * 2 = 12 та 7 * 2 = 14. Це підтверджує, що вона зрозуміла залежність y = 2x.


Візуалізація результатів

Побудуємо графік, щоб наочно побачити, як модель "проводить лінію" через дані:

In [4]:
import matplotlib.pyplot as plt

# Створення графіка
plt.figure(figsize=(10, 6))

# Вихідні дані
plt.scatter(X, y, color='dodgerblue', s=120, label='Вихідні дані', zorder=3, edgecolor='black')

# Лінія регресії
X_line = np.linspace(0, 8, 100).reshape(-1, 1)
y_line = model.predict(X_line)
plt.plot(X_line, y_line, color='crimson', linewidth=2.5, label='Лінія регресії', zorder=2)

# Передбачення для нових точок
plt.scatter(X_new, predictions, color='limegreen', s=180, marker='*', 
            label='Передбачення', zorder=4, edgecolor='black')

# Оформлення
plt.xlabel('X', fontsize=12)
plt.ylabel('y', fontsize=12)
plt.title('Перша модель scikit-learn: y = 2x', fontsize=14, fontweight='bold')
plt.legend(fontsize=10)
plt.grid(alpha=0.3, linestyle='--')
plt.xlim(0, 8)
plt.ylim(0, 16)
plt.tight_layout()
plt.show()
Out[4]:
На графіку видно три елементи:
  • Сині точки — вихідні дані, на яких навчалась модель
  • Червона лінія — лінія регресії y = 2x, знайдена моделлю
  • Зелені зірочки — передбачення для нових точок (x=6, x=7)
Усі точки лежать точно на лінії, тому що дані ідеальні (без шуму). У реальних задачах точки завжди розкидані навколо лінії.

Метрики якості моделі

Як зрозуміти, наскільки добре модель працює? Для цього використовуються метрики якості. У попередній статті ми розглянули три основні метрики для регресії:

  • MAE (Mean Absolute Error) — середня абсолютна помилка
  • MSE (Mean Squared Error) — середня квадратична помилка
  • R² (R-squared) — коефіцієнт детермінації

Метод .score() — швидка оцінка

Найпростіший спосіб оцінити модель — метод .score(X, y), який повертає R²:

In [5]:
# Оцінка якості на тренувальних даних
r2 = model.score(X, y)

print(f"R² (коефіцієнт детермінації): {r2:.4f}")
Out[5]:
R² (коефіцієнт детермінації): 1.0000

R² = 1.0 означає ідеальну модель — вона на 100% пояснює варіацію даних. Це логічно, адже дані ідеальні (без шуму), і модель точно знайшла закономірність.

Обчислення всіх трьох метрик

Для детальної оцінки можна обчислити всі три метрики окремо:

In [6]:
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# Передбачення на тренувальних даних
y_pred = model.predict(X)

# Обчислення метрик
mae = mean_absolute_error(y, y_pred)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)

print("Метрики якості:")
print(f"  MAE:  {mae:.6f}")
print(f"  MSE:  {mse:.6f}")
print(f"  R²:   {r2:.6f}")
Out[6]:
Метрики якості:
MAE: 0.000000
MSE: 0.000000
R²: 1.000000

Усі метрики підтверджують: модель ідеальна. MAE та MSE дорівнюють нулю (жодної помилки), R² дорівнює 1.0 (пояснює 100% варіації).

Інтерпретація метрик:
  • MAE = 0 → в середньому помилка 0 (ідеально)
  • MSE = 0 → квадратична помилка 0 (ідеально)
  • R² = 1.0 → модель пояснює 100% варіації (ідеально)
У реальних задачах такі результати неможливі через шум у даних. Типові значення:
  • R² > 0.7 — добра модель
  • R² > 0.5 — прийнятна модель
  • R² < 0.3 — погана модель (потрібно покращувати)

Приклад з реальнішими даними — Зріст vs Вага

Тепер розглянемо приклад, ближчий до реальності: залежність ваги людини від зросту. Дані містять шум (індивідуальні відмінності), тому модель не буде ідеальною.

height_weight.ipynb
Python 3 (ipykernel)
Code
In [1]:
import numpy as np
from sklearn.linear_model import LinearRegression

# Дані: 10 людей
heights = np.array([[150], [160], [165], [170], [175], 
                    [180], [185], [190], [195], [200]])  # см
weights = np.array([50, 58, 62, 68, 73, 78, 83, 88, 93, 98])  # кг

print(f"Кількість зразків: {len(heights)}")
print(f"Діапазон зросту: {heights.min()} - {heights.max()} см")
print(f"Діапазон ваги: {weights.min()} - {weights.max()} кг")
Out[1]:
Кількість зразків: 10
Діапазон зросту: 150 - 200 см
Діапазон ваги: 50 - 98 кг
In [2]:
# Створити та навчити модель
model = LinearRegression()
model.fit(heights, weights)

print("Модель навчена!")
print(f"Коефіцієнт (w): {model.coef_[0]:.4f} кг/см")
print(f"Зсув (b): {model.intercept_:.4f} кг")
print(f"\nРівняння: вага = {model.coef_[0]:.4f} * зріст + {model.intercept_:.4f}")
Out[2]:
Модель навчена!
Коефіцієнт (w): 0.9818 кг/см
Зсув (b): -98.6818 кг
Рівняння: вага = 0.9818 * зріст + -98.6818

Модель знайшла залежність: вага ≈ 0.98 × зріст - 98.7. Це означає, що зі збільшенням зросту на 1 см вага зростає приблизно на 0.98 кг.

Чи має сенс від'ємний зсув (b = -98.7)?Математично — так, це просто константа у рівнянні. Але фізично це означає, що людина зростом 0 см мала б від'ємну вагу, що безглуздо. Це підкреслює важливий принцип: модель працює лише в діапазоні даних, на яких вона навчалась (150-200 см). Екстраполяція за межі цього діапазону ненадійна.

Передбачення для нового зросту

In [3]:
# Передбачити вагу для зросту 172 см
new_height = np.array([[172]])
predicted_weight = model.predict(new_height)

print(f"Зріст: {new_height[0][0]} см")
print(f"Передбачена вага: {predicted_weight[0]:.2f} кг")
Out[3]:
Зріст: 172 см
Передбачена вага: 70.19 кг

Оцінка якості моделі

In [4]:
from sklearn.metrics import mean_absolute_error, r2_score

# Передбачення на всіх даних
y_pred = model.predict(heights)

# Метрики
mae = mean_absolute_error(weights, y_pred)
r2 = model.score(heights, weights)

print(f"R²:  {r2:.4f}")
print(f"MAE: {mae:.4f} кг")
print(f"\nІнтерпретація:")
print(f"  - Модель пояснює {r2*100:.2f}% варіації ваги")
print(f"  - Середня помилка: ±{mae:.2f} кг")
Out[4]:
R²: 0.9981
MAE: 0.4273 кг
Інтерпретація:
- Модель пояснює 99.81% варіації ваги
- Середня помилка: ±0.43 кг
Чому R² ≈ 0.998, а не рівно 1.0? На відміну від першого ідеального прикладу, у цих даних є невеликі індивідуальні відхилення (шум). Хоча залежність дуже сильна і модель пояснює 99.81% варіації, середня похибка прогнозу становить близько 430 грамів.Важливо: Оцінка на тих самих даних, на яких навчалась модель — це погана практика. У наступних статтях ми навчимося правильно розбивати дані на тренувальну та тестову вибірки.

Візуалізація моделі

In [5]:
import matplotlib.pyplot as plt

# Графік
plt.figure(figsize=(10, 6))

# Вихідні дані
plt.scatter(heights, weights, color='dodgerblue', s=120, 
            label='Вихідні дані', zorder=3, edgecolor='black')

# Лінія регресії
heights_line = np.linspace(145, 205, 100).reshape(-1, 1)
weights_line = model.predict(heights_line)
plt.plot(heights_line, weights_line, color='crimson', linewidth=2.5, 
         label='Лінія регресії', zorder=2)

# Нове передбачення
plt.scatter(new_height, predicted_weight, color='limegreen', s=200, marker='*',
            label=f'Передбачення ({new_height[0][0]} см → {predicted_weight[0]:.1f} кг)',
            zorder=4, edgecolor='black')

# Оформлення
plt.xlabel('Зріст (см)', fontsize=12)
plt.ylabel('Вага (кг)', fontsize=12)
plt.title(f'Зріст vs Вага (R² = {r2:.4f})', fontsize=14, fontweight='bold')
plt.legend(fontsize=10)
plt.grid(alpha=0.3, linestyle='--')
plt.tight_layout()
plt.show()
Out[5]:

Порівняння: ручна реалізація vs scikit-learn

Підсумуємо переваги використання scikit-learn замість написання алгоритмів з нуля:

АспектРучна реалізаціяscikit-learn
Кількість коду~50 рядків3 рядки (.fit(), .predict(), .score())
СкладністьПотрібна математика (градієнти, матриці)Не потрібна (абстрагована)
Час розробкиГодини (написання + налагодження)Хвилини
Швидкість виконанняПовільно (Python loops)Швидко (C/Cython, оптимізовано)
НадійністьЛегко зробити помилкуПеревірено мільйонами користувачів
ПідтримкаСамостійнаВелика спільнота, документація
Інші алгоритмиКожен треба писати з нуляДоступно 50+ алгоритмів з тим самим API
Коли писати власну реалізацію?
  • Для навчання — щоб зрозуміти, як працює алгоритм (саме це ми робили у статті 3.1)
  • Для дослідження — якщо потрібен унікальний алгоритм, якого немає в scikit-learn
  • Для оптимізації — якщо стандартна реалізація не підходить під специфічні вимоги
У всіх інших випадках використовуйте scikit-learn — це стандарт індустрії.

Що далі?

У цій статті ми познайомились з основами scikit-learn:

✅ Встановили бібліотеку та перевірили версію
✅ Зрозуміли універсальний API: .fit(), .predict(), .score()
✅ Побудували першу модель на синтетичних даних
✅ Навчились обчислювати метрики якості (MAE, MSE, R²)
✅ Візуалізували результати з matplotlib

У наступній статті ми перейдемо до роботи з реальним датасетом Housing Prices — датасетом про ціни на житло з Kaggle. Це змагання, в якому брали участь тисячі Data Scientists. Ми:

  • Завантажимо датасет з 80 ознаками та 1460 будинками
  • Проведемо Exploratory Data Analysis (EDA) — розвідувальний аналіз даних
  • Виявимо пропуски, викиди, кореляції між ознаками
  • Побудуємо візуалізації для розуміння даних
  • Підготуємо базу для побудови моделі у наступних статтях

Практика


Резюме

scikit-learn

Стандартна бібліотека машинного навчання для Python. Open-source, швидка, з єдиним API для всіх алгоритмів.

Estimator

Універсальний інтерфейс для всіх моделей ML. Будь-яка модель має методи .fit(), .predict(), .score().

.fit(X, y)

Навчити модель на даних. Модель знаходить оптимальні параметри (w, b).

.predict(X)

Зробити передбачення для нових даних X. Повертає масив передбачень.

.score(X, y)

Оцінити якість моделі. Для регресії повертає R² (коефіцієнт детермінації, від 0 до 1).

MAE

Mean Absolute Error — середня абсолютна помилка. Показує, наскільки в середньому модель помиляється (в одиницях цільової змінної).

MSE

Mean Squared Error — середня квадратична помилка. Сильніше "карає" великі помилки через квадрат.

R² (R-squared)

Коефіцієнт детермінації. Показує, яку частку варіації даних пояснює модель. R²=1.0 — ідеально, R²=0.0 — модель не краща за просте середнє.
Copyright © 2026