├── .gitignore
├── 2022-2023
├── lesson1
│ ├── hello_numpy.ipynb
│ └── numpy_practice.ipynb
├── lesson2
│ ├── Pandas_Cheat_Sheet.pdf
│ ├── pandas_lecture.ipynb
│ └── task
│ │ └── pandas_practice.ipynb
├── lesson3
│ ├── lecture
│ │ ├── lesson.ipynb
│ │ └── pic
│ │ │ ├── anatomy.png
│ │ │ ├── boxplot.png
│ │ │ └── violin.jpg
│ └── task
│ │ └── visual_practice.ipynb
├── lesson4
│ ├── age_sal_tree.png
│ ├── age_tree.png
│ ├── balls
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ └── 5.png
│ ├── classification.ipynb
│ └── small_tree.png
├── lesson5
│ └── regression.ipynb
├── lesson6
│ ├── 1.png
│ └── linery_model.ipynb
├── lesson7
│ ├── 2.png
│ ├── 3.png
│ ├── bagging.png
│ ├── bootstrap.jpg
│ └── forest'n'bagging.ipynb
└── lesson8
│ ├── PCA.ipynb
│ └── clusterization.ipynb
└── 2023-2024
└── fall
├── lesson0
└── Hello,ML.pdf
├── lesson1
├── hello_numpy.ipynb
└── hello_python.ipynb
├── lesson2
├── pandas_lecture.ipynb
└── pics
│ ├── 0.png
│ ├── 1.png
│ └── 2.png
├── lesson3
├── hello_visualization.ipynb
└── pics
│ ├── 1.jpg
│ ├── 2.jpeg
│ └── 3.jpeg
└── lesson4
├── hello_classification.ipynb
├── pics
├── balls
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ └── 5.png
├── book.jpeg
├── cat.jpg
└── tree.jpg
└── small_tree.dot
/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.DS_Store
--------------------------------------------------------------------------------
/2022-2023/lesson1/hello_numpy.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "### Основные преимущества списков NumPy перед стандартными списками"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "Собственно, векторное применение функций - самый очевидный бонус numpy. Он избавляет от необходимости оборачивания в map или в цикл какой-либо функции.\n",
15 | "\n",
16 | "Важна также функциональность: вы получаете много встроенных функций с NumPy, FFT, свертками, быстрым поиском, базовой статистикой, линейной алгеброй, гистограммами и т.д."
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": null,
22 | "metadata": {},
23 | "outputs": [],
24 | "source": [
25 | "import math\n",
26 | "import numpy as np"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "a = [1, 2, 3, 4, 5]\n",
36 | "a = list(map(math.sqrt, a))\n",
37 | "a\n",
38 | "\n",
39 | "# здесь можно также указывать точность\n",
40 | "# (количество чисел после запятой)\n",
41 | "# np.set_printoptions(precision=4)\n",
42 | "a = [1, 2, 3, 4, 5]\n",
43 | "a = np.sqrt(a)\n",
44 | "a"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "Также часто упоминают хорошую скорость выполнения операций по сравнению операции с теми же оригинальными списками"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 4,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "name": "stdout",
61 | "output_type": "stream",
62 | "text": [
63 | "Python array: 10.291004419326782\n",
64 | "Numpy array: 0.22296142578125\n"
65 | ]
66 | }
67 | ],
68 | "source": [
69 | "import time\n",
70 | "\n",
71 | "a = [i for i in range(100000000)]\n",
72 | "\n",
73 | "b = np.array(a, int)\n",
74 | "\n",
75 | "t = time.time()\n",
76 | "a = [a[i] + 1 for i in range(len(a))]\n",
77 | "print(f'Python array: {time.time() - t}')\n",
78 | "\n",
79 | "t = time.time()\n",
80 | "b = b + 1\n",
81 | "print(f'Numpy array: {time.time() - t}')"
82 | ]
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {},
87 | "source": [
88 | "## Переходим к описаниям функций NumPy"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "### 3. Создание массива и матриц NumPy"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "#### Создание массива из списка"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": null,
108 | "metadata": {},
109 | "outputs": [],
110 | "source": [
111 | "some_array = np.array([1, 4, 5, 8], float)\n",
112 | "print(type(some_array))\n",
113 | "\n",
114 | "# созданный массив, кстати, позволяет работать с собой\n",
115 | "# также, как и обычный список\n",
116 | "print(some_array[:2])\n",
117 | "print(some_array[3])\n",
118 | "some_array[2] = 69\n",
119 | "print(some_array)"
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "execution_count": null,
125 | "metadata": {},
126 | "outputs": [],
127 | "source": [
128 | "# массивы так то могут быть и не одномерными (удивительно)\n",
129 | "big_array = np.array([[1, 2, 3], [4, 5, 6]])\n",
130 | "print(big_array)\n",
131 | "# в отличии от списков можно использовать запятые в скобках\n",
132 | "print(big_array[0, 0] == big_array[0][0])"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "#### np.arange()"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {},
146 | "outputs": [],
147 | "source": [
148 | "kek = np.arange(3)\n",
149 | "# можно явно указывать тип значений\n",
150 | "kek = np.arange(3.0)\n",
151 | "kek = np.arange(0, 5)\n",
152 | "# от 0 до 5 с шагом 2\n",
153 | "kek = np.arange(0, 5, 2)\n",
154 | "print(kek)"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "#### np.zeros() и np.ones()"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": null,
167 | "metadata": {},
168 | "outputs": [],
169 | "source": [
170 | "kavo = np.zeros(5)\n",
171 | "# явное указание типа здесь тоже есть\n",
172 | "# (вообще оно почти везде есть, можно к этому больше не возвращаться)\n",
173 | "kavo = np.zeros((5), dtype=int)\n",
174 | "# можно указывать размерность\n",
175 | "kavo = np.zeros((5, 2))\n",
176 | "\n",
177 | "# (штука, в очень многом схожая с np.zeros())\n",
178 | "chevo = np.ones(5)\n",
179 | "chevo = np.ones((5, 2))"
180 | ]
181 | },
182 | {
183 | "cell_type": "markdown",
184 | "metadata": {},
185 | "source": [
186 | "#### np.linspace()"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "# (штука очень похожая на arange, только arange\n",
196 | "# создает с указанием шага, а тут указывается\n",
197 | "# кол-во элементов)\n",
198 | "np.linspace(2.0, 3.0, num=22)\n",
199 | "\n",
200 | "# можно указать, включать ли правую границу в\n",
201 | "# содержимое массива\n",
202 | "np.linspace(2.0, 3.0, num=5, endpoint=False)\n",
203 | "\n",
204 | "# можно даже возвращать не просто список, а кортеж\n",
205 | "# из списка и вычисленного шага между элементами\n",
206 | "np.linspace(2.0, 3.0, num=8, retstep=True)"
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "#### np.identity() и np.eye()"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": null,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": [
222 | "# просто единичная матрица\n",
223 | "np.identity(5)\n",
224 | "\n",
225 | "# возвращает двумерный массив с единицами на указанной\n",
226 | "# диагонали (во всех остальных местах ставятся нули)\n",
227 | "np.eye(2, dtype=int)\n",
228 | "np.eye(4, dtype=int)\n",
229 | "# второй аргумент указывает на размерность\n",
230 | "np.eye(4, 3, 1, dtype=int)\n",
231 | "# иногда удобнее явно задавать номер диагонали\n",
232 | "np.eye(3, k=1)"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {},
238 | "source": [
239 | "### 4. Мелкие вспомогательные функции"
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {},
245 | "source": [
246 | "#### np.shape"
247 | ]
248 | },
249 | {
250 | "cell_type": "code",
251 | "execution_count": null,
252 | "metadata": {},
253 | "outputs": [],
254 | "source": [
255 | "# np.shape позволяет\n",
256 | "# получить размерность некоторого массива\n",
257 | "np.shape(np.eye(3))\n",
258 | "np.shape(some_array)\n",
259 | "np.shape(big_array)"
260 | ]
261 | },
262 | {
263 | "cell_type": "markdown",
264 | "metadata": {},
265 | "source": [
266 | "#### np.dtype"
267 | ]
268 | },
269 | {
270 | "cell_type": "code",
271 | "execution_count": null,
272 | "metadata": {},
273 | "outputs": [],
274 | "source": [
275 | "# np.dtype указывает\n",
276 | "# на тип содержимого списка\n",
277 | "big_array.dtype\n",
278 | "print((np.arange(3.0)).dtype)\n",
279 | "print(np.array([\"pepega\", \"nice\"]).dtype)\n",
280 | "print(np.array([{\"a\": 1}, {\"b\": 2}]).dtype)"
281 | ]
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {},
286 | "source": [
287 | "#### np.copy()"
288 | ]
289 | },
290 | {
291 | "cell_type": "code",
292 | "execution_count": null,
293 | "metadata": {},
294 | "outputs": [],
295 | "source": [
296 | "# np.copy() копирует список\n",
297 | "# с содержимым в другую ячейку в памяти\n",
298 | "a = np.array([1, 'm', [2, 3, 4]], dtype=object)\n",
299 | "b = np.copy(a)\n",
300 | "a[1] = 1\n",
301 | "print(a)\n",
302 | "print(b)"
303 | ]
304 | },
305 | {
306 | "cell_type": "markdown",
307 | "metadata": {},
308 | "source": [
309 | "#### np.flatten()"
310 | ]
311 | },
312 | {
313 | "cell_type": "code",
314 | "execution_count": null,
315 | "metadata": {},
316 | "outputs": [],
317 | "source": [
318 | "# делает одномерный массив из многомерного\n",
319 | "a = np.array([[1,2], [3,4]])\n",
320 | "print(a.flatten())\n",
321 | "a = np.array([[1,2], [[3, 3.5, 3.6], 4]])\n",
322 | "print(a.flatten())"
323 | ]
324 | },
325 | {
326 | "cell_type": "markdown",
327 | "metadata": {},
328 | "source": [
329 | "#### np.concatenate()"
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {},
336 | "outputs": [],
337 | "source": [
338 | "# np.concatenate()\n",
339 | "# осуществляет конкатенацию списков\n",
340 | "a = np.array([[1,2], [3,4]])\n",
341 | "a = np.array([[1, 2], [3, 4]])\n",
342 | "b = np.array([[5, 6]])\n",
343 | "print(np.concatenate((a, b), axis=0))\n",
344 | "print(np.concatenate((a, b), axis=None))"
345 | ]
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "metadata": {},
350 | "source": [
351 | "### 5. Арифметические и логические операции в NumPy"
352 | ]
353 | },
354 | {
355 | "cell_type": "code",
356 | "execution_count": null,
357 | "metadata": {},
358 | "outputs": [],
359 | "source": [
360 | "# база\n",
361 | "a = np.array([1,2,3], float)\n",
362 | "b = np.array([5,2,6], float)\n",
363 | "print(a + b)\n",
364 | "print(a - b)\n",
365 | "\n",
366 | "# умножение даже двумерных матриц с помощью оператора \"*\"\n",
367 | "# происходит тоже ПОЭЛЕМЕНТНО\n",
368 | "print(a * b)\n",
369 | "print(a / b)\n",
370 | "print(a % b)\n",
371 | "print(a ** b)\n",
372 | "\n",
373 | "# ещё база\n",
374 | "a = np.array([1, 3, 0], float)\n",
375 | "b = np.array([0, 3, 2], float)\n",
376 | "print(a > b)\n",
377 | "print(a == b)\n",
378 | "print(a <= b)\n",
379 | "print(c = a > b)\n",
380 | "# можем сравнивать с одиночным значением\n",
381 | "a = np.array([1, 3, 0], float)\n",
382 | "print(a > 2)"
383 | ]
384 | },
385 | {
386 | "cell_type": "markdown",
387 | "metadata": {},
388 | "source": [
389 | "#### np.all() и np.any()"
390 | ]
391 | },
392 | {
393 | "cell_type": "code",
394 | "execution_count": null,
395 | "metadata": {},
396 | "outputs": [],
397 | "source": [
398 | "# возвращает true, если все значения списка ненулевые\n",
399 | "# (по сути это логическое И)\n",
400 | "np.all([1, 1, 1])\n",
401 | "np.all([0, 1, 1])\n",
402 | "# ключевое слово - НЕНУЛЕВЫЕ\n",
403 | "np.all([-1, 4, 5])\n",
404 | "\n",
405 | "# можно указывать, возвращать ли значение для всех списков,\n",
406 | "# или значения для каждого конкретного\n",
407 | "np.all([[True,False],[True,True]])\n",
408 | "np.all([[True,False],[True,True]], axis=0)\n",
409 | "\n",
410 | "# np.any()\n",
411 | "# возвращает true, если хотя бы одно значение списка ненулевое\n",
412 | "# (по сути это логическое ИЛИ)\n",
413 | "np.any([0, 0, 0])\n",
414 | "np.any([0, 0, 1])"
415 | ]
416 | },
417 | {
418 | "cell_type": "markdown",
419 | "metadata": {},
420 | "source": [
421 | "#### np.sqrt(). np.exp(), np.log()"
422 | ]
423 | },
424 | {
425 | "cell_type": "code",
426 | "execution_count": null,
427 | "metadata": {},
428 | "outputs": [],
429 | "source": [
430 | "# векторизованные до боли знакомые функции\n",
431 | "np.sqrt([1, 4, 9])\n",
432 | "np.exp([1, 4, 9])\n",
433 | "np.log([1, 4, 9])\n",
434 | "\n",
435 | "# можно работать и с комплексными числами\n",
436 | "# но нужно ли...\n",
437 | "np.sqrt([4, -1, -3+4J])\n",
438 | "np.log([4, -1, -3+4J])"
439 | ]
440 | },
441 | {
442 | "cell_type": "markdown",
443 | "metadata": {},
444 | "source": [
445 | "#### np.sum() и np.prod()"
446 | ]
447 | },
448 | {
449 | "cell_type": "code",
450 | "execution_count": null,
451 | "metadata": {},
452 | "outputs": [],
453 | "source": [
454 | "# сумма значений списка по конкретной оси\n",
455 | "print(np.sum([0.5, 1.5]))\n",
456 | "print(np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32))\n",
457 | "print(np.sum([[0, 1], [0, 5]]))\n",
458 | "print(np.sum([[0, 1], [1, 5]], axis=0))\n",
459 | "print(np.sum([[0, 1], [1, 5]], axis=1))\n",
460 | "\n",
461 | "# произведение значений списка по конкретной оси\n",
462 | "print(np.prod([0.5, 1.5]))\n",
463 | "print(np.prod([0.5, 0.7, 0.2, 1.5], dtype=np.int32))\n",
464 | "print(np.prod([[1, 2], [3, 4]]))\n",
465 | "print(np.prod([[1, 2], [3, 4]], axis=0))\n",
466 | "print(np.prod([[1, 2], [3, 4]], axis=1))"
467 | ]
468 | },
469 | {
470 | "cell_type": "markdown",
471 | "metadata": {},
472 | "source": [
473 | "#### np.dot() и np.matmul()"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": null,
479 | "metadata": {},
480 | "outputs": [],
481 | "source": [
482 | "# с помощью np.dot()\n",
483 | "# можно умножать массивы между собой\n",
484 | "# (представляет собой поэлементное\n",
485 | "# умножение элементов списков)\n",
486 | "print(np.dot(3, 4))\n",
487 | "print(np.dot([2j, 3j], [2j, 3j]))\n",
488 | "a = [[1, 0],\n",
489 | " [1, 1]]\n",
490 | "b = [[4, 1],\n",
491 | " [2, 2]]\n",
492 | "print(np.dot(a, b))\n",
493 | "\n",
494 | "\n",
495 | "# np.matmul()\n",
496 | "# (по сути является обычным\n",
497 | "# матричным произведением)\n",
498 | "a = [[1, 0],\n",
499 | " [1, 1]]\n",
500 | "b = [[4, 1],\n",
501 | " [2, 2]]\n",
502 | "print(np.matmul(a, b))\n",
503 | "\n",
504 | "a = np.array([[1, 1],\n",
505 | " [1, 1]])\n",
506 | "b = np.array([1, 2])\n",
507 | "print(np.matmul(a, b))"
508 | ]
509 | },
510 | {
511 | "cell_type": "markdown",
512 | "metadata": {},
513 | "source": [
514 | "### 6. Константы и статистические приколы"
515 | ]
516 | },
517 | {
518 | "cell_type": "code",
519 | "execution_count": null,
520 | "metadata": {},
521 | "outputs": [],
522 | "source": [
523 | "# ничего интересно, просто держим в курсе\n",
524 | "print(np.pi)\n",
525 | "print(np.e)"
526 | ]
527 | },
528 | {
529 | "cell_type": "markdown",
530 | "metadata": {},
531 | "source": [
532 | "#### np.min() и np.max()"
533 | ]
534 | },
535 | {
536 | "cell_type": "code",
537 | "execution_count": null,
538 | "metadata": {},
539 | "outputs": [],
540 | "source": [
541 | "print(np.min(np.array([7, 8, 4, 5, 2])))\n",
542 | "print(np.min([[1, 2], [2], [3, 4, 3]]))\n",
543 | "print(np.max([[1, 2], [2], [3, 4, 3]]))"
544 | ]
545 | },
546 | {
547 | "cell_type": "markdown",
548 | "metadata": {},
549 | "source": [
550 | "#### Статистика (медиана, среднее значение, дисперсия, стандартное отклонение)"
551 | ]
552 | },
553 | {
554 | "cell_type": "code",
555 | "execution_count": null,
556 | "metadata": {},
557 | "outputs": [],
558 | "source": [
559 | "a = np.array([[10, 7, 4], [3, 2, 1]])\n",
560 | "a\n",
561 | "\n",
562 | "print(np.median(a))\n",
563 | "print(np.median(a, axis=0))\n",
564 | "print(np.median(a, axis=1))\n",
565 | "\n",
566 | "print(np.mean(a))\n",
567 | "print(np.mean(a, axis=0))\n",
568 | "print(np.mean(a, axis=1))\n",
569 | "\n",
570 | "print(np.var(a))\n",
571 | "print(np.var(a, axis=0))\n",
572 | "print(np.var(a, axis=1))\n",
573 | "\n",
574 | "print(np.std(a))\n",
575 | "print(np.std(a, axis=0))\n",
576 | "print(np.std(a, axis=1))"
577 | ]
578 | },
579 | {
580 | "cell_type": "markdown",
581 | "metadata": {},
582 | "source": [
583 | "### 7. Ещё полезные функции"
584 | ]
585 | },
586 | {
587 | "cell_type": "markdown",
588 | "metadata": {},
589 | "source": [
590 | "#### np.unique()"
591 | ]
592 | },
593 | {
594 | "cell_type": "code",
595 | "execution_count": 82,
596 | "metadata": {},
597 | "outputs": [
598 | {
599 | "data": {
600 | "text/plain": [
601 | "array([False, False, True, False])"
602 | ]
603 | },
604 | "execution_count": 82,
605 | "metadata": {},
606 | "output_type": "execute_result"
607 | }
608 | ],
609 | "source": [
610 | "# возвращает уникальные значения из списка\n",
611 | "print(np.unique([1, 1, 2, 2, 3, 3]))\n",
612 | "# работает и для многомерных списков\n",
613 | "a = np.array([[1, 1], [2, 3]])\n",
614 | "print(np.unique(a))"
615 | ]
616 | },
617 | {
618 | "cell_type": "markdown",
619 | "metadata": {},
620 | "source": [
621 | "#### np.diagonal()"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": null,
627 | "metadata": {},
628 | "outputs": [],
629 | "source": [
630 | "# получение значение на конкретной\n",
631 | "# диагонали матрицы\n",
632 | "a = np.arange(16).reshape(4,4)\n",
633 | "print(a)\n",
634 | "print(a.diagonal())\n",
635 | "print(a.diagonal(1))"
636 | ]
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "metadata": {},
641 | "source": [
642 | "#### np.nonzero()"
643 | ]
644 | },
645 | {
646 | "cell_type": "code",
647 | "execution_count": null,
648 | "metadata": {},
649 | "outputs": [],
650 | "source": [
651 | "# возвращает индексы ненулевых элементов списка\n",
652 | "x = np.array([1, 0, 0, 0, 12, 0, -1])\n",
653 | "print(x)\n",
654 | "print(np.nonzero(x))\n",
655 | "\n",
656 | "# это работает и с многомерными массивами\n",
657 | "x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])\n",
658 | "print(x)\n",
659 | "print(np.nonzero(x))\n",
660 | "\n",
661 | "# таким хитрым образом можно получить\n",
662 | "# сами ненулевые элементы в списке\n",
663 | "print(x[np.nonzero(x)])"
664 | ]
665 | },
666 | {
667 | "cell_type": "markdown",
668 | "metadata": {},
669 | "source": [
670 | "#### np.isnan()"
671 | ]
672 | },
673 | {
674 | "cell_type": "code",
675 | "execution_count": null,
676 | "metadata": {},
677 | "outputs": [],
678 | "source": [
679 | "# возвращает True, если значение None, Null, NaN\n",
680 | "print(np.isnan([1, 2, np.nan, 12]))"
681 | ]
682 | },
683 | {
684 | "cell_type": "markdown",
685 | "metadata": {},
686 | "source": [
687 | "### 8. Случайные случайности"
688 | ]
689 | },
690 | {
691 | "cell_type": "code",
692 | "execution_count": null,
693 | "metadata": {},
694 | "outputs": [],
695 | "source": [
696 | "print(np.random.rand(4))\n",
697 | "print(np.random.rand(1, 2))\n",
698 | "\n",
699 | "print(np.random.randint(3))\n",
700 | "print(np.random.randint(low=3, high=5, size=3))\n",
701 | "\n",
702 | "# возвращает значение\n",
703 | "# стандартного нормального распределения\n",
704 | "print(np.random.randn(5, 2))\n",
705 | "\n",
706 | "\n",
707 | "# перемешивает значения списка\n",
708 | "a = [1, 2, 3, 4, 5]\n",
709 | "np.random.shuffle(a)\n",
710 | "print(a)"
711 | ]
712 | }
713 | ],
714 | "metadata": {
715 | "interpreter": {
716 | "hash": "bb399e1a834aa17b35df3c7b12c8f19baf7d93a1973604970edfee6e51c1813f"
717 | },
718 | "kernelspec": {
719 | "display_name": "Python 3.9.10 64-bit (windows store)",
720 | "language": "python",
721 | "name": "python3"
722 | },
723 | "language_info": {
724 | "codemirror_mode": {
725 | "name": "ipython",
726 | "version": 3
727 | },
728 | "file_extension": ".py",
729 | "mimetype": "text/x-python",
730 | "name": "python",
731 | "nbconvert_exporter": "python",
732 | "pygments_lexer": "ipython3",
733 | "version": "3.9.10"
734 | },
735 | "orig_nbformat": 4
736 | },
737 | "nbformat": 4,
738 | "nbformat_minor": 2
739 | }
740 |
--------------------------------------------------------------------------------
/2022-2023/lesson1/numpy_practice.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Первая домашняя работа или Goodbye python list, now numpy array is my best friend!\n",
8 | "\n",
9 | "### Не очень большое предисловие (краткий список правил по домашним заданиям):\n",
10 | "\n",
11 | "1. Эти домашние задания нужны в первую очередь для вас и вашего роста, как инженера Data Science.\n",
12 | "За их невыполнение вас никто не осудит. Вы просто возьмёте от курса меньше, чем ребята\n",
13 | "которые их прорешивали, закрепляя свои новые знания.\n",
14 | "2. Не стоит фанатично выполнять эти домашки. Если у вас горят дедлайны по учебе,\n",
15 | "то лучше закрывайте их и забудьте о домашках до того момента, когда у вас будет на это время.\n",
16 | "3. Если возникают вопросы по ходу выполнения - в первую очередь погуглите! Если же чувствуется сильный затуп или вы хотите, чтобы ваше\n",
17 | "решение задания проверили на качество, напишите кому-нибудь из организаторов курса (можно это сделать как в дискорде, так и в любой удобной для вас соцсети). Не знаю, насколько оперативно мы будем отвечать, но мы очень постараемся!\n",
18 | "4. У данных домашек нет и не будет жесткого дедлайна, поэтому нет ничего страшного в том, что вы будете что-то не успевать. Но лучше всё же не откладывать в долгий ящик: цените свое время и наше, если учитывать факт проверки.\n",
19 | "5. Единственное жесткое требование: по данным занятиям вести свой git-репозиторий, иначе вероятность того, что мы проверим вашу работу: 0 +-\n",
20 | "эпсилон. За ответами на вопросы по типу: \"Что это?\", \"Зачем это?\", рекомендуем зайти на https://hellocsit.ru/.\n",
21 | "6. Не исключается возможность работать с обычными файлами формата .py. Однако всё же стоит учитывать, что первые два-три домашних задания гораздо проще выполнять непосредственно в тетрадках jupyter, да и многие соревнования на Kaggle прорешиваются исключительно в них.\n",
22 | "7. Часть домашних заданий будут разбираться через занятие-другое (если у большого количества людей возникнут проблемы, домашнее задание будем рассматривать и прорабатывать незамедлительно, на следующем же занятии).\n",
23 | "\n",
24 | "Вы ничего не потеряете, если сделаете их позже, но разве не интереснее быть первопроходцем, чем идти за кем-то?)))"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {},
30 | "source": [
31 | "### Hello, python!\n",
32 | "\n",
33 | "Данный топик посвящен тем людям, которые не работали или почти не работали с языком программирования python (если есть опыт\n",
34 | "можно скипнуть).\n",
35 | "\n",
36 | "1. Не бойтесь, если ваш опыт работы с данным языком не велик. Сейчас классический python - один из самых простых языков для\n",
37 | "изучения. Если вы будете выполнять домашние задания и слушать лекции, то вы сможете приспособиться. Другое дело, что python - это чаще всего только инструмент для работы с фреймворками и библиотеками. С ними уже всё посложнее. С классическим библиотеками для ML мы вас познакомим, но если решите с чем-то поработать сами, то гугл и открытая документация каждой из библиотек вам в помощь.\n",
38 | "2. Чтобы установить библиотеку на вашу компудахтер, пропишите `!pip` (у кого-то это может быть `!pip3`) `install <название библиотеки>` в терминале. В jupyter notebook можно прописать эти команды в ячейке кода с восклицательным знаком в начале и выполнить эту ячейку (Например: `!pip install numpy`).\n",
39 | "3. Мы не будем посвящать отдельную лекцию по конструкциям и синтаксису обычного python, но будем о чем-то упоминать на занятиях\n",
40 | "и в домашней работе (речь о list, dict comprehension, и т.д.). Все нюансы будут обосновываться и объясняться, однако одно и то же по 100 раз рассматривать что-то будет уже слишком так себе. Те, кто чувствует, что плохо знаком с python - будьте готовы, а главное - не стесняйтесь задавать вопросы, вникать и узнавать что-то новое =)\n",
41 | "4. Небольшое напоминание о python: он не является строго типизированным языком, поэтому будьте с этим осторожнее. Чтобы проверить тип переменной, можете написать `print(type(<название переменной>))`.\n",
42 | "#### Теперь можно наконец-то приступать к выполнению первых заданий, всем удачи и максимум удовольстия от курса!"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "### Задание 0: List и Dict Comprehension\n",
50 | "\n",
51 | "Задания, представленные ниже, нужно сделать ТОЛЬКО с помощью list и dict comprehension. Они специально не трудные, чтобы дать вам возможность быстро разобраться (или же вспомнить), как это всё работает.\n",
52 | "\n",
53 | "Примечание: все задачи должны решаться в ОДНУ строчку! (список с результатом должен создаваться с помощью одной строчки)"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 2,
59 | "metadata": {},
60 | "outputs": [],
61 | "source": [
62 | "# выведите список, в котором будут хранится индексы всех букв 'a' в строке some_str\n",
63 | "some_str = \"Quick brown cat jumps over the lazy dog\""
64 | ]
65 | },
66 | {
67 | "cell_type": "code",
68 | "execution_count": 3,
69 | "metadata": {},
70 | "outputs": [],
71 | "source": [
72 | "# выведите список, в котором будут хранится все слова из some_str, в которых содержится буква 'н'\n",
73 | "some_str = \"Знаете почему парни, у которых отец из Непала, очень хороши собой? Они все непальцем деланные.\""
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 4,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "# Создайте список из 20 случайных чисел.\n",
83 | "import random\n",
84 | "\n",
85 | "# Переписать все элементы списка из прошлого задания в новый список следующим образом: сначала все четные, затем все\n",
86 | "# нечетные."
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 5,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "# Создать матрицу (таблицу) при помощи list comprehension"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 6,
101 | "metadata": {},
102 | "outputs": [],
103 | "source": [
104 | "# Создайте список bin_str, который будет состоять из бинарного\n",
105 | "# представления кода ASCII каждой буквы из строки some_str\n",
106 | "# Например: ['0b1101011', '0b100001']\n",
107 | "some_str = \"welcome to ml homework!\"\n"
108 | ]
109 | },
110 | {
111 | "cell_type": "code",
112 | "execution_count": null,
113 | "metadata": {},
114 | "outputs": [],
115 | "source": [
116 | "# Далее создайте словарь, в котором каждая буква из some_str\n",
117 | "# будет ключом, по которому можно получить соответствующее\n",
118 | "# значение, являющееся бинарным представлением кода ASCII буквы\n",
119 | "# (можно пользоваться созданным в прошлом задании списком bin_str)\n",
120 | "# Например: [' ': '0b100000', 'e': '0b1100101']\n"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": null,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": [
129 | "# Сделайте прошлое задание без использования списка bin_str"
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": 1,
135 | "metadata": {},
136 | "outputs": [],
137 | "source": [
138 | "# На основе списка с элементами от 100 до 1000 с шагом 50 (обозначим как list1), создайте словарь, в котором будут\n",
139 | "# храниться результаты деления элемента из списка list1 на квадрат самого себя, а ключами будут значения из списка list1"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {},
146 | "outputs": [],
147 | "source": [
148 | "# БОНУСНОЕ ЗАДАНИЕ\n",
149 | "some_str = \"\"\"Я в своем познании настолько преисполнился, что я как будто бы уже сто триллионов миллиардов лет проживаю на триллионах и триллионах таких же планет, как эта Земля, мне этот мир абсолютно понятен, и я здесь ищу только одного - покоя, умиротворения и вот этой гармонии, от слияния с бесконечно вечным, от созерцания великого фрактального подобия и от вот этого замечательного всеединства существа, бесконечно вечного, куда ни посмотри, хоть вглубь - бесконечно малое, хоть ввысь - бесконечное большое, понимаешь? А ты мне опять со своим вот этим, иди суетись дальше, это твоё распределение, это твой путь и твой горизонт познания и ощущения твоей природы, он несоизмеримо мелок по сравнению с моим, понимаешь? Я как будто бы уже давно глубокий старец, бессмертный, ну или там уже почти бессмертный, который на этой планете от её самого зарождения, ещё когда только Солнце только-только сформировалось как звезда, и вот это газопылевое облако, вот, после взрыва, Солнца, когда оно вспыхнуло, как звезда, начало формировать вот эти коацерваты, планеты, понимаешь, я на этой Земле уже как будто почти пять миллиардов лет живу и знаю её вдоль и поперёк этот весь мир, а ты мне какие-то... мне не важно на твои тачки, на твои яхты, на твои квартиры, там, на твоё благо. Я был на этой планете бесконечным множеством, и круче Цезаря, и круче Гитлера, и круче всех великих, понимаешь, был, а где-то был конченым говном, ещё хуже, чем здесь. Я множество этих состояний чувствую. Где-то я был больше подобен растению, где-то я больше был подобен птице, там, червю, где-то был просто сгусток камня, это всё есть душа, понимаешь? Она имеет грани подобия совершенно многообразные, бесконечное множество. Но тебе этого не понять, поэтому ты езжай себе , мы в этом мире как бы живем разными ощущениями и разными стремлениями, соответственно, разное наше и место, разное и наше распределение. Тебе я желаю все самые крутые тачки чтоб были у тебя, и все самые лучше самки, если мало идей, обращайся ко мне, я тебе на каждую твою идею предложу сотню триллионов, как всё делать. Ну а я всё, я иду как глубокий старец,узревший вечное, прикоснувшийся к Божественному, сам стал богоподобен и устремлен в это бесконечное, и который в умиротворении, покое, гармонии, благодати, в этом сокровенном блаженстве пребывает, вовлеченный во всё и во вся, понимаешь, вот и всё, в этом наша разница. Так что я иду любоваться мирозданием, а ты идёшь преисполняться в ГРАНЯХ каких-то, вот и вся разница, понимаешь, ты не зришь это вечное бесконечное, оно тебе не нужно. Ну зато ты, так сказать, более активен, как вот этот дятел долбящий, или муравей, который очень активен в своей стезе, поэтому давай, наши пути здесь, конечно, имеют грани подобия, потому что всё едино, но я-то тебя прекрасно понимаю, а вот ты меня - вряд ли, потому что я как бы тебя в себе содержу, всю твою природу, она составляет одну маленькую там песчиночку, от того что есть во мне, вот и всё, поэтому давай, ступай, езжай, а я пошел наслаждаться прекрасным осенним закатом на берегу теплой южной реки. Всё, ступай, и я пойду. \"\"\"\n",
150 | "# создайте словарь ascended_dict, в котором каждому слову из строки some_str будет соответствовать число повторений этого слова в строке (допускается решение в сколь угодно строк, но попробуйте сделать с dict comprehension)"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": 2,
156 | "metadata": {},
157 | "outputs": [],
158 | "source": [
159 | "import numpy as np"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "### Задание 1 (Бинарные отношения):\n",
167 | "\n",
168 | "Что такое бинарное отношение? Если сильно не углублятся в алгебру или дискретную математику, то бинарное отношение можно\n",
169 | "понять как отображение одного элемента множества в другой (или факт того, как взаимодействует один объект на другой). Следовательно, оператором бинарного отношения можно считать функцию (от элемента множества), которая переводит этот элемент в другой элемент (возможно в себя) этого множества.\n",
170 | "\n",
171 | "Кстати, функции на питоне определяются как `def <название функции> (<ее аргументы>)`.\n",
172 | "\n",
173 | "Допустим, у нас есть игрушечный пример:\n",
174 | "\n",
175 | "`def лень (`$some\\_set_{i}$`)`, где $some\\_set_{i}$ - это элемент множества $some\\_set$, которое пусть будет заданно как {1, 2, 3, 4, 5}.\n",
176 | "Функция лень должна считать интеграл некоторого распределения вероятности начала 3 мировой войны, но, к сожалению, искусственный интеллект настолько сильно развился, что функция стала черезчур ленивой для этого, и поэтому теперь она просто возвращает значение, которое ей было передано, отказываясь работать.\n",
177 | "\n",
178 | "Функцию лень можно спокойно назвать оператором бинарного отношения, так как она получает на вход значение из множества $some\\_set$\n",
179 | "и возвращает значение из множества $some\\_set$. То-есть, ее бинарное отношение будет иметь вид: {(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)}.\n",
180 | "Давайте попробуем задать матрицу такого бинарного отношения с помощью инструментов numpy. Сделайте это задание функцией,\n",
181 | "принимающей на вход множество бинарного отношения и колличество элементов в заданном множестве $some\\_set$. Это нужно для обобщения\n",
182 | "этого задания на произвольное бинарное отношение.\n",
183 | "\n",
184 | "Пояснительная бригада: матрица бинарного отношения это двумерная матрица, элементы которой могут принимать значения 0 или 1, и которая показывает отображение с помощью бинарного оператора одного элемента множества в другой."
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": null,
190 | "metadata": {},
191 | "outputs": [],
192 | "source": [
193 | "def laziness(some_set):\n",
194 | " return some_set\n",
195 | "\n",
196 | "some_set = [1, 2, 3, 4, 5]\n",
197 | "\n",
198 | "mapping = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]\n",
199 | "\n",
200 | "def matrix_init(n, mapping):\n",
201 | " # TODO:\n",
202 | " return a\n",
203 | "\n",
204 | "a = matrix_init(len(some_set), mapping)\n",
205 | "\n",
206 | "a"
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "Для проверки правильности идущих далее заданий (а они будут связаны между собой) предлагаю написать небольшую функцию relation_init. Это творческое задание, поэтому способ реализации этой функции остается на усмотрение выполняющего: можно сразу ввести матрицу бинарного отношения, можно ввести множество бинарного отображение, можно придумать что-то другое.\n",
214 | "\n",
215 | "Примечание: ввод значения с клавиатуры в питоне производится через функцию `input()`. Введеное значение будет иметь тип 'str',\n",
216 | "поэтому, чтобы, например, получить целочисленное значение, к нему надо применить `int(<ваша переменная>)`. Чтобы считать несколько\n",
217 | "значений, можно использовать оператор `input().split()`. Например: `a1, a2 = input.split()`. Превратить обе переменные в int можно\n",
218 | "с помощью оператора `map()`, но это мы оставим вам на самостоятельное изучение. Для тех, кто реализует данное задание через файл формата .py, можете сугубо ради спортивного интереса вообще запариться и сделать это через `argparse`."
219 | ]
220 | },
221 | {
222 | "cell_type": "code",
223 | "execution_count": null,
224 | "metadata": {},
225 | "outputs": [],
226 | "source": [
227 | "# Для функции ниже необходимо указать также аргументы\n",
228 | "def relation_init():\n",
229 | " # TODO"
230 | ]
231 | },
232 | {
233 | "cell_type": "markdown",
234 | "metadata": {},
235 | "source": [
236 | "Говорят, что бинарное отношение является рефлексивным, если все элементы матрицы этого бинарного отношения на ее главной диагонали равны единице (это означает, что существует отображение элемента множества в себя же). Отсюда можно сделать вывод, что бинарное отношение может быть и анти-рефлексивным: если на главной диагонали стоят все нули. В случае, если ни первое, ни второе не верно, то бинарное отношение считается просто \"не рефлексивным\". Давай напишем такую функцию, которая будет принимать на вход матрицу бинарного отношения и проверять факт\n",
237 | "его рефлексивности или антирефлексивности, а если ничего из этого не выполняется, то будет говорить нам, что отношение не рефлексивно."
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {},
244 | "outputs": [],
245 | "source": [
246 | "def isRefl(a):\n",
247 | " # TODO\n",
248 | "\n",
249 | "isRefl(a)"
250 | ]
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {},
255 | "source": [
256 | "Говорят, что бинарное отношение является симметричным, если для его матрицы $A$ справедливо: $A^T = A$. Если же все элементы вне главной диагонали матрицы $B$, определяемой как $B = A \\odot A^T$, равны нулю, то бинарное отношение называют антисимметричным. Если оба условия выше не выполняются, отношение считается не симметричным. Напишите функцию, проверяющую этот факт, по аналогии с прошлым заданием. (Примечание-подсказка: символ $\\odot$ означает поэлементное умножение)"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": null,
262 | "metadata": {},
263 | "outputs": [],
264 | "source": [
265 | "def isSymm(a):\n",
266 | " # TODO\n",
267 | "\n",
268 | "isSymm(a)"
269 | ]
270 | },
271 | {
272 | "cell_type": "markdown",
273 | "metadata": {},
274 | "source": [
275 | "Пришло время для еще одного занимательного факта о бинарном отношении: если $A^2 \\leq A$, то бинарное отношение называют\n",
276 | "транзитивным, иначе - не транзитивным. Дальше вы сами знаете, что дальше делать ))"
277 | ]
278 | },
279 | {
280 | "cell_type": "code",
281 | "execution_count": null,
282 | "metadata": {},
283 | "outputs": [],
284 | "source": [
285 | "def isTran(a):\n",
286 | " # TODO\n",
287 | "\n",
288 | "isTran(a)"
289 | ]
290 | },
291 | {
292 | "cell_type": "markdown",
293 | "metadata": {},
294 | "source": [
295 | "Бинарные отношения можно также классифицировать, причем классификация бинарных отношений напрямую определяются их свойствами.\n",
296 | "\n",
297 | "Виды бинарных отношений:\n",
298 | "\n",
299 | "1. Рефлексивное транзитивное отношение называется отношением квазипорядка.\n",
300 | "2. Рефлексивное симметричное транзитивное отношение называется отношением эквивалентности.\n",
301 | "3. Рефлексивное антисимметричное транзитивное отношение называется отношением (частичного) порядка.\n",
302 | "4. Антирефлексивное, антисимметричное и транзитивное отношение называется отношением строгого порядка.\n",
303 | "\n",
304 | "Реализуйте функцию, которая будет классифицировать бинарное отношение по его входной матрице."
305 | ]
306 | },
307 | {
308 | "cell_type": "code",
309 | "execution_count": null,
310 | "metadata": {},
311 | "outputs": [],
312 | "source": [
313 | "def classifier (a):\n",
314 | " # TODO"
315 | ]
316 | },
317 | {
318 | "cell_type": "markdown",
319 | "metadata": {},
320 | "source": [
321 | "Если вы все сделали правильно, то у вас должно получиться, что бинарное отношение лень являеся отношением эквивалентности."
322 | ]
323 | },
324 | {
325 | "cell_type": "markdown",
326 | "metadata": {},
327 | "source": [
328 | "### Задание 2 (Вероятная статистика):\n",
329 | "\n",
330 | "Иннокентий работает в сверхсекретной организации над сверхсекретным проектом, из-за чего у него мало времени на учебу в университете,\n",
331 | "а его преподаватель по математической статистике - это душный дед, который не понятно как ставит оценки на экзамене. Однако Никита не сдается, и он смог взломать компьютер своего преподавателя. Но, к его сожалению, соединение периодически обрывается, из-за чего он получает результаты экзамена только ста студентов и их уровень подготовки к экзамену (на момент сдачи), который представляет собой число в диапазоне [0, 1]. Это за все 50 лет, которые преподает дед.\n",
332 | "По этим данным он пытается узнать несколько вещей: \n",
333 | "1. Какая оценка была самой вероятной среди тех 100 людей, результаты которых он получил в данный момент.\n",
334 | "2. Какова была средняя оценка.\n",
335 | "3. Чему равняется математическое ожидание оценок студентов.\n",
336 | "4. Среднеквадратичное отклонение этих оценок и их дисперсия.\n",
337 | "5. Какова его вероятность сдать экзамен (хотя бы на 3), которая вычисляется как (gcd(p, p-1) - 1) * 1000, где\n",
338 | "p - это колличество людей среди этой сотни, которое сдало на 5.\n",
339 | "\n",
340 | "Помогите ему это сделать.\n",
341 | "\n",
342 | "\"Взлом\" компьютера и получение данных будет представлять собой 2 генератора случайных чисел, один из которых будет генерировать\n",
343 | "целые числа в диапозоне [2, 5], а второй числа с плавающей точкой в диапозоне [0, 1]."
344 | ]
345 | },
346 | {
347 | "cell_type": "code",
348 | "execution_count": 4,
349 | "metadata": {},
350 | "outputs": [],
351 | "source": []
352 | },
353 | {
354 | "cell_type": "markdown",
355 | "metadata": {},
356 | "source": [
357 | "### Задание 3: Конченные шахматы\n",
358 | "\n",
359 | "Иван - гроссмейстер по берляндским шахматам и сегодня он дает мастеркласс молодому поколению берляндцев.\n",
360 | "Берляндские шахматы - это самая интересная игра в Берляндии и по совместительству единственная, так как грозный\n",
361 | "мер Андрей запретил все другие игры. Но это никак не касается нашей истории.\n",
362 | "\n",
363 | "В первую очередь игроку нужно расставить фигуры на доску размером n на n в шахматном порядке, все фигуры\n",
364 | "игрока должны стоять только на белых клетках (клетка с координатами 0 0 будет всегда черной), если в клетке\n",
365 | "есть фигура - в ней стоит 1, если фигуры нет - 0.\n",
366 | "\n",
367 | "Примечание: для решения данного задания используйте только срезы массивов. Пример среза: a[:1]. Данная конструкция значит, что\n",
368 | "мы берем все элементы массива a, начиная с 1 позиции.\n",
369 | "\n",
370 | "Необходимо получить матрицу, определяющую доску берляндских шахмат"
371 | ]
372 | },
373 | {
374 | "cell_type": "code",
375 | "execution_count": null,
376 | "metadata": {},
377 | "outputs": [],
378 | "source": []
379 | },
380 | {
381 | "cell_type": "markdown",
382 | "metadata": {},
383 | "source": [
384 | "Затем игрок выбирает любой столбец или строку и переставляет фигуры так, чтобы они были отсортированны в порядке неубывания или неворастания.\n",
385 | "Реализуйте это кодом."
386 | ]
387 | },
388 | {
389 | "cell_type": "code",
390 | "execution_count": null,
391 | "metadata": {},
392 | "outputs": [],
393 | "source": []
394 | },
395 | {
396 | "cell_type": "markdown",
397 | "metadata": {},
398 | "source": [
399 | "Затем размерность доски уменьшается, путем удаления бокового столбца и боковой строки, и она становится размером n - 1 на n - 1.\n",
400 | "Реализуйте это кодом."
401 | ]
402 | },
403 | {
404 | "cell_type": "code",
405 | "execution_count": 7,
406 | "metadata": {},
407 | "outputs": [],
408 | "source": []
409 | },
410 | {
411 | "cell_type": "markdown",
412 | "metadata": {},
413 | "source": [
414 | "Для победы в этой игре, необходимо, чтобы при размерности доски 1 на 1 в ней осталась только одна 1. Попробуйте написать стратегию, которая будет всегда побеждать в берляндских шахматах\n",
415 | "для доски любой размерности."
416 | ]
417 | },
418 | {
419 | "cell_type": "code",
420 | "execution_count": null,
421 | "metadata": {},
422 | "outputs": [],
423 | "source": []
424 | },
425 | {
426 | "cell_type": "markdown",
427 | "metadata": {},
428 | "source": [
429 | "### Задание 4 (Дополнительное):"
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "metadata": {},
435 | "source": [
436 | "Данные пункты предполагают использование вами смекалочки и подразумевают возможное использование функций NumPy, не\n",
437 | "рассмотренных на очном занятии. Постарайтесь покопаться в документации NumPy, поискать возможные полезные функции и инструкции."
438 | ]
439 | },
440 | {
441 | "cell_type": "markdown",
442 | "metadata": {},
443 | "source": [
444 | "4.1 Пусть дан некоторый массив. Надо реализовать функцию, которая находит наиболее частое значение в массиве."
445 | ]
446 | },
447 | {
448 | "cell_type": "code",
449 | "execution_count": null,
450 | "metadata": {},
451 | "outputs": [],
452 | "source": [
453 | "z = np.random.randint(0,10,50)"
454 | ]
455 | },
456 | {
457 | "cell_type": "markdown",
458 | "metadata": {},
459 | "source": [
460 | "4.2 А теперь напиши функцию, которая позволяет найти n наибольших значений в массиве"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": null,
466 | "metadata": {},
467 | "outputs": [],
468 | "source": [
469 | "z = np.arange(5000)\n",
470 | "np.random.shuffle(z)\n",
471 | "n = 5"
472 | ]
473 | },
474 | {
475 | "cell_type": "markdown",
476 | "metadata": {},
477 | "source": [
478 | "4.3 Предполагая, что даны на вход два массива, реализовать функцию, которая осуществляет картезианское произведение"
479 | ]
480 | },
481 | {
482 | "cell_type": "code",
483 | "execution_count": null,
484 | "metadata": {},
485 | "outputs": [],
486 | "source": [
487 | "def cartesian(arrays):\n",
488 | " #TODO\n",
489 | "\n",
490 | "print(cartesian(([1, 2, 3], [4, 5])))"
491 | ]
492 | },
493 | {
494 | "cell_type": "markdown",
495 | "metadata": {},
496 | "source": [
497 | "Прикрепи сюда пожалуйста картинку или гифку, которая описывала твоё состояние в процессе выполнения этого задания! :)"
498 | ]
499 | },
500 | {
501 | "cell_type": "markdown",
502 | "metadata": {},
503 | "source": []
504 | }
505 | ],
506 | "metadata": {
507 | "interpreter": {
508 | "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
509 | },
510 | "kernelspec": {
511 | "display_name": "Python 3.9.7 64-bit",
512 | "name": "python3"
513 | },
514 | "language_info": {
515 | "codemirror_mode": {
516 | "name": "ipython",
517 | "version": 3
518 | },
519 | "file_extension": ".py",
520 | "mimetype": "text/x-python",
521 | "name": "python",
522 | "nbconvert_exporter": "python",
523 | "pygments_lexer": "ipython3",
524 | "version": "3.9.10"
525 | },
526 | "orig_nbformat": 4
527 | },
528 | "nbformat": 4,
529 | "nbformat_minor": 2
530 | }
531 |
--------------------------------------------------------------------------------
/2022-2023/lesson2/Pandas_Cheat_Sheet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson2/Pandas_Cheat_Sheet.pdf
--------------------------------------------------------------------------------
/2022-2023/lesson2/task/pandas_practice.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Deep Pandas Fantasies\n",
8 | "## Практическое домашнее задание по Pandas\n",
9 | "(Оригинальный ресурс был достопочтенно заимствован из открытого гитхаба Евгения Соколова, дополнен, транспонирован, ортонормирован и ещё всячески изменен для более мягенького вхождения в наше прекрасное болото под названием дата саенс)\n",
10 | "\n",
11 | "Евгений Соколов - препод ВШЭ по Машинному обучению, и у него суперкрутые лекции на ютубчике в открытом доступе, оч рекомендую посмотреть на досуге."
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "
\n"
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "Удачи!\n",
26 | "\n",
27 | "
"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {},
33 | "source": [
34 | "## 1. Табличные данные и Pandas"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {},
40 | "source": [
41 | "Pandas — удобная библиотека для работы с табличными данными в Python, если данных не слишком много и они помещаются в оперативную память вашего компьютера. Несмотря на неэффективность реализации и некоторые проблемы, библиотека стала стандартом в анализе данных.\n",
42 | "\n",
43 | "Основной объект в pandas — это DataFrame, представляющий собой таблицу с именованными колонками различных типов, индексом (может быть многоуровневым). DataFrame можно создавать, считывая таблицу из файла или задавая вручную из других объектов.\n",
44 | "\n",
45 | "В этой части потребуется выполнить несколько небольших заданий. Можно пойти двумя путями: сначала изучить материалы, а потом приступить к заданиям, или же разбираться \"по ходу\". Выбирайте сами.\n",
46 | "\n",
47 | "Материалы:\n",
48 | "1. [Pandas за 10 минут из официального руководства](http://pandas.pydata.org/pandas-docs/stable/10min.html)\n",
49 | "2. [Документация](http://pandas.pydata.org/pandas-docs/stable/index.html) (стоит обращаться, если не понятно, как вызывать конкретный метод)\n",
50 | "3. [Примеры использования функционала](http://nbviewer.jupyter.org/github/justmarkham/pandas-videos/blob/master/pandas.ipynb)\n",
51 | "\n",
52 | "Многие из заданий можно выполнить несколькими способами. Не существуют единственно верного, но попробуйте максимально задействовать арсенал pandas и ориентируйтесь на простоту и понятность вашего кода. Мы не будем подсказывать, что нужно использовать для решения конкретной задачи, попробуйте находить необходимый функционал сами (название метода чаще всего очевидно). В помощь вам документация, поиск и stackoverflow."
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {},
58 | "source": [
59 | "Скачаем данные (это если у тебя есть утилита wget, или же ты на linux):"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": null,
65 | "metadata": {},
66 | "outputs": [],
67 | "source": [
68 | "!wget -O 'end_seminar.xlsx' -q 'https://www.dropbox.com/s/f4rm8sjc3v99p0m/_end_seminar.xlsx?dl=0'"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "Для пользователей Windows: скачайте файл самостоятельно и поместите его в папку с тетрадкой. Или попробуйте один из следующих вариантов:"
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "metadata": {},
82 | "outputs": [],
83 | "source": [
84 | "# !powershell iwr -outf somefile https://somesite/somefile"
85 | ]
86 | },
87 | {
88 | "cell_type": "code",
89 | "execution_count": null,
90 | "metadata": {},
91 | "outputs": [],
92 | "source": [
93 | "# !pip install wget\n",
94 | "# import wget \n",
95 | "# wget.download('https://dropbox.com/s/f4rm8sjc3v99p0m/_end_seminar.xlsx?dl=1', 'end_seminar.xlsx')"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "##### Кстати, убедительная просьба не использовать явно циклы (for loop, while и т.д.). Ограничение делается как раз для того, чтобы помочь тебе проникнуться удобностью, востребованностью и качеством функций pandas, которые позволяют сократить затрачиваемое время на написание каких-то преобразований. Допускается использование list и dict comprehension, так как они работают быстрее, чем циклы."
103 | ]
104 | },
105 | {
106 | "cell_type": "markdown",
107 | "metadata": {},
108 | "source": [
109 | "Для каждой задачи и вопроса из этого раздела напиши код для получения ответа, а также попробуй дать текстовый ответ, если он предполагается.\n",
110 | "\n",
111 | "На некоторые вопросы ты можешь получить ответ путём пристального взгляда на таблицу, но это не прикольно. Постарайся получить ответ с помощью кода. Если же будут какие-то проблемы с этим - вместе разберемся на занятии)"
112 | ]
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "metadata": {},
117 | "source": [
118 | "#### 1. Открой файл с таблицей (не забудь про её формат). Выведи последние 10 строк.\n",
119 | "\n",
120 | "Посмотри на данные и скажи, что они из себя представляют, сколько в таблице строк, какие столбцы? Можешь на этот вопрос ответ не писать кодом, достаточно хотя бы подумать об этом. Но и написать кодец тоже никто не запрещает :)"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": null,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": [
129 | "import pandas as pd\n",
130 | "# возможно пригодится\n",
131 | "import numpy as np"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": null,
137 | "metadata": {},
138 | "outputs": [],
139 | "source": [
140 | "# ВСТАВЬ В МЕНЯ СВОЙ КОД"
141 | ]
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "metadata": {},
146 | "source": [
147 | "#### 2. Ответь на вопросы:\n",
148 | "1. Сколько было заявок из групп 18-го года набора, а сколько из групп 17-го года?\n",
149 | "2. Есть ли студенты с равными перцентилями?"
150 | ]
151 | },
152 | {
153 | "cell_type": "code",
154 | "execution_count": null,
155 | "metadata": {},
156 | "outputs": [],
157 | "source": [
158 | "# your code"
159 | ]
160 | },
161 | {
162 | "cell_type": "markdown",
163 | "metadata": {},
164 | "source": [
165 | "#### 3. Есть ли в данных пропуски? В каких колонках? Сколько их в каждой из этих колонок?"
166 | ]
167 | },
168 | {
169 | "cell_type": "code",
170 | "execution_count": null,
171 | "metadata": {},
172 | "outputs": [],
173 | "source": [
174 | "# your code"
175 | ]
176 | },
177 | {
178 | "cell_type": "markdown",
179 | "metadata": {},
180 | "source": [
181 | "Заполни пропуски пустой строкой для строковых колонок и нулём для числовых."
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": [
190 | "# your code"
191 | ]
192 | },
193 | {
194 | "cell_type": "markdown",
195 | "metadata": {},
196 | "source": [
197 | "#### 4. Посмотрите повнимательнее на колонку 'is_first_time'. \n",
198 | "\n",
199 | "Есть ли в ней ответы \"Нет\"? Сколько их?\n",
200 | "\n",
201 | "Если найдешь повторные обращения студентов, оставь только самую позднюю версию. "
202 | ]
203 | },
204 | {
205 | "cell_type": "code",
206 | "execution_count": null,
207 | "metadata": {},
208 | "outputs": [],
209 | "source": [
210 | "# your code"
211 | ]
212 | },
213 | {
214 | "cell_type": "markdown",
215 | "metadata": {},
216 | "source": [
217 | "#### 5. Какие blended-курсы для челиков существуют? На какой blended-курс записалось наибольшее количество студентов? На каком из курсов собрались студенты с самым высоким средним рейтингом? "
218 | ]
219 | },
220 | {
221 | "cell_type": "code",
222 | "execution_count": null,
223 | "metadata": {},
224 | "outputs": [],
225 | "source": [
226 | "# your code"
227 | ]
228 | },
229 | {
230 | "cell_type": "markdown",
231 | "metadata": {},
232 | "source": [
233 | "#### 6. Выясни, есть ли в данных студенты с абсолютно одинаковыми предпочтениями по всем курсам (не забудь учесть blended-курсы для студентов). Сколько таких наборов, которые взяли несколько студентов? Выведи их все вместе с количеством выбравших их студентов."
234 | ]
235 | },
236 | {
237 | "cell_type": "code",
238 | "execution_count": null,
239 | "metadata": {},
240 | "outputs": [],
241 | "source": [
242 | "# your code"
243 | ]
244 | },
245 | {
246 | "cell_type": "markdown",
247 | "metadata": {},
248 | "source": [
249 | "#### 7. Найди курсы предметов за первую осень, на которые записывались как студенты 18-го года набора, так и студенты 17-го года."
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": null,
255 | "metadata": {},
256 | "outputs": [],
257 | "source": [
258 | "# your code"
259 | ]
260 | },
261 | {
262 | "cell_type": "markdown",
263 | "metadata": {},
264 | "source": [
265 | "Методом исключения (или аналогичным образом как до этого) найди курсы, которые предлагались только студентам 18-го года и только студентам 17-го года."
266 | ]
267 | },
268 | {
269 | "cell_type": "code",
270 | "execution_count": null,
271 | "metadata": {},
272 | "outputs": [],
273 | "source": [
274 | "# your code"
275 | ]
276 | },
277 | {
278 | "cell_type": "markdown",
279 | "metadata": {},
280 | "source": [
281 | "### Доп. задание: визуализации и matplotlib"
282 | ]
283 | },
284 | {
285 | "cell_type": "markdown",
286 | "metadata": {},
287 | "source": [
288 | "При работе с данными часто неудобно делать какие-то выводы, если смотреть на таблицу и числа в частности, поэтому важно уметь визуализировать данные. Здесь будут описаны основные оформления различных графиков. Да и вообще лучше нормально оформлять, а то потом ваш коллега вам по жопе настучит за какие-то шизоидные чертежи которые бог знает что означают.\n",
289 | "\n",
290 | "У matplotlib, конечно же, есть [документация](https://matplotlib.org/users/index.html) с большим количеством [примеров](https://matplotlib.org/examples/), но для начала достаточно знать про несколько основных типов графиков:\n",
291 | "- plot — обычный поточечный график, которым можно изображать кривые или отдельные точки;\n",
292 | "- hist — гистограмма, показывающая распределение некоторой величины;\n",
293 | "- scatter — график, показывающий взаимосвязь двух величин;\n",
294 | "- bar — столбцовый график, показывающий взаимосвязь количественной величины от категориальной.\n",
295 | "\n",
296 | "В этом задании тебе, мой друг, предстоит попробовать построить один из них. Не забудь про базовые принципы построения приличных графиков:\n",
297 | "- оси должны быть подписаны, причём не слишком мелко;\n",
298 | "- у графика должно быть название;\n",
299 | "- если изображено несколько графиков, то необходима поясняющая легенда;\n",
300 | "- все линии на графиках должны быть чётко видны (нет похожих цветов или цветов, сливающихся с фоном);\n",
301 | "- если отображена величина, имеющая очевидный диапазон значений (например, проценты могут быть от 0 до 100), то желательно масштабировать ось на весь диапазон значений (исключением является случай, когда вам необходимо показать малое отличие, которое незаметно в таких масштабах);\n",
302 | "- сетка на графике помогает оценить значения в точках на глаз, это обычно полезно, поэтому лучше ее отрисовывать;\n",
303 | "- если распределение на гистограмме имеет тяжёлые хвосты, лучше использовать логарифмическую шкалу."
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": 1,
309 | "metadata": {},
310 | "outputs": [],
311 | "source": [
312 | "%matplotlib inline\n",
313 | "import matplotlib.pyplot as plt"
314 | ]
315 | },
316 | {
317 | "cell_type": "markdown",
318 | "metadata": {},
319 | "source": [
320 | "Еще одна библиотека для визуализации: [seaborn](https://jakevdp.github.io/PythonDataScienceHandbook/04.14-visualization-with-seaborn.html). Это настройка над matplotlib, иногда удобнее и красивее делать визуализации через неё. "
321 | ]
322 | },
323 | {
324 | "cell_type": "code",
325 | "execution_count": 38,
326 | "metadata": {},
327 | "outputs": [],
328 | "source": [
329 | "import seaborn as sns"
330 | ]
331 | },
332 | {
333 | "cell_type": "markdown",
334 | "metadata": {},
335 | "source": [
336 | "#### 8. Построй график средних рейтингов по дням получения ответов (bar plot). Сохрани график в формате pdf (так он останется векторизованным, а значит не будет терять качество при масштабировании и вообще красивенько всё будет)."
337 | ]
338 | },
339 | {
340 | "cell_type": "code",
341 | "execution_count": null,
342 | "metadata": {},
343 | "outputs": [],
344 | "source": [
345 | "# your code"
346 | ]
347 | },
348 | {
349 | "cell_type": "markdown",
350 | "metadata": {},
351 | "source": [
352 | "Небольшая провер очка\n",
353 | "\n",
354 | "Здесь ты можешь увидеть, успешно ли ты выполнил некоторые задания первой части, и проверить ваши данные на наличие пропусков и повторов:"
355 | ]
356 | },
357 | {
358 | "cell_type": "code",
359 | "execution_count": 478,
360 | "metadata": {},
361 | "outputs": [],
362 | "source": [
363 | "# df здесь - твой результирующий датафрейм\n",
364 | "\n",
365 | "assert df.shape[0] == 347, 'В таблице остались повторы или потеряны данные'\n",
366 | "\n",
367 | "assert df.isna().sum().sum() == 0, 'В таблице остались пропуски'"
368 | ]
369 | },
370 | {
371 | "cell_type": "markdown",
372 | "metadata": {},
373 | "source": [
374 | "Если ты не получил AssertionError, то ты крутой!\n",
375 | "А вообще если ты осилил эти все задания, то не стесняйся на досуге залить своё творение в репозиторий и сообщить об этом кому-нибудь из ведущих курса."
376 | ]
377 | },
378 | {
379 | "cell_type": "markdown",
380 | "metadata": {},
381 | "source": [
382 | "Вставьте картинку или гифку, описывающую ваше состояние в момент выполнения этого задания:"
383 | ]
384 | },
385 | {
386 | "cell_type": "markdown",
387 | "metadata": {},
388 | "source": []
389 | }
390 | ],
391 | "metadata": {
392 | "kernelspec": {
393 | "display_name": "Python 3",
394 | "language": "python",
395 | "name": "python3"
396 | },
397 | "language_info": {
398 | "codemirror_mode": {
399 | "name": "ipython",
400 | "version": 3
401 | },
402 | "file_extension": ".py",
403 | "mimetype": "text/x-python",
404 | "name": "python",
405 | "nbconvert_exporter": "python",
406 | "pygments_lexer": "ipython3",
407 | "version": "3.9.10"
408 | }
409 | },
410 | "nbformat": 4,
411 | "nbformat_minor": 2
412 | }
413 |
--------------------------------------------------------------------------------
/2022-2023/lesson3/lecture/pic/anatomy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson3/lecture/pic/anatomy.png
--------------------------------------------------------------------------------
/2022-2023/lesson3/lecture/pic/boxplot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson3/lecture/pic/boxplot.png
--------------------------------------------------------------------------------
/2022-2023/lesson3/lecture/pic/violin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson3/lecture/pic/violin.jpg
--------------------------------------------------------------------------------
/2022-2023/lesson3/task/visual_practice.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "source": [
6 | "## Visual Data Analysis Homework\n",
7 | "## Практическое домашнее задание по визуализации данных с последующим их анализом\n",
8 | "\n",
9 | "(Оригинальный ресурс был основан на открытом курсе машинного обучения от mail.ru, в частности, был использован блок материалов по визуализации)\n",
10 | "\n",
11 | "Екатерина Демидова - Data Scientist @ Segmento, у неё есть открытые репозитории с интересными ресурсами по машинному обучениею, можете поискать =)"
12 | ],
13 | "metadata": {}
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "source": [
18 | "Импорт используемых библиотек (в целом можешь использовать и numpy, но задачи вполне выполнимы и без него)"
19 | ],
20 | "metadata": {}
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 1,
25 | "source": [
26 | "import pandas as pd\n",
27 | "\n",
28 | "%matplotlib inline\n",
29 | "import matplotlib.pyplot as plt\n",
30 | "import seaborn as sns"
31 | ],
32 | "outputs": [],
33 | "metadata": {}
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "source": [
38 | "# Загрузка и знакомство с данными\n",
39 | "\n",
40 | "Для работы тебе понадобятся данные учебного конкурса mail.ru на kaggle «Прогноз популярности статьи на Хабре». Для них необходимо осуществить предобработку (да да, pandas ты не должен забывать никогда)."
41 | ],
42 | "metadata": {}
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "source": [
47 | "## 1. Прочитай датасет. Сколько строк и столбцов в нем?\n"
48 | ],
49 | "metadata": {}
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 2,
54 | "source": [],
55 | "outputs": [],
56 | "metadata": {}
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 3,
61 | "source": [
62 | "df.shape"
63 | ],
64 | "outputs": [
65 | {
66 | "output_type": "execute_result",
67 | "data": {
68 | "text/plain": [
69 | "(134137, 17)"
70 | ]
71 | },
72 | "metadata": {},
73 | "execution_count": 3
74 | }
75 | ],
76 | "metadata": {}
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "source": [
82 | "df.head(3).T"
83 | ],
84 | "outputs": [],
85 | "metadata": {}
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "source": [
90 | "## 2. В первую очередь необходимо избавиться от тех данных, названия которых заканчиваются на `_lognorm` (они нужны для соревнования на Kaggle, но это не наша история). Дропни их, пожалуйста."
91 | ],
92 | "metadata": {}
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": 5,
97 | "source": [],
98 | "outputs": [],
99 | "metadata": {}
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "source": [
104 | "Можешь повертеть данные, чтобы как-то их проанализировать и понять, что тут происходит вообще"
105 | ],
106 | "metadata": {}
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "source": [
112 | "df.describe().T"
113 | ],
114 | "outputs": [],
115 | "metadata": {}
116 | },
117 | {
118 | "cell_type": "code",
119 | "execution_count": null,
120 | "source": [
121 | "df.describe(include=[\"object\", \"bool\"]).T # бинарные и категориальные переменные"
122 | ],
123 | "outputs": [],
124 | "metadata": {}
125 | },
126 | {
127 | "cell_type": "markdown",
128 | "source": [
129 | "### По желанию можешь применить настройки ниже, либо указать какие-то свои"
130 | ],
131 | "metadata": {}
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 8,
136 | "source": [
137 | "# настройка внешнего вида графиков в seaborn\n",
138 | "sns.set_style(\"dark\")\n",
139 | "sns.set_palette(\"RdBu\")\n",
140 | "sns.set_context(\n",
141 | " \"notebook\", font_scale=1.5, rc={\"figure.figsize\": (15, 5), \"axes.titlesize\": 18}\n",
142 | ")"
143 | ],
144 | "outputs": [],
145 | "metadata": {}
146 | },
147 | {
148 | "cell_type": "markdown",
149 | "source": [
150 | "## 3. Столбец **`published`** (время публикации) содержит строки. Чтобы мы могли работать с этими данными как с датой/временем публикации, приведи их к типу `datetime`."
151 | ],
152 | "metadata": {}
153 | },
154 | {
155 | "cell_type": "code",
156 | "execution_count": null,
157 | "source": [],
158 | "outputs": [],
159 | "metadata": {}
160 | },
161 | {
162 | "cell_type": "markdown",
163 | "source": [
164 | "## 4. Создай несколько столбцов на основе данных о времени публикации (укажи для каждой публикации год, месяц, день недели и час):"
165 | ],
166 | "metadata": {}
167 | },
168 | {
169 | "cell_type": "code",
170 | "execution_count": 10,
171 | "source": [],
172 | "outputs": [],
173 | "metadata": {}
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "source": [
178 | "# Наконец-то, визуализация!\n",
179 | "\n",
180 | "В каждом пункте предлагается построить картинку и с ее помощью ответить на вопрос. Конечно, можно попытаться ответить на все вопросы только с Pandas, без картинок, но чел... Потренируйся строить (красивые) визуализации. И не забудь про правила построения красивого графика, который был в прошлом домашнем задании! "
181 | ],
182 | "metadata": {}
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "source": [
187 | "## 1\\. В каком месяце (и какого года) было больше всего публикаций?"
188 | ],
189 | "metadata": {}
190 | },
191 | {
192 | "cell_type": "code",
193 | "execution_count": null,
194 | "source": [],
195 | "outputs": [],
196 | "metadata": {}
197 | },
198 | {
199 | "cell_type": "markdown",
200 | "source": [
201 | "## 2\\. А теперь проанализируй публикации в месяце из предыдущего вопроса (имеется ввиду конкретный месяц конкретного года)\n",
202 | "\n",
203 | "Подсказ о4ка: построй график зависимости числа публикаций от дня; попробуй использовать параметр `hue`;"
204 | ],
205 | "metadata": {}
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "source": [
210 | "### 2.1 Есть ли один или несколько дней, которые сильно выделяются из общей картины? Если да, то какие это дни в месяце? Может быть, это какие-то конкретные дни недели? "
211 | ],
212 | "metadata": {}
213 | },
214 | {
215 | "cell_type": "code",
216 | "execution_count": null,
217 | "source": [],
218 | "outputs": [],
219 | "metadata": {}
220 | },
221 | {
222 | "cell_type": "markdown",
223 | "source": [
224 | "### 2.2 Всегда ли на хабре больше статей, чем на гиктаймсе? Если нет, то в какие дни месяца на гиктаймсе больше статей?"
225 | ],
226 | "metadata": {}
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": null,
231 | "source": [],
232 | "outputs": [],
233 | "metadata": {}
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "source": [
238 | "### 2.3 В какой день недели на гиктаймс и на хабрахабр публикуют примерно одинаковое число статей?"
239 | ],
240 | "metadata": {}
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": null,
245 | "source": [],
246 | "outputs": [],
247 | "metadata": {}
248 | },
249 | {
250 | "cell_type": "markdown",
251 | "source": [
252 | "## 3\\. Когда лучше всего публиковать статью?"
253 | ],
254 | "metadata": {}
255 | },
256 | {
257 | "cell_type": "markdown",
258 | "source": [
259 | "### 3.1. Опубликованные в какой час суток (от 0 до 24) статьи имеют больше всего информации? (на geektimes.ru и на habrahabr.ru) \n",
260 | "P.S. Имеется ввиду просто количество подсчитанного материала в зависимости от часа."
261 | ],
262 | "metadata": {}
263 | },
264 | {
265 | "cell_type": "code",
266 | "execution_count": null,
267 | "source": [],
268 | "outputs": [],
269 | "metadata": {}
270 | },
271 | {
272 | "cell_type": "markdown",
273 | "source": [
274 | "### 3.2. Опубликованные в какой час (от 0 до 24) суток статьи имеют больше всего комментариев? (на geektimes.ru и на habrahabr.ru)"
275 | ],
276 | "metadata": {}
277 | },
278 | {
279 | "cell_type": "code",
280 | "execution_count": null,
281 | "source": [],
282 | "outputs": [],
283 | "metadata": {}
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "source": [
288 | "### 3.3. Опубликованные в какой час суток статьи набирают больше всего просмотров (в среднем)?"
289 | ],
290 | "metadata": {}
291 | },
292 | {
293 | "cell_type": "code",
294 | "execution_count": null,
295 | "source": [],
296 | "outputs": [],
297 | "metadata": {}
298 | },
299 | {
300 | "cell_type": "markdown",
301 | "source": [
302 | "### 3.4. Опубликованная в какой час суток статья на гиктаймсе набрала максимальное число комментариев?"
303 | ],
304 | "metadata": {}
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": null,
309 | "source": [],
310 | "outputs": [],
311 | "metadata": {}
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "source": [
316 | "### 3.5. Какие статьи на хабре комментируют чаще: дневные или вечерние?"
317 | ],
318 | "metadata": {}
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": null,
323 | "source": [],
324 | "outputs": [],
325 | "metadata": {}
326 | },
327 | {
328 | "cell_type": "markdown",
329 | "source": [
330 | "## 4\\. Кого из топ-20 авторов чаще всего минусуют?\n",
331 | "\n",
332 | "Варианты ответа:\n",
333 | "* @Mordatyj\n",
334 | "* @Mithgol\n",
335 | "* @alizar\n",
336 | "* @ilya42"
337 | ],
338 | "metadata": {}
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": null,
343 | "source": [],
344 | "outputs": [],
345 | "metadata": {}
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "source": [
350 | "## 5\\. Сравните субботы и понедельники\n",
351 | "\n",
352 | "Правда ли, что по субботам авторы пишут в основном днём, а по понедельникам — в основном вечером?"
353 | ],
354 | "metadata": {}
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": null,
359 | "source": [],
360 | "outputs": [],
361 | "metadata": {}
362 | },
363 | {
364 | "cell_type": "markdown",
365 | "source": [
366 | "# Ну и по традиции - вставь ниже картинку или гифку, которая полностью описывает тебя в процессе выполнения этого задания:"
367 | ],
368 | "metadata": {}
369 | },
370 | {
371 | "cell_type": "markdown",
372 | "source": [],
373 | "metadata": {}
374 | }
375 | ],
376 | "metadata": {
377 | "kernelspec": {
378 | "name": "python3",
379 | "display_name": "Python 3.9.7 64-bit"
380 | },
381 | "language_info": {
382 | "codemirror_mode": {
383 | "name": "ipython",
384 | "version": 3
385 | },
386 | "file_extension": ".py",
387 | "mimetype": "text/x-python",
388 | "name": "python",
389 | "nbconvert_exporter": "python",
390 | "pygments_lexer": "ipython3",
391 | "version": "3.9.7"
392 | },
393 | "interpreter": {
394 | "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
395 | }
396 | },
397 | "nbformat": 4,
398 | "nbformat_minor": 2
399 | }
--------------------------------------------------------------------------------
/2022-2023/lesson4/age_sal_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/age_sal_tree.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/age_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/age_tree.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/balls/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/balls/1.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/balls/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/balls/2.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/balls/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/balls/3.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/balls/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/balls/4.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/balls/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/balls/5.png
--------------------------------------------------------------------------------
/2022-2023/lesson4/small_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson4/small_tree.png
--------------------------------------------------------------------------------
/2022-2023/lesson6/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson6/1.png
--------------------------------------------------------------------------------
/2022-2023/lesson7/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson7/2.png
--------------------------------------------------------------------------------
/2022-2023/lesson7/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson7/3.png
--------------------------------------------------------------------------------
/2022-2023/lesson7/bagging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson7/bagging.png
--------------------------------------------------------------------------------
/2022-2023/lesson7/bootstrap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2022-2023/lesson7/bootstrap.jpg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson0/Hello,ML.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson0/Hello,ML.pdf
--------------------------------------------------------------------------------
/2023-2024/fall/lesson1/hello_numpy.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "### Основные преимущества списков NumPy перед стандартными списками"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "Собственно, векторное применение функций - самый очевидный бонус numpy. Он избавляет от необходимости оборачивания в map или в цикл какой-либо функции.\n",
15 | "\n",
16 | "Важна также функциональность: вы получаете много встроенных функций с NumPy, FFT, свертками, быстрым поиском, базовой статистикой, линейной алгеброй, гистограммами и т.д."
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": null,
22 | "metadata": {},
23 | "outputs": [],
24 | "source": [
25 | "import math\n",
26 | "import numpy as np"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "a = [1, 2, 3, 4, 5]\n",
36 | "a = list(map(math.sqrt, a))\n",
37 | "a\n",
38 | "\n",
39 | "# здесь можно также указывать точность\n",
40 | "# (количество чисел после запятой)\n",
41 | "# np.set_printoptions(precision=4)\n",
42 | "a = [1, 2, 3, 4, 5]\n",
43 | "a = np.sqrt(a)\n",
44 | "a"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "Также часто упоминают хорошую скорость выполнения операций по сравнению операции с теми же оригинальными списками"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 4,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "name": "stdout",
61 | "output_type": "stream",
62 | "text": [
63 | "Python array: 10.291004419326782\n",
64 | "Numpy array: 0.22296142578125\n"
65 | ]
66 | }
67 | ],
68 | "source": [
69 | "import time\n",
70 | "\n",
71 | "a = [i for i in range(100000000)]\n",
72 | "\n",
73 | "b = np.array(a, int)\n",
74 | "\n",
75 | "t = time.time()\n",
76 | "a = [a[i] + 1 for i in range(len(a))]\n",
77 | "print(f'Python array: {time.time() - t}')\n",
78 | "\n",
79 | "t = time.time()\n",
80 | "b = b + 1\n",
81 | "print(f'Numpy array: {time.time() - t}')"
82 | ]
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {},
87 | "source": [
88 | "## Переходим к описаниям функций NumPy"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "### 3. Создание массива и матриц NumPy"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "#### Создание массива из списка"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": null,
108 | "metadata": {},
109 | "outputs": [],
110 | "source": [
111 | "some_array = np.array([1, 4, 5, 8], float)\n",
112 | "print(type(some_array))\n",
113 | "\n",
114 | "# созданный массив, кстати, позволяет работать с собой\n",
115 | "# также, как и обычный список\n",
116 | "print(some_array[:2])\n",
117 | "print(some_array[3])\n",
118 | "some_array[2] = 69\n",
119 | "print(some_array)"
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "execution_count": null,
125 | "metadata": {},
126 | "outputs": [],
127 | "source": [
128 | "# массивы так то могут быть и не одномерными (удивительно)\n",
129 | "big_array = np.array([[1, 2, 3], [4, 5, 6]])\n",
130 | "print(big_array)\n",
131 | "# в отличии от списков можно использовать запятые в скобках\n",
132 | "print(big_array[0, 0] == big_array[0][0])"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "#### np.arange()"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {},
146 | "outputs": [],
147 | "source": [
148 | "kek = np.arange(3)\n",
149 | "# можно явно указывать тип значений\n",
150 | "kek = np.arange(3.0)\n",
151 | "kek = np.arange(0, 5)\n",
152 | "# от 0 до 5 с шагом 2\n",
153 | "kek = np.arange(0, 5, 2)\n",
154 | "print(kek)"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "#### np.zeros() и np.ones()"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": null,
167 | "metadata": {},
168 | "outputs": [],
169 | "source": [
170 | "kavo = np.zeros(5)\n",
171 | "# явное указание типа здесь тоже есть\n",
172 | "# (вообще оно почти везде есть, можно к этому больше не возвращаться)\n",
173 | "kavo = np.zeros((5), dtype=int)\n",
174 | "# можно указывать размерность\n",
175 | "kavo = np.zeros((5, 2))\n",
176 | "\n",
177 | "# (штука, в очень многом схожая с np.zeros())\n",
178 | "chevo = np.ones(5)\n",
179 | "chevo = np.ones((5, 2))"
180 | ]
181 | },
182 | {
183 | "cell_type": "markdown",
184 | "metadata": {},
185 | "source": [
186 | "#### np.linspace()"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "# (штука очень похожая на arange, только arange\n",
196 | "# создает с указанием шага, а тут указывается\n",
197 | "# кол-во элементов)\n",
198 | "np.linspace(2.0, 3.0, num=22)\n",
199 | "\n",
200 | "# можно указать, включать ли правую границу в\n",
201 | "# содержимое массива\n",
202 | "np.linspace(2.0, 3.0, num=5, endpoint=False)\n",
203 | "\n",
204 | "# можно даже возвращать не просто список, а кортеж\n",
205 | "# из списка и вычисленного шага между элементами\n",
206 | "np.linspace(2.0, 3.0, num=8, retstep=True)"
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "#### np.identity() и np.eye()"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": null,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": [
222 | "# просто единичная матрица\n",
223 | "np.identity(5)\n",
224 | "\n",
225 | "# возвращает двумерный массив с единицами на указанной\n",
226 | "# диагонали (во всех остальных местах ставятся нули)\n",
227 | "np.eye(2, dtype=int)\n",
228 | "np.eye(4, dtype=int)\n",
229 | "# второй аргумент указывает на размерность\n",
230 | "np.eye(4, 3, 1, dtype=int)\n",
231 | "# иногда удобнее явно задавать номер диагонали\n",
232 | "np.eye(3, k=1)"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {},
238 | "source": [
239 | "### 4. Мелкие вспомогательные функции"
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {},
245 | "source": [
246 | "#### np.shape"
247 | ]
248 | },
249 | {
250 | "cell_type": "code",
251 | "execution_count": null,
252 | "metadata": {},
253 | "outputs": [],
254 | "source": [
255 | "# np.shape позволяет\n",
256 | "# получить размерность некоторого массива\n",
257 | "np.shape(np.eye(3))\n",
258 | "np.shape(some_array)\n",
259 | "np.shape(big_array)"
260 | ]
261 | },
262 | {
263 | "cell_type": "markdown",
264 | "metadata": {},
265 | "source": [
266 | "#### np.dtype"
267 | ]
268 | },
269 | {
270 | "cell_type": "code",
271 | "execution_count": null,
272 | "metadata": {},
273 | "outputs": [],
274 | "source": [
275 | "# np.dtype указывает\n",
276 | "# на тип содержимого списка\n",
277 | "big_array.dtype\n",
278 | "print((np.arange(3.0)).dtype)\n",
279 | "print(np.array([\"pepega\", \"nice\"]).dtype)\n",
280 | "print(np.array([{\"a\": 1}, {\"b\": 2}]).dtype)"
281 | ]
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {},
286 | "source": [
287 | "#### np.copy()"
288 | ]
289 | },
290 | {
291 | "cell_type": "code",
292 | "execution_count": null,
293 | "metadata": {},
294 | "outputs": [],
295 | "source": [
296 | "# np.copy() копирует список\n",
297 | "# с содержимым в другую ячейку в памяти\n",
298 | "a = np.array([1, 'm', [2, 3, 4]], dtype=object)\n",
299 | "b = np.copy(a)\n",
300 | "a[1] = 1\n",
301 | "print(a)\n",
302 | "print(b)"
303 | ]
304 | },
305 | {
306 | "cell_type": "markdown",
307 | "metadata": {},
308 | "source": [
309 | "#### np.flatten()"
310 | ]
311 | },
312 | {
313 | "cell_type": "code",
314 | "execution_count": null,
315 | "metadata": {},
316 | "outputs": [],
317 | "source": [
318 | "# делает одномерный массив из многомерного\n",
319 | "a = np.array([[1,2], [3,4]])\n",
320 | "print(a.flatten())\n",
321 | "a = np.array([[1,2], [[3, 3.5, 3.6], 4]])\n",
322 | "print(a.flatten())"
323 | ]
324 | },
325 | {
326 | "cell_type": "markdown",
327 | "metadata": {},
328 | "source": [
329 | "#### np.concatenate()"
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {},
336 | "outputs": [],
337 | "source": [
338 | "# np.concatenate()\n",
339 | "# осуществляет конкатенацию списков\n",
340 | "a = np.array([[1,2], [3,4]])\n",
341 | "a = np.array([[1, 2], [3, 4]])\n",
342 | "b = np.array([[5, 6]])\n",
343 | "print(np.concatenate((a, b), axis=0))\n",
344 | "print(np.concatenate((a, b), axis=None))"
345 | ]
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "metadata": {},
350 | "source": [
351 | "### 5. Арифметические и логические операции в NumPy"
352 | ]
353 | },
354 | {
355 | "cell_type": "code",
356 | "execution_count": null,
357 | "metadata": {},
358 | "outputs": [],
359 | "source": [
360 | "# база\n",
361 | "a = np.array([1,2,3], float)\n",
362 | "b = np.array([5,2,6], float)\n",
363 | "print(a + b)\n",
364 | "print(a - b)\n",
365 | "\n",
366 | "# умножение даже двумерных матриц с помощью оператора \"*\"\n",
367 | "# происходит тоже ПОЭЛЕМЕНТНО\n",
368 | "print(a * b)\n",
369 | "print(a / b)\n",
370 | "print(a % b)\n",
371 | "print(a ** b)\n",
372 | "\n",
373 | "# ещё база\n",
374 | "a = np.array([1, 3, 0], float)\n",
375 | "b = np.array([0, 3, 2], float)\n",
376 | "print(a > b)\n",
377 | "print(a == b)\n",
378 | "print(a <= b)\n",
379 | "print(c = a > b)\n",
380 | "# можем сравнивать с одиночным значением\n",
381 | "a = np.array([1, 3, 0], float)\n",
382 | "print(a > 2)"
383 | ]
384 | },
385 | {
386 | "cell_type": "markdown",
387 | "metadata": {},
388 | "source": [
389 | "#### np.all() и np.any()"
390 | ]
391 | },
392 | {
393 | "cell_type": "code",
394 | "execution_count": null,
395 | "metadata": {},
396 | "outputs": [],
397 | "source": [
398 | "# возвращает true, если все значения списка ненулевые\n",
399 | "# (по сути это логическое И)\n",
400 | "np.all([1, 1, 1])\n",
401 | "np.all([0, 1, 1])\n",
402 | "# ключевое слово - НЕНУЛЕВЫЕ\n",
403 | "np.all([-1, 4, 5])\n",
404 | "\n",
405 | "# можно указывать, возвращать ли значение для всех списков,\n",
406 | "# или значения для каждого конкретного\n",
407 | "np.all([[True,False],[True,True]])\n",
408 | "np.all([[True,False],[True,True]], axis=0)\n",
409 | "\n",
410 | "# np.any()\n",
411 | "# возвращает true, если хотя бы одно значение списка ненулевое\n",
412 | "# (по сути это логическое ИЛИ)\n",
413 | "np.any([0, 0, 0])\n",
414 | "np.any([0, 0, 1])"
415 | ]
416 | },
417 | {
418 | "cell_type": "markdown",
419 | "metadata": {},
420 | "source": [
421 | "#### np.sqrt(). np.exp(), np.log()"
422 | ]
423 | },
424 | {
425 | "cell_type": "code",
426 | "execution_count": null,
427 | "metadata": {},
428 | "outputs": [],
429 | "source": [
430 | "# векторизованные до боли знакомые функции\n",
431 | "np.sqrt([1, 4, 9])\n",
432 | "np.exp([1, 4, 9])\n",
433 | "np.log([1, 4, 9])\n",
434 | "\n",
435 | "# можно работать и с комплексными числами\n",
436 | "# но нужно ли...\n",
437 | "np.sqrt([4, -1, -3+4J])\n",
438 | "np.log([4, -1, -3+4J])"
439 | ]
440 | },
441 | {
442 | "cell_type": "markdown",
443 | "metadata": {},
444 | "source": [
445 | "#### np.sum() и np.prod()"
446 | ]
447 | },
448 | {
449 | "cell_type": "code",
450 | "execution_count": null,
451 | "metadata": {},
452 | "outputs": [],
453 | "source": [
454 | "# сумма значений списка по конкретной оси\n",
455 | "print(np.sum([0.5, 1.5]))\n",
456 | "print(np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32))\n",
457 | "print(np.sum([[0, 1], [0, 5]]))\n",
458 | "print(np.sum([[0, 1], [1, 5]], axis=0))\n",
459 | "print(np.sum([[0, 1], [1, 5]], axis=1))\n",
460 | "\n",
461 | "# произведение значений списка по конкретной оси\n",
462 | "print(np.prod([0.5, 1.5]))\n",
463 | "print(np.prod([0.5, 0.7, 0.2, 1.5], dtype=np.int32))\n",
464 | "print(np.prod([[1, 2], [3, 4]]))\n",
465 | "print(np.prod([[1, 2], [3, 4]], axis=0))\n",
466 | "print(np.prod([[1, 2], [3, 4]], axis=1))"
467 | ]
468 | },
469 | {
470 | "cell_type": "markdown",
471 | "metadata": {},
472 | "source": [
473 | "#### np.dot() и np.matmul()"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": null,
479 | "metadata": {},
480 | "outputs": [],
481 | "source": [
482 | "# с помощью np.dot()\n",
483 | "# можно умножать массивы между собой\n",
484 | "# (представляет собой поэлементное\n",
485 | "# умножение элементов списков)\n",
486 | "print(np.dot(3, 4))\n",
487 | "print(np.dot([2j, 3j], [2j, 3j]))\n",
488 | "a = [[1, 0],\n",
489 | " [1, 1]]\n",
490 | "b = [[4, 1],\n",
491 | " [2, 2]]\n",
492 | "print(np.dot(a, b))\n",
493 | "\n",
494 | "\n",
495 | "# np.matmul()\n",
496 | "# (по сути является обычным\n",
497 | "# матричным произведением)\n",
498 | "a = [[1, 0],\n",
499 | " [1, 1]]\n",
500 | "b = [[4, 1],\n",
501 | " [2, 2]]\n",
502 | "print(np.matmul(a, b))\n",
503 | "\n",
504 | "a = np.array([[1, 1],\n",
505 | " [1, 1]])\n",
506 | "b = np.array([1, 2])\n",
507 | "print(np.matmul(a, b))"
508 | ]
509 | },
510 | {
511 | "cell_type": "markdown",
512 | "metadata": {},
513 | "source": [
514 | "### 6. Константы и статистические приколы"
515 | ]
516 | },
517 | {
518 | "cell_type": "code",
519 | "execution_count": null,
520 | "metadata": {},
521 | "outputs": [],
522 | "source": [
523 | "# ничего интересно, просто держим в курсе\n",
524 | "print(np.pi)\n",
525 | "print(np.e)"
526 | ]
527 | },
528 | {
529 | "cell_type": "markdown",
530 | "metadata": {},
531 | "source": [
532 | "#### np.min() и np.max()"
533 | ]
534 | },
535 | {
536 | "cell_type": "code",
537 | "execution_count": null,
538 | "metadata": {},
539 | "outputs": [],
540 | "source": [
541 | "print(np.min(np.array([7, 8, 4, 5, 2])))\n",
542 | "print(np.min([[1, 2], [2], [3, 4, 3]]))\n",
543 | "print(np.max([[1, 2], [2], [3, 4, 3]]))"
544 | ]
545 | },
546 | {
547 | "cell_type": "markdown",
548 | "metadata": {},
549 | "source": [
550 | "#### Статистика (медиана, среднее значение, дисперсия, стандартное отклонение)"
551 | ]
552 | },
553 | {
554 | "cell_type": "code",
555 | "execution_count": null,
556 | "metadata": {},
557 | "outputs": [],
558 | "source": [
559 | "a = np.array([[10, 7, 4], [3, 2, 1]])\n",
560 | "a\n",
561 | "\n",
562 | "print(np.median(a))\n",
563 | "print(np.median(a, axis=0))\n",
564 | "print(np.median(a, axis=1))\n",
565 | "\n",
566 | "print(np.mean(a))\n",
567 | "print(np.mean(a, axis=0))\n",
568 | "print(np.mean(a, axis=1))\n",
569 | "\n",
570 | "print(np.var(a))\n",
571 | "print(np.var(a, axis=0))\n",
572 | "print(np.var(a, axis=1))\n",
573 | "\n",
574 | "print(np.std(a))\n",
575 | "print(np.std(a, axis=0))\n",
576 | "print(np.std(a, axis=1))"
577 | ]
578 | },
579 | {
580 | "cell_type": "markdown",
581 | "metadata": {},
582 | "source": [
583 | "### 7. Ещё полезные функции"
584 | ]
585 | },
586 | {
587 | "cell_type": "markdown",
588 | "metadata": {},
589 | "source": [
590 | "#### np.unique()"
591 | ]
592 | },
593 | {
594 | "cell_type": "code",
595 | "execution_count": 82,
596 | "metadata": {},
597 | "outputs": [
598 | {
599 | "data": {
600 | "text/plain": [
601 | "array([False, False, True, False])"
602 | ]
603 | },
604 | "execution_count": 82,
605 | "metadata": {},
606 | "output_type": "execute_result"
607 | }
608 | ],
609 | "source": [
610 | "# возвращает уникальные значения из списка\n",
611 | "print(np.unique([1, 1, 2, 2, 3, 3]))\n",
612 | "# работает и для многомерных списков\n",
613 | "a = np.array([[1, 1], [2, 3]])\n",
614 | "print(np.unique(a))"
615 | ]
616 | },
617 | {
618 | "cell_type": "markdown",
619 | "metadata": {},
620 | "source": [
621 | "#### np.diagonal()"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": null,
627 | "metadata": {},
628 | "outputs": [],
629 | "source": [
630 | "# получение значение на конкретной\n",
631 | "# диагонали матрицы\n",
632 | "a = np.arange(16).reshape(4,4)\n",
633 | "print(a)\n",
634 | "print(a.diagonal())\n",
635 | "print(a.diagonal(1))"
636 | ]
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "metadata": {},
641 | "source": [
642 | "#### np.nonzero()"
643 | ]
644 | },
645 | {
646 | "cell_type": "code",
647 | "execution_count": null,
648 | "metadata": {},
649 | "outputs": [],
650 | "source": [
651 | "# возвращает индексы ненулевых элементов списка\n",
652 | "x = np.array([1, 0, 0, 0, 12, 0, -1])\n",
653 | "print(x)\n",
654 | "print(np.nonzero(x))\n",
655 | "\n",
656 | "# это работает и с многомерными массивами\n",
657 | "x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])\n",
658 | "print(x)\n",
659 | "print(np.nonzero(x))\n",
660 | "\n",
661 | "# таким хитрым образом можно получить\n",
662 | "# сами ненулевые элементы в списке\n",
663 | "print(x[np.nonzero(x)])"
664 | ]
665 | },
666 | {
667 | "cell_type": "markdown",
668 | "metadata": {},
669 | "source": [
670 | "#### np.isnan()"
671 | ]
672 | },
673 | {
674 | "cell_type": "code",
675 | "execution_count": null,
676 | "metadata": {},
677 | "outputs": [],
678 | "source": [
679 | "# возвращает True, если значение None, Null, NaN\n",
680 | "print(np.isnan([1, 2, np.nan, 12]))"
681 | ]
682 | },
683 | {
684 | "cell_type": "markdown",
685 | "metadata": {},
686 | "source": [
687 | "### 8. Случайные случайности"
688 | ]
689 | },
690 | {
691 | "cell_type": "code",
692 | "execution_count": null,
693 | "metadata": {},
694 | "outputs": [],
695 | "source": [
696 | "print(np.random.rand(4))\n",
697 | "print(np.random.rand(1, 2))\n",
698 | "\n",
699 | "print(np.random.randint(3))\n",
700 | "print(np.random.randint(low=3, high=5, size=3))\n",
701 | "\n",
702 | "# возвращает значение\n",
703 | "# стандартного нормального распределения\n",
704 | "print(np.random.randn(5, 2))\n",
705 | "\n",
706 | "\n",
707 | "# перемешивает значения списка\n",
708 | "a = [1, 2, 3, 4, 5]\n",
709 | "np.random.shuffle(a)\n",
710 | "print(a)"
711 | ]
712 | }
713 | ],
714 | "metadata": {
715 | "interpreter": {
716 | "hash": "bb399e1a834aa17b35df3c7b12c8f19baf7d93a1973604970edfee6e51c1813f"
717 | },
718 | "kernelspec": {
719 | "display_name": "Python 3.9.10 64-bit (windows store)",
720 | "language": "python",
721 | "name": "python3"
722 | },
723 | "language_info": {
724 | "codemirror_mode": {
725 | "name": "ipython",
726 | "version": 3
727 | },
728 | "file_extension": ".py",
729 | "mimetype": "text/x-python",
730 | "name": "python",
731 | "nbconvert_exporter": "python",
732 | "pygments_lexer": "ipython3",
733 | "version": "3.9.10"
734 | },
735 | "orig_nbformat": 4
736 | },
737 | "nbformat": 4,
738 | "nbformat_minor": 2
739 | }
740 |
--------------------------------------------------------------------------------
/2023-2024/fall/lesson1/hello_python.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Содержание:\n",
8 | "* [Общие моменты](#general)\n",
9 | " 1. [Установка Python](#install)\n",
10 | " 2. [Работа с виртуальными окружениями](#virtualenv)\n",
11 | "* [Основная часть](#main)\n",
12 | " 1. [Динамическая типизация](#dyn)\n",
13 | " 2. [Отсутствие статического анализа кода](#static)\n",
14 | " 3. [Немного о рефлексии](#reflex)\n",
15 | " 4. [Изменяемые объекты](#mut)\n",
16 | " * Списки и операции над ними\n",
17 | " * Генераторы вообще\n",
18 | " 5. [Ещё немного интересного с изменяемыми объектами](#mut2)\n",
19 | " 6. [Функция как объект](#func)\n",
20 | " * Коварность mutable-аргументов\n",
21 | " * Вложенные функции и каррирование\n",
22 | " * Декораторы\n",
23 | " * Лямбда-функции и приложения\n",
24 | " 7. [NumPy](#numpy)\n",
25 | " * Статистика и другое\n",
26 | " * Производительность\n",
27 | " * Векторизация\n",
28 | " * Экономия памяти\n",
29 | " * Удобство\n",
30 | " * Практическое задание #1\n",
31 | " * Практическое задание #2\n",
32 | " * Практическое задание #3\n"
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": [
39 | "## Общие моменты "
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "### Установка Python "
47 | ]
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {},
52 | "source": [
53 | "Установить Python для Windows [можно тут](https://www.python.org/downloads/), следуя стандартным инструкциям установки, не забыв добавить исполняемый файл Python в `PATH`.\n",
54 | "\n",
55 | "Для UNIX-based операционных систем установку можно осуществить с помощью пакетного менеджера (будь то `apt`, `apk`, `pacman` или `brew`).\n",
56 | "\n",
57 | "С более полным гайдом по установке можно ознакомиться [тут](https://dsc.sgu.ru/machine-learning/setup/)."
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "metadata": {},
63 | "source": [
64 | "### Работа с виртуальными окружениями "
65 | ]
66 | },
67 | {
68 | "cell_type": "markdown",
69 | "metadata": {},
70 | "source": [
71 | "Python, как и любой другой язык, позволяет использовать пользовательские\n",
72 | "библиотеки с помощью собственного пакетного менеджера под названием `pip`.\n",
73 | "\n",
74 | "Но при одновременной работе с несколькими проектами установка пакетов может\n",
75 | "привести к конфликту установленных библиотек разных версий, поэтому на практике\n",
76 | "применяют виртуальные окружения.\n",
77 | "\n",
78 | "Создать виртуальное окружение в текущей директории можно с помощью команды \n",
79 | "\n",
80 | "`python3 -m venv .venv`. \n",
81 | "\n",
82 | "Здесь `venv` — имя модуля, `.venv` — директория окружения. Логично создавать окружение в корневой директории проекта.\n",
83 | "\n",
84 | "При работе в [Jupyter Notebook](https://docs.jupyter.org/en/latest/running.html) (не [Google Colab](https://colab.google/)) необходимо также убедиться в том, что вы используете именно это окружение. В Visual Studio Code это отображается в верхней правой части экрана — там указывается папка с окружением и соответствующая версия Python.\n",
85 | "\n",
86 | "В рамках Клуба мы рекомендуем пользоваться Google Colab в случае, если он кажется наиболее удобным, либо у вас нет собственного ноутбука, поскольку Colab — веб-сервис и доступен с любого устройства.\n",
87 | "\n",
88 | "Здесь стоит оговориться, что для Windows нам не известно какого-то очень удобного способа создавать эти окружения — можно использовать либо командную строку, либо специфичные средства создания таких окружений в текстовом редакторе, если таковые имеются.\n",
89 | "\n",
90 | "Можно также использовать любые надстройки над `venv`-ом — [Poetry](https://python-poetry.org/), [Conda](https://docs.conda.io/en/latest/) или, например, относительно свежий проект [Rye](https://github.com/mitsuhiko/rye)."
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {},
96 | "source": [
97 | "## Основная часть "
98 | ]
99 | },
100 | {
101 | "cell_type": "markdown",
102 | "metadata": {},
103 | "source": [
104 | "Далее будут рассмотрены основные особенности языка, которые принципиально важны в практической деятельности."
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "### Динамическая типизация (dynamic typing) "
112 | ]
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "metadata": {},
117 | "source": [
118 | "Хорошо известно, что Python — динамических язык. В связи\n",
119 | "с этим одна и та же переменная может принимать значения различных типов.\n",
120 | "\n",
121 | "Поэтому, любое из следующий выражений будет вполне справедливо"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": null,
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "x = 3\n",
131 | "x = '3'\n",
132 | "x = ['3']\n",
133 | "x = [['3']]"
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {},
139 | "source": [
140 | "Возможность одной и той же переменной присваивать значения различных типов является одновременно и плюсом, и минусом. \n",
141 | "\n",
142 | "С одной стороны, это позволяет меньше задумываться о типах значений. С другой стороны, это заставляет больше задумываться о них в последствии."
143 | ]
144 | },
145 | {
146 | "cell_type": "code",
147 | "execution_count": null,
148 | "metadata": {},
149 | "outputs": [],
150 | "source": [
151 | "def f(x: int, y: str) -> dict:\n",
152 | " return x + y\n",
153 | "\n",
154 | "\n",
155 | "print(f(3, 5))"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "Существует возможность добавлять аннотации типов, но эти аннотации имеют смысл\n",
163 | "лишь для программиста, но не интерпретатора.\n",
164 | "\n",
165 | "Выражение выше при заданных аргументах будет выполнено корректно, хотя `y` имеет при себе аннотацию `str`, а сам метод в теории должен возвращать `dict`."
166 | ]
167 | },
168 | {
169 | "cell_type": "markdown",
170 | "metadata": {},
171 | "source": [
172 | "### Отсутствие статического анализа кода (static checking) "
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "Ещё одной важной чертой Python является отсутствие полноценной системы статического анализа кода.\n",
180 | "\n",
181 | "Иными словами — ошибки обнаруживаются не на этапе запуска программы, а во время её исполнения.\n",
182 | "\n",
183 | "Таким образом, программа может не завершиться успешно спустя долгое время и \"обрушить\" значительную часть предшествующей работы программы."
184 | ]
185 | },
186 | {
187 | "cell_type": "code",
188 | "execution_count": null,
189 | "metadata": {},
190 | "outputs": [],
191 | "source": [
192 | "df = [i for i in range(int(1e6))]\n",
193 | "\n",
194 | "SOME_RESULT = \"very_meaningful_result\"\n",
195 | "SOME_TASK = \"very long python is learning how to be a python\"\n",
196 | "\n",
197 | "\n",
198 | "def job(some_arg):\n",
199 | " \n",
200 | " SOME_TASK(some_arg)\n",
201 | " # ...VERY VERY VERY LONG TIME PASSED\n",
202 | " SOME_RESULT.to_csv(\"output.csv\") # where result is numpy array, \n",
203 | " # not dataframe as expected\n",
204 | "\n",
205 | "job(df)\n"
206 | ]
207 | },
208 | {
209 | "cell_type": "markdown",
210 | "metadata": {},
211 | "source": [
212 | "### Немного о рефлексии "
213 | ]
214 | },
215 | {
216 | "cell_type": "markdown",
217 | "metadata": {},
218 | "source": [
219 | "Механизм рефлексии можно понимать как способность программы \"обращаться\" к самой себе в ходе исполнения — просматривать список методов или полей\n",
220 | "объекта, дополнять и изменять классы и так далее.\n",
221 | "\n",
222 | "В Python много полезных применений этого механизма, но среди них есть особенно полезные."
223 | ]
224 | },
225 | {
226 | "cell_type": "markdown",
227 | "metadata": {},
228 | "source": [
229 | "Например, функция `dir` позволяет отобразить список существующих методов\n",
230 | "заданного класса."
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "execution_count": null,
236 | "metadata": {},
237 | "outputs": [],
238 | "source": [
239 | "dir(list)"
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {},
245 | "source": [
246 | "Если отсеять \"магические\" методы, то зачем вообще открывать документацию в\n",
247 | "браузере? :)"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": null,
253 | "metadata": {},
254 | "outputs": [],
255 | "source": [
256 | "def vdir(obj):\n",
257 | " return [x for x in dir(obj) if not x.startswith('__')]\n",
258 | "\n",
259 | "methods = vdir(list)\n",
260 | "\n",
261 | "for method in methods:\n",
262 | " help(getattr(list, method))"
263 | ]
264 | },
265 | {
266 | "cell_type": "markdown",
267 | "metadata": {},
268 | "source": [
269 | "Функция `help` может отобразить документацию для заданного метода. Но так как\n",
270 | "результат работы `dir` — названия методов, а не сами методы, то необходимо\n",
271 | "предварительно получить сам метод с помощью функции `getattr`."
272 | ]
273 | },
274 | {
275 | "cell_type": "markdown",
276 | "metadata": {},
277 | "source": [
278 | "### Изменяемые объекты (mutable objects) "
279 | ]
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {},
284 | "source": [
285 | "Проще всего мыслить так. Изменяемые объекты это:\n",
286 | "1. Списки\n",
287 | "2. Словари\n",
288 | "3. Множества\n",
289 | "4. Пользовательские классы\n",
290 | "\n",
291 | "Все остальные классы можно причислить к неизменяемым."
292 | ]
293 | },
294 | {
295 | "cell_type": "code",
296 | "execution_count": null,
297 | "metadata": {},
298 | "outputs": [],
299 | "source": [
300 | "# Mutable\n",
301 | "d = {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}\n",
302 | "\n",
303 | "# Mutable\n",
304 | "lst = d.values()\n",
305 | "\n",
306 | "# Mutable\n",
307 | "s = set(lst)\n",
308 | "\n",
309 | "# Will it work?\n",
310 | "# c = {[1, 2, 3]: \"[1, 2, 3]\"}"
311 | ]
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "metadata": {},
316 | "source": [
317 | "#### Списки и операции над ними"
318 | ]
319 | },
320 | {
321 | "cell_type": "markdown",
322 | "metadata": {},
323 | "source": [
324 | "Срезы списков (slices)"
325 | ]
326 | },
327 | {
328 | "cell_type": "code",
329 | "execution_count": null,
330 | "metadata": {},
331 | "outputs": [],
332 | "source": [
333 | "x = [1, 2, 3, 4, 5]\n",
334 | "\n",
335 | "print(x[1:3])\n",
336 | "print(x[:-1]) # or x[:len(x) - 1]\n",
337 | "print(x[0::2])"
338 | ]
339 | },
340 | {
341 | "cell_type": "markdown",
342 | "metadata": {},
343 | "source": [
344 | "Добавление элемента/списка"
345 | ]
346 | },
347 | {
348 | "cell_type": "markdown",
349 | "metadata": {},
350 | "source": [
351 | "Операция `append` с точностью до названия присутствует практически в каждом\n",
352 | "языке программирования, а вот `extend` встречается не везде. В целом, смысл\n",
353 | "функций должен быть вполне потянен исходя из вывода интерпретатора. "
354 | ]
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": null,
359 | "metadata": {},
360 | "outputs": [],
361 | "source": [
362 | "a = [1, 2, 3, 4, 5]\n",
363 | "b = [1, 2, 3]\n",
364 | "\n",
365 | "print(a.append(b))\n",
366 | "print(a)\n",
367 | "print(a.extend(b))\n",
368 | "print(a)"
369 | ]
370 | },
371 | {
372 | "cell_type": "markdown",
373 | "metadata": {},
374 | "source": [
375 | "Генераторы списков (list comprehension)"
376 | ]
377 | },
378 | {
379 | "cell_type": "markdown",
380 | "metadata": {},
381 | "source": [
382 | "Генераторы списков — специальная конструкция, которая позволяет компактно\n",
383 | "создавать списки. Ключевым оператором здесь выступает `in` — который требует\n",
384 | "генератор и возвращает... список? Или генератор? Давайте посмотрим."
385 | ]
386 | },
387 | {
388 | "cell_type": "code",
389 | "execution_count": null,
390 | "metadata": {},
391 | "outputs": [],
392 | "source": [
393 | "print([x * x for x in range(10)])"
394 | ]
395 | },
396 | {
397 | "cell_type": "markdown",
398 | "metadata": {},
399 | "source": [
400 | "А что если опустить квадратные скобки?"
401 | ]
402 | },
403 | {
404 | "cell_type": "code",
405 | "execution_count": null,
406 | "metadata": {},
407 | "outputs": [],
408 | "source": [
409 | "print(x * x for x in range(10))"
410 | ]
411 | },
412 | {
413 | "cell_type": "markdown",
414 | "metadata": {},
415 | "source": [
416 | "Давайте сохраним этот объект"
417 | ]
418 | },
419 | {
420 | "cell_type": "code",
421 | "execution_count": null,
422 | "metadata": {},
423 | "outputs": [],
424 | "source": [
425 | "gen = (x * x for x in range(10))"
426 | ]
427 | },
428 | {
429 | "cell_type": "markdown",
430 | "metadata": {},
431 | "source": [
432 | "И преобразуем в его список"
433 | ]
434 | },
435 | {
436 | "cell_type": "code",
437 | "execution_count": null,
438 | "metadata": {},
439 | "outputs": [],
440 | "source": [
441 | "list(gen)"
442 | ]
443 | },
444 | {
445 | "cell_type": "markdown",
446 | "metadata": {},
447 | "source": [
448 | "#### Генераторы вообще"
449 | ]
450 | },
451 | {
452 | "cell_type": "markdown",
453 | "metadata": {},
454 | "source": [
455 | "Генераторы, на самом деле, могут быть сколь угодно сложными. Если синтаксически\n",
456 | "Python не позволяет реализовать нужную функциональность, то можно описать поведение\n",
457 | "генератора в виде функции."
458 | ]
459 | },
460 | {
461 | "cell_type": "code",
462 | "execution_count": null,
463 | "metadata": {},
464 | "outputs": [],
465 | "source": [
466 | "def traverse(obj):\n",
467 | " if type(obj) != list:\n",
468 | " yield obj\n",
469 | " else:\n",
470 | " for subobj in obj:\n",
471 | " for element in traverse(subobj):\n",
472 | " yield element"
473 | ]
474 | },
475 | {
476 | "cell_type": "markdown",
477 | "metadata": {},
478 | "source": [
479 | "Ключевое слово `yield` похоже на `return` — оно тоже возвращает значение, но\n",
480 | "отличие в том\n",
481 | "Его наличие гарантирует, что результатом вызова функции будет генератор. \n",
482 | "\n",
483 | "Кроме того, `yield` приостанавливает выполнение функции до тех пор, пока\n",
484 | "от генератора не понадобится следующее значение генератора."
485 | ]
486 | },
487 | {
488 | "cell_type": "markdown",
489 | "metadata": {},
490 | "source": [
491 | "Тогда `t` — генератор, и мы все ещё можем сгенерировать список на его основе:"
492 | ]
493 | },
494 | {
495 | "cell_type": "code",
496 | "execution_count": null,
497 | "metadata": {},
498 | "outputs": [],
499 | "source": [
500 | "t = traverse([[1, 2, 3], 2, [[3]]])\n",
501 | "list(t)"
502 | ]
503 | },
504 | {
505 | "cell_type": "markdown",
506 | "metadata": {},
507 | "source": [
508 | "Можно попробовать взять четыре элемента генератора, а не все. \n",
509 | "\n",
510 | "Для этого можно воспользоваться методом `next`, который возвращает следующий\n",
511 | "элемент итератора."
512 | ]
513 | },
514 | {
515 | "cell_type": "code",
516 | "execution_count": null,
517 | "metadata": {},
518 | "outputs": [],
519 | "source": [
520 | "[next(t) for _ in range(4)]"
521 | ]
522 | },
523 | {
524 | "cell_type": "markdown",
525 | "metadata": {},
526 | "source": [
527 | "Ничем хорошим это не закончится, поскольку генератор — вещь, имеющая состояние\n",
528 | "и оно не обнуляется между операциями. \n",
529 | "\n",
530 | "\"Обнулить\" его можно, например, пересоздав итератор."
531 | ]
532 | },
533 | {
534 | "cell_type": "code",
535 | "execution_count": null,
536 | "metadata": {},
537 | "outputs": [],
538 | "source": [
539 | "t = traverse([[1, 2, 3], 2, [[3]]])\n",
540 | "[next(t) for _ in range(4)]"
541 | ]
542 | },
543 | {
544 | "cell_type": "markdown",
545 | "metadata": {},
546 | "source": [
547 | "Генераторы dict-ов (dict comprehension)"
548 | ]
549 | },
550 | {
551 | "cell_type": "markdown",
552 | "metadata": {},
553 | "source": [
554 | "То же выражение генератора можно обернуть и в привычные нам фигурные скобки, \n",
555 | "и мы получим словарь."
556 | ]
557 | },
558 | {
559 | "cell_type": "code",
560 | "execution_count": null,
561 | "metadata": {},
562 | "outputs": [],
563 | "source": [
564 | "{x + y: x * y for x in [1, 2, 3] for y in [5, 7]}"
565 | ]
566 | },
567 | {
568 | "cell_type": "markdown",
569 | "metadata": {},
570 | "source": [
571 | "### Ещё немного интересного с изменяемыми объектами "
572 | ]
573 | },
574 | {
575 | "cell_type": "markdown",
576 | "metadata": {},
577 | "source": [
578 | "Хотим скопировать список. Так можно?"
579 | ]
580 | },
581 | {
582 | "cell_type": "code",
583 | "execution_count": null,
584 | "metadata": {},
585 | "outputs": [],
586 | "source": [
587 | "x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
588 | "\n",
589 | "y = x\n",
590 | "\n",
591 | "y[0] = [2, 3, 4]\n",
592 | "\n",
593 | "x"
594 | ]
595 | },
596 | {
597 | "cell_type": "markdown",
598 | "metadata": {},
599 | "source": [
600 | "А так?"
601 | ]
602 | },
603 | {
604 | "cell_type": "code",
605 | "execution_count": null,
606 | "metadata": {},
607 | "outputs": [],
608 | "source": [
609 | "y = list(x)\n",
610 | "\n",
611 | "y[0] = [1, 2, 3]\n",
612 | "#y[0][1] = [2, 3, 5]\n",
613 | "\n",
614 | "x"
615 | ]
616 | },
617 | {
618 | "cell_type": "markdown",
619 | "metadata": {},
620 | "source": [
621 | "Может, что-то такое?"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": null,
627 | "metadata": {},
628 | "outputs": [],
629 | "source": [
630 | "y = x.copy()\n",
631 | "\n",
632 | "y[0][1] = [2, 3, 6]\n",
633 | "\n",
634 | "x"
635 | ]
636 | },
637 | {
638 | "cell_type": "markdown",
639 | "metadata": {},
640 | "source": [
641 | "Ну или такое...?"
642 | ]
643 | },
644 | {
645 | "cell_type": "code",
646 | "execution_count": null,
647 | "metadata": {},
648 | "outputs": [],
649 | "source": [
650 | "from copy import deepcopy\n",
651 | "\n",
652 | "y = deepcopy(x)\n",
653 | "\n",
654 | "y[0][1] = 7\n",
655 | "\n",
656 | "x"
657 | ]
658 | },
659 | {
660 | "cell_type": "markdown",
661 | "metadata": {},
662 | "source": [
663 | "### Функция как объект (functions) "
664 | ]
665 | },
666 | {
667 | "cell_type": "markdown",
668 | "metadata": {},
669 | "source": [
670 | "#### Коварность mutable-аргументов по умолчанию (mutable default arguments)"
671 | ]
672 | },
673 | {
674 | "cell_type": "markdown",
675 | "metadata": {},
676 | "source": [
677 | "Известно, что Python может принимать аргументы по умолчанию. Но у изменяемых\n",
678 | "аргументов по умолчанию есть особенности."
679 | ]
680 | },
681 | {
682 | "cell_type": "code",
683 | "execution_count": null,
684 | "metadata": {},
685 | "outputs": [],
686 | "source": [
687 | "# Append all odd numbers less than n to x or use empty if not passed\n",
688 | "def f(n, x=[]):\n",
689 | " for i in range(0, n, 2):\n",
690 | " x.append(i)\n",
691 | "\n",
692 | " return x\n",
693 | "\n",
694 | "print(f(6))\n",
695 | "print(f(4))\n",
696 | "print(f(4, []))"
697 | ]
698 | },
699 | {
700 | "cell_type": "markdown",
701 | "metadata": {},
702 | "source": [
703 | "Давайте попробуем вывести в интерпретатор, что из себя представляет функция."
704 | ]
705 | },
706 | {
707 | "cell_type": "code",
708 | "execution_count": null,
709 | "metadata": {},
710 | "outputs": [],
711 | "source": [
712 | "f"
713 | ]
714 | },
715 | {
716 | "cell_type": "markdown",
717 | "metadata": {},
718 | "source": [
719 | "Оказывается, что функция — это объект cо своими полями и методами. \n",
720 | "\n",
721 | "Среди полей есть переменная `__defaults__`, в котором и сокрыта вся магия такого\n",
722 | "поведения."
723 | ]
724 | },
725 | {
726 | "cell_type": "code",
727 | "execution_count": null,
728 | "metadata": {},
729 | "outputs": [],
730 | "source": [
731 | "f.__defaults__"
732 | ]
733 | },
734 | {
735 | "cell_type": "markdown",
736 | "metadata": {},
737 | "source": [
738 | "Оказывается, что такое поведение обусловлено тем, что аргумент по умолчанию\n",
739 | "представляет из себя поле класса, которое, очевидно, не обновляется с каждым\n",
740 | "вызовом функции."
741 | ]
742 | },
743 | {
744 | "cell_type": "markdown",
745 | "metadata": {},
746 | "source": [
747 | "#### Вложенные функции и каррирование (nested functions)"
748 | ]
749 | },
750 | {
751 | "cell_type": "markdown",
752 | "metadata": {},
753 | "source": [
754 | "Python также позволяет объявлять вложенные функции, что в совокупности с тем,\n",
755 | "что функция представляет собой объект, позволяет реализовывать т.н. каррирование.\n",
756 | "\n",
757 | "Говоря простым языком, это когда одна функция (например, двух аргументов) возвращает\n",
758 | "другую функцию (соответственно, одного аргумента)."
759 | ]
760 | },
761 | {
762 | "cell_type": "code",
763 | "execution_count": null,
764 | "metadata": {},
765 | "outputs": [],
766 | "source": [
767 | "def f(x):\n",
768 | " def g(y):\n",
769 | " return x + y\n",
770 | " return g\n",
771 | " \n",
772 | "add_5 = f(5)\n",
773 | "print(add_5(3))"
774 | ]
775 | },
776 | {
777 | "cell_type": "markdown",
778 | "metadata": {},
779 | "source": [
780 | "#### Декораторы (decorators)"
781 | ]
782 | },
783 | {
784 | "cell_type": "markdown",
785 | "metadata": {},
786 | "source": [
787 | "Декораторы — это функции, которые принимают на вход функцию и модифицирует или\n",
788 | "дополняет её поведение. "
789 | ]
790 | },
791 | {
792 | "cell_type": "code",
793 | "execution_count": null,
794 | "metadata": {},
795 | "outputs": [],
796 | "source": [
797 | "def add_one_more(call):\n",
798 | " def wrapper(*args, **kwargs):\n",
799 | " return call(*args, **kwargs) + 1\n",
800 | " \n",
801 | " return wrapper\n",
802 | "\n",
803 | "\n",
804 | "@add_one_more\n",
805 | "def h(x):\n",
806 | " return x + 1\n",
807 | "\n",
808 | "h(3)"
809 | ]
810 | },
811 | {
812 | "cell_type": "markdown",
813 | "metadata": {},
814 | "source": [
815 | "Например, декоратор `add_one_more` добавляет дополнительную\n",
816 | "единицу к результату вызова функции, к которой она применяется."
817 | ]
818 | },
819 | {
820 | "cell_type": "markdown",
821 | "metadata": {},
822 | "source": [
823 | "А вот пример применения декоратора в промышленном программировании"
824 | ]
825 | },
826 | {
827 | "cell_type": "markdown",
828 | "metadata": {},
829 | "source": [
830 | "todo добавить пару комментариев в блоке"
831 | ]
832 | },
833 | {
834 | "cell_type": "code",
835 | "execution_count": null,
836 | "metadata": {},
837 | "outputs": [],
838 | "source": [
839 | "def verifiable_request(call):\n",
840 | " async def wrapper(*args, **kwargs):\n",
841 | " # Получаем результат функции-аргумента декоратора.\n",
842 | " response = await call(*args, **kwargs)\n",
843 | " # Если код не соответствует нормальному ответу, то особым образом\n",
844 | " # обрабатываем это\n",
845 | " if response.status_code != status.HTTP_200_OK:\n",
846 | " logger.error(\n",
847 | " f\"Got {response.status_code} after calling to {call.__name__} (args['uuid'])\"\n",
848 | " )\n",
849 | " raise HTTPException(\n",
850 | " status.HTTP_500_INTERNAL_SERVER_ERROR,\n",
851 | " detail=\"One of a services is unavailable at the moment.\",\n",
852 | " )\n",
853 | " # Иначе возвращаем тело ответа\n",
854 | " return response.json()\n",
855 | "\n",
856 | " return wrapper"
857 | ]
858 | },
859 | {
860 | "cell_type": "code",
861 | "execution_count": null,
862 | "metadata": {},
863 | "outputs": [],
864 | "source": [
865 | "@verifiable_request\n",
866 | "async def call_scraper(uuid: UUID, request: Request):\n",
867 | "...\n",
868 | "async with httpx.AsyncClient() as client:\n",
869 | " return await client.post(url, json=body, timeout=30)"
870 | ]
871 | },
872 | {
873 | "cell_type": "markdown",
874 | "metadata": {},
875 | "source": [
876 | "Декоратор `verifiable_request` применяется к другим функциям, осуществляющим\n",
877 | "некоторый запрос по сети. Если запрос завершается успешно, он возвращает\n",
878 | "результат. \n",
879 | "\n",
880 | "Но если в результате вызова функции код ответа не 200, то декоратор бросает\n",
881 | "исключение с необходимым текстом."
882 | ]
883 | },
884 | {
885 | "cell_type": "markdown",
886 | "metadata": {},
887 | "source": [
888 | "#### Лямбда-функции и приложения (lambda-functions/lambda-expressions)"
889 | ]
890 | },
891 | {
892 | "cell_type": "markdown",
893 | "metadata": {},
894 | "source": [
895 | "Лямбда-функции — это неименованные функции. Чаще всего они применяются для\n",
896 | "описания однострочных преобразований, либо сложных, но использующихся лишь\n",
897 | "раз."
898 | ]
899 | },
900 | {
901 | "cell_type": "code",
902 | "execution_count": null,
903 | "metadata": {},
904 | "outputs": [],
905 | "source": [
906 | "three_x_plus_1 = lambda x: 3 * x + 1 \\\n",
907 | " if x % 2 == 1 else x // 2\n",
908 | "\n",
909 | "three_x_plus_1"
910 | ]
911 | },
912 | {
913 | "cell_type": "markdown",
914 | "metadata": {},
915 | "source": [
916 | "Эта функция — тоже объект, поэтому его можно сохранить в переменную, как и\n",
917 | "любую другую, и затем получить её значение от некоторого аргумента."
918 | ]
919 | },
920 | {
921 | "cell_type": "code",
922 | "execution_count": null,
923 | "metadata": {},
924 | "outputs": [],
925 | "source": [
926 | "three_x_plus_1(3)"
927 | ]
928 | },
929 | {
930 | "cell_type": "markdown",
931 | "metadata": {},
932 | "source": [
933 | "Кстати, вышеописанная функция занимает большое место в математике. С ней связана т.н.\n",
934 | "гипотеза Коллатца, которая утверждает о том, что для любого числа есть конечное число итераций из применений этой функции к её предыдущему результату снова и снова, необходимое для того, чтобы свести любое число к циклу 1-2-4.\n",
935 | "\n",
936 | "Подробнее об этой гипотезе можно [есть очень хороший видеоролик](https://www.youtube.com/watch?v=QgzBDZwanWA&ab_channel=VertDider). \n",
937 | "\n",
938 | "Давайте опишем функцию `iterate_until`, которая будет итеративно получать\n",
939 | "последующие композиции некоторой функции до тех пор, пока не будет соблюдено\n",
940 | "некоторое условие для заданного числа."
941 | ]
942 | },
943 | {
944 | "cell_type": "code",
945 | "execution_count": null,
946 | "metadata": {},
947 | "outputs": [],
948 | "source": [
949 | "def iterate_until(f, condition):\n",
950 | " def iterate(x):\n",
951 | " iterations = 0\n",
952 | " while True:\n",
953 | " x = f(x)\n",
954 | " if condition(x):\n",
955 | " return iterations\n",
956 | " iterations += 1\n",
957 | " \n",
958 | " return iterate"
959 | ]
960 | },
961 | {
962 | "cell_type": "markdown",
963 | "metadata": {},
964 | "source": [
965 | "Используя в качестве функции `three_x_plus_1` и условие `x == 1` получим\n",
966 | "процесс, который и описывается в гипотезе Коллатца."
967 | ]
968 | },
969 | {
970 | "cell_type": "code",
971 | "execution_count": null,
972 | "metadata": {},
973 | "outputs": [],
974 | "source": [
975 | "iterate_until(three_x_plus_1, lambda x: x == 1)(989345275647)"
976 | ]
977 | },
978 | {
979 | "cell_type": "markdown",
980 | "metadata": {},
981 | "source": [
982 | "Теперь мы можем посчитать, сколько итераций может понадобиться до сведения\n",
983 | "каждого числа до цикла 1-2-4. Давайте в качестве примера возьмем все числа\n",
984 | "до $10^7$."
985 | ]
986 | },
987 | {
988 | "cell_type": "code",
989 | "execution_count": null,
990 | "metadata": {},
991 | "outputs": [],
992 | "source": [
993 | "x = range(1, int(1e7))\n",
994 | "\n",
995 | "map_func = iterate_until(three_x_plus_1, lambda x: x == 1)\n",
996 | "\n",
997 | "iterations = map(map_func, x)\n",
998 | "iterations"
999 | ]
1000 | },
1001 | {
1002 | "cell_type": "markdown",
1003 | "metadata": {},
1004 | "source": [
1005 | "Лямбда-функции часто применяются вместе с встроенными функциями-генераторами. В\n",
1006 | "частности, функция `map`.\n",
1007 | "\n",
1008 | "Применяя `map` массив чисел от $1$ до $10^7$ получаем массив, где вместо чисел —\n",
1009 | "соответствующее им число итераций."
1010 | ]
1011 | },
1012 | {
1013 | "cell_type": "code",
1014 | "execution_count": null,
1015 | "metadata": {},
1016 | "outputs": [],
1017 | "source": [
1018 | "iterations = list(iterations)"
1019 | ]
1020 | },
1021 | {
1022 | "cell_type": "markdown",
1023 | "metadata": {},
1024 | "source": [
1025 | "### NumPy "
1026 | ]
1027 | },
1028 | {
1029 | "cell_type": "markdown",
1030 | "metadata": {},
1031 | "source": [
1032 | "Библиотека NumPy позволяет выполнять общие математические операции над\n",
1033 | "массивами данных.\n",
1034 | "\n",
1035 | "Библиотека использует скомпилированные на С функции. "
1036 | ]
1037 | },
1038 | {
1039 | "cell_type": "markdown",
1040 | "metadata": {},
1041 | "source": [
1042 | "Давайте посмотрим, чем нам может быть интересен NumPy."
1043 | ]
1044 | },
1045 | {
1046 | "cell_type": "code",
1047 | "execution_count": null,
1048 | "metadata": {},
1049 | "outputs": [],
1050 | "source": [
1051 | "import numpy as np"
1052 | ]
1053 | },
1054 | {
1055 | "cell_type": "markdown",
1056 | "metadata": {},
1057 | "source": [
1058 | "#### Статистика и другое"
1059 | ]
1060 | },
1061 | {
1062 | "cell_type": "markdown",
1063 | "metadata": {},
1064 | "source": [
1065 | "С помощью NumPy мы легко можем получить стандартные величины, такие как\n",
1066 | "среднее, максимальное, минимальное и другие статистические величины.\n",
1067 | "\n",
1068 | "Так, например, мы можем получить среднее число итераций, необходимых до сходимости\n",
1069 | "до 1 чисел из задачи Колллатца."
1070 | ]
1071 | },
1072 | {
1073 | "cell_type": "code",
1074 | "execution_count": null,
1075 | "metadata": {},
1076 | "outputs": [],
1077 | "source": [
1078 | "print(np.max(iterations))\n",
1079 | "print(np.mean(iterations))"
1080 | ]
1081 | },
1082 | {
1083 | "cell_type": "markdown",
1084 | "metadata": {},
1085 | "source": [
1086 | "#### Производительность"
1087 | ]
1088 | },
1089 | {
1090 | "cell_type": "markdown",
1091 | "metadata": {},
1092 | "source": [
1093 | "NumPy является высокопроизводительным модулем, и это достаточно легко\n",
1094 | "продемонстрировать наглядно.\n",
1095 | "\n",
1096 | "Давайте для примера перемножим два вектора размера $10^7$."
1097 | ]
1098 | },
1099 | {
1100 | "cell_type": "code",
1101 | "execution_count": null,
1102 | "metadata": {},
1103 | "outputs": [],
1104 | "source": [
1105 | "import random\n",
1106 | "\n",
1107 | "a = [random.randint(1, 100) for _ in range(int(1e7))]\n",
1108 | "b = [random.randint(1, 100) for _ in range(int(1e7))]"
1109 | ]
1110 | },
1111 | {
1112 | "cell_type": "markdown",
1113 | "metadata": {},
1114 | "source": [
1115 | "##### Векторизация"
1116 | ]
1117 | },
1118 | {
1119 | "cell_type": "code",
1120 | "execution_count": null,
1121 | "metadata": {},
1122 | "outputs": [],
1123 | "source": [
1124 | "%timeit -n 10 [a_i * b_i for a_i, b_i in zip(a, b)]"
1125 | ]
1126 | },
1127 | {
1128 | "cell_type": "code",
1129 | "execution_count": null,
1130 | "metadata": {},
1131 | "outputs": [],
1132 | "source": [
1133 | "a_np = np.array(a, dtype=np.int16)\n",
1134 | "b_np = np.array(b)"
1135 | ]
1136 | },
1137 | {
1138 | "cell_type": "code",
1139 | "execution_count": null,
1140 | "metadata": {},
1141 | "outputs": [],
1142 | "source": [
1143 | "%timeit -n 10 a_np * b_np"
1144 | ]
1145 | },
1146 | {
1147 | "cell_type": "markdown",
1148 | "metadata": {},
1149 | "source": [
1150 | "#### Экономия памяти"
1151 | ]
1152 | },
1153 | {
1154 | "cell_type": "code",
1155 | "execution_count": null,
1156 | "metadata": {},
1157 | "outputs": [],
1158 | "source": [
1159 | "import sys\n",
1160 | "\n",
1161 | "sys.getsizeof(a)"
1162 | ]
1163 | },
1164 | {
1165 | "cell_type": "code",
1166 | "execution_count": null,
1167 | "metadata": {},
1168 | "outputs": [],
1169 | "source": [
1170 | "sys.getsizeof(a_np)"
1171 | ]
1172 | },
1173 | {
1174 | "cell_type": "markdown",
1175 | "metadata": {},
1176 | "source": [
1177 | "#### Удобство"
1178 | ]
1179 | },
1180 | {
1181 | "cell_type": "markdown",
1182 | "metadata": {},
1183 | "source": [
1184 | "Скалярные, векторные и матричные операции (scalar, vector and matrix operations)"
1185 | ]
1186 | },
1187 | {
1188 | "cell_type": "code",
1189 | "execution_count": null,
1190 | "metadata": {},
1191 | "outputs": [],
1192 | "source": [
1193 | "x = np.array([1, 2, 3])\n",
1194 | "mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
1195 | "\n",
1196 | "print(x + 1)\n",
1197 | "print(x * 3)\n",
1198 | "print(x + x)"
1199 | ]
1200 | },
1201 | {
1202 | "cell_type": "markdown",
1203 | "metadata": {},
1204 | "source": [
1205 | "Манипуляции с представлением данных"
1206 | ]
1207 | },
1208 | {
1209 | "cell_type": "code",
1210 | "execution_count": null,
1211 | "metadata": {},
1212 | "outputs": [],
1213 | "source": [
1214 | "print(mat.reshape(3, 3))\n",
1215 | "print(mat.reshape(-1, 1))"
1216 | ]
1217 | },
1218 | {
1219 | "cell_type": "markdown",
1220 | "metadata": {},
1221 | "source": [
1222 | "Операции из линейной алгебры"
1223 | ]
1224 | },
1225 | {
1226 | "cell_type": "code",
1227 | "execution_count": null,
1228 | "metadata": {},
1229 | "outputs": [],
1230 | "source": [
1231 | "# Transposing\n",
1232 | "\n",
1233 | "print(mat.T)\n",
1234 | "print(np.linalg.inv(mat))"
1235 | ]
1236 | },
1237 | {
1238 | "cell_type": "markdown",
1239 | "metadata": {},
1240 | "source": [
1241 | "#### Практическое задание #1 (min-max нормализация)"
1242 | ]
1243 | },
1244 | {
1245 | "cell_type": "markdown",
1246 | "metadata": {},
1247 | "source": [
1248 | "Дан список чисел. \n",
1249 | "\n",
1250 | "Необходимо:\n",
1251 | "1. преобразовать его к массиву NumPy\n",
1252 | "2. вычислить максимальное и минимальное значение массива\n",
1253 | "3. изменить каждое значение $x_i$ массива по формуле \n",
1254 | "\n",
1255 | "\\begin{equation}\n",
1256 | "x_i = \\frac{x_i - min}{max - min}\n",
1257 | "\\end{equation}\n",
1258 | "\n",
1259 | "для этого необходимо использовать `np.vectorize`, аргументом которой объявить\n",
1260 | "лямбда-функцию, описывающую формулу (1)."
1261 | ]
1262 | },
1263 | {
1264 | "cell_type": "markdown",
1265 | "metadata": {},
1266 | "source": [
1267 | "#### Практическое задание #2 (Гипотеза NumPy-Коллатца)\n",
1268 | "\n",
1269 | "Ранее была описана гипотеза Коллатца. Выполните аналогичные ранее действия, используя `np.array` и операции NumPy вместо обычных.\n",
1270 | "\n",
1271 | "Оцените вклад NumPy в производительность такого решения. Попытайтесь объяснить себе, почему был получен именно такой результат и поделитесь ответом с кем-то из организаторов Клуба, нам ведь интересно :)"
1272 | ]
1273 | },
1274 | {
1275 | "cell_type": "markdown",
1276 | "metadata": {},
1277 | "source": [
1278 | "#### Практическое задание #3 (факультатив)\n",
1279 | "\n",
1280 | "Mojo — это новый язык программирования, который создан специально для ML и призван решить одну из главных проблем в Python, а именно его плохую производительность.\n",
1281 | "\n",
1282 | "[Здесь](https://gist.github.com/eugeneyan/1d2ea70fed81662271f784034cc30b73) приведен сравнение производительности для нагруженных матричными и векторными операциями задач. \n",
1283 | "\n",
1284 | "Конечно, он не совсем справедлив, поскольку в среднем выигрыш будет не настолько велик, но тем не менее связанные с машинным обучением операции потенциально могут работать в сотни и тысячи раз быстрее.\n",
1285 | "\n",
1286 | "\n",
1287 | "В качестве факультативного задания можно ознакомиться с основами этого языка в [этом видео](https://www.youtube.com/watch?v=5Sm9IVMet9c&t=6771s&ab_channel=freeCodeCamp.org)."
1288 | ]
1289 | },
1290 | {
1291 | "cell_type": "markdown",
1292 | "metadata": {},
1293 | "source": []
1294 | }
1295 | ],
1296 | "metadata": {
1297 | "kernelspec": {
1298 | "display_name": "Python 3",
1299 | "language": "python",
1300 | "name": "python3"
1301 | },
1302 | "language_info": {
1303 | "codemirror_mode": {
1304 | "name": "ipython",
1305 | "version": 3
1306 | },
1307 | "file_extension": ".py",
1308 | "mimetype": "text/x-python",
1309 | "name": "python",
1310 | "nbconvert_exporter": "python",
1311 | "pygments_lexer": "ipython3",
1312 | "version": "3.11.5"
1313 | }
1314 | },
1315 | "nbformat": 4,
1316 | "nbformat_minor": 2
1317 | }
1318 |
--------------------------------------------------------------------------------
/2023-2024/fall/lesson2/pics/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson2/pics/0.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson2/pics/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson2/pics/1.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson2/pics/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson2/pics/2.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson3/pics/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson3/pics/1.jpg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson3/pics/2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson3/pics/2.jpeg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson3/pics/3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson3/pics/3.jpeg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/balls/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/balls/1.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/balls/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/balls/2.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/balls/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/balls/3.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/balls/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/balls/4.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/balls/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/balls/5.png
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/book.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/book.jpeg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/cat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/cat.jpg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/pics/tree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dsc-sgu/ml-course/33b59e73d2cefa24e6566d21ce5d2bc3497a05c3/2023-2024/fall/lesson4/pics/tree.jpg
--------------------------------------------------------------------------------
/2023-2024/fall/lesson4/small_tree.dot:
--------------------------------------------------------------------------------
1 | digraph Tree {
2 | node [shape=box, style="filled", color="black", fontname="helvetica"] ;
3 | edge [fontname="helvetica"] ;
4 | 0 [label="x1 <= 1.103\nentropy = 1.0\nsamples = 200\nvalue = [100, 100]", fillcolor="#ffffff"] ;
5 | 1 [label="x2 <= 1.325\nentropy = 0.657\nsamples = 106\nvalue = [88, 18]", fillcolor="#ea9b61"] ;
6 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
7 | 2 [label="x2 <= 0.447\nentropy = 0.276\nsamples = 84\nvalue = [80, 4]", fillcolor="#e68743"] ;
8 | 1 -> 2 ;
9 | 3 [label="entropy = 0.0\nsamples = 57\nvalue = [57, 0]", fillcolor="#e58139"] ;
10 | 2 -> 3 ;
11 | 4 [label="x1 <= 0.554\nentropy = 0.605\nsamples = 27\nvalue = [23, 4]", fillcolor="#ea975b"] ;
12 | 2 -> 4 ;
13 | 5 [label="entropy = 0.286\nsamples = 20\nvalue = [19, 1]", fillcolor="#e68843"] ;
14 | 4 -> 5 ;
15 | 6 [label="entropy = 0.985\nsamples = 7\nvalue = [4, 3]", fillcolor="#f8e0ce"] ;
16 | 4 -> 6 ;
17 | 7 [label="x1 <= -0.346\nentropy = 0.946\nsamples = 22\nvalue = [8, 14]", fillcolor="#aad5f4"] ;
18 | 1 -> 7 ;
19 | 8 [label="entropy = 0.0\nsamples = 4\nvalue = [4, 0]", fillcolor="#e58139"] ;
20 | 7 -> 8 ;
21 | 9 [label="x2 <= 2.253\nentropy = 0.764\nsamples = 18\nvalue = [4, 14]", fillcolor="#72b9ec"] ;
22 | 7 -> 9 ;
23 | 10 [label="entropy = 0.971\nsamples = 10\nvalue = [4, 6]", fillcolor="#bddef6"] ;
24 | 9 -> 10 ;
25 | 11 [label="entropy = 0.0\nsamples = 8\nvalue = [0, 8]", fillcolor="#399de5"] ;
26 | 9 -> 11 ;
27 | 12 [label="x2 <= 0.992\nentropy = 0.551\nsamples = 94\nvalue = [12, 82]", fillcolor="#56abe9"] ;
28 | 0 -> 12 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;
29 | 13 [label="x1 <= 2.291\nentropy = 0.996\nsamples = 26\nvalue = [12, 14]", fillcolor="#e3f1fb"] ;
30 | 12 -> 13 ;
31 | 14 [label="x2 <= -0.31\nentropy = 0.971\nsamples = 20\nvalue = [12, 8]", fillcolor="#f6d5bd"] ;
32 | 13 -> 14 ;
33 | 15 [label="entropy = 0.0\nsamples = 4\nvalue = [4, 0]", fillcolor="#e58139"] ;
34 | 14 -> 15 ;
35 | 16 [label="entropy = 1.0\nsamples = 16\nvalue = [8, 8]", fillcolor="#ffffff"] ;
36 | 14 -> 16 ;
37 | 17 [label="entropy = 0.0\nsamples = 6\nvalue = [0, 6]", fillcolor="#399de5"] ;
38 | 13 -> 17 ;
39 | 18 [label="entropy = 0.0\nsamples = 68\nvalue = [0, 68]", fillcolor="#399de5"] ;
40 | 12 -> 18 ;
41 | }
--------------------------------------------------------------------------------