Вы находитесь на странице: 1из 19

27.04.

2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В прошлом уроке мы узнали, как обучить и применить модель линейной регрессии, а так же как
измерить качество модели. В этом уроке поговорим, как улучшить этот простой алгоритм и сделать
обучение более эффективным. Мы познакомимся с понятиями "регуляризация" и "градиентный спуск".

Вы сможете обучать линейную регрессию, не "упираясь" в аппаратные ресурсы, а так же узнаете, как
увеличить качество решения с помощью механизма регуляризации.

Урок 1. Регуляризация
Регуляризация - это способ борьбы с таким явлением как "переобучение".

Что такое переобучение? Переобучение (англ. overfitting, буквально - "переподгонка") - негативное


явление, возникающее, когда алгоритм обучения вырабатывает предсказания, которые слишком близко
или точно соответствуют конкретному набору данных и поэтому не подходят для применения алгоритма
к дополнительным данным или будущим наблюдениям.

Пример оверфиттинга проще всего привести в виде картинки. Пусть вы решаете задачу классификации
на два класса ( о которой уже знаете с первых уроков этого курса)

сначала модель, которая обучена не совсем хорошо (underfit) - разделяющая линия прямая и много
"красных" точек неправильно классифицированы
затем хорошо обученная модель (normal) - есть какой-то баланс
переобученная модель (overfit) - разделяющая линия слишком сильно "облизывает" обучающие
данные.

Чем же плохо переобучение? Когда в модель придут "новые" точки, то качество модели будет низким,
потому что модель слишком сильно подогналась под обучающие данные. В этом случае говорят, что
падает "обобщающая способность" - модель не получается обощить на новые данные.

Почему происходит переобучение? Всё дело в алгоритме подбора параметров модели. В модуле
"Линейная регрессия. Часть I" в домашнем задании по уроку "Полиномиальная регрессия" нужно было
подобрать такой параметр, как "степень полинома". Напомним общий алгоритм выбора наилучшей
степени полинома:

1. возьмите все степени от 1 до 10 по порядку, без пропусков


2. для каждой степени полинома: обучите полиномиальную регрессию, сделайте предсказания и
вычислите метрику качества (например, r2-score)
3. найдите степень полинома, при которой у модели будет лучший r2-score

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 1/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

Вспомним, что эта процедура называется Grid Search и помогает найти лучшие параметры для модели
методом перебора.

Вот тут-то и поджидает нас переобучение! Мы выберем модель, которая даёт лучший скор на
обучающих данных. А вот когда в модель придут новые данные, то качество может быть сильно хуже

Как детектировать переобучение? Перед нами стоит вопрос, как выбрать правильные пераметры
модели, чтобы она не "оверфитнулась". Есть простой алгоритм, который называется "контроль на
отложенной (валидационной) выборке". Тренировку модели из пункта (2) алгоритма GridSearch придётся
немного усложнить:

разбиваем обучающую выборку на две части: в одной части 80% обучающих примеров (эта часть
называется train set), в другой части 20% обучающих примеров (эта часть называется validation set)
выбираем метрику качества модели (для регрессии, например, MSE)
обучаем модель на тренировочном наборе данных
делаем предсказания на валидационном наборе данных и вычисляем метрику качества

Признак переобучения: Если качество на валидации сильно хуже, чем качество на обучающем сете -
всё плохо, модель переобучилась. Запомните этот признак, скоро мы его применим на практике. Такую
модель нельзя использовать, с переобучением надо бороться!

Как бороться с переобучением линейной регрессии? Нам надо как-то "наказать" модель за то, что
она слишком сильно подгоняется под обучающую выборку. Это можно сделать помощью регуляризации!
Регуляризация - это специальная модификация модели линейной регрессии. В стандартной библиотеки
sklearn есть два класса, в которых реализована регуляризация:

sklearn.linear_model.Ridge, ссылка на доку https://scikit-


learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html (https://scikit-
learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html)
sklearn.linear_model.Lasso, ссылка на доку https://scikit-
learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html (https://scikit-
learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html)

Чем отличаются эти два класса мы узнаем в следующих уроках этого модуля. Мы уже знакомы с классом
sklearn.linear_model.LinearRegression , с который вообще не требует никаких параметров при
создании, а вот классы Ridge и Lasso принимают на вход т.н. параметр регуляризации alpha, который
0 1
принимает значения от до - чем ближе к единице, тем регуляризация сильнее, тем сильнее
наказываем модель за сильную "подгонку" под обучающие данные.

В следующем уроке мы продемонстрируем, как переобучается полиномиальная регрессия, а так же


попытаемся победить этот эффект с помощью регуляризации

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 2/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [47]:

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import LinearRegression
from numpy.linalg import norm
from matplotlib import pyplot as plt
from sklearn.linear_model import SGDRegressor
from scipy.spatial import distance
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import r2_score
%matplotlib inline

data = pd.read_csv("non_linear.csv")
data.head()

Out[47]:

x_train y_train

0 0.138368 0.838812

1 0.157237 0.889313

2 0.188684 1.430040

3 0.685553 1.717309

4 0.874237 2.032588

В [48]:

def generate_degrees(source_data: list, degree: int):


"""Функция, которая принимает на вход одномерный массив, а возвращает n-мерный

Для каждой степени от 1 до degree возводим x в эту степень


"""
return np.array([
source_data**n for n in range(1, degree + 1)
]).T

В [49]:

degree = 8
X = generate_degrees(data['x_train'], degree)

X.shape
Out[49]:

(50, 8)

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 3/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [50]:

y = data.y_train.values

y
Out[50]:

array([ 0.83881243, 0.88931326, 1.43003955, 1.7173094 , 2.03258831,


1.86034102, 1.87892766, 2.43001534, 2.32785552, 2.20364916,
2.20770757, 1.38803901, 1.71854419, 2.1032645 , 2.29517686,
1.96515239, 0.74594859, 1.16079805, 0.8472635 , 0.75558457,
1.3045932 , 1.06644218, 0.67694404, 0.57916634, 0.13337461,
0.17123457, 0.1961104 , -0.07201584, 0.11811017, 0.46667278,
0.31561051, 0.21494492, 0.05031305, 0.10614754, 0.05713164,
-0.05725158, 0.44923374, -0.33611985, -0.03823668, 0.09524973,
0.31302894, -0.23125656, 0.02493584, 0.41871855, 0.16572723,
0.26609198, 0.66943982, 0.89238334, 1.26586897, 0.66483917])

В [51]:

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, \


random_state=10)

В [52]:

model = Ridge(alpha=0.01).fit(X_train, y_train)

В [53]:

y_pred = model.predict(X_valid)
y_pred_train = model.predict(X_train)

В [54]:

print("Качество валидации %.3f" % mean_squared_error(y_valid, y_pred))


print("Качество на обучении %.3f" % mean_squared_error(y_train, y_pred_train))

Качество валидации 0.070


Качество на обучении 0.064

В [55]:

degree = 12
X = generate_degrees(data['x_train'], degree)
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, \
random_state = 10)
model = Ridge(alpha=0.01).fit(X_train, y_train)

D:\Anaconda\lib\site-packages\sklearn\linear_model\_ridge.py:148: LinAlgWarn
ing: Ill-conditioned matrix (rcond=5.80566e-22): result may not be accurate.
overwrite_a=True).T

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 4/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [56]:

y_pred = model.predict(X_valid)
y_pred_train = model.predict(X_train)
print("Качество валидации %.3f" % mean_squared_error(y_valid, y_pred))
print("Качество на обучении %.3f" % mean_squared_error(y_train, y_pred_train))

Качество валидации 0.077


Качество на обучении 0.058

В [ ]:

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 5/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [57]:

def train_polynomial(degree, data):


"""Генерим данные, тренируем модель
дополнительно рисуем график
"""
X = generate_degrees(data['x_train'], degree)
y = data.y_train.values
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state
model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_valid)
y_pred_train = model.predict(X_train)
error_valid = mean_squared_error(y_valid, y_pred)
error_train = mean_squared_error(y_train, y_pred_train)
print(
"Степень полинома %d\nОшибка на валидации %.3f\nОшибка на обучении %.3f" %
(degree, error_valid, error_train)
)
order_test = np.argsort(X_valid[:,0])
plt.scatter(X_valid[:,0][order_test], y_valid[order_test], 40, 'r', 'o', alpha=0.8)
print("Норма вектора весов \t||w|| = %.2f" % (norm(model.coef_)))
# визуализируем решение
x_linspace = np.linspace(data['x_train'].min(), data['x_train'].max(), num=100)
y_linspace = model.predict(generate_degrees(x_linspace, degree))
plt.plot(x_linspace, y_linspace)
return error_valid, error_train, norm(model.coef_)

degrees = []
valid_errors = []
train_errors = []
w_norm = []

train_polynomial(degree, data)
Степень полинома 12
Ошибка на валидации 0.125
Ошибка на обучении 0.051
Норма вектора весов ||w|| = 225.51

Out[57]:

(0.12518745769379575, 0.051126603910735445, 225.5082819466019)

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 6/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [58]:

degree = 3
error_valid, error_train, coef_norm = train_polynomial(degree, data)

degrees.append(degree)
valid_errors.append(error_valid)
w_norm.append(coef_norm)

Степень полинома 3
Ошибка на валидации 0.051
Ошибка на обучении 0.077
Норма вектора весов ||w|| = 2.19

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 7/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [59]:

mode_ridge = Ridge(alpha=0.01)
mode_linear = Ridge(alpha=0)
degree = 10
X = generate_degrees(data['x_train'], degree)
y = data.y_train.values
# обучение моделей
mode_ridge.fit(X, y)
mode_linear.fit(X, y)

x_linspace = np.linspace(data['x_train'].min(), data['x_train'].max(), num=100)


y_linspace_linear = mode_linear.predict(generate_degrees(x_linspace, degree))
y_linspace_ridge = mode_ridge.predict(generate_degrees(x_linspace, degree))

plt.plot(x_linspace, y_linspace_linear)
plt.plot(x_linspace, y_linspace_ridge)
plt.show()
D:\Anaconda\lib\site-packages\sklearn\linear_model\_ridge.py:148: LinAlgWarn
ing: Ill-conditioned matrix (rcond=5.48971e-19): result may not be accurate.
overwrite_a=True).T
D:\Anaconda\lib\site-packages\sklearn\linear_model\_ridge.py:148: LinAlgWarn
ing: Ill-conditioned matrix (rcond=2.24411e-22): result may not be accurate.
overwrite_a=True).T

В [ ]:

В [60]:

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, \


random_state=42)
print(X_train.shape, X_valid.shape)
(40, 10) (10, 10)

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 8/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [61]:

alphas = [0.1, 0.15, 0.35, 0.5, 0.8]

best_alpha = alphas[0]
best_rmse = np.infty

for alpha in alphas:


mode_ridge = Ridge(alpha=alpha)
mode_ridge.fit(X_train, y_train)
y_pred = mode_ridge.predict(X_valid)
error = mean_squared_error(y_valid, y_pred)
if error < best_rmse:
best_rmse = error
best_alpha = alpha
print("alpha=%.2f Ошибка %.5f" % (alpha, error))
print('\n-------\nЛучшая модель alpha=%.2f с ошибкой RMSE=%.5f\n------' % (best_alpha, best

alpha=0.10 Ошибка 0.04262


alpha=0.15 Ошибка 0.04230
alpha=0.35 Ошибка 0.04253
alpha=0.50 Ошибка 0.04295
alpha=0.80 Ошибка 0.04369

-------
Лучшая модель alpha=0.15 с ошибкой RMSE=0.04230
------

D:\Anaconda\lib\site-packages\sklearn\linear_model\_ridge.py:148: LinAlgWa
rning: Ill-conditioned matrix (rcond=8.01097e-18): result may not be accur
ate.
overwrite_a=True).T
D:\Anaconda\lib\site-packages\sklearn\linear_model\_ridge.py:148: LinAlgWa
rning: Ill-conditioned matrix (rcond=1.16361e-17): result may not be accur
ate.
overwrite_a=True).T
D:\Anaconda\lib\site-packages\sklearn\linear model\ ridge py:148: LinAlgWa

В [ ]:

В [62]:

X = np.array([[5,25],[2,10]])

В [63]:

np.linalg.inv(X)
Out[63]:

array([[-3.60287970e+15, 9.00719925e+15],
[ 7.20575940e+14, -1.80143985e+15]])

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 9/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [64]:

data.head()
data = data[(data.x_train > 1) & (data.x_train < 5)].copy()

X = data['x_train'].values.reshape(-1, 1) # превращаем X из простого массива в вектор-столб


y = data['y_train'].values

# разбиваем на трейн и валидацию


X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=10)

data.head()

Out[64]:

x_train y_train

5 1.182421 1.860341

6 1.251605 1.878928

7 1.270474 2.430015

8 1.402553 2.327856

9 1.427711 2.203649

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 10/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [65]:

sgd_regressor = SGDRegressor(learning_rate='constant', eta0=0.02, fit_intercept=True, rando


w_current, epsilon = np.random.random(2), 0.0001
weight_evolution, mse_evolution = [], [] # изменения весов и ошибка на валидации
for step in list(range(800)):
sgd_regressor = sgd_regressor.partial_fit(X_train, y_train)
weight_evolution.append(distance.euclidean(w_current, sgd_regressor.coef_))
if weight_evolution[-1]<epsilon:
print("Итарации остановлены на шаге %d" % step); break
mse_evolution.append(mean_squared_error(y_valid, sgd_regressor.predict(X_valid)))
w_current = sgd_regressor.coef_.copy()
plt.plot(range(step), mse_evolution)

Итарации остановлены на шаге 107

Out[65]:

[<matplotlib.lines.Line2D at 0x263384be548>]

В [66]:

x_linspace = np.linspace(data['x_train'].min(), data['x_train'].max(), num=100)

y_linspace= sgd_regressor.predict(x_linspace.reshape(-1,1))

plt.plot(x_linspace, y_linspace)
plt.scatter(data.x_train, data.y_train, 40, 'g', 'o', alpha=0.8, label='data')

plt.show()

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 11/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [ ]:

В [67]:

data = data[(data.x_train > 1) & (data.x_train < 5)].copy()


data.head()
Out[67]:

x_train y_train

5 1.182421 1.860341

6 1.251605 1.878928

7 1.270474 2.430015

8 1.402553 2.327856

9 1.427711 2.203649

В [68]:

def gradient (X, y, w) -> np.array:


#кол-во примеров в обучающей выборке
n = X.shape[0]
# прогноз
y_hat = X.dot(w.T)
# вычисляем ошибку
error = y - y_hat
# градиент
grad = np.multiply(X, error).sum(axis=0)*(-1)*2/n
return grad, error
def eval_w_next(X, y, eta, w_current):
# вычисляем градиент
grad, error = gradient(X, y, w_current)
# делаем шаг градиентного спуска
w_next = w_current - eta*grad
# проверяем условие сходимости
weight_evolution = distance.euclidean(w_current, w_next)
return (w_next, weight_evolution, grad)

def gradient_descent(X: np.array, y: np.array, eta=0.01, epsilon=0.001) -> np.array:


m = X.shape[1] # количество фичей
# инициализируем рандомом веса
w = np.random.random(m).reshape(1, -1)
w_next, weight_evolution, grad = eval_w_next(X, y, eta, w)
step = 0
# повторяем до сходимости вектора весов
while weight_evolution > epsilon:
w = w_next
w_next, weight_evolution, grad = eval_w_next(X, y, eta, w)
step += 1
if step % 100 ==0:
print("step %s |w-w_next|=%.5f, grad=%s" % (step, weight_evolution, grad))
return w

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 12/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [69]:

# трансформируем плоский массив X в вектор-столбец


X = data['x_train'].values.reshape(-1, 1)
n = X.shape[0]
# добавляем тривиальный признак w_0, столбец из единиц. См. прошлый урок, почему так
X = np.hstack([
np.ones(n).reshape(-1,1),
X
])
w = gradient_descent(X, data['y_train'].values.reshape(-1, 1), eta=0.008)

step 100 |w-w_next|=0.00422, grad=[-0.50658353 0.14634192]


step 200 |w-w_next|=0.00347, grad=[-0.41688066 0.12042853]
step 300 |w-w_next|=0.00286, grad=[-0.34306186 0.09910375]
step 400 |w-w_next|=0.00235, grad=[-0.28231445 0.08155503]
step 500 |w-w_next|=0.00193, grad=[-0.23232385 0.06711374]
step 600 |w-w_next|=0.00159, grad=[-0.19118529 0.05522963]
step 700 |w-w_next|=0.00131, grad=[-0.15733131 0.04544989]
step 800 |w-w_next|=0.00108, grad=[-0.12947199 0.03740188]

В [ ]:

Урок 3. Домашняя работа


Задание простого уровня Загрузите данные из файла non_linear.csv и сгенерируйте данные до
степени degree = 8 включительно. Обучите модель sklearn.linear_model.Lasso и модель
sklearn.linear_model.Ridge на полученных данных, используйте коэффициент регуляризации
𝛼 = 0.8 для обеих моделей. Постройте два столбчатых графика, на которых отобразите величину
коэффициентов для Ridge регрессии и Lasso регрессии в виде столбиков.

Пример графиков для 3-й степени (просто для примера, у вас может по-другому выглядеть). Какой
можно сделать в вывод по величине коэффициентов?:

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 13/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [70]:

data = pd.read_csv("non_linear.csv")
degree = 8

X = generate_degrees(data['x_train'], degree)
y = data.y_train.values

В [71]:

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=10)


model_R = Ridge(alpha=0.8).fit(X_train, y_train)
model_L = Lasso(alpha=0.8).fit(X_train, y_train)
R_coef = model_R.coef_
L_coef = model_L.coef_
print(R_coef)
print(L_coef)
[ 4.54261785e-01 3.41976833e-01 3.27582088e-02 -2.07134532e-01
3.63216319e-02 1.18194116e-02 -3.68031932e-03 2.63585521e-04]
[-0.00000000e+00 -0.00000000e+00 -1.08299601e-02 -9.52247249e-03
1.03490179e-03 1.87872250e-04 3.38785318e-06 -2.14838285e-06]

D:\Anaconda\lib\site-packages\sklearn\linear_model\_coordinate_descent.py:53
1: ConvergenceWarning: Objective did not converge. You might want to increas
e the number of iterations. Duality gap: 3.7134369621139554, tolerance: 0.00
24481555784964045
positive)

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 14/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [72]:

fig, ax = plt.subplots(figsize=(12, 8))


x = np.arange(len(R_coef))

bar_width = 0.4

ax.bar(x, R_coef, width=bar_width, label="Ridge")


ax.bar(x + bar_width, L_coef, width=bar_width, label="Lasso")
ax.legend()
Out[72]:

<matplotlib.legend.Legend at 0x2633946f808>

В [73]:

y_pred_valid_R = model_R.predict(X_valid)
y_pred_train_R = model_R.predict(X_train)

В [74]:

y_pred_valid_L = model_L.predict(X_valid)
y_pred_train_L = model_L.predict(X_train)

В [75]:

print("Качество валидации Ридж-регрессии %.3f" % mean_squared_error(y_valid, y_pred_valid_R


print("Качество на обучении Ридж-регрессии %.3f" % mean_squared_error(y_train, y_pred_train
Качество валидации Ридж-регрессии 0.079
Качество на обучении Ридж-регрессии 0.070

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 15/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [76]:

print("Качество валидации Лассо-регрессии%.3f" % mean_squared_error(y_valid, y_pred_valid_L


print("Качество на обучении Лассо-регрессии%.3f" % mean_squared_error(y_train, y_pred_train

Качество валидации Лассо-регрессии0.093


Качество на обучении Лассо-регрессии0.155

Урок 8. Домашняя работа


Задание среднего уровня Примените градиентный спуск к задаче прогнозирования цен на
недвижимость в Бостоне. Какого качества на валидации удалось достичь по r2-score? Сколько итераций
понадобилось?

В [77]:

from sklearn.datasets import load_boston


boston_dataset = load_boston()
X = boston_dataset.data
y = boston_dataset.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)

В [78]:

num_features = X.shape[1] #смотрим размерность массива


#learning_rate="constant", eta0 = 2.1

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 16/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [79]:

sgd_regressor = SGDRegressor(learning_rate="constant", fit_intercept=True, random_state=42)


#sgd_regressor = SGDRegressor(learning_rate="constant", eta0=2.1, fit_intercept=True, rando
w_current, epsilon = np.random.random(num_features), 0.001

weight_evolution, r2_evolution = [], [] # изменения весов и ошибка на валидации

for step in list(range(800)):


X_train = StandardScaler().fit_transform(X_train)
X_test = StandardScaler().fit_transform(X_test)
sgd_regressor = sgd_regressor.partial_fit(X_train, y_train)
weight_evolution.append(distance.euclidean(w_current, sgd_regressor.coef_))
if weight_evolution[-1]<epsilon:
print("Итарации остановлены на шаге %d" % step); break
r2_evolution.append(r2_score(y_test, sgd_regressor.predict(X_test)))
w_current = sgd_regressor.coef_.copy()

plt.plot(range(step), r2_evolution)

Итарации остановлены на шаге 24

Out[79]:

[<matplotlib.lines.Line2D at 0x26339516c88>]

Вы можете начать использовать градиентный спуск уже сейчас! Если вы хотите глубже понять
механизмы, которые использует этот приём - добро пожаловать в урок 5, где мы поговорим о
математике, которая стоит за градиентным спуском и даже реализуем градиентный спуск на языке
Python.

Урок 12. Домашняя работа


Задача высокого уровня В реализацию функции gradient добавьте параметр , чтобы получить 𝜆
регуляризованный градиентный спуск

Формула поменяется следующим образом:

∂𝑤0 = 𝑛 ⋅ (−1) ⋅ ∑𝑖=1 (1 ⋅ (𝑦𝑖 − ∑𝑗=1 𝑤𝑗 𝑥𝑗 ) + 𝜆 ⋅ 2 ⋅ 𝑤0 )


∂𝐿 2 𝑛 𝑚 𝑖
{ ∂𝑤∂𝐿𝑘 = 2𝑛 ⋅ (−1) ⋅ ∑𝑛𝑖=1 (𝑥𝑖𝑘 ⋅ (𝑦𝑖 − ∑𝑚𝑗=1 𝑤𝑗 𝑥𝑖𝑗 ) + 𝜆 ⋅ 2 ⋅ 𝑤𝑘 ) 𝑘≠0

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 17/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

В [87]:

def gradient (X, y, w, alpha) -> np.array: #<--добавляем альфу


#кол-во примеров в обучающей выборке
n = X.shape[0]
# прогноз
y_hat = X.dot(w.T)
# вычисляем ошибку
error = y - y_hat
# градиент
grad = (np.multiply(X, error) + 2*alpha*w).sum(axis=0)*(-1)*2/n #<--добавляем альфу
return grad, error

def eval_w_next(X, y, eta, w_current, alpha): #<--добавляем альфу


# вычисляем градиент
grad, error = gradient(X, y, w_current, alpha) #<--добавляем альфу
# делаем шаг градиентного спуска
w_next = w_current - eta*grad
# проверяем условие сходимости
weight_evolution = distance.euclidean(w_current, w_next)
return (w_next, weight_evolution, grad)

def gradient_descent(X: np.array, y: np.array, eta=0.001, epsilon=0.001, alpha = 0.1) -> np


m = X.shape[1] # количество фичей
# инициализируем рандомом веса
w = np.random.random(m).reshape(1, -1)
w_next, weight_evolution, grad = eval_w_next(X, y, eta, w, alpha)
step = 0
# повторяем до сходимости вектора весов
while weight_evolution > epsilon:
w = w_next
w_next, weight_evolution, grad = eval_w_next(X, y, eta, w, alpha) #<--добавляем аль
step += 1
if step % 10 ==0:
print("step %s |w-w_next|=%.5f, grad=%s" % (step, weight_evolution, grad))
return step, w

В [88]:

# трансформируем плоский массив X в вектор-столбец


X = data['x_train'].values.reshape(-1, 1)
n = X.shape[0]
# добавляем тривиальный признак w_0, столбец из единиц. См. прошлый урок, почему так
X = np.hstack([np.ones(n).reshape(-1,1), X])
w = gradient_descent(X, data['y_train'].values.reshape(-1, 1))

step 10 |w-w_next|=0.00338, grad=[-0.00415401 3.377353 ]


step 20 |w-w_next|=0.00257, grad=[-0.20124638 2.559426 ]
step 30 |w-w_next|=0.00198, grad=[-0.34782306 1.95114834]
step 40 |w-w_next|=0.00157, grad=[-0.45683209 1.49878329]
step 50 |w-w_next|=0.00128, grad=[-0.5379027 1.16236777]
step 60 |w-w_next|=0.00109, grad=[-0.59819598 0.91218192]

В [ ]:

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 18/19
27.04.2021 REGUL_linear_regression_II_les_1 - Jupyter Notebook

localhost:8889/notebooks/REGUL_linear_regression_II_les_1.ipynb 19/19