基于逻辑回归的优惠券核销预测模型实现(附完整代码)

一、项目背景

某超市希望通过历史优惠券核销数据,建立精准营销模型以识别高潜力客户。数据包含客户性别、年龄、消费水平、商品品类等特征,目标是通过逻辑回归模型预测客户核销优惠券的概率。

二、实现步骤详解

1. 数据加载与预览

import pandas as pd

# 加载数据
df = pd.read_csv("优惠券核销数据.csv")

# 数据概览
print("数据前5行:")
display(df.head())
print("\n数据基本信息:")
print(df.info())
print("\n数据统计描述:")
display(df.describe())

 

输出说明

  • 包含5个特征:是否核销(Accepted)、性别(Sex)、年龄(Age)、液奶品类(Class)、平均消费额(AvgSpending)
  • 数据类型验证(无缺失值)

2. 数据可视化分析

import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示
plt.figure(figsize=(15, 10))

# 性别与核销关系
plt.subplot(2, 2, 1)
sns.countplot(x='Sex', hue='Accepted', data=df)
plt.title('不同性别优惠券核销情况')

# 年龄段与核销关系
plt.subplot(2, 2, 2)
sns.countplot(x='Age', hue='Accepted', data=df)
plt.title('不同年龄段优惠券核销情况')

# 商品品类与核销关系
plt.subplot(2, 2, 3)
sns.countplot(x='Class', hue='Accepted', data=df)
plt.title('不同液奶品类优惠券核销情况')

# 平均消费额分布
plt.subplot(2, 2, 4)
sns.histplot(data=df, x='AvgSpending', hue='Accepted', multiple='stack', kde=True)
plt.title('平均消费额分布与核销关系')

plt.tight_layout()
plt.show()

 

3. 数据预处理

from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder

# 特征工程
X = df.drop('Accepted', axis=1)
y = df['Accepted']

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 预处理管道
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), ['AvgSpending']),  # 数值标准化
        ('cat', OneHotEncoder(drop='first'), ['Sex', 'Age', 'Class'])  # 类别编码
    ])

处理要点

  • 类别特征独热编码(避免顺序影响)
  • 数值特征标准化(加速模型收敛)
  • 保留20%数据用于最终验证

4. 模型构建与训练

from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

# 构建流水线
model = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', LogisticRegression(max_iter=1000, solver='lbfgs'))
])

# 训练模型
model.fit(X_train, y_train)

1. 准确率(Accuracy):0.78

表示整体预测的准确程度。模型在测试集上正确预测了78%的样本。

2. 混淆矩阵

混淆矩阵展示了模型在不同类别上的预测结果,分为“实际未核销”和“实际已核销”两列,以及“预测未核销”和“预测已核销”两行。

预测未核销预测已核销
实际未核销4120
实际已核销2098
  • 实际未核销(61个样本)

    • 41个被正确预测为未核销(True Negative)。

    • 20个被错误预测为已核销(False Positive)。

  • 实际已核销(118个样本)

    • 98个被正确预测为已核销(True Positive)。

    • 20个被错误预测为未核销(False Negative)。

3. 分类报告

分类报告提供了每个类别的详细性能指标,包括精确率(Precision)、召回率(Recall)、F1分数(F1-score)和支持(Support)。

类别PrecisionRecallF1-scoreSupport
未核销0.670.670.6761
已核销0.830.830.83118

未核销类别:

  • Precision(精确率):0.67
    在预测为未核销的样本中,67%是实际未核销。

  • Recall(召回率):0.67
    实际未核销的样本中,67%被正确识别。

  • F1-score:0.67
    Precision和Recall的调和平均值,综合性能指标。

已核销类别:

  • Precision(精确率):0.83
    在预测为已核销的样本中,83%是实际已核销。

  • Recall(召回率):0.83
    实际已核销的样本中,83%被正确识别。

  • F1-score:0.83
    综合性能指标。

宏观平均(Macro Avg)和加权平均(Weighted Avg):

  • Macro Avg

    • Precision: 0.75

    • Recall: 0.75

    • F1-score: 0.75

    • 对所有类别同等权重的平均值,不考虑样本数量。

  • Weighted Avg

    • Precision: 0.78

    • Recall: 0.78

    • F1-score: 0.78

    • 根据样本数量加权的平均值,更符合实际分布。

 

 

参数说明

  • max_iter=1000:确保模型充分收敛
  • solver='lbfgs':适合小规模数据集

5. 模型评估

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_curve, roc_auc_score

# 预测与评估
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:, 1]

print(f"准确率:{accuracy_score(y_test, y_pred):.2f}")
print("混淆矩阵:")
print(pd.DataFrame(confusion_matrix(y_test, y_pred),
                   index=['实际未核销','实际已核销'],
                   columns=['预测未核销','预测已核销']))

print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['未核销','已核销']))

# 绘制ROC曲线
fpr, tpr, _ = roc_curve(y_test, y_proba)
plt.plot(fpr, tpr, label=f'AUC={roc_auc_score(y_test, y_proba):.2f}')
plt.plot([0,1],[0,1],'--')
plt.title('ROC曲线')
plt.xlabel('假阳性率')
plt.ylabel('真阳性率')
plt.legend()
plt.show()

 

6. 特征重要性分析

# 获取特征名称
ohe = model.named_steps['preprocessor'].transformers_[1][1]
feature_names = ['AvgSpending'] + list(ohe.get_feature_names_out(['Sex','Age','Class']))

# 可视化系数
coef = model.named_steps['classifier'].coef_[0]
pd.DataFrame({'特征': feature_names, '系数': coef}).sort_values('系数').plot(
    x='特征', y='系数', kind='barh', 
    title='特征对核销概率的影响(正值促进核销)'
)
plt.show()

 

  • 横轴 :表示逻辑回归系数,正值表示促进核销,负值表示抑制核销。

  • 纵轴 :列出了各个特征的名称,包括 Age_2、AvgSpending、Class_2、Class_3 和 Sex_2。

  • 数据解读

    • Age_2 :逻辑回归系数约为 0.434,在所列特征中对核销概率的促进作用最明显,意味着在 Age 这一特征的某种取值情况下(可能对应年龄的一个区间或类别),核销概率会增加。

    • AvgSpending :对核销概率有一定的抑制作用,系数约为 -0.089。

    • _Class2 :对核销概率有抑制作用,系数约为 -1.096。

    • Class_3 :对核销概率有较大的抑制作用,系数约为 -1.973。

    • Sex_2 :对核销概率的抑制作用最为显著,系数约为 -2.475,在所列特征中对核销概率的阻碍作用最大。

三、完整代码

 

# 导入必要库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, roc_curve, roc_auc_score, classification_report
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline

# 设置中文显示(解决坐标轴中文乱码)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题

# 1. 数据加载与预览
print("数据预览:")
df = pd.read_csv(r'd:\Users\Administrator\Desktop\实验四\优惠券核销数据.csv')
display(df.head())
print("\n数据基本信息:")
print(df.info())
print("\n数据统计描述:")
display(df.describe())

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

# 2. 数据可视化分析
plt.figure(figsize=(15, 10))

# 性别与核销关系
plt.subplot(2, 2, 1)
sns.countplot(x='Sex', hue=df['Accepted'].astype(str), data=df)
plt.title('不同性别优惠券核销情况')
plt.xlabel('性别(1=女,2=男)')
plt.ylabel('人数')
plt.legend(['未核销', '已核销'])

# 年龄段与核销关系
plt.subplot(2, 2, 2)
sns.countplot(x='Age', hue=df['Accepted'].astype(str), data=df)
plt.title('不同年龄段优惠券核销情况')
plt.xlabel('年龄段(1=中青年,2=中老年)')
plt.ylabel('人数')
plt.legend(['未核销', '已核销'])

# 商品品类与核销关系
plt.subplot(2, 2, 3)
sns.countplot(x='Class', hue=df['Accepted'].astype(str), data=df)
plt.title('不同液奶品类优惠券核销情况')
plt.xlabel('液奶品类(1=低端,2=中档,3=高端)')
plt.ylabel('人数')
plt.legend(['未核销', '已核销'])

# 平均消费额分布
plt.subplot(2, 2, 4)
sns.histplot(data=df, x='AvgSpending', hue='Accepted', multiple='stack', kde=True)
plt.title('平均消费额分布与核销关系')
plt.xlabel('平均消费额(元)')
plt.ylabel('人数')

plt.tight_layout()
plt.show()

# 3. 数据预处理
# 定义特征和目标变量
X = df.drop('Accepted', axis=1)
y = df['Accepted']

# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 预处理管道
categorical_features = ['Sex', 'Age', 'Class']
numerical_features = ['AvgSpending']

preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numerical_features),
        ('cat', OneHotEncoder(drop='first'), categorical_features)
    ])

# 4. 模型训练

model = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', LogisticRegression(max_iter=1000, solver='lbfgs', verbose=1))
])

model.fit(X_train, y_train)

# 5. 模型评估
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]

# 输出评估指标
print("\n模型评估结果:")
print(f"准确率: {accuracy_score(y_test, y_pred):.2f}")
print("混淆矩阵:\n", pd.DataFrame(confusion_matrix(y_test, y_pred),
                                  index=['实际未核销', '实际已核销'],
                                  columns=['预测未核销', '预测已核销']))
print("\n分类报告:\n", classification_report(y_test, y_pred, target_names=['未核销', '已核销']))

# 绘制ROC曲线
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'ROC曲线 (AUC = {roc_auc_score(y_test, y_pred_proba):.2f})')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlabel('假阳性率')
plt.ylabel('真阳性率')
plt.title('ROC曲线与AUC值')
plt.legend()
plt.show()

# 6. 特征重要性分析
# 获取特征名称
ohe = model.named_steps['preprocessor'].transformers_[1][1]
feature_names = (numerical_features + 
                [f"{col}_{cat}" for col, cats in zip(categorical_features, ohe.categories_) 
                 for cat in cats[1:]])

# 创建系数DataFrame
coef_df = pd.DataFrame({
    '特征名称': feature_names,
    '影响系数': model.named_steps['classifier'].coef_[0]
}).sort_values(by='影响系数', ascending=False)

print("\n特征影响系数排序:")
display(coef_df)

# 可视化特征重要性
plt.figure(figsize=(12, 6))
sns.barplot(x='影响系数', y='特征名称', data=coef_df)
plt.title('特征对核销概率的影响程度')
plt.xlabel('逻辑回归系数(正值促进核销,负值抑制核销)')
plt.show()

# 7. 模型参数输出
print("\n模型训练详情:")
print(f"最大迭代次数: {model.named_steps['classifier'].max_iter}")
print(f"实际迭代次数: {model.named_steps['classifier'].n_iter_[0]}")
print(f"是否收敛: {'是' if model.named_steps['classifier'].n_iter_ < model.named_steps['classifier'].max_iter else '否'}")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值