Введение в анализ данных¶

Домашнее задание 1. Простой анализ данных.¶

Правила, прочитайте внимательно:

  1. Общее

    • Выполненную работу в формате ipynb нужно отправить телеграм-боту @thetahat_ds26_bot согласно инструкции. Работы, присланные иным способом, не принимаются. Дедлайны указаны в боте, они являются строгими. Переносы дедлайнов осуществляются по установленным правилам.

    • Обязательно изучите руководство по оформлению ДЗ. В частности, оно содержит примеры случаев, когда могут быть снижены баллы.

    • Обратите внимание на правила использования ИИ-инструментов при решении домашнего задания.

    • Выполнять задание необходимо полностью самостоятельно. При обнаружении списывания (в т.ч. злоупотребление ИИ) всем участникам списывания дается штраф -3 скор-балла к итоговой оценке.

    • Решение проверяется системой ИИ-проверки No description has been provided for this image ThetaGrader. Результат проверки валидируется и исправляется человеком, после чего комментарии отправляются студентам.

  2. Правила заполнения ноутбука

    • Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения существующих ячеек.
    • Отвечайте на вопросы, а также добавляйте новые ячейки в любом количестве в предложенных местах, которые обозначены <...>.
    • Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз. Комментарии к решению пишите в markdown-ячейках.
    • Условия запрещается модифицировать.
    • При нарушении данных правил работа может получить 0 баллов.

Баллы за задание:

  • Задача 1 — 30 баллов
  • Задача 2 — 20 баллов
  • Задача 3 — 90 баллов
  • Задача 4 — 80 баллов
In [ ]:
# Bot check

# HW_ID: fpmi_ad1
# Бот проверит этот ID и предупредит, если случайно сдать что-то не то

# Status: not final
# Перед отправкой в финальном решении удали "not" в строчке выше
# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную

Тренировочные задачи на библиотеки¶

Если вы неуверенно себя чувствуете в библиотеках numpy, pandas, matplotlib, seaborn, рекомендуем сначала

  • посмотреть материалы по библиотекам на нашем сайте
  • прийти на онлайн-лекцию 14.02
  • прорешать два упражнения на numpy в системе Яндекс.Контест.

Ссылки на использование ИИ¶

Если при решении задач использовался ИИ, укажи здесь публичные ссылки на все чаты с ИИ и поясни, для каких целей он применялся. Обрати внимание на правила.

Задача 1

  1. ссылка
    • для чего использована
    • для чего использована
  2. ссылка
    • для чего использована

Задача 2

  1. ссылка
    • для чего использована

Задача 1.¶

Рассмотрим задачу классификации на $K$ классов, которые встречаются с вероятностями $p_1, ..., p_K$. На лекции мы разбирали, почему качество вашей построенной модели полезно сравнивать с качеством бейзлайн-моделей. В качестве таких моделей можно рассмотреть, например,

  • классификатор, который всегда выдает самый частый класс в train-выборке,
  • классификатор, который выдает случайный класс в соответствии с частотой встречаемости классов в train-выборке.

Сравните эти два классификатора по вероятности ошибочной классификации в предположении, что распределение классов между train и test не отличается.

Предполагается теоретическое обоснование с математическим выводом формул. Применение семплирования не предполагается и не оценивается.

Решение оформите в ячейке ниже в формате $\LaTeX$. При решении можно использовать ИИ-инструменты только для оформления написанного самостоятельно решения. Например, написать черновик формул и попросить ИИ оформить эти формулы в $\LaTeX$.

Ожидается достаточно подробное решение с обоснованием математических переходов и пояснениями.

<...>


Задача 2.¶

Цель этой задачи — разобраться самостоятельно в библиотеке plotly. Для этого можно использовать ИИ-инструменты, задавая вопросы поэтапно. Скинуть условие целиком в ИИ и скопипастить ответ нельзя. Не забудьте прикрепить ссылку на диалог с ИИ.

В этой задаче вам предстоит поработать с библиотекой Plotly. Это полезный инструмент для создания привлекательных и удобных графиков, который вы наверняка будете использовать в своей работе. Мы рекомендуем заранее изучить его функции и возможности, чтобы вы могли уверенно использовать его в дальнейшем.

Одна из главных особенностей этой библиотеки — возможность настраивать и украшать графики по своему вкусу. Именно этим мы и предлагаем вам заняться в рамках данной задачи.

Внимание! Интерактивные графики могут не сохраниться в ноутбуке, а если сохранятся, то вес ноутбука может превзойти 20 Мб, и его не получится отправить боту. В любом случае необходимо сохранить график в html и отправить ее отдельным файлом в бот. При этом каждый файл html должен не превышать 20 Мб, присылать файлы в архиве нельзя. Аналогично со всеми следующими интерактивными графиками в этом задании.

Ниже приведен код для построения 3D-графика функции с помощью Plotly.

In [ ]:
import plotly.graph_objects as go


def plot_3d_surface():
    x = np.linspace(-10, 10, 200)
    y = np.linspace(-10, 10, 200)
    x, y = np.meshgrid(x, y)
    z = np.cos(np.sqrt(x**2 + y**2))

    fig = go.Figure(data=[go.Surface(z=z, x=x, y=y)])
    fig.update_layout(
        title='Cosine Function 3D Surface Plot',
        scene=dict(
            xaxis_title='X Axis',
            yaxis_title='Y Axis',
            zaxis_title='Z Axis',
            aspectmode='cube',
        ),
        margin=dict(l=0, r=0, b=0, t=0)
    )


    fig.show()

plot_3d_surface()

Выполните следующие действия в ячейках ниже.

1. Задокументируйте функцию и добавьте комментариев. Необходимо это сделать так, чтобы любой человек мог понять, какая у нее задача и что делают отдельные части кода.

In [ ]:
<...>

2. Напишите, что делают следующие функции и опции:

  • meshgrid

  • Figure

  • Surface

  • update_layout

  • scene

  • margin

<...>

3. Выясните, какой параметр отвечает за настройку цветовой палитры графика? Измените код так, чтобы палитра была от светло-розового до светло-голубого.

In [ ]:
<...>

4. Измените функцию так, чтобы она могла получать любые параметры настройки графиков через kwargs. Это позволит пользователям гибко настраивать параметры графика.

...И напишите подробную инструкцию для пользователя этой функции😃

In [ ]:
<...>

Инструкция:

<...>


Задача 3.¶

Перед выполнением задачи рекомендуется посмотреть материал с семинара.

0. Подготовка данных¶

Титаник был крупнейшим пассажирским судном в 1912—1913 годах. Во время первого рейса затонул в северной Атлантике, столкнувшись с айсбергом в ночь с 14 на 15 апреля 1912 года, при этом погибло 1502 из 2224 пассажиров и членов экипажа. Данные о пассажирах были собраны в таблицы, которые можно скачать с Kaggle. Эти данные часто используются в качестве обучающих в анализе данных.

Загрузите данные с помощью pandas.

In [ ]:
titanic = pd.read_csv("train.csv")
titanic.head()

Для лучшего понимания процесса работы с данными, уточним ключевые термины.

Объект — это единица данных, представленная набором признаков и используемая для обучения или предсказаний модели. В данной задаче являются пассажиры, им соответствуют строки таблицы данных.

Признаки (features) — это характеристики, которые описывают объекты в данных. В таблицах данных они обычно соответствуют колонкам. В данной задаче мы будем работать со следующими признаками

  • Pclass — класс билета (1 = первый класс, 2 = второй класс, 3 = третий класс);

  • Age — возраст пассажира;

  • Sex — пол пассажира;

  • SibSp — количество братьев, сестер или супругов на борту;

  • Parch — количество родителей или детей на борту;

  • Fare — стоимость билета.

Таргет (target) — это целевая переменная, которую мы хотим предсказать. В данной задаче мы будем предсказывать Survived — бинарная переменная, указывающая, выжил ли пассажир (1) или нет (0). Значения этой переменной имеются для обучающего набора данных, а для тестого — нет.

Из каждой части оставим несколько признаков, с которыми мы будем работать, а также отдельно — целевой признак, который мы хотим предсказать.

In [ ]:
features_columns = ["Pclass", "Age", "Sex", "SibSp", "Parch", "Fare"]
target_column = "Survived"  # Целевой признак

X, y = titanic[features_columns], titanic[target_column]

В данных могут присутствовать пропуски. Пока что мы не умеем с ними работать, так что исключим из данных.

Посмотрите, сколько объектов имеют хотя бы один пропуск. Удалите их из данных.

In [ ]:
<...>

Разделите данные по строкам на две части случайным образом в соотношении 7:3. Первую часть мы будем называть обучающей, а вторую — тестовой.

In [ ]:
<...>

1. Исследование¶

❗ Внимание. Эта часть задачи должна выполняться исключительно на обучающих данных. За использование тестовых данных решение не будет оценено.

Проведите визуальный анализ данных чтобы понять, как различные признаки влияют на целевой. Исследовать можно не целиком обучающие данные, а разделить их на две части по одному из признаков, а далее рассматривать каждую часть отдельно.

Не забывайте про информативность и эстетичность графиков, посмотрите презентацию про оформление домашних заданий.

In [ ]:
<...>

2. Классификация логическими правилами¶

На основе выше проведенного исследования предложите два разных правила вида

1). если признак $x_1 > 5$, то класс 0, иначе посмотрим на признак $x_2$ и ...

2). если $x_1 > 5$ и $x_2 < 2$, то класс 1, иначе ...

В совокупности используйте не менее трех различных признаков. Никакие статистические методы использовать не требуется, только логику и графики. Любые решения "из коробки" использовать запрещено. Например, достаточно пояснения "по графику <описание графика> визуально я увидел, что при X > 100 большинство пассажиров выжило, поэтому использую правило <описание правила>".

Правило 1:

<...>

Правило 2:

<...>

Реализуйте полученные логические правила по шаблону

In [ ]:
def model(features: pd.DataFrame) -> pd.Series:
    """
    Предсказание целевого признака для данных features -- pandas-таблица данных.
    Возвращает pandas.Series с теми же индексами, что и у features.
    """

    <...>
    return predicted

Проверьте работоспособность данных моделей на тестовой выборке и оцените качество модели по метрике accuracy.

❕ Примечание. Полученные значения не влияют на оценку по заданию. Оценивается только корректность и обоснованность решения, а также графики и выводы.

In [ ]:
def accuracy(target: pd.Series, predicted: pd.Series) -> float:
    """
    Вычисление критерия качества для предсказания predicted,
    если истинные значения -- target.
    Возвращает одно вещественное число.
    """

    <...>
In [ ]:
<...>

3. Классификация методом ближайшего соседа¶

В данной части задачи оставим только признаки 'Pclass', 'Age', 'Sex','Fare'.

❓ Вопрос ❓

Какие могли бы возникнуть проблемы при использовании признаков 'SibSp', 'Parch'? Имеется ли подобная проблема для признака 'Pclass'?

Ваш ответ: <...>

Признак 'Sex' имеет два различных строковых значения. Чтобы использовать его в модели kNN, преобразуйте их в 0 и 1.

In [ ]:
<...>

Постройте классификатор методом ближайшего соседа. Обучите его и оцените качество модели. Сравните с предыдущим методом.

Пока никаких других преобразований данных делать не нужно.

In [ ]:
<...>

Попробуем улучшить результаты предсказаний, для этого надо сначала посмотреть на сами данные. Выведите значение минимального и максимального объекта для каждого признака.

In [ ]:
<...>

Как мы видим данные в каждом столбце распределены очень по-разному.

❓ Вопрос ❓

Как это может повлиять на работу kNN, почему?

Ваш ответ: <...>

Для решения этой проблемы нужно привести признаки к единому масштабу. Существует много методов масштабирования рассмотрим работу одного из них — минимаксная нормализация

Минимакс — линейное преобразование данных в диапазоне $[0, 1]$, где минимальное и максимальное масштабируемые значения соответствуют 0 и 1 соответственно. Реализуется оно по следующей формуле:

$$\widetilde{x}_{ij} = \frac{x_{ij} - m_j}{M_j - m_j}$$

где $x_{ij}$ — значение признака $j$ для объекта $i$, а $m_j$ и $M_j$ — минимальное и максимальное значения признака $j$ в обучающем наборе данных.
В модуле sklearn.preprocessing есть класс MinMaxScaler, который реализует эту операцию. Давайте рассмотрим методы этого класса подробнее:

  • fit(X): вычисляет минимальные и максимальные значения для каждого признака.

  • transform(X): применяет масштабирование к данным.

  • fit_transform(X): объединяет оба метода, сначала подгоняя модель, а затем трансформируя данные.

  • inverse_transform(X): восстанавливает исходные данные из масштабированных.

Обратите внимание, что методы fit(X) и fit_transform(X) можно применять только к обучающим данным.

Стоит отметить что существуют и другие методы масштабирования данных.

❓ Вопрос ❓

В чем может быть недостаток такого метода масштабирования?

Ваш ответ: <...>

Отмасштабируйте данные

In [ ]:
<...>

Теперь выведите значения максимума и минимума нормализованных признаков. Обратите внимание MinMaxScaler возвращается объект в виде np.ndarray.

In [ ]:
<...>

Обучите модель и сравните результат предсказаний со стандартизацией и без.

In [ ]:
<...>

Вывод: <...>

А можем ли мы как-то еще повысить точность модели?

Как мы видели, параметр $k$ числа соседей является необучаемым т.е. гиперпараметром, который выставляется вручную. Выбор оптимального значения $k$ важен, так как слишком маленькое значение может привести к переобучению, а слишком большое — к недообучению.

Постройте графики зависимостей точности (accuracy_score) от значения $k$ (от 1 до 20) для обучающей и тестовой выборок, на одной фигуре должно быть нарисовано две зависимости.

In [ ]:
<...>

Вывод: <...>


Задача 4.¶

Эта задача предназначена для развития навыков работы с библиотекой pandas и простого анализа табличных данных. В ней детально описаны все шаги, которые необходимо выполнить. Если что-то не понятно, спросите ИИ или в чате курса.

Yelp — веб-сайт для поиска на местном рынке услуг, например ресторанов или парикмахерских, с возможностью добавлять и просматривать рейтинги и обзоры этих услуг. Для популярных бизнесов имеются сотни обзоров. Для обозревателей на сайте предусмотрены элементы социальной сети.

Yelp


Вам предоставляется следующая информация о компаниях на Yelp:

Файл yelp_business.csv:

  • business_id — уникальный идентификатор компании;
  • name — имя компании;
  • address, city, state — месторасположении компании;
  • latitude, longitude — географические координаты;
  • categories — категории услуг компании.

Файл yelp_review.csv, содержащий оценки пользователей:

  • business_id — идентификатор компании, соответствующий файлу yelp_business.csv;
  • stars — поставленная пользователем оценка от 1 до 5.

В целях сокращения объема файла, текстовые отзывы пользователей не были включены.

Оригинальную версию датасета в формате json можно посмотреть по ссылке, но использовать нужно выданные данные.


Что нужно сделать:

  • Найти город с наибольшим количеством компаний;
  • Для этого города определить районы с наиболее качественными услугами. Пример с несколько другой задачей.
  • А также найти рестораны с наилучшими отзывами.

Далее в условии встречаются различные подсказки, как можно выполнить определенные части задачи. Вы можете их игнорировать и делать иным способом для получения того же самого промежуточного результата. Однако, если ваше решение окажется значительно менее эффективным (по скорости, количеству и красоте кода) по сравнению с предполагаемым, баллы могут быть снижены.


1. Город с наибольшим количеством компаний¶

Загрузите данные из файла yelp_business.csv с помощью функции pd.read_csv. Посмотрите на первые несколько строк с помощью метода head.

In [ ]:
<...>

Найдите пять городов, по которым присутствует информация о наибольшем количестве компаний. В таблице должен быть указан город (название) и количество компаний в этом городе.

Подсказка. Для выполнения стоит воспользоваться методами groupby, count, sort_values, head.

In [ ]:
<...>

Пусть N — город с наибольшим количеством компаний. Оставьте в таблице только записи, соответствующие городу N. Нанесите все эти компании на график, в котором по оси $x$ отметьте долготу, а по оси $y$ — широту.

In [ ]:
<...>

Сам город находится в сгустке точек. Есть какие-то компании, которые приписаны к этому городу, но находятся далеко от него. Избавьтесь от них, подобрав некоторые границы значений широты и долготы. Изобразите все компании на новом графике. На этом графике должны выделяться некоторые улицы.

In [ ]:
<...>

Разберитесь с тем, как подгрузить интерактивную карту города в качестве фона графика. Можно пойти двумя следующими способами.

  1. Изучить материалы по библиотеке Plotly. Возможно, потребуется также заглянуть в документацию.
  2. Поразбираться с библиотекой Folium. Посмотрите множество примеров, может также помочь статья на русском.

Внимание! Интерактивная карта может не сохраниться в ноутбуке, а если сохранится, то вес ноутбука может превзойти 20 Мб, и его не получится отправить боту. В любом случае необходимо сохранить карту в html и отправить ее отдельным файлом в бот. При этом каждый файл html должен не превышать 20 Мб, присылать файлы в архиве нельзя. Аналогично со всеми следующими интерактивными графиками в этом задании.

In [ ]:
<...>

Если все получилось, вы молодцы! Далее в этой задаче везде, где необходимо построить график по координатам, тоже стройте интерактивные карты. Если нет желания разбираться с интерактивными графиками, можно построить статичные, но баллы будут снижены.

2. Оценки компаний¶

Для выполнения задания нужно посчитать среднюю оценку каждой компании, а также количество выставленных оценок.

Загрузите таблицу оценок yelp_review.csv.

In [ ]:
<...>

В подгруженной таблице оценок оставьте только компании города N с учетом фильтрации, которую мы выполнили на предыдущем шаге. Для этого установите значения business_id в качестве индекса у таблицы оценок и воспользуйтесь методом loc.

Подсказка. Чтобы индекс снова сделать полем таблицы, можно воспользоваться методом reset_index.

In [ ]:
<...>

Теперь посчитайте среднюю оценку каждой компании, а также количество выставленных компании оценок.

Подсказка. Помочь в этом могут функции groupby и aggregate([np.mean, np.size]).

In [ ]:
<...>

Назовите колонки таблицы красивыми именами, изменив <имя таблицы>.columns, после чего напечатайте несколько строк полученной таблицы. Красивые имена — то, что будет понятно простому человеку при чтении ваших результатов. Как именно их назвать — задача аналитика, то есть в данном случае ваша :)

In [ ]:
<...>

Соедините две полученные ранее таблицы по компаниям города N в одну. Для этого сначала установите поле business_id в качестве индекса в обеих таблицах с помощью set_index. В одной из них это уже должно было быть сделано. В полученной таблице должны получится поля latitude, longitude, categories, name, а также две колонки со средней оценкой компаний и количеством оценок, которые вы посчитали выше.

Подсказка. Соединение таблиц можно выполнить с помощью join. Индексы у этих таблиц одинаковые, так что тип джойна не имеет значения.

In [ ]:
<...>

Изобразите все компании на графике, раскрасив точку в цвет, оттенок которого соответствует средней оценке компании. Прозрачность точки выставляйте не более $0.3$. Если у одной компании несколько филиалов с разными адресами, наносите на график все адреса.

In [ ]:
<...>

Чтобы получить районы города, то есть разделить город на "клетки", округлите значения широты и долготы, подобрав оптимальный размер района.

Подсказка. Например, можно сделать так np.round(долгота*4, decimals=1)*0.25.

In [ ]:
<...>

Для получения средней оценки компаний по району постройте сводную таблицу при помощи pd.pivot_table, взяв в качестве индексов и колонок округленные широту и долготу, а в качестве значений — оценки. Аггрегирующей функцией является среднее.

Изобразите полученную таблицу при помощи sns.heatmap.

Замечание. В качестве среднего можно было бы посчитать как общее среднее по всем оценкам всех компаний, так и среднее по компаниям их средних оценок. В чем разница этих подходов? Какой из них необходимо использовать в данном случае?

In [ ]:
<...>

Полученный график имеет ряд недостатков. Во-первых, не очень правильно судить о районе, если в нем мало компаний. Во-вторых, на графике цветовая гамма автоматически подстроилась под минимальное и максимальное значения оценки.

Почему эти недостатки могут быть существенными?

Ответ: <...>

Подсказка. Подумайте, действительно ли соответствует большой разброс цветов на цветовой шкале полученному разбросу среднего? Насколько для нас значим такой разброс среднего?

Оставьте районы, в которых имеется информация о не менее $30$ компаний. Постройте новый график районов, использовав параметры vmin и vmax у функции sns.heatmap.

In [ ]:
<...>

Сравните полученный график с предыдущим и сделайте выводы отн.

Вывод: <...>

3. Рестораны¶

Будем считать компанию рестораном, если в поле categories содержится слово restaurant. Обратите внимание, что в анализе данных часто нет четкого формата данных. Например, данное слово может быть написано как с большой буквы, так и с маленькой; может как разделяться ;, так и не разделяться. При возникновении недопонимания стоит посмотреть данные.

Составьте таблицу, в которой будет информация о всех ресторанах города N, для которых имеется не менее $5$ отзывов. Далее постройте heatmap-график районов, в котором каждому району сопоставьте среднюю оценку по ресторанам этого района. Рассматривайте только те районы, в которых есть не менее $10$ ресторанов, для каждого из которых есть не менее $5$ отзывов.

In [ ]:
<...>

Чем полезны ограничения снизу на количество отзывов для ресторана и количество ресторанов в районе?

Ответ: <...>

Кот Василий из города N очень придирчив к выбору ресторана. Он доверяет только ресторанам с высоким рейтингом, который основывается на большом количестве отзывов. Напечатайте в виде таблицы информацию $10$ ресторанах с самым большим рейтингом в порядке убывания рейтинга. Для каждого из этих ресторанов должно быть не менее $50$ отзывов. По каждому ресторану необходимо вывести следующую информации: название ресторана, средняя оценка, количество отзывов, географические координаты, категории.

In [ ]:
<...>

Нанесите на карту все рестораны со средней оценкой не менее $4.7$, которая посчитана по не менее $50$ отзывам. Отдельным цветом отметьте 10 ресторанов, которые вы получили ранее.

In [ ]:
<...>

4. Выводы¶

Охарактеризуйте кота Василия, а также сделайте общий вывод по задаче.

Вывод: <...>


© 2026 команда ThetaHat для ВвАД