← Назад к вопросам
Как работает machine learning под капотом?
2.0 Middle🔥 141 комментариев
#Python Core#Soft Skills
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает Machine Learning под капотом
Machine Learning (МЛ) — это дисциплина, которая позволяет компьютерам учиться на примерах без явного программирования каждого правила. Вот как это происходит.
1. Основной цикл обучения
Все МЛ алгоритмы следуют одной схеме:
# 1. Подготовка данных
X_train = [[2, 3], [4, 5], [6, 7], ...] # Признаки (features)
y_train = [1, 1, 0, ...] # Ответы (labels)
# 2. Инициализация модели со случайными весами
weights = [0.1, 0.2] # w1, w2
bias = 0.5 # b
# 3. Цикл обучения (эпохи)
for epoch in range(100):
# Прямой проход (Forward pass)
predictions = []
for x in X_train:
y_pred = x[0] * weights[0] + x[1] * weights[1] + bias
predictions.append(y_pred)
# Вычисляем ошибку (Loss function)
loss = sum((y_true - y_pred) ** 2 for y_true, y_pred in zip(y_train, predictions)) / len(y_train)
# Градиентный спуск (Backward pass)
# Вычисляем производные (градиенты)
dw1 = sum(2 * (y_pred - y_true) * x[0] for x, y_true, y_pred in zip(X_train, y_train, predictions)) / len(y_train)
dw2 = sum(2 * (y_pred - y_true) * x[1] for x, y_true, y_pred in zip(X_train, y_train, predictions)) / len(y_train)
db = sum(2 * (y_pred - y_true) for y_true, y_pred in zip(y_train, predictions)) / len(y_train)
# Обновляем веса (Update weights)
learning_rate = 0.01
weights[0] -= learning_rate * dw1
weights[1] -= learning_rate * dw2
bias -= learning_rate * db
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss}")
# 4. Предсказание на новых данных
new_x = [3, 4]
prediction = new_x[0] * weights[0] + new_x[1] * weights[1] + bias
2. Градиентный спуск визуально
Oшибка (Loss) по осям весов:
Loss
/\
/ \
/ \ <- Локальный минимум
/ \
___/________\___
w1, w2
На каждой итерации делаем маленький шаг вниз (вдоль градиента).
Цель: достичь локального минимума где Loss наименьшее.
# Пример: функция потерь и градиентный спуск
import numpy as np
import matplotlib.pyplot as plt
def loss_function(w):
"""Квадратичная функция потерь"""
return (w - 5) ** 2
def gradient(w):
"""Производная"""
return 2 * (w - 5)
# Начинаем с w=0
w = 0
learning_rate = 0.1
history = [w]
for _ in range(50):
grad = gradient(w)
w = w - learning_rate * grad # Шаг в направлении минимума
history.append(w)
print(f"w={w:.3f}, loss={loss_function(w):.3f}")
# После 50 итераций w ≈ 5 (минимум функции)
print(f"\nНайденное значение: w={w:.3f}")
print(f"Истинный минимум: w=5")
Вывод:
w=0.400, loss=21.160
w=0.720, loss=18.506
w=0.976, loss=16.105
...
w=4.999, loss=0.000
3. Нейронная сеть (Neural Network)
Это граф из нейронов и слоев:
# Простая нейронная сеть (2 входа -> 1 выход)
import numpy as np
class SimpleNeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
# Инициализируем веса случайно
self.W1 = np.random.randn(input_size, hidden_size) * 0.01
self.b1 = np.zeros((1, hidden_size))
self.W2 = np.random.randn(hidden_size, output_size) * 0.01
self.b2 = np.zeros((1, output_size))
def relu(self, x):
"""Функция активации ReLU"""
return np.maximum(0, x)
def relu_derivative(self, x):
return (x > 0).astype(float)
def sigmoid(self, x):
"""Функция активации Sigmoid"""
return 1 / (1 + np.exp(-np.clip(x, -500, 500)))
def forward(self, X):
"""Прямой проход (Forward pass)"""
# Скрытый слой
self.z1 = np.dot(X, self.W1) + self.b1
self.a1 = self.relu(self.z1) # Активация
# Выходной слой
self.z2 = np.dot(self.a1, self.W2) + self.b2
self.a2 = self.sigmoid(self.z2) # Вероятность
return self.a2
def backward(self, X, y, learning_rate=0.01):
"""Обратный проход (Backward pass) - backpropagation"""
m = X.shape[0]
# Ошибка на выходе
dz2 = self.a2 - y
dW2 = np.dot(self.a1.T, dz2) / m
db2 = np.sum(dz2, axis=0, keepdims=True) / m
# Ошибка на скрытом слое
da1 = np.dot(dz2, self.W2.T)
dz1 = da1 * self.relu_derivative(self.z1)
dW1 = np.dot(X.T, dz1) / m
db1 = np.sum(dz1, axis=0, keepdims=True) / m
# Обновляем веса
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
def train(self, X, y, epochs=100, learning_rate=0.01):
for epoch in range(epochs):
# Прямой проход
output = self.forward(X)
# Вычисляем ошибку
loss = -np.mean(y * np.log(output + 1e-8) + (1-y) * np.log(1-output + 1e-8))
# Обратный проход
self.backward(X, y, learning_rate)
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss:.4f}")
def predict(self, X):
return (self.forward(X) > 0.5).astype(int)
# Использование
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]]) # XOR задача
model = SimpleNeuralNetwork(input_size=2, hidden_size=4, output_size=1)
model.train(X, y, epochs=100)
print("\nПредсказания:")
for x, y_true in zip(X, y):
pred = model.predict(x.reshape(1, -1))[0, 0]
print(f"Input: {x}, True: {y_true[0]}, Predicted: {pred}")
4. Основные концепции
Overfitting vs Underfitting
# Overfitting: модель слишком сложная, запомнила всё
# Train loss = 0.01, Test loss = 0.80
# Underfitting: модель слишком простая
# Train loss = 0.50, Test loss = 0.50
# Golden sweet spot:
# Train loss = 0.10, Test loss = 0.12
# Регуляризация (L2, L1) помогает избежать overfitting:
class RegularizedNN:
def compute_loss(self, output, y, lambda_reg=0.01):
# Loss + регуляризация
ce_loss = -np.mean(y * np.log(output))
l2_loss = lambda_reg * np.sum(self.W1**2 + self.W2**2)
return ce_loss + l2_loss
Батчи (Batch Processing)
# Вместо обновления весов на всех примерах сразу,
# обновляем на батче (подмножество)
def train_with_batches(X, y, batch_size=32, epochs=10):
for epoch in range(epochs):
# Перемешиваем данные
indices = np.random.permutation(len(X))
X_shuffled = X[indices]
y_shuffled = y[indices]
# Итерируем по батчам
for i in range(0, len(X), batch_size):
X_batch = X_shuffled[i:i+batch_size]
y_batch = y_shuffled[i:i+batch_size]
# Обучаем на батче
model.forward(X_batch)
model.backward(X_batch, y_batch)
5. Популярные алгоритмы
Linear Regression (Линейная регрессия)
from sklearn.linear_model import LinearRegression
# Предсказываем непрерывное значение
X = [[1], [2], [3], [4], [5]]
y = [2, 4, 5, 4, 6]
model = LinearRegression()
model.fit(X, y)
prediction = model.predict([[6]]) # [7.2]
Decision Trees (Деревья решений)
from sklearn.tree import DecisionTreeClassifier
# Классификация с помощью дерева
X = [[0, 0], [1, 1], [0, 1], [1, 0]]
y = [0, 1, 1, 0]
model = DecisionTreeClassifier()
model.fit(X, y)
prediction = model.predict([[0.5, 0.5]]) # [1]
K-Means (Кластеризация)
from sklearn.cluster import KMeans
# Группируем данные в K групп
X = [[1, 1], [2, 2], [10, 10], [11, 11]]
model = KMeans(n_clusters=2)
model.fit(X)
print(model.labels_) # [0, 0, 1, 1]
6. Практический пример: классификатор цифр
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
# Загружаем данные (изображения цифр 0-9)
digits = load_digits()
X, y = digits.data, digits.target
# Нормализуем данные
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Разделяем на train и test
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42
)
# Обучаем нейронную сеть
model = MLPClassifier(
hidden_layer_sizes=(128, 64, 32), # 3 скрытых слоя
learning_rate_init=0.001,
batch_size=32,
max_iter=500,
random_state=42
)
model.fit(X_train, y_train)
# Оцениваем
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Точность: {accuracy:.2%}") # ~97%
print(confusion_matrix(y_test, y_pred))
7. Типичные ошибки в МЛ
# Ошибка 1: Не нормализировать данные
# Плохо
model.fit(X, y) # X может быть в разных масштабах
# Хорошо
from sklearn.preprocessing import StandardScaler
X_scaled = StandardScaler().fit_transform(X)
model.fit(X_scaled, y)
# Ошибка 2: Использовать одни же данные для train и test
# Плохо
model.fit(X, y)
accuracy = model.score(X, y) # Переобучение!
# Хорошо
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model.fit(X_train, y_train)
accuracy = model.score(X_test, y_test)
# Ошибка 3: Неправильный выбор метрики
# Плохо: использовать accuracy для imbalanced dataset
y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] # 90% класс 0
# Хорошо: использовать F1-score
from sklearn.metrics import f1_score
f1 = f1_score(y_test, y_pred)
Заключение
Machine Learning под капотом — это:
- Функция потерь — мера того, насколько модель ошибается
- Градиентный спуск — алгоритм нахождения оптимальных весов
- Нейронные сети — универсальные аппроксиматоры функций
- Backpropagation — эффективный способ вычисления градиентов
- Регуляризация — предотвращение переобучения
- Батчи и эпохи — стратегия обучения
Это как обучение человека: делаем ошибку, учимся на ошибке, улучшаемся!