Привет, Хабр!

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

И первый вопрос касается перекрестной проверки.

Что такое перекрестная проверка?

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

Основные техники перекрестной проверки

K-Fold Cross-Validation

Самый популярный метод. Заключается в следующем:

  1. Разделение данных на k частей: данные делятся на k равных подмножеств или "фолдов".

  2. Обучение и тестирование: модель обучается на k-1 фолдах и тестируется на оставшемся фолде. Этот процесс повторяется k раз, каждый раз с новым фолдом для тестирования.

  3. Среднее значение результатов: все k результатов тестирования усредняются, чтобы получить окончательную оценку производительности модели.

Например, если есть 1000 наблюдений и мы используем 5-fold cross-validation, то данные будут разделены на 5 частей по 200 наблюдений. Модель обучается на 800 наблюдениях и тестируется на 200. Этот процесс повторяется 5 раз, каждый раз с новым набором для тестирования.

Time-Series Cross-Validation

Особый случай перекрестной проверки используется для временных рядов — time-series cross-validation. Поскольку данные временных рядов имеют временную зависимость, традиционные методы перекрестной проверки не подходят. В данном методе данные делятся так, чтобы каждый набор данных для тестирования содержал более поздние временные точки по сравнению с обучающими наборами.

Пример:

  1. Разделение данных по времени: Данные делятся на обучающие и тестовые наборы таким образом, что тестовые наборы всегда следуют за обучающими по времени.

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

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

Переходим к следующему вопросу.

Как бы вы обработали набор данных с пропущенными значениями?

Если пропущенные значения встречаются в небольшом количестве строк, самый простой способ — удалить эти строки. В Python это можно сделать с помощью функции dropna() из pandas:

df = df.dropna()

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

Если в каком-то столбце много пропущенных значений, возможно, имеет смысл удалить весь столбец:

df = df.dropna(axis=1)

Этот метод применим, если столбец не содержит важной информации и его удаление не повлияет на анализ данных.

Для числовых данных часто используют замещение средним или медианой значением:

df['column_name'] = df['column_name'].fillna(df['column_name'].mean())
df['column_name'] = df['column_name'].fillna(df['column_name'].median())

Среднее значение подходит для нормального распределения данных, а медиана — для данных с выбросами.

Для категориальных данных можно использовать замещение наиболее частым значением:

df['column_name'] = df['column_name'].fillna(df['column_name'].mode()[0])

Можно использовать регрессионные модели для предсказания пропущенных значений на основе других признаков:

from sklearn.linear_model import LinearRegression

# создаем копию данных без пропусков
complete_data = df.dropna()
missing_data = df[df['column_name'].isnull()]

# обучаем модель
model = LinearRegression()
model.fit(complete_data[['feature1', 'feature2']], complete_data['column_name'])

# прогнозируем пропущенные значения
df.loc[df['column_name'].isnull(), 'column_name'] = model.predict(missing_data[['feature1', 'feature2']])

Так можно учитывать зависимость между признаками, что в целом улучшает точность замещения.

В случайной иммутации пропущенные значения заменяются случайным образом выбранными значениями из имеющихся данных:

import numpy as np

def random_imputation(df, feature):
    missing = df[feature].isnull()
    num_missing = missing.sum()
    sampled = np.random.choice(df[feature].dropna(), num_missing)
    df.loc[missing, feature] = sampled
    return df

df = random_imputation(df, 'column_name')

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

Множественная иммутация выполняет несколько итераций замещения пропущенных значений и усредняет результаты:

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

imp = IterativeImputer(max_iter=10, random_state=0)
df_imputed = imp.fit_transform(df)

Метод лучше сохраняет вариативность данных.

Можете ли вы объяснить принцип работы метода главных компонент (PCA)?

PCA помогет упростить анализ данных, уменьшить их размерность и при этом сохранить как можно больше информации.

Первый шаг в PCA — стандартизация данных. Это нужно, чтобы каждая переменная в данных вносила равный вклад в анализ. Для стандартизации вычитается среднее значение и оно делится на стандартное отклонение каждой переменной:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaled_data = scaler.fit_transform(data)

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

После стандартизации вычисляется ковариационная матрица, чтобы понять, как переменные связаны друг с другом:

import numpy as np

cov_matrix = np.cov(scaled_data, rowvar=False)

Ковариационная матрица показывает, как изменения одной переменной связаны с изменениями других переменных.

Следующий шаг — вычисление собственных векторов и собственных значений ковариационной матрицы. Собственные векторы указывают направления, в которых данные имеют наибольшую дисперсию, а собственные значения показывают, сколько дисперсии в данных объясняется каждой главной компонентой:

eig_values, eig_vectors = np.linalg.eig(cov_matrix)

Собственные векторы определяют оси новых координат, в которых дисперсия данных максимальна.

Собственные векторы сортируются в порядке убывания их собственных значений. Так можно определить, какие главные компоненты содержат наибольшую часть информации:

sorted_index = np.argsort(eig_values)[::-1]
sorted_eig_values = eig_values[sorted_index]
sorted_eig_vectors = eig_vectors[:, sorted_index]

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

На последнем этапе данные преобразуются в новое пространство, заданное главными компонентами:

n_components = 2  # выбор количества главных компонент
pca_components = sorted_eig_vectors[:, :n_components]
transformed_data = np.dot(scaled_data, pca_components)

Так мы сократили размерность данных, сохраняя при этом большую часть их информации.


Больше практических навыков по машинному обучению вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.

Также приглашаем всех начинающих в этой области на открытый урок, посвященный подготовке данных в Pandas. На нем мы последовательно рассмотрим этапы обработки данных: обработка пропусков, обработка дубликатов и поиск аномалий.

Комментарии (0)