用 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.通过线性回归分析,我们能得到两个核心结论:

  1. 趋势明确:广告费用越高,销售额整体越高(红色直线向上倾斜);

  2. 存在其他影响:模型的 R² 不是 1(比如实际运行可能得到 0.69 左右),说明 “除了广告费,还有其他因素影响销售额”(比如品牌知名度、竞品动作等)。

残差和残差平方和,则能帮我们定位 “模型哪里预测得不准”,后续可以针对这些 “误差大的点” 分析原因(比如某段时间有特殊促销,导致销售额和广告费的关系不符合常规)。

如果想让模型更准,还可以加入更多因素(比如是否有大型促销、季节因素等),但线性回归已经能帮我们理解 **“广告费和销售额最核心的关系”** 啦~

希望这篇内容能让你轻松搞懂线性回归的应用~如果有问题,欢迎留言交流~

(注:实际运行代码时,数值结果会有具体输出,比如 R² 可能是0.7861左右,残差平方和也会有具体数字,大家可以自己跑一跑代码看看~)

更多推荐