декабря 21, 2025
14 мин. чтения

Вопросы для собеседования на должность младшего специалиста по Data Science: Полное руководство

interview
career-advice
job-search
entry-level
Вопросы для собеседования на должность младшего специалиста по Data Science: Полное руководство
MB

Milad Bonakdar

Автор

Освойте основы науки о данных с помощью основных вопросов для собеседования, охватывающих статистику, Python, основы машинного обучения, манипулирование данными и визуализацию для начинающих специалистов по Data Science.


Введение

Наука о данных (Data Science) сочетает в себе статистику, программирование и знания предметной области для извлечения информации из данных. От начинающих специалистов по данным ожидается наличие прочной базы знаний в Python, статистике, основах машинного обучения и инструментах обработки данных.

В этом руководстве рассматриваются основные вопросы для собеседования с начинающими специалистами по данным. Мы рассмотрим программирование на Python, основы статистики, манипулирование данными с помощью pandas, концепции машинного обучения, визуализацию данных и SQL, чтобы помочь вам подготовиться к вашей первой роли в области науки о данных.


Основы Python (5 вопросов)

1. В чем разница между списком и кортежем в Python?

Ответ:

  • Список: Изменяемый (можно изменять), определяется квадратными скобками []
  • Кортеж: Неизменяемый (нельзя изменять), определяется круглыми скобками ()
  • Производительность: Кортежи немного быстрее и используют меньше памяти
  • Примеры использования:
    • Списки: Когда вам нужно изменить данные
    • Кортежи: Для фиксированных коллекций, ключей словарей, возвратов функций
# Список - изменяемый
my_list = [1, 2, 3]
my_list[0] = 10  # Работает
my_list.append(4)  # Работает
print(my_list)  # [10, 2, 3, 4]

# Кортеж - неизменяемый
my_tuple = (1, 2, 3)
# my_tuple[0] = 10  # Ошибка: кортежи неизменяемы
# my_tuple.append(4)  # Ошибка: нет метода append

# Распаковка кортежа
x, y, z = (1, 2, 3)
print(x, y, z)  # 1 2 3

Распространенность: Очень часто Сложность: Легко


2. Объясните генератор списка и приведите пример.

Ответ: Генератор списка предоставляет краткий способ создания списков на основе существующих итерируемых объектов.

  • Синтаксис: [выражение for элемент in итерируемый_объект if условие]
  • Преимущества: Более читаемый, часто быстрее, чем циклы
# Традиционный цикл
squares = []
for i in range(10):
    squares.append(i ** 2)

# Генератор списка
squares = [i ** 2 for i in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# С условием
even_squares = [i ** 2 for i in range(10) if i % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# Вложенный генератор
matrix = [[i * j for j in range(3)] for i in range(3)]
print(matrix)  # [[0, 0, 0], [0, 1, 2], [0, 2, 4]]

# Генератор словаря
squares_dict = {i: i ** 2 for i in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Распространенность: Очень часто Сложность: Легко


3. Что такое лямбда-функции и когда вы их используете?

Ответ: Лямбда-функции — это анонимные функции с одним выражением.

  • Синтаксис: lambda аргументы: выражение
  • Примеры использования: Короткие функции, обратные вызовы, сортировка, фильтрация
# Обычная функция
def square(x):
    return x ** 2

# Лямбда-функция
square_lambda = lambda x: x ** 2
print(square_lambda(5))  # 25

# С map
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# С filter
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# Сортировка с ключом
students = [('Alice', 85), ('Bob', 92), ('Charlie', 78)]
sorted_students = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_students)  # [('Bob', 92), ('Alice', 85), ('Charlie', 78)]

Распространенность: Очень часто Сложность: Легко


4. Объясните разницу между append() и extend() для списков.

Ответ:

  • append(): Добавляет один элемент в конец списка
  • extend(): Добавляет несколько элементов из итерируемого объекта в конец
# append - добавляет один элемент
list1 = [1, 2, 3]
list1.append(4)
print(list1)  # [1, 2, 3, 4]

list1.append([5, 6])
print(list1)  # [1, 2, 3, 4, [5, 6]] - список как один элемент

# extend - добавляет несколько элементов
list2 = [1, 2, 3]
list2.extend([4, 5, 6])
print(list2)  # [1, 2, 3, 4, 5, 6]

# Альтернатива extend
list3 = [1, 2, 3]
list3 += [4, 5, 6]
print(list3)  # [1, 2, 3, 4, 5, 6]

Распространенность: Часто Сложность: Легко


5. Что такое *args и **kwargs?

Ответ: Они позволяют функциям принимать переменное количество аргументов.

  • *args: Переменное количество позиционных аргументов (кортеж)
  • **kwargs: Переменное количество именованных аргументов (словарь)
# *args - позиционные аргументы
def sum_all(*args):
    return sum(args)

print(sum_all(1, 2, 3))  # 6
print(sum_all(1, 2, 3, 4, 5))  # 15

# **kwargs - именованные аргументы
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="NYC")
# name: Alice
# age: 25
# city: NYC

# Комбинированный
def flexible_function(*args, **kwargs):
    print("Positional:", args)
    print("Keyword:", kwargs)

flexible_function(1, 2, 3, name="Alice", age=25)
# Positional: (1, 2, 3)
# Keyword: {'name': 'Alice', 'age': 25}

Распространенность: Часто Сложность: Средне


Статистика и теория вероятностей (5 вопросов)

6. В чем разница между средним арифметическим, медианой и модой?

Ответ:

  • Среднее арифметическое: Среднее значение всех значений (сумма / количество)
  • Медиана: Среднее значение при сортировке
  • Мода: Наиболее часто встречающееся значение
  • Когда использовать:
    • Среднее арифметическое: Данные с нормальным распределением
    • Медиана: Скошенные данные или наличие выбросов
    • Мода: Категориальные данные
import numpy as np
from scipy import stats

data = [1, 2, 2, 3, 4, 5, 100]

# Среднее арифметическое - подвержено влиянию выбросов
mean = np.mean(data)
print(f"Mean: {mean}")  # 16.71

# Медиана - устойчива к выбросам
median = np.median(data)
print(f"Median: {median}")  # 3

# Мода
mode = stats.mode(data, keepdims=True)
print(f"Mode: {mode.mode[0]}")  # 2

Распространенность: Очень часто Сложность: Легко


7. Объясните дисперсию и стандартное отклонение.

Ответ:

  • Дисперсия: Среднее квадратичное отклонение от среднего
  • Стандартное отклонение: Квадратный корень из дисперсии (те же единицы измерения, что и данные)
  • Цель: Измерение разброса/рассеяния данных
import numpy as np

data = [2, 4, 4, 4, 5, 5, 7, 9]

# Дисперсия
variance = np.var(data, ddof=1)  # ddof=1 для выборочной дисперсии
print(f"Variance: {variance}")  # 4.57

# Стандартное отклонение
std_dev = np.std(data, ddof=1)
print(f"Std Dev: {std_dev}")  # 2.14

# Ручной расчет
mean = np.mean(data)
variance_manual = sum((x - mean) ** 2 for x in data) / (len(data) - 1)
print(f"Manual Variance: {variance_manual}")

Распространенность: Очень часто Сложность: Легко


8. Что такое p-значение и как его интерпретировать?

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

  • Интерпретация:
    • p < 0,05: Отклонить нулевую гипотезу (статистически значимо)
    • p ≥ 0,05: Не удается отклонить нулевую гипотезу
  • Примечание: p-значение не измеряет размер эффекта или важность
from scipy import stats

# Пример: Проверка честности монеты
# Нулевая гипотеза: монета честная (p = 0,5)
# Мы получили 65 орлов из 100 бросков

observed_heads = 65
n_flips = 100
expected_proportion = 0.5

# Биномиальный тест
p_value = stats.binom_test(observed_heads, n_flips, expected_proportion)
print(f"P-value: {p_value}")  # 0.0018

if p_value < 0.05:
    print("Reject null hypothesis - coin is likely biased")
else:
    print("Fail to reject null hypothesis - coin appears fair")

Распространенность: Очень часто Сложность: Средне


9. Что такое центральная предельная теорема?

Ответ: Центральная предельная теорема утверждает, что выборочное распределение выборочного среднего приближается к нормальному распределению по мере увеличения размера выборки, независимо от распределения генеральной совокупности.

  • Ключевые моменты:
    • Работает для любого распределения (если размер выборки достаточно велик)
    • Обычно n ≥ 30 считается достаточным
    • Позволяет проводить проверку гипотез и строить доверительные интервалы
import numpy as np
import matplotlib.pyplot as plt

# Генеральная совокупность с ненормальным распределением (экспоненциальное)
population = np.random.exponential(scale=2, size=10000)

# Возьмите много выборок и рассчитайте их средние значения
sample_means = []
for _ in range(1000):
    sample = np.random.choice(population, size=30)
    sample_means.append(np.mean(sample))

# Выборочные средние значения распределены нормально (CLT)
print(f"Population mean: {np.mean(population):.2f}")
print(f"Mean of sample means: {np.mean(sample_means):.2f}")
print(f"Std of sample means: {np.std(sample_means):.2f}")

Распространенность: Часто Сложность: Средне


10. Что такое корреляция и причинно-следственная связь?

Ответ:

  • Корреляция: Статистическая взаимосвязь между двумя переменными
  • Причинно-следственная связь: Одна переменная напрямую вызывает изменения в другой
  • Ключевой момент: Корреляция НЕ подразумевает причинно-следственную связь
  • Причины:
    • Смешивающие переменные
    • Обратная причинно-следственная связь
    • Совпадение
import numpy as np
import pandas as pd

# Пример: Продажи мороженого и случаи утопления коррелируют
# Но мороженое не вызывает утопления (смешивающая переменная: температура)

# Коэффициент корреляции
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])

correlation = np.corrcoef(x, y)[0, 1]
print(f"Correlation: {correlation:.2f}")  # 0.82

# Корреляция Пирсона
from scipy.stats import pearsonr
corr, p_value = pearsonr(x, y)
print(f"Pearson r: {corr:.2f}, p-value: {p_value:.3f}")

Распространенность: Очень часто Сложность: Легко


Манипулирование данными с помощью Pandas (5 вопросов)

11. Как прочитать CSV-файл и отобразить основную информацию?

Ответ: Используйте pandas для чтения и изучения данных.

import pandas as pd

# Чтение CSV
df = pd.read_csv('data.csv')

# Основная информация
print(df.head())  # Первые 5 строк
print(df.tail())  # Последние 5 строк
print(df.shape)   # (строки, столбцы)
print(df.info())  # Типы данных и количество ненулевых значений
print(df.describe())  # Статистическая сводка

# Названия столбцов и типы
print(df.columns)
print(df.dtypes)

# Проверка на наличие пропущенных значений
print(df.isnull().sum())

# Конкретные столбцы
print(df[['column1', 'column2']].head())

Распространенность: Очень часто Сложность: Легко


12. Как обрабатывать пропущенные значения в DataFrame?

Ответ: Несколько стратегий для обработки пропущенных данных:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, np.nan, 8],
    'C': [9, 10, 11, 12]
})

# Проверка пропущенных значений
print(df.isnull().sum())

# Удаление строк с любыми пропущенными значениями
df_dropped = df.dropna()

# Удаление столбцов с любыми пропущенными значениями
df_dropped_cols = df.dropna(axis=1)

# Заполнение определенным значением
df_filled = df.fillna(0)

# Заполнение средним значением
df['A'] = df['A'].fillna(df['A'].mean())

# Заполнение медианой
df['B'] = df['B'].fillna(df['B'].median())

# Прямое заполнение (использовать предыдущее значение)
df_ffill = df.fillna(method='ffill')

# Обратное заполнение (использовать следующее значение)
df_bfill = df.fillna(method='bfill')

# Интерполяция
df_interpolated = df.interpolate()

Распространенность: Очень часто Сложность: Легко


13. Как фильтровать и выбирать данные в pandas?

Ответ: Несколько способов фильтрации и выбора данных:

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
    'age': [25, 30, 35, 28],
    'salary': [50000, 60000, 75000, 55000],
    'department': ['IT', 'HR', 'IT', 'Finance']
})

# Выбор столбцов
print(df['name'])  # Один столбец (Series)
print(df[['name', 'age']])  # Несколько столбцов (DataFrame)

# Фильтрация строк
high_salary = df[df['salary'] > 55000]
print(high_salary)

# Несколько условий
it_high_salary = df[(df['department'] == 'IT') & (df['salary'] > 50000)]
print(it_high_salary)

# Использование .loc (на основе меток)
print(df.loc[0:2, ['name', 'age']])

# Использование .iloc (на основе позиции)
print(df.iloc[0:2, 0:2])

# Метод query
result = df.query('age > 28 and salary > 55000')
print(result)

# Метод isin
it_or_hr = df[df['department'].isin(['IT', 'HR'])]
print(it_or_hr)

Распространенность: Очень часто Сложность: Легко


14. Как группировать и агрегировать данные?

Ответ: Используйте groupby() для операций агрегирования:

import pandas as pd

df = pd.DataFrame({
    'department': ['IT', 'HR', 'IT', 'Finance', 'HR', 'IT'],
    'employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
    'salary': [50000, 45000, 60000, 55000, 48000, 65000],
    'age': [25, 30, 35, 28, 32, 40]
})

# Группировка по одному столбцу
dept_avg_salary = df.groupby('department')['salary'].mean()
print(dept_avg_salary)

# Несколько агрегаций
dept_stats = df.groupby('department').agg({
    'salary': ['mean', 'min', 'max'],
    'age': 'mean'
})
print(dept_stats)

# Пользовательская агрегация
dept_custom = df.groupby('department').agg({
    'salary': lambda x: x.max() - x.min(),
    'employee': 'count'
})
print(dept_custom)

# Группировка по нескольким столбцам
result = df.groupby(['department', 'age'])['salary'].sum()
print(result)

Распространенность: Очень часто Сложность: Средне


15. Как объединять или связывать DataFrames?

Ответ: Используйте merge(), join() или concat():

import pandas as pd

# Пример DataFrames
df1 = pd.DataFrame({
    'employee_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Charlie', 'David']
})

df2 = pd.DataFrame({
    'employee_id': [1, 2, 3, 5],
    'salary': [50000, 60000, 75000, 55000]
})

# Inner join (только совпадающие строки)
inner = pd.merge(df1, df2, on='employee_id', how='inner')
print(inner)

# Left join (все строки слева)
left = pd.merge(df1, df2, on='employee_id', how='left')
print(left)

# Right join (все строки справа)
right = pd.merge(df1, df2, on='employee_id', how='right')
print(right)

# Outer join (все строки с обеих сторон)
outer = pd.merge(df1, df2, on='employee_id', how='outer')
print(outer)

# Конкатенация по вертикали
df3 = pd.concat([df1, df2], ignore_index=True)
print(df3)

# Конкатенация по горизонтали
df4 = pd.concat([df1, df2], axis=1)
print(df4)

Распространенность: Очень часто Сложность: Средне


Основы машинного обучения (5 вопросов)

16. В чем разница между обучением с учителем и обучением без учителя?

Ответ:

  • Обучение с учителем:
    • Имеет размеченные обучающие данные (пары вход-выход)
    • Цель: Изучить отображение входных данных в выходные
    • Примеры: Классификация, Регрессия
    • Алгоритмы: Линейная регрессия, Деревья решений, SVM
  • Обучение без учителя:
    • Нет размеченных данных (только входные данные)
    • Цель: Найти закономерности или структуру в данных
    • Примеры: Кластеризация, Снижение размерности
    • Алгоритмы: K-Means, PCA, Иерархическая кластеризация
from sklearn.linear_model import LinearRegression
from sklearn.cluster import KMeans
import numpy as np

# Обучение с учителем - Линейная регрессия
X_train = np.array([[1], [2], [3], [4], [5]])
y_train = np.array([2, 4, 6, 8, 10])

model = LinearRegression()
model.fit(X_train, y_train)
prediction = model.predict([[6]])
print(f"Supervised prediction: {prediction[0]}")  # 12

# Обучение без учителя - Кластеризация K-Means
X = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])

kmeans = KMeans(n_clusters=2, random_state=42)
clusters = kmeans.fit_predict(X)
print(f"Cluster assignments: {clusters}")

Распространенность: Очень часто Сложность: Легко


17. Что такое переобучение и как его предотвратить?

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

  • Признаки:
    • Высокая точность обучения, низкая точность тестирования
    • Модель слишком сложна для данных
  • Предотвращение:
    • Больше обучающих данных
    • Перекрестная проверка
    • Регуляризация (L1, L2)
    • Более простые модели
    • Ранняя остановка
    • Dropout (нейронные сети)
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
from sklearn.preprocessing import PolynomialFeatures
import numpy as np

# Генерация данных
X = np.random.rand(100, 1) * 10
y = 2 * X + 3 + np.random.randn(100, 1) * 2

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Пример переобучения - полином высокой степени
poly = PolynomialFeatures(degree=15)
X_poly = poly.fit_transform(X_train)

# Регуляризация для предотвращения переобучения
# Ridge (L2 регуляризация)
ridge = Ridge(alpha=1.0)
ridge.fit(X_poly, y_train)

# Lasso (L1 регуляризация)
lasso = Lasso(alpha=0.1)
lasso.fit(X_poly, y_train)

print(f"Ridge score: {ridge.score(X_poly, y_train)}")
print(f"Lasso score: {lasso.score(X_poly, y_train)}")

Распространенность: Очень часто Сложность: Средне


18. Объясните разделение на обучающую и тестовую выборки и почему это важно.

Ответ: Разделение на обучающую и тестовую выборки делит данные на обучающие и тестовые наборы для оценки производительности модели на невидимых данных.

  • Цель: Предотвратить переобучение, оценить производительность в реальном мире
  • Типичное разделение: 70-30 или 80-20 (обучение-тест)
  • Перекрестная проверка: Более надежная оценка
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris

# Загрузка данных
iris = load_iris()
X, y = iris.data, iris.target

# Разделение на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

print(f"Training set size: {len(X_train)}")
print(f"Test set size: {len(X_test)}")

# Обучение модели
model = LogisticRegression(max_iter=200)
model.fit(X_train, y_train)

# Оценка
train_score = model.score(X_train, y_train)
test_score = model.score(X_test, y_test)

print(f"Training accuracy: {train_score:.2f}")
print(f"Test accuracy: {test_score:.2f}")

# Перекрестная проверка (более надежная)
cv_scores = cross_val_score(model, X, y, cv=5)
print(f"CV scores: {cv_scores}")
print(f"Mean CV score: {cv_scores.mean():.2f}")

Распространенность: Очень часто Сложность: Легко


19. Какие метрики оценки вы используете для классификации?

Ответ: Различные метрики для разных сценариев:

  • Точность (Accuracy): Общая правильность (хорошо для сбалансированных наборов данных)
  • Точность (Precision): Из предсказанных положительных, сколько верных
  • Полнота (Recall): Из фактических положительных, сколько было найдено
  • F1-мера (F1-Score): Гармоническое среднее точности и полноты
  • Матрица ошибок (Confusion Matrix): Подробная разбивка прогнозов
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

# Загрузка данных
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Обучение модели
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# Метрики
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print(f"Accuracy: {accuracy:.2f}")
print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
print(f"F1-Score: {f1:.2f}")

# Матрица ошибок
cm = confusion_matrix(y_test, y_pred)
print(f"\nConfusion Matrix:\n{cm}")

# Отчет о классификации
print(f"\n{classification_report(y_test, y_pred)}")

Распространенность: Очень часто Сложность: Средне


20. В чем разница между классификацией и регрессией?

Ответ:

  • Классификация:
    • Предсказывает дискретные категории/классы
    • Выход: Метка класса
    • Примеры: Обнаружение спама, классификация изображений
    • Алгоритмы: Логистическая регрессия, Деревья решений, SVM
    • Метрики: Точность, Precision, Recall, F1
  • Регрессия:
    • Предсказывает непрерывные числовые значения
    • Выход: Число
    • Примеры: Прогнозирование цен на жилье, прогнозирование температуры
    • Алгоритмы: Линейная регрессия, Random Forest Regressor
    • Метрики: MSE, RMSE, MAE, R²
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np

# Пример регрессии
X_reg = np.array([[1], [2], [3], [4], [5]])
y_reg = np.array([2.1, 3.9, 6.2, 7.8, 10.1])

reg_model = LinearRegression()
reg_model.fit(X_reg, y_reg)
y_pred_reg = reg_model.predict([[6]])
print(f"Regression prediction: {y_pred_reg[0]:.2f}")  # Непрерывное значение

# Пример классификации
X_clf = np.array([[1], [2], [3], [4], [5]])
y_clf = np.array([0, 0, 1, 1, 1])  # Бинарные классы

clf_model = LogisticRegression()
clf_model.fit(X_clf, y_clf)
y_pred_clf = clf_model.predict([[3.5]])
print(f"Classification prediction: {y_pred_clf[0]}")  # Метка класса (0 или 1)

Распространенность: Очень часто Сложность: Легко

Newsletter subscription

Еженедельные советы по карьере, которые действительно работают

Получайте последние идеи прямо на вашу почту

Похожие посты

Decorative doodle

Создайте резюме, которое поможет вам устроиться на 60% быстрее

За несколько минут создайте персонализированное резюме, совместимое с ATS, которое доказано увеличивает количество собеседований в 6 раз.

Создать лучшее резюме

Поделиться этим постом

Преодолейте 75% Уровень Отказа ATS

3 из 4 резюме никогда не доходят до человеческих глаз. Наша оптимизация ключевых слов повышает ваш процент прохождения до 80%, гарантируя, что рекрутеры действительно увидят ваш потенциал.