#!/usr/bin/env python # coding: utf-8 # # Машинное обучение на факультете математики # ## НИУ ВШЭ, 2018-19 учебный год # ### Домашнее задание №2 # [Страница курса](http://wiki.cs.hse.ru/%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_%D0%BC%D0%B0%D1%82%D1%84%D0%B0%D0%BA%D0%B5_2018/2019) # Задание выполнил(а): _(впишите свои фамилию и имя)_ # __Внимание!__ Домашнее задание выполняется самостоятельно. При попытке сдать хотя бы частично списанный текст, или текст, полученный в результате совместного решения задач, вся работа будет оценена на 0 баллов. Мы также уведомим администрацию факультета и попросим применить дисциплинарное взыскание (предупреждение, выговор, отчисление) ко всем вовлеченным студентам. # В данном домашнем задании вы попрактикуетесь в работе с библиотеками numpy, pandas и matplotlib, а при желании сможете поучаствовать в настоящем соревновании по машинному обучению! # # Обратите внимание, что многие задания сопровождаются функциями, которые могут пригодиться при их решении. Это всего лишь подсказка, а не требование — необязательно использовать все эти функции для решения или вообще использовать какие-либо из них. # # ## Схема оценивания # # Каждая задача оценивается в 1 балл, за бонусную часть можно получить 3 балла. # # Оценка за ДЗ вычисляется по следующей формуле: # # $$ # \min(6, s_{\text{numpy}}, s_{\text{pandas}} + s_{\text{bonus}}) \times 10 / 6, # $$ # # где $s_{\text{numpy}}$, $s_{\text{pandas}}$, $s_{\text{bonus}}$ — количество баллов, которые вы набрали за соответствующую часть. Задач больше, чем необходимо сделать для получения полного балла за ДЗ — вы можете сделать те, которые вам больше нравятся, или сделать все, чтобы дополнительно потренироваться. # ## Часть 1. Numpy # In[ ]: import numpy as np # Во всех задачах необходимо написать код решения внутри функции и проверить его работу, вызвав функцию для данных из условия. # # При решении задач запрещается использовать циклы (`for`, `while`) и оператор `if`. # # Везде, где встречаются массивы или матрицы, подразумевается, что это `numpy.array`. # ### 1 # Напишите функцию, возвращающую округленную взвешенную сумму оценок по данным оценкам и весам. Можете посчитать свою оценку за курс :) В нашем случае вес экзамена равен 0.3, вес домашек - 0.406, а вес кр - 0.294. Например, если за домашки у вас 10, за кр 8, а за экзамен - 6, то вы получите отличную оценку 8! # # _Функции, которые могут пригодиться при решении: `.around()`, `.sum()`. Помните, что арифметические операции с массивами выполняются поэлементно._ # In[ ]: def result_mark(weights, marks): # your code here # In[ ]: result_mark(np.array([0.3, 0.406, 0.294]), np.array([6, 10, 8])) # ### 2 # Напишите функцию, меняющую все четные значения массива целых чисел на заданное число. Например, если на вход поступает массив `array([3, 5, 1, 0, -3, 22, 213436])` и число `-111`, то на выходе должен получиться массив `array([ 3, 5, 1, -111, -3, -111, -111])`. # In[ ]: def change_array(array, number): # your code here # In[ ]: change_array(np.array([3, 5, 1, 0, -3, 22, 213436]), -111) # ### 3 # Напишите функцию, вычисляющую самое близкое и самое дальнее числа к данному в рассматриваемом массиве чисел. Например, если на вход поступают массив `array([0, 1, 2, 3, 4])` и число 1.33, то ответом будет `(1, 4)`. # # _Функции, которые могут пригодиться при решении: `.abs()`, `.argmax()`, `.argmin()`_ # In[ ]: def closest_value(array, value): # your code here # In[ ]: closest_value(np.array([0, 1, 2, 3, 4]), 1.33) # ### 4 # Напишите функцию, создающую массив первых n нечетных чисел, записанных в порядке убывания. Например, если `n=5`, то ответом будет `array([9, 7, 5, 3, 1])`. # # *Функции, которые могут пригодиться при решении: `.arange()`* # In[ ]: def first_odds(n): # your code here # In[ ]: first_odds(5) # ### 5 # Напишите функцию, вычисляющую произведение всех ненулевых диагональных элементов на диагонали данной квадратной матрицы. Например, если на вход поступает матрица # $$ # \begin{pmatrix} # 0 & 1 & 2\\ # 3 & 4 & 5\\ # 6 & 7 & 8\\ # \end{pmatrix}, # $$ # то ответом будет 32. # # _Функции, которые могут пригодиться при решении: `.diagonal()`, `.prod()`_ # In[ ]: def diag_prod(matrix): # your code here # In[ ]: diag_prod(np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])) # ### 6 # Для улучшения качества работы некоторых алгоритмов машинного обучения может быть полезно использовать [нормализацию данных](https://vk.cc/8xmfQk), чтобы привести признаки в выборке к одному масштабу — а именно, из каждого столбца вычесть среднее его значений и поделить на их стандартное отклонение. Напишите функцию, нормализующую входящую матрицу (по столбцам). Например, если на вход подается матрица # $$ # \begin{pmatrix} # 1 & 4 & 4200\\ # 0 & 10 & 5000\\ # 1 & 2 & 1000\\ # \end{pmatrix}, # $$ # то результатом с точностью до сотых будет матрица # $$ # \begin{pmatrix} # 0.71 & -0.39 & 0.46\\ # -1.41 & 1.37 & 0.93\\ # 0.71 & -0.98 & -1.39\\ # \end{pmatrix} # $$ # Учтите, что в вашей матрице не должно получаться никаких nan. Подумайте, в каком случае они могут возникнуть и как обойти эту проблему. # # _Подсказка. Казалось бы, при чем здесь деление на ноль._ # # _Функции, которые могут пригодиться при решении: `.mean()`, `.std()`. Ещё полезно понимать, как работают [broadcasting rules](https://docs.scipy.org/doc/numpy-1.15.0/user/basics.broadcasting.html). Например, что будет, если к матрице с 3 строками и 2 столбцами прибавить вектор из двух элементов?_ # In[ ]: def normalize(matrix): # your code here # In[ ]: normalize(np.array([[1, 4, 4200], [0, 10, 5000], [1, 2, 1000]])) # ### 7 # Напишите функцию, вычисляющую какую-нибудь первообразную данного полинома (в качестве константы возьмите ваше любимое число). Например, если на вход поступает массив коэффициентов `array([4, 6, 0, 1])`, что соответствует полиному $4x^3 + 6x^2 + 1$, на выходе получается массив коэффициентов `array([1, 2, 0, 1, -2])`, соответствующий полиному $x^4 + 2x^3 + x - 2$. # # _Функции, которые могут пригодиться при решении: `.append()`_ # In[ ]: def antiderivative(coefs): # your code here # In[ ]: antiderivative(np.array([4, 6, 0, 1])) # ### 8 # Напишите функцию, делающую данную [треугольную матрицу](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B0) симметричной. Например, если на вход поступает матрица # $$ # \begin{pmatrix} # 1 & 2 & 3 & 4\\ # 0 & 5 & 6 & 7\\ # 0 & 0 & 8 & 9\\ # 0 & 0 & 0 & 10\\ # \end{pmatrix}, # $$ # то на выходе должна быть матрица # $$ # \begin{pmatrix} # 1 & 2 & 3 & 4\\ # 2 & 5 & 6 & 7\\ # 3 & 6 & 8 & 9\\ # 4 & 7 & 9 & 10\\ # \end{pmatrix}. # $$ # # _Функции, которые могут пригодиться при решении: `.diag()`, `.diagonal()`, `.T`_ # In[ ]: def make_symmetric(matrix): # your code here # In[ ]: make_symmetric(np.array([[1, 2, 3, 4], [0, 5, 6, 7], [0, 0, 8, 9], [0, 0, 0, 10]])) # ### 9 # Напишите функцию, создающую прямоугольную матрицу из m одинаковых строк, заполненных последовательными натуральными числами от a до b включительно в возрастающем порядке. Например, если m = 5, a = 3, b = 10, то на выходе будет матрица # $$ # \begin{pmatrix} # 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ # 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ # 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ # 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ # 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ # \end{pmatrix} # $$ # # _Функции, которые могут пригодиться при решении: `.arange()`, `.zeros()`, а также [broadcasting rules](https://docs.scipy.org/doc/numpy-1.15.0/user/basics.broadcasting.html)._ # In[ ]: def construct_matrix(m, a, b): # your code here # In[ ]: construct_matrix(5, 3, 10) # ### 10 # Напишите функцию, вычисляющую [косинусную близость](https://en.wikipedia.org/wiki/Cosine_similarity) двух векторов. Например, если на вход поступают вектора `array([-2, 1, 0, -5, 4, 3, -3])` и `array([0, 2, -2, 10, 6, 0, 0])`, ответом будет -0.25. # # _Функции, которые могут пригодиться при решении: `.dot()`, `.norm()`, `.sum()`_ # In[ ]: def cosine_similarity(vec1, vec2): # your code here # In[ ]: cosine_similarity(np.array([-2, 1, 0, -5, 4, 3, -3]), np.array([0, 2, -2, 10, 6, 0, 0])) # ## Часть 2. Pandas и Matplotlib # In[ ]: import matplotlib.pyplot as plt import pandas as pd get_ipython().run_line_magic('matplotlib', 'inline') # В этой части домашнего задания вы поработаете с данными о пассажирах с затонувшего «Титаника». Описание данных: # # https://www.kaggle.com/c/titanic/data # # Каждый построенный график необходимо красиво оформить - для этого требуется как минимум указать его название, а также отметить, что изображено по каждой из осей. # # *Функции, которые могут пригодиться при оформлении графиков: `.show()`, `.title()`, `.xlabel()`, `.ylabel()`* # ### 11 # Откройте в ноутбуке файл с данными ("titanic-train.csv"). Какой размер имеет таблица? Выведите первые 5 и последние 5 строк. # # *Функции, которые могут пригодиться при решении: .head(), .read_csv(), .tail()* # In[ ]: # your code here # ### 12 # Для каждого из признаков укажите его тип (вещественый, целый, категориальный, другое). Придумайте три задачи, которые можно было бы решать для данного датасета — задачу регрессии, задачу классификации и задачу кластеризации. # ### 13 # Какова доля выживших после крушения пассажиров? Какова доля мужчин и женщин среди выживших? # In[ ]: # your code here # ### 14 # Сколько пассажиров ехало в каждом классе? Кого было больше в самом многолюдном классе — мужчин или женщин? # # *Функции, которые могут пригодиться при решении: `.value_counts()`* # In[ ]: # your code here # ### 15 # Выведите минимальную, среднюю и максимальную сумму, которую заплатили пассажиры за проезд. Проделайте то же самое только для тех пассажиров, которые сели на корабль в Саутгемптоне. Выведите гистограммы, показывающие распределения стоимостей билетов в зависимости от места посадки. # # _Функции, которые могут пригодиться при решении: `.hist()`, `.max()`, `.mean()`, `.median()`, `.min()`_ # In[ ]: # your code here # ### 16 # Все ли признаки несут в себе полезную информацию? Почему? Избавьтесь от ненужных столбцов. # # *Функции, которые могут пригодиться при решении: `.drop()` (обратите внимание на параметры `axis` и `inplace`)* # In[ ]: # your code here # ### 17 # Есть ли в данных пропуски? Если да, то в каких столбцах? Сколько пропусков в каждом из них? # # *Функции, которые могут пригодиться при решении: `.any()`, `.isnull()`, `.sum()`* # In[ ]: # your code here # ### 18 # Подумайте, как стоит заполнить пропуски в каждом столбце в зависимости от его типа, и сделайте это. Проверьте, что пропусков нигде не осталось. # # *Функции, которые могут пригодиться при решении: `.any()`, `.fillna()` (обратите внимание на параметр `inplace`), `.isnull()`, `.mean()`, `.median()`, `.mode()`* # In[ ]: # your code here # ### 19 # Посчитайте, насколько сильно коррелируют друг с другом цена за билет и возраст пассажиров. Также проверьте наличие этой зависимости визуально (в этом вам поможет построение [диаграммы рассеяния](https://ru.wikipedia.org/wiki/%D0%94%D0%B8%D0%B0%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0_%D1%80%D0%B0%D1%81%D1%81%D0%B5%D1%8F%D0%BD%D0%B8%D1%8F)). # # *Функции, которые могут пригодиться при решении: `.corr()`, `.scatter()`* # In[ ]: # your code here # ### 20 # Правда ли, что чаще выживали пассажиры с более дорогими билетами? А есть ли зависимость выживаемости от класса? # # *Функции, которые могут пригодиться при решении: `.groupby()`, `.mean()`* # In[ ]: # your code here # ### 21 # Создание новых признаков (feature engineering) является одним из основных средств улучшения качества работы алгоритмов машинного обучения на этапе обработки данных. Добавьте в таблицу столбец, который будет показывать, сколько родных плыло вместе с пассажиром на корабле, включая его самого. Затем придумайте свой признак, который может быть полезен для алгоритма (несет в себе какую-то информацию), и добавьте его в таблицу. # In[ ]: # your code here # ### 22 # Придумайте какое-нибудь интересное задание на анализ предлагаемых данных и решите его. Например, какая фамилия была самой популярной на корабле? # # *Функции, которые могут пригодиться при решении данного конкретного задания: `.idxmax()`, `.split()`, `.str`, `.value_counts()`* # In[ ]: # your code here # ### 23 # Постройте гистограммы распределения вещественных признаков. Есть ли в них разница? Чем это может быть плохо с точки зрения машинного обучения? Отнормируйте вещественные признаки и посмотрите, как изменилась ситуация. # # *Функции, которые могут пригодиться при решении: `.hist()`, `.mean()`, `.std()`* # In[ ]: # your code here # ### 24 # Есть ли в данных категориальные признаки, которые принимают значения строк, а не чисел? Если да, то для многих алгоритмов машинного обучения это может стать серьезным препятствием, поэтому закодируйте категориальные признаки так, чтобы к данным можно было применить любые алгоритмы машинного обучения. # # *Функции, которые могут пригодиться при решении: `.get_dummies()`, `.map()`, а также `LabelEncoder` из `sklearn`.* # In[ ]: # your code here # # 3 Sklearn + Kaggle (бонусная часть) # ### 25 # # Решите задачу бинарной классификации по предсказанию выживаемости пассажира. Для этого отделите от обучающей выборки целевую переменную `'Survived'` и обучите на них какой-нибудь алгоритм машинного обучения для классификации (например, kNN). С помощью него постройте предсказание на тестовой выборке, предварительно обработав ее аналогичным образом, что и обучающую. # In[ ]: # your code here # На основе данных, с которыми вы работали, было сделано соревнование на Kaggle, ориентированное на начинающих Data Scientists: https://www.kaggle.com/c/titanic. Вам предлагается в нем поучаствовать — если вы дошли до этого момента, то для этого осталось совсем ничего. Зарегистрируйтесь на Kaggle и примите правила соревнования. Если у вас уже есть ответ для тестовой выборки, который вы хотите отправить для оценивания и попасть в лидерборд, его нужно добавить в .csv файл и оформить нужным образом. Для этого во вкладке с данными (https://www.kaggle.com/c/titanic/data) есть пример того, как должен выглядеть этот файл ("gender_submission.csv"). Вы можете скачать и изучить его. Для вашего удобства ниже приведен код, который позволяет сформировать файл для отправки. # In[ ]: subm = pd.read_csv('gender_submission.csv') subm['Survived'] = prediction_test # In[ ]: subm.to_csv('test_subm_proba.csv', index=False) # Отправьте файл на оценивание с помощью кнопки "Submit Predictions". Метрика, используемая в соревновании — accuracy. Какой получился результат? Попробуйте его улучшить! Например, попробуйте выбрать признаки, которые были бы наиболее полезны для предсказания (feature selection) или создайте новые признаки (feature generation). Вы можете найти очень много полезной информации в https://www.kaggle.com/c/titanic/kernels и https://www.kaggle.com/c/titanic/discussion. # Наш бейзлайн: 0.67942 # # Ваш лучший результат: ...