Реализуйте функцию mserror среднеквадратичную ошибку прогноза

# coding: utf-8 # # Линейная регрессия и стохастический градиентный спуск # Задание основано на материалах лекций по линейной регрессии и градиентному спуску. Вы будете прогнозировать выручку компании в зависимости от уровня ее инвестиций в рекламу по TV, в газетах и по радио. # ## Вы научитесь: # — решать задачу восстановления линейной регрессии # — реализовывать стохастический градиентный спуск для ее настройки # — решать задачу линейной регрессии аналитически # ## Введение # Линейная регрессия — один из наиболее хорошо изученных методов машинного обучения, позволяющий прогнозировать значения количественного признака в виде линейной комбинации прочих признаков с параметрами — весами модели. Оптимальные (в смысле минимальности некоторого функционала ошибки) параметры линейной регрессии можно найти аналитически с помощью нормального уравнения или численно с помощью методов оптимизации. # Линейная регрессия использует простой функционал качества — среднеквадратичную ошибку. Мы будем работать с выборкой, содержащей 3 признака. Для настройки параметров (весов) модели решается следующая задача: # $$frac{1}{ell}sum_{i=1}^ell{{(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}))}^2} rightarrow min_{w_0, w_1, w_2, w_3},$$ # где $x_{i1}, x_{i2}, x_{i3}$ — значения признаков $i$-го объекта, $y_i$ — значение целевого признака $i$-го объекта, $ell$ — число объектов в обучающей выборке. # ## Градиентный спуск # Параметры $w_0, w_1, w_2, w_3$, по которым минимизируется среднеквадратичная ошибка, можно находить численно с помощью градиентного спуска. # Градиентный шаг для весов будет выглядеть следующим образом: # $$w_0 leftarrow w_0 + frac{2eta}{ell} sum_{i=1}^ell{{(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}))}}$$ # $$w_j leftarrow w_j + frac{2eta}{ell} sum_{i=1}^ell{{x_{ij}(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}))}}, j in {1,2,3}$$ # Здесь $eta$ — параметр, шаг градиентного спуска. # ## Стохастический градиентный спуск # У градиентного спуска, описанного выше, есть один недостаток. На больших выборках вычисление градиента по всем имеющимся данным на каждом шаге может быть вычислительно сложно. # В стохастическом варианте градиентного спуска поправки для весов вычисляются только с учетом одного случайно взятого объекта обучающей выборки: # $$w_0 leftarrow w_0 + frac{2eta}{ell} {(y_k — (w_0 + w_1x_{k1} + w_2x_{k2} + w_3x_{k3}))}$$ # $$w_j leftarrow w_j + frac{2eta}{ell} {x_{kj}(y_k — (w_0 + w_1x_{k1} + w_2x_{k2} + w_3x_{k3}))}, j in {1,2,3},$$ # где $k$ — случайный индекс, $k in {1, ldots, ell}$. # ## Нормальное уравнение # Нахождение вектора оптимальных весов $w$ может быть сделано и аналитически. # Мы хотим найти такой вектор весов $w$, чтобы вектор $y$, соответствующий целевому признаку, получался умножением матрицы $X$ (состоящей из всех признаков объектов обучающей выборки, кроме целевого) на вектор весов $w$. То есть, чтобы выполнялось матричное уравнение: # $$y = Xw$$ # Домножением слева на $X^T$ получаем: # $$X^Ty = X^TXw$$ # Это хорошо, поскольку теперь матрица $X^TX$ — квадратная, и можно найти решение (вектор $w$) в виде: # $$w = {(X^TX)}^{-1}X^Ty$$ # Матрица ${(X^TX)}^{-1}X^T$ — [*псевдообратная*](https://ru.wikipedia.org/wiki/Псевдообратная_матрица) для матрицы $X$. В NumPy такую матрицу можно вычислить с помощью функции [numpy.linalg.pinv](http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.linalg.pinv.html). # # Однако, нахождение псевдообратной матрицы — операция вычислительно сложная и нестабильная в случае малого определителя матрицы $X$ (проблема мультиколлинеарности). # На практике лучше находить вектор весов $w$ решением матричного уравнения # $$X^TXw = X^Ty$$Это может быть сделано с помощью функции [numpy.linalg.solve](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.linalg.solve.html). # # Но все же на практике для больших матриц $X$ быстрее работает градиентный спуск, особенно его стохастическая версия. # ## Инструкции по выполнению # В начале напишем простую функцию для записи ответов в текстовый файл. Ответами будут числа, полученные в ходе решения этого задания, округленные до 3 знаков после запятой. Полученные файлы после выполнения задания надо отправить в форму на странице задания на Coursera.org. # In[1]: def write_answer_to_file(answer, filename): with open(filename, ‘w’) as f_out: f_out.write(str(round(answer, 3))) # **1. Загрузите данные из файла *advertising.csv* в объект pandas DataFrame. [Источник данных](http://www-bcf.usc.edu/~gareth/ISL/data.html).** # In[2]: import pandas as pd adver_data = pd.read_csv(‘advertising.csv’) # **Посмотрите на первые 5 записей и на статистику признаков в этом наборе данных.** # In[3]: adver_data.head(n=5) # In[4]: adver_data.describe() # **Создайте массивы NumPy *X* из столбцов TV, Radio и Newspaper и *y* — из столбца Sales. Используйте атрибут *values* объекта pandas DataFrame.** # In[5]: X = adver_data[[«TV»,«Radio», «Newspaper»]].values Y = adver_data[[«Sales»]].values # **Отмасштабируйте столбцы матрицы *X*, вычтя из каждого значения среднее по соответствующему столбцу и поделив результат на стандартное отклонение.** # In[6]: import numpy as np means, stds = np.mean(X, axis=0), np.std(X, axis=0) # In[7]: X = (X means)/stds # **Добавьте к матрице *X* столбец из единиц, используя методы *hstack*, *ones* и *reshape* библиотеки NumPy. Вектор из единиц нужен для того, чтобы не обрабатывать отдельно коэффициент $w_0$ линейной регрессии.** # In[8]: import numpy as np X = np.hstack([X, np.ones((X.shape[0],1))]) # **2. Реализуйте функцию *mserror* — среднеквадратичную ошибку прогноза. Она принимает два аргумента — объекты Series *y* (значения целевого признака) и *y_pred* (предсказанные значения).** # In[9]: def mserror(y, y_pred): return round((sum((y y_pred)**2)[0])/float(y.shape[0]), 3) # **Какова среднеквадратичная ошибка прогноза значений Sales, если всегда предсказывать медианное значение Sales по исходной выборке? Запишите ответ в файл ‘1.txt’.** # In[10]: eye = np.array([np.median(Y)]*Y.shape[0]).reshape((Y.shape[0], 1)) answer1 = mserror(Y, eye) print(answer1) write_answer_to_file(answer1, ‘1.txt’) # **3. Реализуйте функцию *normal_equation*, которая по заданным матрицам (массивам NumPy) *X* и *y* вычисляет вектор весов $w$ согласно нормальному уравнению линейной регрессии.** # In[11]: def normal_equation(X, y): return np.dot(np.dot(np.linalg.pinv(np.dot(X.T, X)), X.T), y) # In[12]: norm_eq_weights = normal_equation(X, Y) print(norm_eq_weights) # **Какие продажи предсказываются линейной моделью с весами, найденными с помощью нормального уравнения, в случае средних инвестиций в рекламу по ТВ, радио и в газетах? (то есть при нулевых значениях масштабированных признаков TV, Radio и Newspaper). Запишите ответ в файл ‘2.txt’.** # In[13]: answer2 = np.dot(np.mean(X, axis=0), norm_eq_weights)[0] print(answer2) write_answer_to_file(answer2, ‘2.txt’) # **4. Напишите функцию *linear_prediction*, которая принимает на вход матрицу *X* и вектор весов линейной модели *w*, а возвращает вектор прогнозов в виде линейной комбинации столбцов матрицы *X* с весами *w*.** # In[14]: def linear_prediction(X, w): return np.dot(X, w) # **Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью нормального уравнения? Запишите ответ в файл ‘3.txt’.** # In[15]: answer3 = mserror(Y, linear_prediction(X, norm_eq_weights)) print(answer3) write_answer_to_file(answer3, ‘3.txt’) # **5. Напишите функцию *stochastic_gradient_step*, реализующую шаг стохастического градиентного спуска для линейной регрессии. Функция должна принимать матрицу *X*, вектора *y* и *w*, число *train_ind* — индекс объекта обучающей выборки (строки матрицы *X*), по которому считается изменение весов, а также число *$eta$* (eta) — шаг градиентного спуска (по умолчанию *eta*=0.01). Результатом будет вектор обновленных весов.** # In[16]: def stochastic_gradient_step(X, y, w, train_ind, eta=0.01): x_k = X[train_ind, :] y_k = y[train_ind] y_pred = np.dot(x_k, w) l = X.shape[0] return w + (2*eta/l)*(y_k y_pred)*x_k # **6. Напишите функцию *stochastic_gradient_descent*, реализующую стохастический градиентный спуск для линейной регрессии. Функция принимает на вход следующие аргументы:** # — X — матрица, соответствующая обучающей выборке # — y — вектор значений целевого признака # — w_init — вектор начальных весов модели # — eta — шаг градиентного спуска (по умолчанию 0.01) # — max_iter — максимальное число итераций градиентного спуска (по умолчанию 10000) # — max_weight_dist — минимальное евклидово расстояние между векторами весов на соседних итерациях градиентного спуска, # при котором алгоритм прекращает работу (по умолчанию 1e-8) # — seed — число, используемое для воспроизводимости сгенерированных псевдослучайных чисел (по умолчанию 42) # — verbose — флаг печати информации (например, для отладки, по умолчанию False) # # **На каждой итерации в вектор (список) должно записываться текущее значение среднеквадратичной ошибки. Функция должна возвращать вектор весов $w$, а также вектор (список) ошибок.** # In[40]: def stochastic_gradient_descent(X, y, w_init, eta=1e-2, max_iter=1e4, min_weight_dist=1e-8, seed=42, verbose=False): # Инициализируем расстояние между векторами весов на соседних # итерациях большим числом. weight_dist = np.inf # Инициализируем вектор весов w = w_init # Сюда будем записывать ошибки на каждой итерации errors = [] # Счетчик итераций iter_num = 0 # Будем порождать псевдослучайные числа # (номер объекта, который будет менять веса), а для воспроизводимости # этой последовательности псевдослучайных чисел используем seed. np.random.seed(seed) # Основной цикл while weight_dist > min_weight_dist and iter_num < max_iter: # порождаем псевдослучайный # индекс объекта обучающей выборки random_ind = np.random.randint(X.shape[0]) # Ваш код здесь old_w = w w = stochastic_gradient_step(X, y, w, random_ind, eta=eta) weight_dist = np.linalg.norm(w old_w) errors.append(mserror(y, np.dot(X, w))) iter_num += 1 if iter_num % 10000 == 0 and verbose: print «Iteration: «, iter_num return w, errors # **Запустите $10^5$ итераций стохастического градиентного спуска. Укажите вектор начальных весов *w_init*, состоящий из нулей. Оставьте параметры *eta* и *seed* равными их значениям по умолчанию (*eta*=0.01, *seed*=42 — это важно для проверки ответов).** # In[41]: get_ipython().run_cell_magic(u’time’, , u’stoch_grad_desc_weights, stoch_errors_by_iter = stochastic_gradient_descent(X, Y, np.ones((X.shape[1])), eta=1e-2, max_iter=10**5, verbose = True)’) # In[42]: get_ipython().magic(u’pylab inline’) plot(range(len(stoch_errors_by_iter)), stoch_errors_by_iter) xlabel(‘Iteration number’) ylabel(‘MSE’) # **Посмотрим на вектор весов, к которому сошелся метод.** # In[43]: stoch_grad_desc_weights # **Посмотрим на среднеквадратичную ошибку на последней итерации.** # In[44]: stoch_errors_by_iter[1] # **Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью градиентного спуска? Запишите ответ в файл ‘4.txt’.** # In[61]: print sum((Y np.dot(X, stoch_grad_desc_weights).reshape((Y.shape[0], 1)))**2)/float(Y.shape[0]) answer4 = round(np.mean((Y np.dot(X, stoch_grad_desc_weights).reshape((Y.shape[0], 1)))**2), 3) print(answer4) write_answer_to_file(answer4, ‘4.txt’) # **Ответами к заданию будут текстовые файлы, полученные в ходе этого решения. Обратите внимание, что отправленные файлы не должны содержать пустую строку в конце. Данный нюанс является ограничением платформы Coursera. Мы работаем над исправлением этого ограничения.**

Студворк — интернет-сервис помощи студентам

Всем привет!
Прохожу на Курсере *Обучение на размеченных данных*. Сейчас начинаю уже последнюю 5ю неделю, почти всё понятно, всё решаю.
Кроме 1й недели! Она так и осталась несданной, а сроки поджимают.
Там в первом и втором задании ошибиться невозможно, кода на 3 строчки. Но мой ответ почти в 20 раз больше требуемого!!!

Вот первое задание:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# импорт модулей
import pandas as pd
import numpy as np
 
# Взяли данные
adver_data = pd.read_csv('advertising.csv')  
 
# Разбили на 2 выборки
X = adver_data[['TV', 'Radio', 'Newspaper']].values 
y = adver_data[['Sales']].values 
 
# Отмасштабируйте столбцы матрицы X, вычтя из каждого значения среднее по соответствующему столбцу
#  и поделив результат на стандартное отклонение. 
means, stds = np.mean(X, axis=0), np.std(X, axis=0) 
X = (X - means)/stds
 
# Добавьте к матрице X столбец из единиц
X = np.hstack([X, np.ones((X.shape[0], 1))]) 
 
#  -----Задание-----
# 2. Реализуйте функцию mserror - среднеквадратичную ошибку прогноза.
#  Она принимает два аргумента - объекты Series y (значения целевого признака) и y_pred (предсказанные значения). 
# Не используйте в этой функции циклы - тогда она будет вычислительно неэффективной.
def mserr(y, y_pred):
return np.mean((y - y_pred) ** 2)  
answer1 = np.mean((y - np.median(y))**2)

Ответ будет 495.0152, хотя должен быть 28.ххххх — РАСХОЖДЕНИЕ АДОВО!
Пробовал использовать ‘родную’ функцию sklearn.metrics.mean_squared_error — результат ровно такой же 495.0152, т.е. неверный.
Похожая картина во втором задании — вроде бы всё несложно, но ответ совершенно другой!
Все остальные задания в этой неделе основаны на пунктах 1и 2.

Я не понимаю в чём дело, тут не просто ошибка в вычислениях….
Посмотрите, пожалуйста, свежим взглядом, что я упускаю.

  1. # coding: utf-8

  2. # # Линейная регрессия и стохастический градиентный спуск

  3. # Задание основано на материалах лекций по линейной регрессии и градиентному спуску. Вы будете прогнозировать выручку компании в зависимости от уровня ее инвестиций в рекламу по TV, в газетах и по радио.

  4. # ## Вы научитесь:

  5. # — решать задачу восстановления линейной регрессии

  6. # — реализовывать стохастический градиентный спуск для ее настройки

  7. # — решать задачу линейной регрессии аналитически

  8. # ## Введение

  9. # Линейная регрессия — один из наиболее хорошо изученных методов машинного обучения, позволяющий прогнозировать значения количественного признака в виде линейной комбинации прочих признаков с параметрами — весами модели. Оптимальные (в смысле минимальности некоторого функционала ошибки) параметры линейной регрессии можно найти аналитически с помощью нормального уравнения или численно с помощью методов оптимизации.  

  10. # Линейная регрессия использует простой функционал качества — среднеквадратичную ошибку. Мы будем работать с выборкой, содержащей 3 признака. Для настройки параметров (весов) модели решается следующая задача:

  11. # $$frac{1}{ell}sum_{i=1}^ell{{(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} +  w_3x_{i3}))}^2} rightarrow min_{w_0, w_1, w_2, w_3},$$

  12. # где $x_{i1}, x_{i2}, x_{i3}$ — значения признаков $i$-го объекта, $y_i$ — значение целевого признака $i$-го объекта, $ell$ — число объектов в обучающей выборке.

  13. # ## Градиентный спуск

  14. # Параметры $w_0, w_1, w_2, w_3$, по которым минимизируется среднеквадратичная ошибка, можно находить численно с помощью градиентного спуска.

  15. # Градиентный шаг для весов будет выглядеть следующим образом:

  16. # $$w_0 leftarrow w_0 + frac{2eta}{ell} sum_{i=1}^ell{{(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} +  w_3x_{i3}))}}$$

  17. # $$w_j leftarrow w_j + frac{2eta}{ell} sum_{i=1}^ell{{x_{ij}(y_i — (w_0 + w_1x_{i1} + w_2x_{i2} +  w_3x_{i3}))}}, j in {1,2,3}$$

  18. # Здесь $eta$ — параметр, шаг градиентного спуска.

  19. # ## Стохастический градиентный спуск

  20. # У градиентного спуска, описанного выше, есть один недостаток. На больших выборках вычисление градиента по всем имеющимся данным на каждом шаге может быть вычислительно сложно.

  21. # В стохастическом варианте градиентного спуска поправки для весов вычисляются только с учетом одного случайно взятого объекта обучающей выборки:

  22. # $$w_0 leftarrow w_0 + frac{2eta}{ell} {(y_k — (w_0 + w_1x_{k1} + w_2x_{k2} +  w_3x_{k3}))}$$

  23. # $$w_j leftarrow w_j + frac{2eta}{ell} {x_{kj}(y_k — (w_0 + w_1x_{k1} + w_2x_{k2} +  w_3x_{k3}))}, j in {1,2,3},$$

  24. # где $k$ — случайный индекс, $k in {1, ldots, ell}$.

  25. # ## Нормальное уравнение

  26. # Нахождение вектора оптимальных весов $w$ может быть сделано и аналитически.

  27. # Мы хотим найти такой вектор весов $w$, чтобы вектор $y$, соответствующий целевому признаку, получался умножением матрицы $X$ (состоящей из всех признаков объектов обучающей выборки, кроме целевого) на вектор весов $w$. То есть, чтобы выполнялось матричное уравнение:

  28. # $$y = Xw$$

  29. # Домножением слева на $X^T$ получаем:

  30. # $$X^Ty = X^TXw$$

  31. # Это хорошо, поскольку теперь матрица $X^TX$ — квадратная, и можно найти решение (вектор $w$) в виде:

  32. # $$w = {(X^TX)}^{-1}X^Ty$$

  33. # Матрица ${(X^TX)}^{-1}X^T$ — [*псевдообратная*](https://ru.wikipedia.org/wiki/Псевдообратная_матрица) для матрицы $X$. В NumPy такую матрицу можно вычислить с помощью функции [numpy.linalg.pinv](http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.linalg.pinv.html).

  34. #

  35. # Однако, нахождение псевдообратной матрицы — операция вычислительно сложная и нестабильная в случае малого определителя матрицы $X$ (проблема мультиколлинеарности).

  36. # На практике лучше находить вектор весов $w$ решением матричного уравнения

  37. # $$X^TXw = X^Ty$$Это может быть сделано с помощью функции [numpy.linalg.solve](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.linalg.solve.html).

  38. #

  39. # Но все же на практике для больших матриц $X$ быстрее работает градиентный спуск, особенно его стохастическая версия.

  40. # ## Инструкции по выполнению

  41. # В начале напишем простую функцию для записи ответов в текстовый файл. Ответами будут числа, полученные в ходе решения этого задания, округленные до 3 знаков после запятой. Полученные файлы после выполнения задания надо отправить в форму на странице задания на Coursera.org.

  42. # In[1]:

  43. def write_answer_to_file(answer, filename):

  44. with open(filename, ‘w’) as f_out:

  45.         f_out.write(str(round(answer, 3)))

  46. # **1. Загрузите данные из файла *advertising.csv* в объект pandas DataFrame. [Источник данных](http://www-bcf.usc.edu/~gareth/ISL/data.html).**

  47. # In[2]:

  48. import pandas as pd

  49. adver_data = pd.read_csv(‘advertising.csv’)

  50. # **Посмотрите на первые 5 записей и на статистику признаков в этом наборе данных.**

  51. # In[3]:

  52. adver_data.head(n=5)

  53. # In[4]:

  54. adver_data.describe()

  55. # **Создайте массивы NumPy *X* из столбцов TV, Radio и Newspaper и *y* — из столбца Sales. Используйте атрибут *values* объекта pandas DataFrame.**

  56. # In[5]:

  57. X = adver_data[[«TV»,«Radio», «Newspaper»]].values

  58. Y = adver_data[[«Sales»]].values

  59. # **Отмасштабируйте столбцы матрицы *X*, вычтя из каждого значения среднее по соответствующему столбцу и поделив результат на стандартное отклонение.**

  60. # In[6]:

  61. import numpy as np

  62. means, stds = np.mean(X, axis=0), np.std(X, axis=0)

  63. # In[7]:

  64. X = (X — means)/stds

  65. # **Добавьте к матрице *X* столбец из единиц, используя методы *hstack*, *ones* и *reshape* библиотеки NumPy. Вектор из единиц нужен для того, чтобы не обрабатывать отдельно коэффициент $w_0$ линейной регрессии.**

  66. # In[8]:

  67. import numpy as np

  68. X = np.hstack([X, np.ones((X.shape[0],1))])

  69. # **2. Реализуйте функцию *mserror* — среднеквадратичную ошибку прогноза. Она принимает два аргумента — объекты Series *y* (значения целевого признака) и *y_pred* (предсказанные значения).**

  70. # In[9]:

  71. def mserror(y, y_pred):

  72. return round((sum((y — y_pred)**2)[0])/float(y.shape[0]), 3)

  73. # **Какова среднеквадратичная ошибка прогноза значений Sales, если всегда предсказывать медианное значение Sales по исходной выборке? Запишите ответ в файл ‘1.txt’.**

  74. # In[10]:

  75. eye = np.array([np.median(Y)]*Y.shape[0]).reshape((Y.shape[0], 1))

  76. answer1 = mserror(Y, eye)

  77. print(answer1)

  78. write_answer_to_file(answer1, ‘1.txt’)

  79. # **3. Реализуйте функцию *normal_equation*, которая по заданным матрицам (массивам NumPy) *X* и *y* вычисляет вектор весов $w$ согласно нормальному уравнению линейной регрессии.**

  80. # In[11]:

  81. def normal_equation(X, y):

  82. return np.dot(np.dot(np.linalg.pinv(np.dot(X.T, X)), X.T), y)

  83. # In[12]:

  84. norm_eq_weights = normal_equation(X, Y)

  85. print(norm_eq_weights)

  86. # **Какие продажи предсказываются линейной моделью с весами, найденными с помощью нормального уравнения, в случае средних инвестиций в рекламу по ТВ, радио и в газетах? (то есть при нулевых значениях масштабированных признаков TV, Radio и Newspaper). Запишите ответ в файл ‘2.txt’.**

  87. # In[13]:

  88. answer2 = np.dot(np.mean(X, axis=0), norm_eq_weights)[0]

  89. print(answer2)

  90. write_answer_to_file(answer2, ‘2.txt’)

  91. # **4. Напишите функцию *linear_prediction*, которая принимает на вход матрицу *X* и вектор весов линейной модели *w*, а возвращает вектор прогнозов в виде линейной комбинации столбцов матрицы *X* с весами *w*.**

  92. # In[14]:

  93. def linear_prediction(X, w):

  94. return np.dot(X, w)

  95. # **Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью нормального уравнения? Запишите ответ в файл ‘3.txt’.**

  96. # In[15]:

  97. answer3 = mserror(Y, linear_prediction(X, norm_eq_weights))

  98. print(answer3)

  99. write_answer_to_file(answer3, ‘3.txt’)

  100. # **5. Напишите функцию *stochastic_gradient_step*, реализующую шаг стохастического градиентного спуска для линейной регрессии. Функция должна принимать матрицу *X*, вектора *y* и *w*, число *train_ind* — индекс объекта обучающей выборки (строки матрицы *X*), по которому считается изменение весов, а также число *$eta$* (eta) — шаг градиентного спуска (по умолчанию *eta*=0.01). Результатом будет вектор обновленных весов.**

  101. # In[16]:

  102. def stochastic_gradient_step(X, y, w, train_ind, eta=0.01):

  103.     x_k = X[train_ind, :]

  104.     y_k = y[train_ind]

  105.     y_pred = np.dot(x_k, w)

  106.     l = X.shape[0]

  107. return w + (2*eta/l)*(y_k — y_pred)*x_k

  108. # **6. Напишите функцию *stochastic_gradient_descent*, реализующую стохастический градиентный спуск для линейной регрессии. Функция принимает на вход следующие аргументы:**

  109. # — X — матрица, соответствующая обучающей выборке

  110. # — y — вектор значений целевого признака

  111. # — w_init — вектор начальных весов модели

  112. # — eta — шаг градиентного спуска (по умолчанию 0.01)

  113. # — max_iter — максимальное число итераций градиентного спуска (по умолчанию 10000)

  114. # — max_weight_dist — минимальное евклидово расстояние между векторами весов на соседних итерациях градиентного спуска,

  115. # при котором алгоритм прекращает работу (по умолчанию 1e-8)

  116. # — seed — число, используемое для воспроизводимости сгенерированных псевдослучайных чисел (по умолчанию 42)

  117. # — verbose — флаг печати информации (например, для отладки, по умолчанию False)

  118. #

  119. # **На каждой итерации в вектор (список) должно записываться текущее значение среднеквадратичной ошибки. Функция должна возвращать вектор весов $w$, а также вектор (список) ошибок.**

  120. # In[40]:

  121. def stochastic_gradient_descent(X, y, w_init, eta=1e-2, max_iter=1e4,

  122.                                 min_weight_dist=1e-8, seed=42, verbose=False):

  123. # Инициализируем расстояние между векторами весов на соседних

  124. # итерациях большим числом.

  125.     weight_dist = np.inf

  126. # Инициализируем вектор весов

  127.     w = w_init

  128. # Сюда будем записывать ошибки на каждой итерации

  129.     errors = []

  130. # Счетчик итераций

  131.     iter_num = 0

  132. # Будем порождать псевдослучайные числа

  133. # (номер объекта, который будет менять веса), а для воспроизводимости

  134. # этой последовательности псевдослучайных чисел используем seed.

  135.     np.random.seed(seed)

  136. # Основной цикл

  137. while weight_dist > min_weight_dist and iter_num < max_iter:

  138. # порождаем псевдослучайный

  139. # индекс объекта обучающей выборки

  140.         random_ind = np.random.randint(X.shape[0])

  141. # Ваш код здесь

  142.         old_w = w

  143.         w = stochastic_gradient_step(X, y, w, random_ind, eta=eta)

  144.         weight_dist = np.linalg.norm(w — old_w)

  145.         errors.append(mserror(y, np.dot(X, w)))

  146.         iter_num += 1

  147. if iter_num % 10000 == 0 and verbose:

  148. print «Iteration: «, iter_num

  149. return w, errors

  150. #  **Запустите $10^5$ итераций стохастического градиентного спуска. Укажите вектор начальных весов *w_init*, состоящий из нулей. Оставьте параметры  *eta* и *seed* равными их значениям по умолчанию (*eta*=0.01, *seed*=42 — это важно для проверки ответов).**

  151. # In[41]:

  152. get_ipython().run_cell_magic(u‘time’, u», u‘stoch_grad_desc_weights, stoch_errors_by_iter = stochastic_gradient_descent(X, Y, np.ones((X.shape[1])), eta=1e-2, max_iter=10**5, verbose = True)’)

  153. # In[42]:

  154. get_ipython().magic(u‘pylab inline’)

  155. plot(range(len(stoch_errors_by_iter)), stoch_errors_by_iter)

  156. xlabel(‘Iteration number’)

  157. ylabel(‘MSE’)

  158. # **Посмотрим на вектор весов, к которому сошелся метод.**

  159. # In[43]:

  160. stoch_grad_desc_weights

  161. # **Посмотрим на среднеквадратичную ошибку на последней итерации.**

  162. # In[44]:

  163. stoch_errors_by_iter[1]

  164. # **Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью градиентного спуска? Запишите ответ в файл ‘4.txt’.**

  165. # In[61]:

  166. print sum((Y — np.dot(X, stoch_grad_desc_weights).reshape((Y.shape[0], 1)))**2)/float(Y.shape[0])

  167. answer4 = round(np.mean((Y — np.dot(X, stoch_grad_desc_weights).reshape((Y.shape[0], 1)))**2), 3)

  168. print(answer4)

  169. write_answer_to_file(answer4, ‘4.txt’)

  170. # **Ответами к заданию будут текстовые файлы, полученные в ходе этого решения. Обратите внимание, что отправленные файлы не должны содержать пустую строку в конце. Данный нюанс является ограничением платформы Coursera. Мы работаем над исправлением этого ограничения.**

Время на прочтение
4 мин

Количество просмотров 4.3K

Функции потерь Python являются важной частью моделей машинного обучения. Эти функции показывают, насколько сильно предсказанный моделью результат отличается от фактического.

Существует несколько способов вычислить эту разницу. В этом материале мы рассмотрим некоторые из наиболее распространенных функций потерь.

Ниже будут рассмотрены следующие четыре функции потерь.

  • Среднеквадратическая ошибка

  • Среднеквадратическая ошибка

  • Средняя абсолютная ошибка

  • Кросс-энтропийные потери

Из этих четырех функций потерь первые три применяются к модели классификации.

1. Среднеквадратическая ошибка (MSE)

Среднеквадратичная ошибка (MSE) рассчитывается как среднее значение квадратов разностей между прогнозируемыми и фактически наблюдаемыми значениями. Математически это можно выразить следующим образом:

Реализация MSE на языке Python выглядит следующим образом:

import numpy as np # импортируем библиотеку numpy
def mean_squared_error(act, pred): # функция 

   diff = pred - act # находим разницу между прогнозируемыми и наблюдаемыми значениями
   differences_squared = diff ** 2 # возводим в квадрат (чтобы избавиться от отрицательных значений)
   mean_diff = differences_squared.mean() # находим среднее значение
   
   return mean_diff

act = np.array([1.1,2,1.7]) # создаем список актуальных значений
pred = np.array([1,1.7,1.5]) # список прогнозируемых значений

print(mean_squared_error(act,pred)) 

Выход :

0.04666666666666667

Вы также можете использовать mean_squared_error из sklearn для расчета MSE. Вот как работает функция:

from sklearn.metrics import mean_squared_error
act = np.array([1.1,2,1.7])
pred = np.array([1,1.7,1.5])
mean_squared_error(act, pred)

Выход :

0.04666666666666667

2. Корень среднеквадратической ошибки (RMSE)

Итак, ранее, для того, чтобы найти действительную ошибку среди между прогнозируемыми и фактически наблюдаемыми значениями (там могли быть положительные и отрицательные значения), мы возводили их в квадрат (для того чтобы отрицательные значения участвовали в расчетах в полной мере). Это была среднеквадратичная ошибка (MSE).

Корень среднеквадратической ошибки (RMSE) мы используем для того чтобы избавиться от квадратной степени, в которую мы ранее возвели действительную ошибку среди между прогнозируемыми и фактически наблюдаемыми значениями. Математически мы можем представить это следующим образом:

Реализация Python для RMSE выглядит следующим образом:

import numpy as np
def root_mean_squared_error(act, pred):

   diff = pred - act # находим разницу между прогнозируемыми и наблюдаемыми значениями
   differences_squared = diff ** 2 # возводим в квадрат
   mean_diff = differences_squared.mean() # находим среднее значение
   rmse_val = np.sqrt(mean_diff) # извлекаем квадратный корень
   return rmse_val

act = np.array([1.1,2,1.7])
pred = np.array([1,1.7,1.5])

print(root_mean_squared_error(act,pred))

Выход :

0.21602468994692867

Вы также можете использовать mean_squared_error из sklearn для расчета RMSE. Давайте посмотрим, как реализовать RMSE, используя ту же функцию:

from sklearn.metrics import mean_squared_error
act = np.array([1.1,2,1.7])
pred = np.array([1,1.7,1.5])
mean_squared_error(act, pred, squared = False) #Если установлено значение False, функция возвращает значение RMSE.

Выход :

0.21602468994692867

Если для параметра squared установлено значение True, функция возвращает значение MSE. Если установлено значение False, функция возвращает значение RMSE.

3. Средняя абсолютная ошибка (MAE)

Средняя абсолютная ошибка (MAE) рассчитывается как среднее значение абсолютной разницы между прогнозами и фактическими наблюдениями. Математически мы можем представить это следующим образом:

Реализация Python для MAE выглядит следующим образом:

import numpy as np 
def mean_absolute_error(act, pred): #
    diff = pred - act # находим разницу между прогнозируемыми и наблюдаемыми значениями
    abs_diff = np.absolute(diff) # находим абсолютную разность между прогнозами и фактическими наблюдениями.
    mean_diff = abs_diff.mean() # находим среднее значение
    return mean_diff

act = np.array([1.1,2,1.7])
pred = np.array([1,1.7,1.5])
mean_absolute_error(act,pred)

Выход :

0.20000000000000004

Вы также можете использовать mean_absolute_error из sklearn для расчета MAE.

from sklearn.metrics import mean_absolute_error
act = np.array([1.1,2,1.7])
pred = np.array([1,1.7,1.5])
mean_absolute_error(act, pred)

Выход :

0.20000000000000004

4. Функция потерь перекрестной энтропии в Python

Функция потерь перекрестной энтропии также известна как отрицательная логарифмическая вероятность. Это чаще всего используется для задач классификации. Проблема классификации — это проблема, в которой вы классифицируете пример как принадлежащий к одному из более чем двух классов.

Давайте посмотрим, как вычислить ошибку в случае проблемы бинарной классификации.

Давайте рассмотрим проблему классификации, когда модель пытается провести классификацию между собакой и кошкой.

Код Python для поиска ошибки приведен ниже.

from sklearn.metrics import log_loss
log_loss(["Dog", "Cat", "Cat", "Dog"],[[.1, .9], [.9, .1], [.8, .2], [.35, .65]])

Выход :

0.21616187468057912

Мы используем метод log_loss из sklearn.

Первый аргумент в вызове функции — это список правильных меток классов для каждого входа. Второй аргумент — это список вероятностей, предсказанных моделью.

Вероятности представлены в следующем формате:

[P(dog), P(cat)]

Заключение

Это руководство было посвящено функциям потерь в Python. Мы рассмотрели различные функции потерь как для задач регрессии, так и для задач классификации. Надеюсь, вам понравился материал, ведь все было достаточно легко и понятно!

Кстати, для тех, кто хотел бы пойти дальше в изучении функций потерь, мы предлагаем разобрать одну вот такую — это очень интересная функция потерь Triplet Loss в Python (функцию тройных потерь), которую для вас любезно подготовил автор.

I’m trying to made function that will calculate mean squared error from y (true values) and y_pred (predicted ones) not using sklearn or other implementations.

I’ll try next:

def mserror(y, y_pred):
    i=0
    for i in range (len(y)):
        i+=1
        mse = ((y - y_pred) ** 2).mean(y)   
        return mse

Can you please correct me what I m doing wrong with the calculation and who it can be fixed?

asked Aug 21, 2016 at 13:23

Keithx's user avatar

3

You are modifying the index for no reason. A for loop increments it anyways. Also, you are not using the index, for example, you are not using any y[i] - y_pred[i], hence you don’t need the loop at all.

Use the arrays

mse = np.mean((y - y_pred)**2)

nbro's user avatar

nbro

15.2k32 gold badges111 silver badges196 bronze badges

answered Aug 21, 2016 at 14:20

percusse's user avatar

percussepercusse

3,0061 gold badge14 silver badges28 bronze badges

1

I would say :

def get_mse(y, y_pred):
d1 = y - y_pred
mse = (1/N)*d1.dot(d1) # N is int(len(y))
return mse

it would only work if y and y_pred are numpy arrays,
but you would want them to be numpy arrays as long as you decide not to use other libraries so you can do math operations on it.

numpy dot() function is the dot product of 2 numpy arrays
(you can also write np.dot(d1, d1) )

answered May 1, 2019 at 22:01

rotem's user avatar

rotemrotem

712 bronze badges

firstly, you are using the i repeatedly and increments it but in range it is automatically iterative to next number. So don’t use i again. The other thing that you are taking the mean of y but instead of taking mean of this, take the mean of ((y — y_pred) ** 2). I hope, you got the point.

answered Jan 30, 2018 at 10:48

Ramzan Shahid's user avatar

Here’s how to implement MSE in python:

def mse_metric(actual, predicted):
    sum_error = 0.0
    # loop over all values
    for i in range(len(actual)):
        # the error is the sum of (actual - prediction)^2
        prediction_error =  actual[i] - predicted[i]
        sum_error += (prediction_error ** 2)
    # now normalize
    mean_error = sum_error / float(len(actual))
    return (mean_error)

m02ph3u5's user avatar

m02ph3u5

2,9576 gold badges37 silver badges50 bronze badges

answered Jan 28, 2020 at 13:33

Ramzan Shahid's user avatar

  • Реализовать возможность лексическая ошибка
  • Реализация алгоритма обратного распространения ошибки
  • Рдр код ошибки 134
  • Рдр 2 ошибка установки
  • Рдр 2 ошибка при запуске приложения