← Назад к вопросам
Как подобрать подходящий оффер для клиента?
2.3 Middle🔥 181 комментариев
#Машинное обучение#Рекомендательные системы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как подобрать подходящий оффер для клиента
Задача рекомендации подходящих офферов одна из ключевых в Data Science. Она решает задачу персонализации и значительно влияет на доход компании. Я опишу несколько подходов от простого к сложному, основываясь на реальном опыте.
Подход 1: Демографический скоринг
Выбираем оффер на основе профиля клиента и характеристик оффера:
import pandas as pd
import numpy as np
clients = pd.DataFrame({
"client_id": [1, 2, 3, 4, 5],
"age": [25, 45, 32, 55, 28],
"income": [30000, 80000, 50000, 120000, 35000],
"has_family": [0, 1, 1, 1, 0],
})
offers = pd.DataFrame({
"offer_id": ["A", "B", "C", "D", "E"],
"min_income": [0, 50000, 40000, 100000, 0],
"max_income": [50000, 200000, 100000, 500000, 30000],
"target_age_min": [18, 30, 25, 40, 18],
"target_age_max": [50, 75, 60, 80, 30]
})
def recommend_offers(client_profile, offers_data):
recommended = []
for idx, offer in offers_data.iterrows():
income_match = (
offer["min_income"] <= client_profile["income"] <= offer["max_income"]
)
age_match = (
offer["target_age_min"] <= client_profile["age"] <= offer["target_age_max"]
)
if income_match and age_match:
recommended.append(offer["offer_id"])
return recommended
client = clients.loc[1]
print(recommend_offers(client, offers))
Подход 2: Collaborative Filtering
Рекомендуем офферы, которые нравились похожим клиентам:
from sklearn.metrics.pairwise import cosine_similarity
purchase_history = pd.DataFrame({
"offer_A": [1, 0, 1, 0, 1],
"offer_B": [0, 1, 0, 1, 0],
"offer_C": [1, 1, 1, 0, 1]
}, index=["client_1", "client_2", "client_3", "client_4", "client_5"])
similarity = cosine_similarity(purchase_history)
similarity_df = pd.DataFrame(
similarity,
index=purchase_history.index,
columns=purchase_history.index
)
def collaborative_recommend(target_client, similarity_matrix, purchase_history):
similar_clients = similarity_matrix[target_client].drop(target_client).nlargest(3)
recommendations = {}
for offer in purchase_history.columns:
if purchase_history.loc[target_client, offer] == 0:
score = purchase_history.loc[similar_clients.index, offer].mean()
recommendations[offer] = score
return sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
recs = collaborative_recommend("client_1", similarity_df, purchase_history)
print(recs)
Подход 3: ML-модель для вероятности покупки
Обучаем модель предсказывать, купит ли клиент конкретный оффер:
from sklearn.ensemble import RandomForestClassifier
training_data = []
for client_idx, client_row in clients.iterrows():
for offer_idx, offer_row in offers.iterrows():
features = [
client_row["age"],
client_row["income"],
offer_row["min_income"],
offer_row["max_income"],
offer_row["target_age_min"],
offer_row["target_age_max"]
]
label = np.random.randint(0, 2) # Пример
training_data.append(features + [label])
training_df = pd.DataFrame(training_data, columns=[
"age", "income",
"offer_min_income", "offer_max_income",
"offer_min_age", "offer_max_age",
"purchased"
])
X = training_df.drop(columns=["purchased"])
y = training_df["purchased"]
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)
def ml_recommend(client_id, client_data, offers_data, model):
client = client_data.loc[client_id]
predictions = []
for offer_idx, offer in offers_data.iterrows():
features = np.array([[
client["age"],
client["income"],
offer["min_income"],
offer["max_income"],
offer["target_age_min"],
offer["target_age_max"]
]])
prob = model.predict_proba(features)[0, 1]
predictions.append({
"offer_id": offer["offer_id"],
"probability": prob
})
predictions_df = pd.DataFrame(predictions).sort_values(
by="probability",
ascending=False
)
return predictions_df.head(3)
print(ml_recommend(0, clients, offers, model))
Подход 4: A/B тестирование рекомендаций
Валидируем на реальных данных:
from scipy import stats
control_group = {"shown": 1000, "purchased": 120}
test_group = {"shown": 1000, "purchased": 165}
control_cr = control_group["purchased"] / control_group["shown"]
test_cr = test_group["purchased"] / test_group["shown"]
print(f"Control: {control_cr:.4f}")
print(f"Test: {test_cr:.4f}")
print(f"Improvement: {(test_cr - control_cr) / control_cr * 100:.2f} percent")
contingency_table = [
[control_group["purchased"], control_group["shown"] - control_group["purchased"]],
[test_group["purchased"], test_group["shown"] - test_group["purchased"]]
]
chi2, p_value = stats.chi2_contingency(contingency_table)[:2]
if p_value < 0.05:
print("Improvement is statistically significant")
else:
print("Need more data")
Гибридный подход (рекомендуемый)
Комбинируем несколько методов с взвешиванием:
def hybrid_recommend(
client_id,
clients_df,
offers_df,
purchase_history_df,
ml_model,
weights=None
):
if weights is None:
weights = {
"content": 0.3,
"collaborative": 0.3,
"ml": 0.4
}
all_offers = list(offers_df["offer_id"])
combined_scores = {}
for offer in all_offers:
client = clients_df.loc[client_id]
# Content-based score
offer_row = offers_df[offers_df["offer_id"] == offer].iloc[0]
content_score = (
(offer_row["min_income"] <= client["income"] <= offer_row["max_income"]) and
(offer_row["target_age_min"] <= client["age"] <= offer_row["target_age_max"])
)
# ML score
features = np.array([[
client["age"],
client["income"],
offer_row["min_income"],
offer_row["max_income"],
offer_row["target_age_min"],
offer_row["target_age_max"]
]])
ml_score = ml_model.predict_proba(features)[0, 1]
# Combined
combined_scores[offer] = (
weights["content"] * (1.0 if content_score else 0.0) +
weights["collaborative"] * 0.5 +
weights["ml"] * ml_score
)
ranked = sorted(
combined_scores.items(),
key=lambda x: x[1],
reverse=True
)
return ranked[:3]
final_recs = hybrid_recommend(
0, clients, offers, purchase_history, model
)
print(final_recs)
Ключевые метрики
- Click-Through Rate (CTR): процент кликов на рекомендацию
- Conversion Rate (CR): процент кликов, приведших к покупке
- Average Order Value (AOV): средняя стоимость заказа
- Precision@K: процент релевантных офферов среди топ K
- NDCG: учитывает позицию в списке рекомендаций
Лучшие практики
- Начни с простого правила (демографические признаки)
- Добавь ML модель для улучшения
- Всегда А/B тести перед deployment
- Мониторь бизнес-метрики в production
- Регулярно переучивай модель на новых данных
- Избегай холодного старта (cold start problem) для новых клиентов
Для production-системы используй гибридный подход с регулярным A/B тестированием и мониторингом метрик.