Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2019
759
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.11 KB | None | 0 0
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# Линейная регрессия и стохастический градиентный спуск"
  8. ]
  9. },
  10. {
  11. "cell_type": "markdown",
  12. "metadata": {},
  13. "source": [
  14. "Задание основано на материалах лекций по линейной регрессии и градиентному спуску. Вы будете прогнозировать выручку компании в зависимости от уровня ее инвестиций в рекламу по TV, в газетах и по радио."
  15. ]
  16. },
  17. {
  18. "cell_type": "markdown",
  19. "metadata": {},
  20. "source": [
  21. "## Вы научитесь:\n",
  22. "- решать задачу восстановления линейной регрессии\n",
  23. "- реализовывать стохастический градиентный спуск для ее настройки\n",
  24. "- решать задачу линейной регрессии аналитически"
  25. ]
  26. },
  27. {
  28. "cell_type": "markdown",
  29. "metadata": {},
  30. "source": [
  31. "## Введение\n",
  32. "Линейная регрессия - один из наиболее хорошо изученных методов машинного обучения, позволяющий прогнозировать значения количественного признака в виде линейной комбинации прочих признаков с параметрами - весами модели. Оптимальные (в смысле минимальности некоторого функционала ошибки) параметры линейной регрессии можно найти аналитически с помощью нормального уравнения или численно с помощью методов оптимизации. "
  33. ]
  34. },
  35. {
  36. "cell_type": "markdown",
  37. "metadata": {},
  38. "source": [
  39. "Линейная регрессия использует простой функционал качества - среднеквадратичную ошибку. Мы будем работать с выборкой, содержащей 3 признака. Для настройки параметров (весов) модели решается следующая задача:\n",
  40. "$$\\Large \\frac{1}{\\ell}\\sum_{i=1}^\\ell{{((w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}) - y_i)}^2} \\rightarrow \\min_{w_0, w_1, w_2, w_3},$$\n",
  41. "где $x_{i1}, x_{i2}, x_{i3}$ - значения признаков $i$-го объекта, $y_i$ - значение целевого признака $i$-го объекта, $\\ell$ - число объектов в обучающей выборке."
  42. ]
  43. },
  44. {
  45. "cell_type": "markdown",
  46. "metadata": {},
  47. "source": [
  48. "## Градиентный спуск\n",
  49. "Параметры $w_0, w_1, w_2, w_3$, по которым минимизируется среднеквадратичная ошибка, можно находить численно с помощью градиентного спуска.\n",
  50. "Градиентный шаг для весов будет выглядеть следующим образом:\n",
  51. "$$\\Large w_0 \\leftarrow w_0 - \\frac{2\\eta}{\\ell} \\sum_{i=1}^\\ell{{((w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}) - y_i)}}$$\n",
  52. "$$\\Large w_j \\leftarrow w_j - \\frac{2\\eta}{\\ell} \\sum_{i=1}^\\ell{{x_{ij}((w_0 + w_1x_{i1} + w_2x_{i2} + w_3x_{i3}) - y_i)}},\\ j \\in \\{1,2,3\\}$$\n",
  53. "Здесь $\\eta$ - параметр, шаг градиентного спуска."
  54. ]
  55. },
  56. {
  57. "cell_type": "markdown",
  58. "metadata": {},
  59. "source": [
  60. "## Стохастический градиентный спуск\n",
  61. "Проблема градиентного спуска, описанного выше, в том, что на больших выборках считать на каждом шаге градиент по всем имеющимся данным может быть очень вычислительно сложно. \n",
  62. "В стохастическом варианте градиентного спуска поправки для весов вычисляются только с учетом одного случайно взятого объекта обучающей выборки:\n",
  63. "$$\\Large w_0 \\leftarrow w_0 - \\frac{2\\eta}{\\ell} {((w_0 + w_1x_{k1} + w_2x_{k2} + w_3x_{k3}) - y_k)}$$\n",
  64. "$$\\Large w_j \\leftarrow w_j - \\frac{2\\eta}{\\ell} {x_{kj}((w_0 + w_1x_{k1} + w_2x_{k2} + w_3x_{k3}) - y_k)},\\ j \\in \\{1,2,3\\},$$\n",
  65. "где $k$ - случайный индекс, $k \\in \\{1, \\ldots, \\ell\\}$."
  66. ]
  67. },
  68. {
  69. "cell_type": "markdown",
  70. "metadata": {},
  71. "source": [
  72. "## Нормальное уравнение \n",
  73. "Нахождение вектора оптимальных весов $w$ может быть сделано и аналитически.\n",
  74. "Мы хотим найти такой вектор весов $w$, чтобы вектор $y$, приближающий целевой признак, получался умножением матрицы $X$ (состоящей из всех признаков объектов обучающей выборки, кроме целевого) на вектор весов $w$. То есть, чтобы выполнялось матричное уравнение:\n",
  75. "$$\\Large y = Xw$$\n",
  76. "Домножением слева на $X^T$ получаем:\n",
  77. "$$\\Large X^Ty = X^TXw$$\n",
  78. "Это хорошо, поскольку теперь матрица $X^TX$ - квадратная, и можно найти решение (вектор $w$) в виде:\n",
  79. "$$\\Large w = {(X^TX)}^{-1}X^Ty$$\n",
  80. "Матрица ${(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).\n",
  81. "\n",
  82. "Однако, нахождение псевдообратной матрицы - операция вычислительно сложная и нестабильная в случае малого определителя матрицы $X$ (проблема мультиколлинеарности). \n",
  83. "На практике лучше находить вектор весов $w$ решением матричного уравнения \n",
  84. "$$\\Large X^TXw = X^Ty$$Это может быть сделано с помощью функции [numpy.linalg.solve](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.linalg.solve.html).\n",
  85. "\n",
  86. "Но все же на практике для больших матриц $X$ быстрее работает градиентный спуск, особенно его стохастическая версия."
  87. ]
  88. },
  89. {
  90. "cell_type": "markdown",
  91. "metadata": {},
  92. "source": [
  93. "## Инструкции по выполнению"
  94. ]
  95. },
  96. {
  97. "cell_type": "markdown",
  98. "metadata": {},
  99. "source": [
  100. "В начале напишем простую функцию для записи ответов в текстовый файл. Ответами будут числа, полученные в ходе решения этого задания, округленные до 3 знаков после запятой. Полученные файлы после выполнения задания надо отправить в форму на странице задания на Coursera.org."
  101. ]
  102. },
  103. {
  104. "cell_type": "code",
  105. "execution_count": 2,
  106. "metadata": {},
  107. "outputs": [],
  108. "source": [
  109. "def write_answer_to_file(answer, filename):\n",
  110. " with open(filename, 'w') as f_out:\n",
  111. " f_out.write(str(round(answer, 3)))"
  112. ]
  113. },
  114. {
  115. "cell_type": "markdown",
  116. "metadata": {},
  117. "source": [
  118. "**1. Загрузите данные из файла *advertising.csv* в объект pandas DataFrame. [Источник данных](http://www-bcf.usc.edu/~gareth/ISL/data.html).**"
  119. ]
  120. },
  121. {
  122. "cell_type": "code",
  123. "execution_count": 1,
  124. "metadata": {},
  125. "outputs": [],
  126. "source": [
  127. "import pandas as pd\n",
  128. "adver_data = pd.read_csv('advertising.csv')"
  129. ]
  130. },
  131. {
  132. "cell_type": "markdown",
  133. "metadata": {
  134. "collapsed": true
  135. },
  136. "source": [
  137. "**Посмотрите на первые 5 записей и на статистику признаков в этом наборе данных.**"
  138. ]
  139. },
  140. {
  141. "cell_type": "code",
  142. "execution_count": 3,
  143. "metadata": {},
  144. "outputs": [
  145. {
  146. "data": {
  147. "text/html": [
  148. "<div>\n",
  149. "<style scoped>\n",
  150. " .dataframe tbody tr th:only-of-type {\n",
  151. " vertical-align: middle;\n",
  152. " }\n",
  153. "\n",
  154. " .dataframe tbody tr th {\n",
  155. " vertical-align: top;\n",
  156. " }\n",
  157. "\n",
  158. " .dataframe thead th {\n",
  159. " text-align: right;\n",
  160. " }\n",
  161. "</style>\n",
  162. "<table border=\"1\" class=\"dataframe\">\n",
  163. " <thead>\n",
  164. " <tr style=\"text-align: right;\">\n",
  165. " <th></th>\n",
  166. " <th>TV</th>\n",
  167. " <th>Radio</th>\n",
  168. " <th>Newspaper</th>\n",
  169. " <th>Sales</th>\n",
  170. " </tr>\n",
  171. " </thead>\n",
  172. " <tbody>\n",
  173. " <tr>\n",
  174. " <th>1</th>\n",
  175. " <td>230.1</td>\n",
  176. " <td>37.8</td>\n",
  177. " <td>69.2</td>\n",
  178. " <td>22.1</td>\n",
  179. " </tr>\n",
  180. " <tr>\n",
  181. " <th>2</th>\n",
  182. " <td>44.5</td>\n",
  183. " <td>39.3</td>\n",
  184. " <td>45.1</td>\n",
  185. " <td>10.4</td>\n",
  186. " </tr>\n",
  187. " <tr>\n",
  188. " <th>3</th>\n",
  189. " <td>17.2</td>\n",
  190. " <td>45.9</td>\n",
  191. " <td>69.3</td>\n",
  192. " <td>9.3</td>\n",
  193. " </tr>\n",
  194. " <tr>\n",
  195. " <th>4</th>\n",
  196. " <td>151.5</td>\n",
  197. " <td>41.3</td>\n",
  198. " <td>58.5</td>\n",
  199. " <td>18.5</td>\n",
  200. " </tr>\n",
  201. " <tr>\n",
  202. " <th>5</th>\n",
  203. " <td>180.8</td>\n",
  204. " <td>10.8</td>\n",
  205. " <td>58.4</td>\n",
  206. " <td>12.9</td>\n",
  207. " </tr>\n",
  208. " </tbody>\n",
  209. "</table>\n",
  210. "</div>"
  211. ],
  212. "text/plain": [
  213. " TV Radio Newspaper Sales\n",
  214. "1 230.1 37.8 69.2 22.1\n",
  215. "2 44.5 39.3 45.1 10.4\n",
  216. "3 17.2 45.9 69.3 9.3\n",
  217. "4 151.5 41.3 58.5 18.5\n",
  218. "5 180.8 10.8 58.4 12.9"
  219. ]
  220. },
  221. "execution_count": 3,
  222. "metadata": {},
  223. "output_type": "execute_result"
  224. }
  225. ],
  226. "source": [
  227. "adver_data.head()"
  228. ]
  229. },
  230. {
  231. "cell_type": "code",
  232. "execution_count": 4,
  233. "metadata": {},
  234. "outputs": [
  235. {
  236. "data": {
  237. "text/html": [
  238. "<div>\n",
  239. "<style scoped>\n",
  240. " .dataframe tbody tr th:only-of-type {\n",
  241. " vertical-align: middle;\n",
  242. " }\n",
  243. "\n",
  244. " .dataframe tbody tr th {\n",
  245. " vertical-align: top;\n",
  246. " }\n",
  247. "\n",
  248. " .dataframe thead th {\n",
  249. " text-align: right;\n",
  250. " }\n",
  251. "</style>\n",
  252. "<table border=\"1\" class=\"dataframe\">\n",
  253. " <thead>\n",
  254. " <tr style=\"text-align: right;\">\n",
  255. " <th></th>\n",
  256. " <th>TV</th>\n",
  257. " <th>Radio</th>\n",
  258. " <th>Newspaper</th>\n",
  259. " <th>Sales</th>\n",
  260. " </tr>\n",
  261. " </thead>\n",
  262. " <tbody>\n",
  263. " <tr>\n",
  264. " <th>count</th>\n",
  265. " <td>200.000000</td>\n",
  266. " <td>200.000000</td>\n",
  267. " <td>200.000000</td>\n",
  268. " <td>200.000000</td>\n",
  269. " </tr>\n",
  270. " <tr>\n",
  271. " <th>mean</th>\n",
  272. " <td>147.042500</td>\n",
  273. " <td>23.264000</td>\n",
  274. " <td>30.554000</td>\n",
  275. " <td>14.022500</td>\n",
  276. " </tr>\n",
  277. " <tr>\n",
  278. " <th>std</th>\n",
  279. " <td>85.854236</td>\n",
  280. " <td>14.846809</td>\n",
  281. " <td>21.778621</td>\n",
  282. " <td>5.217457</td>\n",
  283. " </tr>\n",
  284. " <tr>\n",
  285. " <th>min</th>\n",
  286. " <td>0.700000</td>\n",
  287. " <td>0.000000</td>\n",
  288. " <td>0.300000</td>\n",
  289. " <td>1.600000</td>\n",
  290. " </tr>\n",
  291. " <tr>\n",
  292. " <th>25%</th>\n",
  293. " <td>74.375000</td>\n",
  294. " <td>9.975000</td>\n",
  295. " <td>12.750000</td>\n",
  296. " <td>10.375000</td>\n",
  297. " </tr>\n",
  298. " <tr>\n",
  299. " <th>50%</th>\n",
  300. " <td>149.750000</td>\n",
  301. " <td>22.900000</td>\n",
  302. " <td>25.750000</td>\n",
  303. " <td>12.900000</td>\n",
  304. " </tr>\n",
  305. " <tr>\n",
  306. " <th>75%</th>\n",
  307. " <td>218.825000</td>\n",
  308. " <td>36.525000</td>\n",
  309. " <td>45.100000</td>\n",
  310. " <td>17.400000</td>\n",
  311. " </tr>\n",
  312. " <tr>\n",
  313. " <th>max</th>\n",
  314. " <td>296.400000</td>\n",
  315. " <td>49.600000</td>\n",
  316. " <td>114.000000</td>\n",
  317. " <td>27.000000</td>\n",
  318. " </tr>\n",
  319. " </tbody>\n",
  320. "</table>\n",
  321. "</div>"
  322. ],
  323. "text/plain": [
  324. " TV Radio Newspaper Sales\n",
  325. "count 200.000000 200.000000 200.000000 200.000000\n",
  326. "mean 147.042500 23.264000 30.554000 14.022500\n",
  327. "std 85.854236 14.846809 21.778621 5.217457\n",
  328. "min 0.700000 0.000000 0.300000 1.600000\n",
  329. "25% 74.375000 9.975000 12.750000 10.375000\n",
  330. "50% 149.750000 22.900000 25.750000 12.900000\n",
  331. "75% 218.825000 36.525000 45.100000 17.400000\n",
  332. "max 296.400000 49.600000 114.000000 27.000000"
  333. ]
  334. },
  335. "execution_count": 4,
  336. "metadata": {},
  337. "output_type": "execute_result"
  338. }
  339. ],
  340. "source": [
  341. "adver_data.describe()"
  342. ]
  343. },
  344. {
  345. "cell_type": "markdown",
  346. "metadata": {},
  347. "source": [
  348. "**Создайте массивы NumPy *X* из столбцов TV, Radio и Newspaper и *y* - из столбца Sales. Используйте атрибут *values* объекта pandas DataFrame.**"
  349. ]
  350. },
  351. {
  352. "cell_type": "code",
  353. "execution_count": 64,
  354. "metadata": {},
  355. "outputs": [],
  356. "source": [
  357. "X = adver_data[['TV', 'Radio', 'Newspaper']].values\n",
  358. "y = adver_data[['Sales']].values"
  359. ]
  360. },
  361. {
  362. "cell_type": "markdown",
  363. "metadata": {},
  364. "source": [
  365. "**Отмасштабируйте столбцы матрицы *X*, вычтя из каждого значения среднее по соответствующему столбцу и поделив результат на стандартное отклонение. Для определенности, используйте методы mean и std векторов NumPy (реализация std в Pandas может отличаться). Обратите внимание, что в numpy вызов функции .mean() без параметров возвращает среднее по всем элементам массива, а не по столбцам, как в pandas. Чтобы произвести вычисление по столбцам, необходимо указать параметр axis.**"
  366. ]
  367. },
  368. {
  369. "cell_type": "code",
  370. "execution_count": 65,
  371. "metadata": {},
  372. "outputs": [
  373. {
  374. "data": {
  375. "text/plain": [
  376. "array([85.63933176, 14.80964564, 21.72410606])"
  377. ]
  378. },
  379. "execution_count": 65,
  380. "metadata": {},
  381. "output_type": "execute_result"
  382. }
  383. ],
  384. "source": [
  385. "import numpy as np\n",
  386. "\n",
  387. "means, stds = X.mean(axis=0), X.std(axis=0)\n",
  388. "stds"
  389. ]
  390. },
  391. {
  392. "cell_type": "code",
  393. "execution_count": 66,
  394. "metadata": {},
  395. "outputs": [],
  396. "source": [
  397. "X = (X - means) / stds"
  398. ]
  399. },
  400. {
  401. "cell_type": "markdown",
  402. "metadata": {},
  403. "source": [
  404. "**Добавьте к матрице *X* столбец из единиц, используя методы *hstack*, *ones* и *reshape* библиотеки NumPy. Вектор из единиц нужен для того, чтобы не обрабатывать отдельно коэффициент $w_0$ линейной регрессии.**"
  405. ]
  406. },
  407. {
  408. "cell_type": "code",
  409. "execution_count": 67,
  410. "metadata": {},
  411. "outputs": [],
  412. "source": [
  413. "import numpy as np\n",
  414. "\n",
  415. "N = X.shape[0]\n",
  416. "ones_column = np.ones((N, 1))\n",
  417. "X = np.hstack((X, ones))"
  418. ]
  419. },
  420. {
  421. "cell_type": "markdown",
  422. "metadata": {},
  423. "source": [
  424. "**2. Реализуйте функцию *mserror* - среднеквадратичную ошибку прогноза. Она принимает два аргумента - объекты Series *y* (значения целевого признака) и *y\\_pred* (предсказанные значения). Не используйте в этой функции циклы - тогда она будет вычислительно неэффективной.**"
  425. ]
  426. },
  427. {
  428. "cell_type": "code",
  429. "execution_count": null,
  430. "metadata": {
  431. "collapsed": true
  432. },
  433. "outputs": [],
  434. "source": [
  435. "def mserror(y, y_pred):\n",
  436. " return ((y - y_pred)**2).mean(axis=ax)"
  437. ]
  438. },
  439. {
  440. "cell_type": "markdown",
  441. "metadata": {},
  442. "source": [
  443. "**Какова среднеквадратичная ошибка прогноза значений Sales, если всегда предсказывать медианное значение Sales по исходной выборке? Запишите ответ в файл '1.txt'.**"
  444. ]
  445. },
  446. {
  447. "cell_type": "code",
  448. "execution_count": null,
  449. "metadata": {},
  450. "outputs": [],
  451. "source": [
  452. "answer1 = # Ваш код здесь\n",
  453. "print(answer1)\n",
  454. "write_answer_to_file(answer1, '1.txt')"
  455. ]
  456. },
  457. {
  458. "cell_type": "markdown",
  459. "metadata": {},
  460. "source": [
  461. "**3. Реализуйте функцию *normal_equation*, которая по заданным матрицам (массивам NumPy) *X* и *y* вычисляет вектор весов $w$ согласно нормальному уравнению линейной регрессии.**"
  462. ]
  463. },
  464. {
  465. "cell_type": "code",
  466. "execution_count": null,
  467. "metadata": {
  468. "collapsed": true
  469. },
  470. "outputs": [],
  471. "source": [
  472. "def normal_equation(X, y):\n",
  473. " return np.linalg.inv # Ваш код здесь"
  474. ]
  475. },
  476. {
  477. "cell_type": "code",
  478. "execution_count": null,
  479. "metadata": {},
  480. "outputs": [],
  481. "source": [
  482. "norm_eq_weights = normal_equation(X, y)\n",
  483. "print(norm_eq_weights)"
  484. ]
  485. },
  486. {
  487. "cell_type": "markdown",
  488. "metadata": {},
  489. "source": [
  490. "**Какие продажи предсказываются линейной моделью с весами, найденными с помощью нормального уравнения, в случае средних инвестиций в рекламу по ТВ, радио и в газетах? (то есть при нулевых значениях масштабированных признаков TV, Radio и Newspaper). Запишите ответ в файл '2.txt'.**"
  491. ]
  492. },
  493. {
  494. "cell_type": "code",
  495. "execution_count": null,
  496. "metadata": {},
  497. "outputs": [],
  498. "source": [
  499. "answer2 = # Ваш код здесь\n",
  500. "print(answer2)\n",
  501. "write_answer_to_file(answer2, '2.txt')"
  502. ]
  503. },
  504. {
  505. "cell_type": "markdown",
  506. "metadata": {},
  507. "source": [
  508. "**4. Напишите функцию *linear_prediction*, которая принимает на вход матрицу *X* и вектор весов линейной модели *w*, а возвращает вектор прогнозов в виде линейной комбинации столбцов матрицы *X* с весами *w*.**"
  509. ]
  510. },
  511. {
  512. "cell_type": "code",
  513. "execution_count": null,
  514. "metadata": {
  515. "collapsed": true
  516. },
  517. "outputs": [],
  518. "source": [
  519. "def linear_prediction(X, w):\n",
  520. " # Ваш код здесь"
  521. ]
  522. },
  523. {
  524. "cell_type": "markdown",
  525. "metadata": {},
  526. "source": [
  527. "**Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью нормального уравнения? Запишите ответ в файл '3.txt'.**"
  528. ]
  529. },
  530. {
  531. "cell_type": "code",
  532. "execution_count": null,
  533. "metadata": {},
  534. "outputs": [],
  535. "source": [
  536. "answer3 = # Ваш код здесь\n",
  537. "print(answer3)\n",
  538. "write_answer_to_file(answer3, '3.txt')"
  539. ]
  540. },
  541. {
  542. "cell_type": "markdown",
  543. "metadata": {},
  544. "source": [
  545. "**5. Напишите функцию *stochastic_gradient_step*, реализующую шаг стохастического градиентного спуска для линейной регрессии. Функция должна принимать матрицу *X*, вектора *y* и *w*, число *train_ind* - индекс объекта обучающей выборки (строки матрицы *X*), по которому считается изменение весов, а также число *$\\eta$* (eta) - шаг градиентного спуска (по умолчанию *eta*=0.01). Результатом будет вектор обновленных весов. Наша реализация функции будет явно написана для данных с 3 признаками, но несложно модифицировать для любого числа признаков, можете это сделать.**"
  546. ]
  547. },
  548. {
  549. "cell_type": "code",
  550. "execution_count": null,
  551. "metadata": {},
  552. "outputs": [],
  553. "source": [
  554. "def stochastic_gradient_step(X, y, w, train_ind, eta=0.01):\n",
  555. " grad0 = # Ваш код здесь\n",
  556. " grad1 = # Ваш код здесь\n",
  557. " grad2 = # Ваш код здесь\n",
  558. " grad3 = # Ваш код здесь\n",
  559. " return w - eta * np.array([grad0, grad1, grad2, grad3])"
  560. ]
  561. },
  562. {
  563. "cell_type": "markdown",
  564. "metadata": {},
  565. "source": [
  566. "**6. Напишите функцию *stochastic_gradient_descent*, реализующую стохастический градиентный спуск для линейной регрессии. Функция принимает на вход следующие аргументы:**\n",
  567. "- X - матрица, соответствующая обучающей выборке\n",
  568. "- y - вектор значений целевого признака\n",
  569. "- w_init - вектор начальных весов модели\n",
  570. "- eta - шаг градиентного спуска (по умолчанию 0.01)\n",
  571. "- max_iter - максимальное число итераций градиентного спуска (по умолчанию 10000)\n",
  572. "- max_weight_dist - максимальное евклидово расстояние между векторами весов на соседних итерациях градиентного спуска,\n",
  573. "при котором алгоритм прекращает работу (по умолчанию 1e-8)\n",
  574. "- seed - число, используемое для воспроизводимости сгенерированных псевдослучайных чисел (по умолчанию 42)\n",
  575. "- verbose - флаг печати информации (например, для отладки, по умолчанию False)\n",
  576. "\n",
  577. "**На каждой итерации в вектор (список) должно записываться текущее значение среднеквадратичной ошибки. Функция должна возвращать вектор весов $w$, а также вектор (список) ошибок.**"
  578. ]
  579. },
  580. {
  581. "cell_type": "code",
  582. "execution_count": null,
  583. "metadata": {
  584. "collapsed": true
  585. },
  586. "outputs": [],
  587. "source": [
  588. "def stochastic_gradient_descent(X, y, w_init, eta=1e-2, max_iter=1e4,\n",
  589. " min_weight_dist=1e-8, seed=42, verbose=False):\n",
  590. " # Инициализируем расстояние между векторами весов на соседних\n",
  591. " # итерациях большим числом. \n",
  592. " weight_dist = np.inf\n",
  593. " # Инициализируем вектор весов\n",
  594. " w = w_init\n",
  595. " # Сюда будем записывать ошибки на каждой итерации\n",
  596. " errors = []\n",
  597. " # Счетчик итераций\n",
  598. " iter_num = 0\n",
  599. " # Будем порождать псевдослучайные числа \n",
  600. " # (номер объекта, который будет менять веса), а для воспроизводимости\n",
  601. " # этой последовательности псевдослучайных чисел используем seed.\n",
  602. " np.random.seed(seed)\n",
  603. " \n",
  604. " # Основной цикл\n",
  605. " while weight_dist > min_weight_dist and iter_num < max_iter:\n",
  606. " # порождаем псевдослучайный \n",
  607. " # индекс объекта обучающей выборки\n",
  608. " random_ind = np.random.randint(X.shape[0])\n",
  609. " \n",
  610. " # Ваш код здесь\n",
  611. " \n",
  612. " return w, errors"
  613. ]
  614. },
  615. {
  616. "cell_type": "markdown",
  617. "metadata": {},
  618. "source": [
  619. " **Запустите $10^5$ итераций стохастического градиентного спуска. Укажите вектор начальных весов *w_init*, состоящий из нулей. Оставьте параметры *eta* и *seed* равными их значениям по умолчанию (*eta*=0.01, *seed*=42 - это важно для проверки ответов).**"
  620. ]
  621. },
  622. {
  623. "cell_type": "code",
  624. "execution_count": null,
  625. "metadata": {},
  626. "outputs": [],
  627. "source": [
  628. "%%time\n",
  629. "stoch_grad_desc_weights, stoch_errors_by_iter = # Ваш код здесь"
  630. ]
  631. },
  632. {
  633. "cell_type": "markdown",
  634. "metadata": {},
  635. "source": [
  636. "**Посмотрим, чему равна ошибка на первых 50 итерациях стохастического градиентного спуска. Видим, что ошибка не обязательно уменьшается на каждой итерации.**"
  637. ]
  638. },
  639. {
  640. "cell_type": "code",
  641. "execution_count": null,
  642. "metadata": {},
  643. "outputs": [],
  644. "source": [
  645. "%pylab inline\n",
  646. "plot(range(50), stoch_errors_by_iter[:50])\n",
  647. "xlabel('Iteration number')\n",
  648. "ylabel('MSE')"
  649. ]
  650. },
  651. {
  652. "cell_type": "markdown",
  653. "metadata": {},
  654. "source": [
  655. "**Теперь посмотрим на зависимость ошибки от номера итерации для $10^5$ итераций стохастического градиентного спуска. Видим, что алгоритм сходится.**"
  656. ]
  657. },
  658. {
  659. "cell_type": "code",
  660. "execution_count": null,
  661. "metadata": {
  662. "collapsed": true
  663. },
  664. "outputs": [],
  665. "source": [
  666. "%pylab inline\n",
  667. "plot(range(len(stoch_errors_by_iter)), stoch_errors_by_iter)\n",
  668. "xlabel('Iteration number')\n",
  669. "ylabel('MSE')"
  670. ]
  671. },
  672. {
  673. "cell_type": "markdown",
  674. "metadata": {},
  675. "source": [
  676. "**Посмотрим на вектор весов, к которому сошелся метод.**"
  677. ]
  678. },
  679. {
  680. "cell_type": "code",
  681. "execution_count": null,
  682. "metadata": {},
  683. "outputs": [],
  684. "source": [
  685. "stoch_grad_desc_weights"
  686. ]
  687. },
  688. {
  689. "cell_type": "markdown",
  690. "metadata": {},
  691. "source": [
  692. "**Посмотрим на среднеквадратичную ошибку на последней итерации.**"
  693. ]
  694. },
  695. {
  696. "cell_type": "code",
  697. "execution_count": null,
  698. "metadata": {},
  699. "outputs": [],
  700. "source": [
  701. "stoch_errors_by_iter[-1]"
  702. ]
  703. },
  704. {
  705. "cell_type": "markdown",
  706. "metadata": {},
  707. "source": [
  708. "**Какова среднеквадратичная ошибка прогноза значений Sales в виде линейной модели с весами, найденными с помощью градиентного спуска? Запишите ответ в файл '4.txt'.**"
  709. ]
  710. },
  711. {
  712. "cell_type": "code",
  713. "execution_count": null,
  714. "metadata": {},
  715. "outputs": [],
  716. "source": [
  717. "answer4 = # Ваш код здесь\n",
  718. "print(answer4)\n",
  719. "write_answer_to_file(answer4, '4.txt')"
  720. ]
  721. },
  722. {
  723. "cell_type": "markdown",
  724. "metadata": {},
  725. "source": [
  726. "**Ответами к заданию будут текстовые файлы, полученные в ходе этого решения. Обратите внимание, что отправленные файлы не должны содержать пустую строку в конце. Данный нюанс является ограничением платформы Coursera. Мы работаем над исправлением этого ограничения.**"
  727. ]
  728. }
  729. ],
  730. "metadata": {
  731. "kernelspec": {
  732. "display_name": "Python 3",
  733. "language": "python",
  734. "name": "python3"
  735. },
  736. "language_info": {
  737. "codemirror_mode": {
  738. "name": "ipython",
  739. "version": 3
  740. },
  741. "file_extension": ".py",
  742. "mimetype": "text/x-python",
  743. "name": "python",
  744. "nbconvert_exporter": "python",
  745. "pygments_lexer": "ipython3",
  746. "version": "3.7.2"
  747. }
  748. },
  749. "nbformat": 4,
  750. "nbformat_minor": 1
  751. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement