В данном задании необходимо реализовать обучение логистической и линейной регрессий с помощью различных вариантов градиентного спуска.
Правила оценивания найдите на странице курса.
Реализуйте логистическую регрессию с лог-лоссом, обучаемую с помощью:
Задание 1 (1 балл) Градиентного спуска;
Подробнее о методах можно прочитать тут. Напомним, что лог-лосс вычисляется по формуле $$ \mathcal{L}(y, X, w) = -\cfrac{1}{n} \sum_{i=1}^{n} [y_i=1]\log \sigma(\langle w, x_i\rangle) + [y_i=0]\log (1 - \sigma(\langle w, x_i\rangle)) + \lambda_2 ||w||_2^2 + \lambda_1 ||w||_1 $$ где $\sigma(x) = 1 / (1 + \exp(-x))$, а $\lambda_1, \lambda_2 > 0$ -- параметры регуляризации. Считайте, что либо $\lambda_1 = 0$, либо $\lambda_2 = 0$.
Необходимо соблюдать следующие условия:
Все вычисления должны быть векторизованы;
Циклы средствами python допускается использовать только для итераций градиентного спуска в методе fit; также разрешается использовать только стандартные средства языка Python и библиотеку numpy.
Обучение необходимо приостанавливать, если выполнено хотя бы одно из двух условий:
tolerance
);max_iter
).Чтобы проследить, что оптимизационный процесс действительно сходится, будем использовать атрибут loss_history
— в нём после вызова метода fit
должны содержаться значения функции потерь для всех итераций, начиная с первой (до совершения первого шага по антиградиенту);
Инициализировать веса можно случайным образом или нулевым вектором.
Ниже приведён шаблон класса, который должен содержать код реализации каждого из методов.
import numpy as np
from sklearn.base import BaseEstimator
class LogReg(BaseEstimator):
def __init__(self, lambda_1=0.0, lambda_2=1.0, gd_type='full',
tolerance=1e-4, max_iter=1000, w0=None, alpha=1e-3, eta=0.0):
"""
lambda_1: L1 regularization param
lambda_2: L2 regularization param
gd_type: 'full', 'stochastic' or 'momentum'
tolerance: for stopping gradient descent
max_iter: maximum number of steps in gradient descent
w0: np.array of shape (d) - init weights
alpha: learning rate
eta: ignored
"""
self.lambda_1 = lambda_1
self.lambda_2 = lambda_2
self.gd_type = gd_type
self.tolerance = tolerance
self.max_iter = max_iter
self.w0 = w0
self.alpha = alpha
self.w = None
self.loss_history = None
self.eta = eta
def fit(self, X, y):
"""
X: np.array of shape (l, d)
y: np.array of shape (l)
---
output: self
"""
self.loss_history = []
pass
return self
def predict_proba(self, X):
"""
X: np.array of shape (l, d)
---
output: np.array of shape (l, 2) where
first column has probabilities of -1
second column has probabilities of +1
"""
if self.w is None:
raise Exception('Not trained yet')
pass
def calc_gradient(self, X, y):
"""
X: np.array of shape (l, d) (l can be equal to 1 if stochastic)
y: np.array of shape (l)
---
output: np.array of shape (d)
"""
pass
def calc_loss(self, X, y):
"""
X: np.array of shape (l, d)
y: np.array of shape (l)
---
output: float
"""
pass
Задание 2 (0 баллов).
Ладно, мы сделали это за вас. =)
data = pd.read_csv('train.csv', index_col=0)
target = data.target.values
data = data.drop('target', axis=1)
# some resampling
np.random.seed(910)
mask_plus = np.unique(np.random.choice(np.where(target == 1)[0], 100000, replace=True))
mask_zero = np.unique(np.random.choice(np.where(target == 0)[0], 100000, replace=True))
data = pd.concat((data.iloc[mask_plus], data.iloc[mask_zero]))
target = np.hstack((target[mask_plus], target[mask_zero]))
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.3)
Задание 3 (0.5 балла). Обучите и провалидируйте LogReg на данных из предыдущего пункта, посчитайте по тестовой выборке AUC-ROC и F-меру. Исследуйте влияние параметров max_iter
и alpha
на процесс оптимизации. Согласуется ли оно с вашими ожиданиями? (здесь подразумеваются графики, на которых отображаются значения метрик в зависимости от значения параметра).
Реализуйте логистическую регрессию с лог-лоссом, обучаемую с помощью:
Задание 4 (1.5 балла) Стохастического градиентного спуска;
Задание 5 (1.5 балла) Стохастического градиентного спуска с Momentum.
Подробнее о методах можно прочитать тут. Напомним, что лог-лосс вычисляется по формуле $$ \mathcal{L}(y, X, w) = -\cfrac{1}{n} \sum_{i=1}^{n} [y_i=1]\log \sigma(\langle w, x_i\rangle) + [y_i=0]\log (1 - \sigma(\langle w, x_i\rangle)) + \lambda_2 ||w||_2^2 + \lambda_1 ||w||_1 $$ где $\sigma(x) = 1 / (1 + \exp(-x))$, а $\lambda_1, \lambda_2 > 0$ -- параметры регуляризации. Считайте, что либо $\lambda_1 = 0$, либо $\lambda_2 = 0$.
Во всех пунктах необходимо соблюдать следующие условия:
Все вычисления должны быть векторизованы;
Циклы средствами python допускается использовать только для итераций градиентного спуска в методе fit; также разрешается использовать только стандартные средства языка Python и библиотеку numpy.
Обучение необходимо приостанавливать, если выполнено хотя бы одно из двух условий:
tolerance
);max_iter
).Чтобы проследить, что оптимизационный процесс действительно сходится, будем использовать атрибут loss_history
— в нём после вызова метода fit
должны содержаться значения функции потерь для всех итераций, начиная с первой (до совершения первого шага по антиградиенту);
Инициализировать веса можно случайным образом или нулевым вектором.
Ниже приведён шаблон класса, который должен содержать код реализации каждого из методов.
import numpy as np
from sklearn.base import BaseEstimator
class LogReg(BaseEstimator):
def __init__(self, lambda_1=0.0, lambda_2=1.0, gd_type='stochastic',
tolerance=1e-4, max_iter=1000, w0=None, alpha=1e-3, eta=0.0):
"""
lambda_1: L1 regularization param
lambda_2: L2 regularization param
gd_type: 'full', 'stochastic' or 'momentum'
tolerance: for stopping gradient descent
max_iter: maximum number of steps in gradient descent
w0: np.array of shape (d) - init weights
alpha: learning rate
eta: momentum parameter (weight of momentum vector)
"""
self.lambda_1 = lambda_1
self.lambda_2 = lambda_2
self.gd_type = gd_type
self.tolerance = tolerance
self.max_iter = max_iter
self.w0 = w0
self.alpha = alpha
self.w = None
self.loss_history = None
def fit(self, X, y):
"""
X: np.array of shape (l, d)
y: np.array of shape (l)
---
output: self
"""
self.loss_history = []
pass
return self
def predict_proba(self, X):
"""
X: np.array of shape (l, d)
---
output: np.array of shape (l, 2) where
first column has probabilities of -1
second column has probabilities of +1
"""
if self.w is None:
raise Exception('Not trained yet')
pass
def calc_gradient(self, X, y):
"""
X: np.array of shape (l, d) (l can be equal to 1 if stochastic)
y: np.array of shape (l)
---
output: np.array of shape (d)
"""
pass
def calc_loss(self, X, y):
"""
X: np.array of shape (l, d)
y: np.array of shape (l)
---
output: float
"""
pass
Задание 5.5 (1 балл). Обучите и провалидируйте оба метода на данных из пункта 2, посчитайте по тестовой выборке AUC-ROC и F-меру. Исследуйте влияние параметров max_iter
, alpha
и eta
на процесс оптимизации. Согласуется ли оно с вашими ожиданиями? (здесь подразумеваются графики, на которых отображаются значения метрик в зависимости от значения параметра).
Задание 6 (1.5 балла). Постройте графики (на одной и той же картинке) зависимости величины функции потерь от номера итерации для полного, стохастического градиентного спусков, а также для полного градиентного спуска с методом Momentum. Постройте аналогичные графики для зависимости от времени работы в секундах. Сделайте выводы о скорости сходимости различных модификаций градиентного спуска.
Назовём график красивым, если он соответствует требованиям, предъявленным к графикам в первом дз. В этом задании от вас требуются красивые графики.
Далее мы проанализируем то, как работает линейная регрессия и регуляризация. Тут уже можно пользоваться sklearn'ом.
Задание 7 (0 баллов). Загрузите обучающие данные из соревнования New York City Taxi Trip Duration. Разделите выборку в отношении 7:3. Преобразуйте целевую переменную (trip_duration) как $\widetilde{y} = \log(1 + y)$. Удалите столбец id, а также столбцы, содержащие дату и время. Отнормируйте признаки при помощи MinMaxScaler'a. Как вы думаете, почему такое преобразование имеет смысл?
Задание 8 (1 балл). Обучите три вида линейной регрессии на получившихся данных: обычную, Ridge и Lasso. Оцените качество при помощи MSE и $R^2$.
Задание 9 (1 балл). Постройте графики зависимости значения метрик из предыдущего задания от значения коэффициента регуляризации для методов Lasso и Ridge. Какие выводы можно сделать?
Хорошие ли получились результаты?
Задание 10 (0.5 баллов). При помощи кросс-валидации найдите оптимальные значения коэффициента регуляризации для методов Ridge и Lasso.
Задание 11 (0.5 баллов). Постройте bar plot весов признаков для каждой из трёх моделей (на одном рисунке). Какие выводы можно сделать?
Какие фичи оказались наиболее важными? Согласуется ли это с вашими ожиданиями?
Задание 12 (2 балла). Добавьте в датасет дополнительные признаки, основываясь на существующих, чтобы получить значение метрики MSE на тестовом куске данных не более 0.4. Что вы для этого сделали?
Бонусные задачи оцениваются особенно строго. Оценка может быть снижена за плохой код и даже за некрасивые названия переменных. Подсказок не даём.
Задание 13 (0.5 баллов). Правда ли, что лог-лосс является выпуклой функцией относительно $w$? Правда ли, что она является Липшицевой относительно $w$? Почему?
Задание 14 (3 балла). В этом задании на 2 балла засчитывается один из двух пунктов:
добавьте при необходимости параметры в класс модели, повторите пункты 2 и 3 и сравните результаты.
На 3 балла засчитываются оба пункта со сравнением методов и выводами.
Задание 15 (0.00 баллов). Вставьте ниже самый смешной или самый грустный график, который получился у вас в этом дз.