├── .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 | } --------------------------------------------------------------------------------