Неделя 3: Логистическая регрессия и классификация
1. Теоретическая часть
1.1. Логистическая регрессия
Логистическая регрессия — алгоритм для задач бинарной классификации (да/нет, 1/0). В отличие от линейной регрессии, предсказывает вероятность принадлежности к классу.
Сигмоидная функция (логит)
Преобразует линейную комбинацию признаков в вероятность (от 0 до 1):
𝜎(𝑧)=11+𝑒−𝑧σ(z)=1+e−z1
где 𝑧=𝜃𝑇𝑥z=θTx.
Функция потерь (Log Loss)
𝐽(𝜃)=−1𝑚∑𝑖=1𝑚[𝑦(𝑖)log(ℎ𝜃(𝑥(𝑖)))+(1−𝑦(𝑖))log(1−ℎ𝜃(𝑥(𝑖)))]J(θ)=−m1i=1∑m[y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))]
Градиентный спуск
Аналогичен линейной регрессии, но с производными для сигмоиды:
∂𝐽(𝜃)∂𝜃𝑗=1𝑚∑𝑖=1𝑚(ℎ𝜃(𝑥(𝑖))−𝑦(𝑖))𝑥𝑗(𝑖)∂θj∂J(θ)=m1i=1∑m(hθ(x(i))−y(i))xj(i)
1.2. Метрики качества классификации
Метрика
Формула
Описание
Accuracy
𝑇𝑃+𝑇𝑁𝑇𝑃+𝑇𝑁+𝐹𝑃+𝐹𝑁TP+TN+FP+FNTP+TN
Общая точность
Precision
𝑇𝑃𝑇𝑃+𝐹𝑃TP+FPTP
Точность положительного класса
Recall
𝑇𝑃𝑇𝑃+𝐹𝑁TP+FNTP
Полнота положительного класса
F1-score
2⋅𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛⋅𝑅𝑒𝑐𝑎��𝑙𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛+𝑅𝑒𝑐𝑎𝑙𝑙2⋅Precision+RecallPrecision⋅Recall
Гармоническое среднее
ROC-AUC
Площадь под ROC-кривой
Качество разделения классов
1.3. Многоклассовая классификация
One-vs-Rest (OvR): Для каждого класса обучается отдельный бинарный классификатор.
Softmax: Обобщение сигмоиды для множества классов.
2.1. Реализация логистической регрессии
python
Copy
def sigmoid(z):
return 1 / (1 + np.exp(-z))
class LogisticRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None
def fit(self, X, y):
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0
for _ in range(self.n_iterations):
linear_model = np.dot(X, self.weights) + self.bias
y_pred = sigmoid(linear_model)
dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
db = (1 / n_samples) * np.sum(y_pred - y)
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict_proba(self, X):
linear_model = np.dot(X, self.weights) + self.bias
return sigmoid(linear_model)
def predict(self, X, threshold=0.5):
return (self.predict_proba(X) >= threshold).astype(int)
2.2. Использование Scikit-learn
python
Copy
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
# Данные
X, y = ... # Например, датасет breast_cancer
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Обучение
model = LogisticRegression()
model.fit(X_train, y_train)
# Предсказания
y_pred = model.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred))
print("Confusion Matrix:\n", confusion_matrix(y_test, y_pred))
2.3. ROC-кривая и AUC
python
Copy
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt
y_proba = model.predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
auc = roc_auc_score(y_test, y_proba)
plt.plot(fpr, tpr, label=f"AUC = {auc:.2f}")
plt.plot([0, 1], [0, 1], linestyle='--')
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.legend()
plt.show()
3. Домашнее задание
Задача 1: Классификация на Iris
1. Загрузите датасет Iris (from sklearn.datasets import load_iris).
2. Обучите логистическую регрессию в режиме многоклассовой классификации (multi_class='ovr').
3. Оцените качество через accuracy и confusion matrix.
Решение:
python
Copy
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
model = LogisticRegression(multi_class='ovr')
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print("Accuracy:", accuracy_score(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
Задача 2: Влияние порога классификации
1. Для датасета breast_cancer постройте график Precision-Recall при изменении порога от 0.1 до 0.9.
2. Найдите оптимальный порог по метрике F1-score.
Решение:
python
Copy
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_test, y_proba)
f1_scores = 2 * (precisions * recalls) / (precisions + recalls)
optimal_idx = np.argmax(f1_scores)
optimal_threshold = thresholds[optimal_idx]
plt.plot(thresholds, precisions[:-1], label="Precision")
plt.plot(thresholds, recalls[:-1], label="Recall")
plt.plot(thresholds, f1_scores[:-1], label="F1")
plt.axvline(optimal_threshold, color='red', linestyle='--')
plt.legend()
plt.show()
Задача 3: Регуляризация
Исследуйте влияние L2-регуляризации на логистическую регрессию:
Сравните качество модели при C=0.01, 1, 100 (меньше C → сильнее регуляризация).
Визуализируйте веса признаков для каждого случая.
Решение:
python
Copy
for C in [0.01, 1, 100]:
model = LogisticRegression(C=C, penalty='l2')
model.fit(X_train, y_train)
print(f"C={C}, Weights:", model.coef_)
plt.bar(range(n_features), model.coef_[0])
plt.title(f"Feature weights (C={C})")
plt.show()
Итоги недели
✅ Разобрали логистическую регрессию и сигмоидную функцию.
✅ Научились оценивать качество через precision, recall, F1, ROC-AUC.
✅ Реализовали многоклассовую классификацию (OvR).
✅ Исследовали регуляризацию и выбор порога.
Следующая тема: Метод опорных векторов (SVM) и ядерные методы.