用 Python 做线性回归:分析广告费用和销售额的关系

大家好~今天我们用 Python 来搞清楚一个实用问题:公司花的广告费用,和最终的销售额到底有啥关系? 很多企业都想知道 “广告费花得值不值”,而「线性回归」就是一个能帮我们找规律的工具~

一、准备 “武器” 和 “原材料”

要完成分析,得先准备好两个关键部分:

1. 工具库(Python 第三方库)

我们需要这几个 “帮手”:

  • numpy:帮我们高效处理数字和数组;

  • matplotlib:把数据画成图,让关系更直观;

  • sklearn:里面有现成的「线性回归模型」,还能评估模型好不好用。

2. 数据(广告费用和销售额)

题目里给了这样一组数据(简化理解:左边是广告费,右边是对应销售额,单位都是万元):

广告费用10132237454859656668687184888989
销售额196071746989146130153144128123127125154150

把这些数据整理成 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左右,残差平方和也会有具体数字,大家可以自己跑一跑代码看看~)

更多推荐