Введение в ML
🎯 Цель
После прочтения этой главы:
- Поймёте, что такое Machine Learning и когда его нужно использовать
- Узнаете разницу между Supervised, Unsupervised и Reinforcement learning
- Узнаете, зачем нужны Training, Validation, Test sets
- Распознаете проблемы Overfitting и Underfitting
- Напишете один полный ML pipeline (idea → data → model → evaluation)
Что нужно изучить
- Что такое ML и когда он нужен(когда не стоит отказываться)
- Типы ML-задач — supervised vs unsupervised vs reinforcement
- Supervised tasks — regression vs classification
- Train / Validation / Test — почему делим на 3 части
- Overfitting и Underfitting — bias-variance tradeoff
- Cross-validation — стратегия k-fold
- Scikit-learn API design —
fit,predict,transform,fit_transform - Pipeline и ColumnTransformer
Библиотеки
pip install scikit-learn pandas numpy matplotlib seaborn joblib
Основная версия: scikit-learn 1.4+.
Важные темы
Когда ML не нужен?
Как backend dev, если работают простые правила if/else — не используйте ML. Случаи, когда ML нужен:
✅ Правил очень много и они меняются (spam filter) ✅ Сложный паттерн (распознавание изображений, перевод) ✅ Персонализация (отдельно для каждого пользователя) ✅ Прогноз (будущие продажи, риск заболевания)
❌ Есть точная формула (area = π * r²) ❌ Мало данных (10 примеров — не ML, пишите правила) ❌ Critical safety (бесконтрольный ML — опасно) ❌ Требуется explainability, а ML — чёрный ящик
Типы ML-задач
1. Supervised Learning (input → output mavjud)
├── Regression: continuous output
│ └── Misol: uy narxi, harorat, foydalanuvchi LTV
└── Classification: discrete classes
├── Binary: spam/not-spam, churn/retain
└── Multi-class: rasm turi, kasallik turi
2. Unsupervised Learning (faqat input)
├── Clustering: o'xshashlarni guruhlash
├── Dimensionality reduction: PCA, t-SNE
└── Anomaly detection: g'ayrioddiy nuqtalar
3. Reinforcement Learning (agent + reward)
└── O'yinlar, robotics, recommendation systems
Разделение Train / Validation / Test
**Зачем?**Чтобы оценить, как модель будет работать на «будущих» данных.
Hammasi (100%)
├── Training set (60-70%) — model o'rganadi
├── Validation set (15-20%) — hyperparameter tuning
└── Test set (15-20%) — yakuniy baholash (faqat 1 marta!)
**Важное правило:**Test set нельзя видеть при обучении модели. Иначе — data leakage и некорректный результат.
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, random_state=42, stratify=y
)
Overfitting vs Underfitting
Underfitting Just right Overfitting
. . .
/ \ / \ /\/\
/ \ / \ / \
/ \ / \ / \
Model juda Model muvozanatda Model trainni
oddiy yodlab olgan
| Training accuracy | Test accuracy | |
|---|---|---|
| Underfitting | Низкая | Низкая |
| Just right | Высокая | Высокая |
| Overfitting | Очень высокая | Низкая |
Решения:
- Underfitting: более сложная модель, больше features
- Overfitting: regularization, больше data, более простая модель, cross-validation
Cross-validation
Один train/test split иногда несправедлив. Решение — k-fold cross-validation:
5-fold CV:
Fold 1: Test=[1], Train=[2,3,4,5]
Fold 2: Test=[2], Train=[1,3,4,5]
Fold 3: Test=[3], Train=[1,2,4,5]
Fold 4: Test=[4], Train=[1,2,3,5]
Fold 5: Test=[5], Train=[1,2,3,4]
→ 5 ta accuracy → mean ± std
Примеры кода
Полный пример pipeline (Iris classification)
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score, classification_report
import joblib
# 1. Загрузка data
iris = load_iris(as_frame=True)
X, y = iris.data, iris.target
# 2. Train/test split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 3. Создание pipeline (preprocessing + model вместе)
pipeline = Pipeline([
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=1000, random_state=42)),
])
# 4. Train
pipeline.fit(X_train, y_train)
# 5. Predict и оценка
y_pred = pipeline.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# 6. Сохранение
joblib.dump(pipeline, "iris_model.joblib")
Cross-validation
from sklearn.model_selection import cross_val_score
scores = cross_val_score(pipeline, X, y, cv=5, scoring="accuracy")
print(f"CV accuracy: {scores.mean():.3f} ± {scores.std():.3f}")
print(f"Each fold: {scores}")
ColumnTransformer (mixed types)
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
# Отдельный preprocessing для числовых и categorical столбцов
preprocessor = ColumnTransformer([
("num", StandardScaler(), ["age", "salary"]),
("cat", OneHotEncoder(handle_unknown="ignore"), ["city", "department"]),
])
full_pipeline = Pipeline([
("preprocess", preprocessor),
("classifier", LogisticRegression()),
])
full_pipeline.fit(X_train, y_train)
Интеграция с backend
Serve ML-модели в FastAPI (минимально)
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
import joblib
import numpy as np
app = FastAPI()
model = joblib.load("iris_model.joblib")
CLASS_NAMES = ["setosa", "versicolor", "virginica"]
class IrisInput(BaseModel):
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class IrisPrediction(BaseModel):
class_name: str
confidence: float
@app.post("/predict", response_model=IrisPrediction)
def predict(data: IrisInput):
X = np.array([[data.sepal_length, data.sepal_width,
data.petal_length, data.petal_width]])
pred = model.predict(X)[0]
proba = model.predict_proba(X)[0]
return IrisPrediction(
class_name=CLASS_NAMES[pred],
confidence=float(proba.max()),
)
@app.get("/health")
def health():
return {"status": "ok", "model_version": "v1"}
uvicorn main:app --reload
# POST http://localhost:8000/predict
# {"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}
Best practices for ML serving
from contextlib import asynccontextmanager
from fastapi import FastAPI
# Загружать модель только один раз (lifespan)
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.model = joblib.load("iris_model.joblib")
app.state.model_version = "v1.2.0"
yield
# cleanup if needed
app = FastAPI(lifespan=lifespan)
Ресурсы
- Scikit-learn User Guide — scikit-learn.org/stable/user_guide.html
- “Hands-On Machine Learning” — Aurélien Géron (3-е издание) — MUST READ книга
- Andrew Ng — Machine Learning Specialization(Coursera) — бесплатный auditing
- StatQuest — лучший YouTube для объяснения ML-алгоритмов
- Kaggle Learn — Intro to Machine Learning (бесплатный мини-курс)
🏋️ Упражнения
🟢 Easy
- Загрузите
sklearn.datasets.load_wine(), выполните classify черезLogisticRegression, выведите accuracy. - Измените
random_stateвtrain_test_splitнесколько раз, посмотрите разницу. - Сравните 3-fold и 10-fold CV через
cross_val_score.
🟡 Medium
- Пример Pipeline: создайте
Pipelineдля Titanic dataset —SimpleImputer+OneHotEncoder+StandardScaler+LogisticRegression. - Stratification: посмотрите разницу с
stratify=yи без него на imbalanced dataset. - Overfitting demo: добавьте
PolynomialFeatures(degree=20)к одному признаку и визуально покажите overfitting.
🔴 Hard
- FastAPI ML-сервис: containerize Iris classifier в Docker, добавьте CI/CD через GitHub Actions, создайте healthcheck endpoint. Эта работа станет основой для MLOps-проекта в 6-м месяце.
- Custom Estimator: создайте custom transformer, наследуясь от
BaseEstimatorиTransformerMixin— чтобы можно было использовать внутриPipeline.
Capstone
notebooks/month-02/00_ml_intro.ipynb:
- Загрузите California Housing dataset (
sklearn.datasets.fetch_california_housing) - Train/test split, train
LinearRegression - Оцените с cross-validation (RMSE)
- Запишите в виде Pipeline (
StandardScaler+LinearRegression) - Создайте FastAPI endpoint и протестируйте с
curl
✅ Чек-лист
- Знаю разницу между Supervised и Unsupervised
- Могу отличить задачи Regression и Classification
- Понимаю, зачем нужно разделение Train/Validation/Test
- Распознаю Overfitting и Underfitting при их появлении
- Пишу cross-validation в коде
- Использую Scikit-learn Pipeline и ColumnTransformer
- Умею сохранять модель и serve в FastAPI
- Понимаю важность
random_state=42
Переходим к Regression.