12 промтов, которые я гоняю через LLM на каждом ML-проекте: от EDA до интерпретации модели
Любой ML-проект — это не только модель. Это гора рутины: посмотреть распределения, найти выбросы, придумать признаки, настроить кросс-валидацию, разобраться, почему модель ошибается на конкретном сегменте. По оценкам опросов Kaggle State of Data Science, дата-саентисты тратят на подготовку и анализ данных больше времени, чем на само обучение моделей. Именно эту рутину LLM ускоряют лучше всего — если давать им правильные промты.
Ниже — 12 промтов, которые я использую в реальных проектах. Каждый — с описанием задачи, примером и кодом. Я проверял их на табличных данных (pandas), но большинство адаптируется под любой стек. Все примеры — рабочий Python, который можно копировать и запускать. Стек: Python 3.11, pandas, scikit-learn, scipy, matplotlib, shap.
Важный принцип: LLM — не оракул. Промт задаёт рамку, а ты проверяешь результат. Ниже везде подразумевается, что ты валидируешь код и выводы сам.
1. Быстрый профиль датасета
Задача: за минуту понять, что вообще в таблице — типы, пропуски, кардинальность, странные значения.
Промт:
Ты — senior data scientist. Вот датасет (df.head(), df.dtypes, df.describe()).
Составь профиль: 1) какие колонки требуют внимания и почему;
2) где вероятны проблемы (пропуски, константы, утечки, странные типы);
3) какие 5 вопросов ты бы задал бизнесу перед моделированием.
Без воды. Только конкретика по колонкам.
Пример: подаёшь вывод df.info() по таблице заказов с 40 колонками. LLM замечает, что order_date хранится как object, а customer_id имеет 98% уникальных значений — значит, как категориальный признак бесполезен.
import pandas as pd
df = pd.read_csv("orders.csv")
print(df.dtypes)
print(df.describe(include="all").T)
print(df.isna().mean().sort_values(ascending=False).head(20))
Этот промт экономит первый час знакомства с чужими данными.
2. Аудит пропусков и стратегия импутации
Задача: не заполнять пропуски «средним по умолчанию», а осознанно выбрать стратегию.
Промт:
Вот доли пропусков по колонкам и тип каждой (числовая/категориальная/дата).
Для каждой колонки с пропусками предложи стратегию: drop, median, mode,
индикатор пропуска, модельная импутация. Объясни риск утечки для каждой.
Отдельно отметь колонки, где пропуск сам по себе — сигнал (MNAR).
Пример: в кредитном скоринге пропуск в поле income часто коррелирует с риском — это MNAR. Заполнять медианой опасно, лучше добавить бинарный признак income_missing.
import numpy as np
miss = df.isna().mean()
missing_cols = miss[miss > 0].sort_values(ascending=False)
for col in missing_cols.index:
if df[col].dtype == "object":
df[col + "_missing"] = df[col].isna().astype(int)
df = df.drop(columns=[c for c in df.columns if df[c].isna().mean() > 0.6])
3. EDA с гипотезами, а не с графиками ради графиков
Задача: превратить разведочный анализ в список проверяемых гипотез.
Промт:
Целевая переменная — churn (бинарь). Вот список признаков и их типов.
Сформулируй 8 проверяемых гипотез о связи признаков с таргетом.
Для каждой: как проверить (тест/график), какой результат подтвердит гипотезу.
Пример гипотезы от LLM: «Клиенты с support_tickets > 3 за последние 30 дней уходят чаще». Проверка — scipy.stats.mannwhitneyu между группами churn/not-churn.
from scipy import stats
for col in ["support_tickets", "days_since_login", "monthly_spend"]:
a = df.loc[df.churn == 1, col].dropna()
b = df.loc[df.churn == 0, col].dropna()
stat, p = stats.mannwhitneyu(a, b, alternative="two-sided")
print(f"{col}: p={p:.4f}")
Это гораздо полезнее, чем просто «постройте pairplot».
4. Поиск выбросов с обоснованием метода
Задача: не удалять всё, что за пределами 3 сигм, а понять природу выбросов.
Промт:
Числовые колонки: [...]. Предложи для каждой подходящий метод детекции выбросов
(IQR, z-score, isolation forest, DBSCAN) и объясни, почему именно он.
Отдельно: какие выбросы могут быть реальными бизнес-кейсами, а не ошибками.
Пример: для сумм транзакций IQR разумнее z-score — распределение с тяжёлым хвостом. Для age — наоборот.
import numpy as np
def iqr_outliers(s):
q1, q3 = s.quantile([0.25, 0.75])
iqr = q3 - q1
return (s < q1 - 1.5 * iqr) | (s > q3 + 1.5 * iqr)
df["amount_outlier"] = iqr_outliers(df["amount"])
print(df["amount_outlier"].mean())
5. Генерация признаков из дат и категорий
Задача: выжать сигнал из datetime и категориальных полей.
Промт:
Вот колонки с датами и категориями. Предложи признаки, которые
имеют бизнес-смысл: циклические кодировки, разницы дат, агрегаты по группам.
Для каждого — формула и почему он может помочь модели.
Пример: signup_date и first_purchase_date → признак «дней до первой покупки». Час суток → sin/cos-кодировка.
import numpy as np
df["days_to_first_purchase"] = (df["first_purchase_date"] - df["signup_date"]).dt.days
df["hour_sin"] = np.sin(2 * np.pi * df["hour"] / 24)
df["hour_cos"] = np.cos(2 * np.pi * df["hour"] / 24)
6. Target encoding без утечки
Задача: закодировать высококардинальные категории, не подглядывая в тест.
Промт:
Нужен target encoding для колонок с кардинальностью 100+.
Напиши код с KFold-схемой внутри train, сглаживанием и защитой от утечки.
Объясни, почему обычный mean по всей выборке — ошибка.
Пример корректной реализации через out-of-fold:
from sklearn.model_selection import KFold
import pandas as pd
def target_encode(train, col, target, n_splits=5, smoothing=10):
prior = train[target].mean()
train[f"{col}_te"] = prior
kf = KFold(n_splits=n_splits, shuffle=True, random_state=42)
for tr_idx, val_idx in kf.split(train):
agg = train.iloc[tr_idx].groupby(col)[target].agg(["mean", "count"])
smooth = (agg["mean"] * agg["count"] + prior * smoothing) / (agg["count"] + smoothing)
train.loc[train.index[val_idx], f"{col}_te"] = (
train.iloc[val_idx][col].map(smooth).fillna(prior).values
)
return train
7. Подбор и сравнение моделей
Задача: не гонять все модели подряд, а выбрать разумный шортлист.
Промт:
Данные: N строк, M признаков, таргет — регрессия/классификация.
Предложи 4 модели с обоснованием (baseline, линейная, ансамбль, бустинг).
Укажи метрику оценки и почему именно её. Учти дисбаланс/выбросы.
Пример: для табличных данных с 50k строк LLM предложит LightGBM как основной кандидат, логистическую регрессию как baseline, и метрику ROC-AUC + PR-AUC при дисбалансе.
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import cross_val_score
models = {
"logreg": LogisticRegression(max_iter=1000),
"hgb": HistGradientBoostingClassifier(),
}
for name, m in models.items():
scores = cross_val_score(m, X, y, cv=5, scoring="roc_auc")
print(name, scores.mean().round(4))
8. Настройка кросс-валидации под структуру данных
Задача: выбрать схему CV, которая не врёт.
Промт:
Данные содержат группы (user_id) и время (date).
Предложи схему кросс-валидации: GroupKFold, TimeSeriesSplit или их комбинация.
Объясни, какую утечку предотвращает каждая схема.
Пример: если один пользователь встречается в train и val — метрика завышена. GroupKFold это чинит.
from sklearn.model_selection import GroupKFold, TimeSeriesSplit
import numpy as np
gkf = GroupKFold(n_splits=5)
for tr, val in gkf.split(X, y, groups=df["user_id"]):
assert set(df["user_id"].iloc[tr]).isdisjoint(df["user_id"].iloc[val])
tscv = TimeSeriesSplit(n_splits=5)
for tr, val in tscv.split(X):
assert df["date"].iloc[tr].max() <= df["date"].iloc[val].min()
9. Калибровка вероятностей
Задача: чтобы predict_proba действительно означал вероятность.
Промт:
Модель — градиентный бустинг, задача — бинарная классификация.
Проверь калибровку (Brier score, reliability curve) и предложи метод:
Platt scaling или isotonic. Объясни, когда какой лучше.
Пример: бустинги часто переуверены. Isotonic работает лучше на больших выборках, Platt — на малых.
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.metrics import brier_score_loss
cal = CalibratedClassifierCV(base_model, method="isotonic", cv=5)
cal.fit(X_train, y_train)
proba = cal.predict_proba(X_val)[:, 1]
print("Brier:", brier_score_loss(y_val, proba).round(4))
10. Анализ ошибок модели
Задача: понять, где именно модель ломается, а не смотреть на одну цифру метрики.
Промт:
Вот confusion matrix и ошибки по сегментам (регион, канал, возраст).
Найди сегменты с аномально высокой ошибкой.
Предложи 3 гипотезы, почему модель там ошибается, и как это проверить.
Пример: LLM замечает, что F1 падает на новом регионе — вероятно, мало обучающих примеров или сдвиг распределения.
import pandas as pd
val = X_val.copy()
val["y_true"] = y_val
val["y_pred"] = model.predict(X_val)
report = val.groupby("region").apply(
lambda g: pd.Series({
"n": len(g),
"acc": (g.y_true == g.y_pred).mean(),
})
)
print(report.sort_values("acc"))
11. Интерпретация модели через SHAP
Задача: объяснить модель бизнесу и себе.
Промт:
Вот SHAP summary (top-15 признаков) для бустинга.
Объясни на человеческом языке: что модель считает важным,
какие есть нелинейности и взаимодействия. Отметь признаки,
которые могут быть утечкой.
Пример: если топ-признак — id_клиента, это почти наверняка утечка.
import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_val)
shap.summary_plot(shap_values, X_val, max_display=15)
12. Отчёт по эксперименту
Задача: зафиксировать, что сделано, чтобы через месяц не гадать.
Промт:
Вот параметры эксперимента: данные, фичи, модель, метрики, CV.
Составь структурированный отчёт: гипотеза, изменения, результат,
что дальше. Укажи, какие метрики выросли/упали и на сколько.
Пример: перед мержем ветки в main — генерируешь отчёт и прикладываешь к PR. Коллеги видят контекст, а не только diff.
import json
experiment = {
"features": "+target_encoding, +hour_sin_cos",
"model": "HistGradientBoosting",
"cv": "GroupKFold(5)",
"roc_auc": 0.842,
"prev_roc_auc": 0.831,
}
print(json.dumps(experiment, ensure_ascii=False, indent=2))
Что важно помнить
LLM ускоряет рутину, но не отменяет базовых принципов: любая утечка данных, неправильная схема CV или некалиброванные вероятности испортят результат, каким бы красивым ни был код. Промты выше — это ускорители, а не замена мышлению. Проверяй каждый предложенный признак на утечку, каждую метрику — на соответствие бизнес-задаче, каждую схему валидации — на реалистичность продакшена.
Начни с первых трёх промтов на текущем датасете — профиль, пропуски, гипотезы. Часто уже на этом этапе становится видно, что модель строить рано: данных мало, таргет шумный или фичи протекают. Лучше узнать это за час, чем за неделю прогонов. Сохрани подборку в свой промпт-менеджер и адаптируй под стек — большинство формулировок переносится с pandas на polars и PySpark почти без изменений.
Комментарии