改进广告投入与销售额预测分析
文章目录
- 一、研究问题
- 二、数据与预处理
- 三、建模流程
- 四、主要结果与分析
- 五、结论
- 代码附录
基于Python机器学习/利用广告投入预测销售额,尝试使用Pipeline进行优化,并通过statsmodels输出详细的统计量和置信区间。
一、研究问题
在实际商业运营中,企业常常需要根据不同渠道的广告投入(如电视、广播、报纸)来预测产品的销售额。如何利用历史数据,建立一个销售预测模型?本项目旨在探索:“广告投入的不同渠道对销售额的影响有多大?能否通过标准化和线性回归等方法,建立一个带有置信区间的销售预测模型?”
二、数据与预处理
- 数据集包含广告投入(TV、Radio、Newspaper)和对应的销售额(Sales)。
- 检查数据完整性,无缺失值。
- 选取TV、Radio、Newspaper三项作为特征,Sales为目标变量。
- 对特征进行标准化处理,消除量纲影响。
三、建模流程
- 数据集划分:将数据集分为训练集和测试集,保证模型评估的客观性。
# 数据划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("数据准备完成。")
print(f"训练集特征形状: {X_train.shape}")
print(f"测试集特征形状: {X_test.shape}")
- 构建Scikit-learn管道:使用Pipeline将标准化(StandardScaler)和线性回归(LinearRegression)整合到一个自动化流程中。这样可以保证数据预处理和建模的一致性,减少数据泄漏风险。
# 构建并拟合 Scikit-learn 管道
# 管道包含标准化和线性回归模型
pipeline = Pipeline([('scaler', StandardScaler()),('regressor', LinearRegression())
])
- 模型训练与评估:在训练集上拟合模型,在测试集上预测销售额。通过计算均方误差(MSE)和决定系数(R²),量化模型性能。
# 拟合整个管道到训练数据
pipeline.fit(X_train, y_train)
# 使用管道进行预测 (获取点预测)
predictions_sklearn = pipeline.predict(X_test)
# 评估 Scikit-learn 管道模型
mse_sklearn = mean_squared_error(y_test, predictions_sklearn)
r2_sklearn = r2_score(y_test, predictions_sklearn)
print(f'\n--- Scikit-learn Pipeline 评估 ---')
print(f'Mean Squared Error (MSE): {mse_sklearn:.2f}')
print(f'R-squared (R²): {r2_sklearn:.2f}')
- 模型参数解释:输出回归系数,分析各广告渠道对销售额的影响。
- 结合Statsmodels获取置信区间:用statsmodels对标准化数据进行回归,获得详细统计摘要和每个预测值的95%置信区间。
- 结果可视化 :绘制实际销售额、预测值及其置信区间,直观展示模型效果和不确定性。
四、主要结果与分析
- 统计摘要(部分)
-
R-squared: 0.900,模型能解释90%的销售额方差,拟合效果优秀。
-
Adj. R-squared: 0.898,调整后的R²考虑了特征数量,依然很高,说明模型没有过拟合。
-
F-statistic: 468.7, Prob (F-statistic): 8.51e-78,F检验显著,p值极小,说明至少有一个特征对销售额有显著影响。
-
coef(系数)
- const(截距):15.3306,表示当所有特征为均值时,预测销售额约为15.33。
- TV:4.5872,说明TV广告投入每增加一个标准差,销售额平均增加4.59。
- Radio:1.4898,广播广告投入每增加一个标准差,销售额平均增加1.49。
- Newspaper:0.0879,报纸广告投入影响很小,且p值为0.537(远大于0.05),说明统计上不显著。
-
std err, t, P>|t|, [0.025, 0.975]
分别为系数的标准误、t检验统计量、p值和95%置信区间。TV和Radio的p值都远小于0.05,说明它们对销售额有显著正向影响。 -
其他诊断指标
- Durbin-Watson: 2.108,接近2,说明残差无自相关问题。
- Omnibus、Jarque-Bera等用于检验残差的正态性。
- 预测与置信区间
Actual | Predicted_Mean | Lower_CI | Upper_CI |
---|---|---|---|
16.9 | 17.03 | 13.74 | 20.33 |
22.4 | 20.41 | 17.09 | 23.73 |
7.3 | 9.27 | 5.95 | 12.60 |
24.7 | 21.68 | 18.32 | 25.05 |
- Predicted_Mean:模型对每个样本的销售额预测值。
- Lower_CI / Upper_CI:该预测值的95%置信区间,表示模型预测的区间范围,反映了不确定性。
- Actual:实际观测值。可以看到,大部分实际值都落在置信区间内,说明模型预测可靠。
3. 可视化:通过散点图和置信区间带,直观展示了模型预测的准确性和可信度。
五、结论
结果显示,TV和Radio广告投入对销售额有显著正向影响,报纸广告影响不显著。模型拟合优良,预测值大多落在置信区间内,说明模型不仅准确,而且能量化预测的不确定性。通过statsmodels输出的详细统计量和置信区间,提升了模型的可解释性和业务参考价值。
代码附录
# 导入必要的库
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.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score# 导入 statsmodels
import statsmodels.api as sm# 1. 读取数据
df = pd.read_csv('advertising.csv')# 2. 定义特征 X 和目标 y
X = df[['TV', 'Radio', 'Newspaper']]
y = df['Sales']# 3. 数据划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("数据准备完成。")
print(f"训练集特征形状: {X_train.shape}")
print(f"测试集特征形状: {X_test.shape}")# 4. 构建并拟合 Scikit-learn 管道
# 管道包含标准化和线性回归模型
pipeline = Pipeline([('scaler', StandardScaler()),('regressor', LinearRegression())
])# 拟合整个管道到训练数据
pipeline.fit(X_train, y_train)# 使用管道进行预测 (获取点预测)
predictions_sklearn = pipeline.predict(X_test)# 评估 Scikit-learn 管道模型
mse_sklearn = mean_squared_error(y_test, predictions_sklearn)
r2_sklearn = r2_score(y_test, predictions_sklearn)
print('\n--- Scikit-learn Pipeline 评估 ---')
print(f'Mean Squared Error (MSE): {mse_sklearn:.2f}')
print(f'R-squared (R²): {r2_sklearn:.2f}')# 访问管道内部的线性回归模型参数
linear_model_in_pipeline = pipeline.named_steps['regressor']
print(f'Pipeline Model Intercept: {linear_model_in_pipeline.intercept_:.2f}')
print(f'Pipeline Model Coefficients (Standardized Data): {linear_model_in_pipeline.coef_}')# --- 结合 Statsmodels 获取置信区间 ---
# 5. 从管道中提取经过标准化处理的训练和测试数据
scaler = pipeline.named_steps['scaler']
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)# 将标准化后的数据转换回 DataFrame
X_train_scaled_df = pd.DataFrame(X_train_scaled, columns=X_train.columns, index=X_train.index)
X_test_scaled_df = pd.DataFrame(X_test_scaled, columns=X_test.columns, index=X_test.index)
print(X_train_scaled_df.head())# 6. 使用 statsmodels 训练模型并获取置信区间
# statsmodels 需要手动添加截距项
X_train_sm = sm.add_constant(X_train_scaled_df)
model_sm = sm.OLS(y_train, X_train_sm)
results_sm = model_sm.fit()print("\n--- Statsmodels 模型摘要 (基于标准化数据) ---")
print(results_sm.summary())# 为标准化后的测试集数据添加常数项,用于预测
X_test_sm = sm.add_constant(X_test_scaled_df)# 获取预测值和95%的预测区间 (Prediction Interval)
# 'obs_ci_lower' 和 'obs_ci_upper' 是单个观测值的预测区间
predictions_sm_df = results_sm.get_prediction(X_test_sm).summary_frame(alpha=0.05)predicted_mean_sm = predictions_sm_df['mean']
lower_bound_sm = predictions_sm_df['obs_ci_lower']
upper_bound_sm = predictions_sm_df['obs_ci_upper']print("\n测试集预测结果及95%置信区间 (来自Statsmodels):")
output_df = pd.DataFrame({'Actual': y_test,'Predicted_Mean': predicted_mean_sm,'Lower_CI': lower_bound_sm,'Upper_CI': upper_bound_sm
}).reset_index(drop=True)
print(output_df.head())# 7. 可视化预测值和置信区间
plt.figure(figsize=(12, 8))
# 绘制实际销售额
plt.scatter(range(len(y_test)), y_test, color='blue', label='Actual Sales', alpha=0.7)
# 绘制预测销售额
plt.scatter(range(len(y_test)), predicted_mean_sm, color='red', label='Predicted Sales (Mean)', alpha=0.7)
# 绘制预测区间
plt.fill_between(range(len(y_test)), lower_bound_sm, upper_bound_sm, color='gray', alpha=0.2, label='95% Prediction Interval')plt.xlabel('Test Sample Index')
plt.ylabel('Sales')
plt.title('Actual, Predicted Sales, and 95% Prediction Interval on Test
博客内容如有错误欢迎指正~
欢迎大家留言交流,也可以在评论区分享你的思路和改进建议!