{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Машинное обучение на матфаке, 2020/2021 уч. год.\n", "\n", "## Практическое домашнее задание 1: numpy, pandas, matplotlib.\n", "\n", "В этом домашнем задании вам предстоит закрепить навыки работы с важнейшими для datascience-библиотеками — numpy, pandas и matplotlib.\n", "\n", "**Внимание!** Часть заданий необходимо сдать в [Яндекс.контест](https://contest.yandex.ru/contest/24321)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 1. numpy\n", "\n", "Задания 1-10 оцениваются в 0.4 баллов." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 1__. Создайте несколько одномерных массивов размера $10^n$ для n от 1 до 6. из случайных чисел при помощи модуля `np.random`. Заполните их независимыми случайными величинами из нормального распределения с матожиданием 5 и дисперсией 10. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В заданиях 2-10 запрещается использование циклов `for` и `while` в сдаваемом вами коде. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 2__. Сгенерируйте случайный вектор (одномерный массив) из нормального распределения со средним в нуле и произвольной дисперсией. С помощью `np.where` замените в созданном массиве все отрицательные элементы на нули." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 3__. Дан массив 10х3, который будет использован как массив с цветами RGB (каждый канал обозначается целым числом от 0 до 255), однако вследствие порчи данных при передаче значения массива вышли за границы заданного диапазона. Напишите функцию `clip_values`, которая вышедшие за границу диапазона значения превращает в ближашие границы диапазона.\n", "\n", "__Хинт__: это можно сделать, дважды используя `np.where`, но вообще есть специальная функция `np.clip` ровно на такой случай." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def clip_values(image: np.ndarray) -> np.ndarray:\n", " ### YOUR CODE\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 4__. Сгенерируйте случайный вектор из нормального распределения со средним в нуле и произвольной дисперсией. С помощью `np.insert` в встаьте в него на четные индексы нули." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 5__. Создайте случайный массиив размера 4х4 из нормального распределения со средним в нуле и произвольной дисперсией и верните индексы положительных элементов (`np.argwhere`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 6__. Создайте матрицу случайных целых чисел от в интервале от 1 до 10 размера 5х5 и посчитайте следующее (сабмодуль `np.linalg`):\n", "\n", "- определитель матрицы\n", "- обратную матрицу\n", "- произведение матрицы на саму себя\n", "- собственные вектора\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Задания 7-10 необходимо сдать в [Яндекс.контест](https://contest.yandex.ru/contest/16930/problems/) и прикрепить ссылку на решение в формате `https://contest.yandex.ru/contest/xxxxx/run-report/xxxxx/`. Сдавайте задания строго в соответствии с написанной сигнатурой и возвращаемыми типами. Для сдачи необходимо отправить в соответствующую задачу файл, содержащий функции и необходимые импорты. Обратите внимание, что вам доступен только `numpy`. При сдаче выберите компилятор make2. __При отсутствии ссылки на решение задание засчитано не будет!__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 7__. Напишите функцию, которая находит сумму квадратов положительных элементов одномерного массива. https://contest.yandex.ru/contest/16930/problems/A/\n", "\n", "__Ссылка на посылку в контесте__:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_squares(a: np.ndarray) -> float:\n", " ### YOUR CODE\n", " pass\n", "\n", "assert get_squares(np.array([1,-2,3])) == 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 8__. Коля — мастер покера и умеет выигрывать только целые суммы денег от 0 до $n - 1$. Коля решил сыграть на турнире. На вход подаётся массив `p` размера $n$, где `p[i]` -- вероятность, что Коля выиграет на турнире $i$ рублей ($\\sum_{i=1}^{n}p_i =1$, $p_i \\geqslant 0, \\forall i$). Посчитайте математическое ожидание выигрыша Коли на турнире.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/B/\n", "\n", "__Ссылка на посылку в контесте__:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def expected_reward(p: np.ndarray) -> float:\n", " ### YOUR CODE\n", " pass\n", "\n", "assert expected_reward(np.array([0.4, 0.5, 0.1])) == 0.7" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 9__. Дана квадратная матрица `A`. Посчитайте произведение диагональных элементов матрицы, __строго__ превосходящих среднее значение элементов всей матрицы.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/C/\n", "\n", "__Хинт__: взять диагональ матрицы — `np.diag()`, произведение элементов массива — `np.prod()`, среднее значение в массиве — `np.mean()`.\n", "\n", "__Ссылка на посылку в контесте__:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def prod_upper_avg_diagonal(a: np.ndarray) -> float:\n", " # YOUR CODE\n", "\n", "assert prod_upper_avg_diagonal(np.array([[ 0, 1, 2, 3],\n", " [ 4, 5, 6, 7],\n", " [ 8, 9, 10, 11],\n", " [12, 13, 14, 15]])) == 150" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 10__. Дано число $n$. Создайте матрицу $A$ размера $n \\times n$ такую, что $A[i][j] = i \\cdot j$. Нумерация строк и столбцов начинается с нуля.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/D/\n", "\n", "__Ссылка на посылку в контесте:__" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def create_ij(n: int) -> np.ndarray:\n", " ### YOUR CODE\n", "\n", "assert np.all(create_ij(5) == np.array([[ 0, 0, 0, 0, 0],\n", " [ 0, 1, 2, 3, 4],\n", " [ 0, 2, 4, 6, 8],\n", " [ 0, 3, 6, 9, 12],\n", " [ 0, 4, 8, 12, 16]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 2. Numpy vs pure python\n", "\n", "\n", "__Задание 11__. (1 балл) Выберите 5 функций из заданий 3 и 7-10 и имплементируйте их, но без использования сторонних библиотек (считайте, что вам доступны только стандартные библиотеки языка Питон и на вход вместо массивов подаются питоновские списки)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 12__. (3 балла) Сравните время работы векторизованных функций с обычными. Для этого постройте графики зависимости времени исполнения функции от размера входного массива. Перебирайте значения от 1 до $10^6$ по логарифмической шкале. Сделайте выводы.\n", "\n", "__Графики должны быть опрятными!__. Подписывайте оси, и единицы измерения, указывайте легенду и название графика. Оценка за задание с неопрятными графиками может быть снижена! Сравнение плохого и хорошего графиков:\n", "\n", "![](https://files.catbox.moe/gtteab.png)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Хинт__: воспользуйтесь библиотекой `time` или мэджиком `%timeit`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Вывод__:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 3. Pandas.\n", "\n", "Задания 13-22 оцениваются в 0.4 баллов. В заданиях 13-22 запрещается пользоваться циклами `for` и `while` в сдаваемом вами коде. Задания 13-15 также сдаются в контест с компилятором python3.6+numpy+pandas. В конце сдаваемого вами файла должны быть строки\n", "```\n", "import sys\n", "exec(sys.stdin.read())\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 13__, Дан датафрейм, в котором существует колонка `'email'` (строка, длиной не более 255). Напишите функцию, которая в заданном датафрейме заменяет все невалидные email'ы на \"unknown@unknown.com\". Валидным сичтается емэйл, выглядящий как `[name]@[subdomain].[domain]`, где `[name]` -- строка, содержащая латинские буквы, цифры, точки и знаки `-` и `_`, `[subdomain]` и `[domain]` -- строки, содержащие только латинские буквы и цифры. Длина строки `[domain]` -- не больше 8 символов.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/E/\n", "\n", "__Хинт__. Вопспользуйтесь методом `.apply()`, в который передайте функцию для обрабоки одного email'a. Подробнее см. [здесь](https://github.com/ischurov/math-ml-2021-public/blob/main/seminars/note-on-apply.ipynb). Можно использовать регулярные выражения, хотя можно обойтись и без них.\n", "\n", "\n", "__Ссылка на посылку в контесте:__" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "def reset_emails(df: pd.DataFrame) -> pd.DataFrame:\n", " ### YOUR CODE\n", " pass\n", "\n", "import sys\n", "exec(sys.stdin.read())" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from pandas.testing import assert_frame_equal\n", "import pandas as pd\n", "\n", "assert_frame_equal(\n", " reset_emails(\n", " pd.DataFrame(\n", " dict(\n", " email=[\"ab12@cd.example\", \"ab@ab@ab\", \"hello\", \"this@is.mynewcooldomain\"],\n", " name=[\"Alice\", \"Bob\", \"Claudia\", \"Dan\"],\n", " )\n", " )\n", " ),\n", " pd.DataFrame(\n", " dict(\n", " email=[\n", " \"ab12@cd.example\",\n", " \"unknown@unknown.com\",\n", " \"unknown@unknown.com\",\n", " \"unknown@unknown.com\",\n", " ],\n", " name=[\"Alice\", \"Bob\", \"Claudia\", \"Dan\"],\n", " )\n", " ),\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 14__. Дан датафрейм, в котором существуют колонки `'age'` (возраст в годах, целое число) и `'income'` (число с плавающей точкой). Напишите функцию, которая вернёт средний заработок людей младше 18 лет.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/F/\n", "\n", "__Ссылка на посылку в контесте:__" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_mean_income(df: pd.DataFrame) -> float:\n", " ### YOUR CODE\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 15__. Дан датафрейм, в котором существуют колонки `'id'` (идентификатор пользователя, целое положительное число), `'age'` (возвраст в годах, целое число), `'sex'` (пол пользователя, строка, равная либо `\"Male\"`, либо `\"Female\"`, либо `\"Other\"`), `\"favorite_color\"` (любимый цвет пользователя, строка длиной не более 255). Найдите число различных любимых цветов у женщин младше 18 лет.\n", "\n", "https://contest.yandex.ru/contest/16930/problems/G/\n", "\n", "__Ссылка на посылку в контесте__:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_fav_color(df: pd.DataFrame) -> int:\n", " ### YOUR CODE\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 4. EDA with pandas.\n", "\n", "В этом задании предлагается сделать разведочный анализ данных в датафрейме. \n", "\n", "Мы будем работать с датасетом русскоязычных твитов. Скачайте данные по ссылке: https://www.dropbox.com/s/ou55qwyhbj1pdav/tweets.csv?dl=1\n", "\n", "Корпус состоит из 12 столбцов:\n", "\n", "\n", "- `id`: уникальный номер сообщения в системе twitter;\n", "- `tdate`: дата публикации сообщения (твита);\n", "- `tmane`: имя пользователя, опубликовавшего сообщение;\n", "- `ttext`: текст сообщения (твита);\n", "- `ttype`: тональность твита (положительная (1) или отрицательная (-1));\n", "- `trep`: количество реплаев к данному сообщению. В настоящий момент API твиттера не отдает эту информацию;\n", "- `tfav`: число сколько раз данное сообщение было добавлено в избранное другими пользователями;\n", "- `tstcount`: число всех сообщений пользователя в сети twitter;\n", "- `tfol`: количество фолловеров пользователя (тех людей, которые читают пользователя);\n", "- `tfrien`: количество друзей пользователя (те люди, которых читает пользователь);\n", "- `listcount`: количество листов-подписок в которые добавлен твиттер-пользователь.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# For linux/google colab users -- download directly from the notebook\n", "! wget -O tweets.csv \"https://www.dropbox.com/s/ou55qwyhbj1pdav/tweets.csv?dl=1\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = pd.read_csv(\"./tweets.csv\")\n", "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 16__. Создайте колонку `'tdif'`, равную разнице числа друзей и числа фолловеров у пользователя." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 16__. Создайте датафрейм, в котором остались только строки с чётными номерами, и пронумеруйте их начиная с 0." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 17__. Создайте датафрейм, в котором остались лишь твиты положительной тональности." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 18__. Посчитайте число уникальных пользователей (пользователей с различными `tmane`).\n", "\n", "__Хинт__: воспользуйтесь `np.unique`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 19__. Посчитайте основные статистики по числу подписчиков (фолловеров) при помощи метода `.describe()`. Постройте гистограмму значений признака." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 20__. Посчитайте число ретвитов в датасете (твитов, начинающихся с \"RT @\")." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 21__. Назовём длинными такой твит, что все более короткие твиты составляют по меньшей мере 80% от всего датасета. Найдите число длинных твитов." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 22__. Постройте столбчатую диаграмму (или гистограмму) распределения числа твитов по месяцам. В какой месяц какого года было опубликовано больше всего твитов?\n", "\n", "__Хинт__: Время в колонке `tdate` — это Unix time, и оно отображает то, сколько секунд прошло с 00:00:00 1 января 1970 года. Для конвертации этого времени в удобный формат воспользуйтесь библиотекой `datetime`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### YOUR CODE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 998__. Вставьте ниже смешную картинку, желательно про машинное обучение." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Задание 999__. Напишите ниже, чего вы ждёте от курса, какой формат лекций и семинаров вам более интересен, а также произвольные пожелания и предложения. Мы постараемся всё это учесть. " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.10" } }, "nbformat": 4, "nbformat_minor": 2 }