用 Python 做线性回归:分析广告费用和销售额的关系
用 Python 做线性回归:分析广告费用和销售额的关系
大家好~今天我们用 Python 来搞清楚一个实用问题:公司花的广告费用,和最终的销售额到底有啥关系? 很多企业都想知道 “广告费花得值不值”,而「线性回归」就是一个能帮我们找规律的工具~
一、准备 “武器” 和 “原材料”
要完成分析,得先准备好两个关键部分:
1. 工具库(Python 第三方库)
我们需要这几个 “帮手”:
-
numpy:帮我们高效处理数字和数组; -
matplotlib:把数据画成图,让关系更直观; -
sklearn:里面有现成的「线性回归模型」,还能评估模型好不好用。
2. 数据(广告费用和销售额)
题目里给了这样一组数据(简化理解:左边是广告费,右边是对应销售额,单位都是万元):
| 广告费用 | 10 | 13 | 22 | 37 | 45 | 48 | 59 | 65 | 66 | 68 | 68 | 71 | 84 | 88 | 89 | 89 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 销售额 | 19 | 60 | 71 | 74 | 69 | 89 | 146 | 130 | 153 | 144 | 128 | 123 | 127 | 125 | 154 | 150 |
把这些数据整理成 Python 能识别的格式:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
# 广告费用(注意:要变成“二维数组”,因为模型需要这样的格式)
X = np.array([10, 13, 22, 37, 45, 48, 59, 65, 66, 68, 68, 71, 84, 88, 89, 89]).reshape(-1, 1)
# 对应的销售额
y = np.array([19, 60, 71, 74, 69, 89, 146, 130, 153, 144, 128, 123, 127, 125, 154, 150])
这里reshape(-1, 1)的作用,是把 “一排数字”(广告费用)变成 “一列数字”—— 因为线性回归模型需要这样的格式(就像表格里 “一列是一个特征”)。
二、让模型学会 “广告费→销售额” 的规律
线性回归的核心,是找一条最能代表数据趋势的直线(就像用尺子把散点尽量 “串” 起来)。代码很简单:
# 初始化线性回归模型
model = LinearRegression()
# 让模型“学习”数据里的关系
model.fit(X, y)
# 用模型预测销售额(模型觉得“这个广告费应该对应多少销售额”)
y_pred = model.predict(X)
这一步后,模型就 “学会” 了广告费用和销售额的关系,y_pred就是模型预测的销售额。
三、画图!直观看关系
光看数字太抽象,我们画个图,能更直观看到 “广告费用越高,销售额是不是越高”:
# 画“实际数据”的散点(蓝色点)
plt.scatter(X, y, color='blue', label='实际销售额')
# 画“模型找的直线”(红色线)
plt.plot(X, y_pred, color='red', linewidth=2, label='模型预测的关系')
# 给图加标签
plt.xlabel('广告费用(万元)')
plt.ylabel('销售额(万元)')
plt.title('广告费用和销售额的关系')
plt.legend() # 显示图例(区分实际数据和模型线)
plt.show() # 显示图片
运行后会弹出一个图:蓝色点是实际的 “广告费 - 销售额”,红色线是模型找的 “最能代表趋势的直线”。能看到:广告费越高,销售额整体确实越高,但不是完美的直线(毕竟现实中还有其他因素影响销售,比如市场环境、产品口碑等)。
四、模型准不准?用 “分数” 和 “残差” 评估
光有图还不够,得用数字指标评估模型准不准。这里介绍两个关键指标:
1. R²:模型的 “解释力打分”
R² 是一个 0 到 1 之间的数,越接近 1,说明模型越准。它的意思是:“销售额的变化,有多少比例能被广告费用解释”。
比如 R² 是 0.69,就表示 “销售额 69% 的变化能被广告费用解释”,剩下 31% 是其他因素(比如促销活动、季节等)导致的。
计算 R² 很简单:
r2 = r2_score(y, y_pred)
print(f"模型的R²分数:{r2:.2f}")
2. 残差:模型 “哪里猜错了”
残差的定义很简单:残差 = 实际销售额 - 模型预测的销售额。
-
如果残差是 “正数”,说明 “模型预测的销售额比实际低”;
-
如果残差是 “负数”,说明 “模型预测的销售额比实际高”;
-
残差的绝对值越大,说明 “这个点模型猜得越不准”。
我们还可以计算残差平方和(把所有残差的平方加起来)—— 这个值越小,说明模型整体预测误差越小。
代码里这样计算和可视化残差:
# 计算每个数据点的残差
residuals = y - y_pred
# 计算残差平方和
ss_res = np.sum(residuals ** 2)
# 计算“总平方和”(可以理解为“数据本身的波动有多大”)
ss_total = np.sum((y - np.mean(y)) ** 2)
# 打印结果
print(f"每个点的残差(实际-预测):{residuals.round(2)}")
print(f"残差平方和:{ss_res:.2f}")
print(f"总平方和:{ss_total:.2f}")
# 把残差画出来(实际点到预测线的竖线)
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color='blue', label='实际销售额')
plt.plot(X, y_pred, color='red', label='模型预测')
# 画“残差的竖线”(实际值到预测线的距离)
for x, y_actual, y_predicted in zip(X, y, y_pred):
plt.plot([x, x], [y_actual, y_predicted], color='green', linestyle='--')
plt.xlabel('广告费用(万元)')
plt.ylabel('销售额(万元)')
plt.title('广告费用、销售额与残差')
plt.legend()
plt.show()
运行后,图里的绿色虚线就是残差 —— 线越长,说明模型在这个 “广告费” 上的预测误差越大。
五、总结:广告费值不值?
1.完整代码与截图
# 完整代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
# 中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
# 准备数据
X = np.array([10, 13, 22, 37, 45, 48, 59, 65, 66, 68, 68, 71, 84, 88, 89, 89]).reshape(-1, 1)
y = np.array([19, 60, 71, 74, 69, 89, 146, 130, 153, 144, 128, 123, 127, 125, 154, 150])
# 构建并训练模型
model = LinearRegression()
model.fit(X, y)
y_pred = model.predict(X)
# 计算残差值(实际值 - 预测值)
residuals = y - y_pred
# 计算残差平方和(Sum of Squared Errors, SSE)
ss_res = np.sum(residuals **2)
# 计算总平方和(Total Sum of Squares, SST)
ss_total = np.sum((y - np.mean(y))** 2)
# 绘制结果(包含残差可视化)
plt.figure(figsize=(12, 7))
# 绘制实际数据和拟合线
plt.scatter(X, y, color='blue', label='实际销售额')
plt.plot(X, y_pred, color='red', linewidth=2, label='线性回归拟合')
# 绘制残差线段(实际值到拟合线的垂直线)
for x, y_actual, y_predicted in zip(X, y, y_pred):
plt.plot([x, x], [y_actual, y_predicted], color='green', linestyle='--', linewidth=1)
plt.xlabel('广告费用(万元)')
plt.ylabel('销售额(万元)')
plt.title('广告费用与销售额的线性回归(含残差)')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
# 输出评估指标
print(f"残差值(实际-预测):{residuals.round(4)}")
print(f"残差平方和(SSE):{ss_res.round(4)}")
print(f"总平方和(SST):{ss_total.round(4)}")
print(f"R²值:{r2_score(y, y_pred).round(4)}")
# 验证R²与平方和的关系:R² = 1 - (SS_res / SS_total)
print(f"验证R²值:{ (1 - ss_res/ss_total).round(4) }")

2.通过线性回归分析,我们能得到两个核心结论:
-
趋势明确:广告费用越高,销售额整体越高(红色直线向上倾斜);
-
存在其他影响:模型的 R² 不是 1(比如实际运行可能得到 0.69 左右),说明 “除了广告费,还有其他因素影响销售额”(比如品牌知名度、竞品动作等)。
残差和残差平方和,则能帮我们定位 “模型哪里预测得不准”,后续可以针对这些 “误差大的点” 分析原因(比如某段时间有特殊促销,导致销售额和广告费的关系不符合常规)。
如果想让模型更准,还可以加入更多因素(比如是否有大型促销、季节因素等),但线性回归已经能帮我们理解 **“广告费和销售额最核心的关系”** 啦~
希望这篇内容能让你轻松搞懂线性回归的应用~如果有问题,欢迎留言交流~
(注:实际运行代码时,数值结果会有具体输出,比如 R² 可能是0.7861左右,残差平方和也会有具体数字,大家可以自己跑一跑代码看看~)
更多推荐

所有评论(0)