🤔 什么是线性回归?
想象你在预测房价:
- 你知道房子的面积越大,价格通常越高
- 你也发现房间越多,价格也会上涨
- 但你想要一个具体的数值预测,而不只是"大概会贵一些"
线性回归就是找一条直线,用这条直线来预测数值。
📈 生活中的直线关系
例子1:学习时间与成绩
成绩 = 50 + 10 × 学习时间
- 不学习也能得50分(基础分)
- 每学习1小时,成绩提高10分
- 学习5小时,预计成绩 = 50 + 10×5 = 100分
例子2:工作年限与工资
工资 = 3000 + 500 × 工作年限
- 刚毕业3000元起薪
- 每多工作1年,工资涨500元
🎯 线性回归的核心思想
🔍 找最佳拟合直线
现实中的数据点往往不是完美地在一条直线上:
房价(万)
↑
| ●
| ●
|● ●
| ●
| ●
+------------------→ 面积(㎡)
我们要找一条直线,让所有点到这条直线的垂直距离之和最小。
这条线就是我们的预测模型!
📐 数学表达
线性回归方程:
y = wx + b
其中:
- y:要预测的值(比如房价)
- x:输入的特征(比如面积)
- w:权重/斜率(面积每增加1㎡,房价增加w万)
- b:偏置/截距(当面积为0时的基础房价)
🛠️ 用Python实现线性回归
方法1:手工实现(理解原理)
import numpy as np
import matplotlib.pyplot as plt
class SimpleLinearRegression:
def __init__(self):
self.w = 0 # 权重
self.b = 0 # 偏置
def fit(self, X, y):
"""
训练模型:找到最佳的w和b
使用最小二乘法
"""
# 将数据转换为numpy数组
X = np.array(X)
y = np.array(y)
# 最小二乘法公式:
# w = Σ[(xi - x̄)(yi - ȳ)] / Σ[(xi - x̄)²]
# b = ȳ - w*x̄
x_mean = np.mean(X)
y_mean = np.mean(y)
numerator = np.sum((X - x_mean) * (y - y_mean))
denominator = np.sum((X - x_mean) ** 2)
self.w = numerator / denominator
self.b = y_mean - self.w * x_mean
print(f"训练完成!")
print(f"直线方程: y = {self.w:.2f}x + {self.b:.2f}")
def predict(self, X):
"""预测"""
return self.w * np.array(X) + self.b
def score(self, X, y):
"""计算R²决定系数(衡量拟合好坏)"""
X = np.array(X)
y = np.array(y)
predictions = self.predict(X)
# 总平方和
ss_tot = np.sum((y - np.mean(y)) ** 2)
# 残差平方和
ss_res = np.sum((y - predictions) ** 2)
r_squared = 1 - (ss_res / ss_tot)
return r_squared
# 准备房价数据:面积(㎡) -> 价格(万)
areas = [50, 80, 100, 120, 150, 180, 200, 220, 250, 280]
prices = [80, 120, 150, 180, 220, 260, 290, 320, 360, 400]
# 创建并训练模型
model = SimpleLinearRegression()
model.fit(areas, prices)
# 预测
test_areas = [60, 130, 200, 300]
predicted_prices = model.predict(test_areas)
print(f"\n预测结果:")
for area, price in zip(test_areas, predicted_prices):
print(f"面积{area}㎡ -> 预测价格{price:.1f}万")
# 评估模型
r2 = model.score(areas, prices)
print(f"\n模型表现:R² = {r2:.3f} (越接近1越好)")
运行结果:
训练完成!
直线方程: y = 1.43x + 8.57
预测结果:
面积60㎡ -> 预测价格94.5万
面积130㎡ -> 预测价格194.1万
面积200㎡ -> 预测价格295.0万
面积300㎡ -> 预测价格437.9万
模型表现:R² = 0.992 (越接近1越好)
方法2:使用sklearn(实际应用)
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
# 准备数据(注意:sklearn要求二维数组)
X = np.array(areas).reshape(-1, 1) # 转换成n×1的矩阵
y = np.array(prices)
# 创建模型
sk_model = LinearRegression()
# 训练模型
sk_model.fit(X, y)
# 查看学到的参数
print(f"sklearn训练结果:")
print(f"权重w: {sk_model.coef_[0]:.2f}")
print(f"偏置b: {sk_model.intercept_:.2f}")
print(f"方程: y = {sk_model.coef_[0]:.2f}x + {sk_model.intercept_:.2f}")
# 预测
test_X = np.array(test_areas).reshape(-1, 1)
sk_predictions = sk_model.predict(test_X)
# 评估
sk_r2 = r2_score(y, sk_model.predict(X))
sk_mse = mean_squared_error(y, sk_model.predict(X))
print(f"\nsklearn模型表现:")
print(f"R² = {sk_r2:.3f}")
print(f"均方误差 = {sk_mse:.2f}")
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(areas, prices, color='blue', label='实际数据')
plt.plot(areas, sk_model.predict(X), color='red', linewidth=2, label='拟合直线')
plt.xlabel('面积(㎡)')
plt.ylabel('价格(万)')
plt.title('房价与面积的关系')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
🔍 深入理解:损失函数
📉 什么是损失函数?
损失函数衡量预测值与真实值的差距。我们希望这个差距越小越好。
对于线性回归,常用均方误差(MSE):
MSE = (1/n) × Σ(yi - ŷi)²
其中:
- yi:真实值
- ŷi:预测值
- n:数据点个数
🎯 梯度下降优化
当数据比较复杂时,我们不能直接用公式求解,需要用梯度下降:
class GradientDescentLinearRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.w = 0
self.b = 0
self.loss_history = []
def compute_loss(self, X, y):
"""计算均方误差"""
predictions = self.w * X + self.b
return np.mean((y - predictions) ** 2)
def fit(self, X, y):
"""使用梯度下降训练"""
X = np.array(X)
y = np.array(y)
n = len(X)
for i in range(self.n_iterations):
# 计算预测值
predictions = self.w * X + self.b
# 计算梯度
dw = (-2/n) * np.sum(X * (y - predictions)) # w的梯度
db = (-2/n) * np.sum(y - predictions) # b的梯度
# 更新参数
self.w -= self.learning_rate * dw
self.b -= self.learning_rate * db
# 记录损失
loss = self.compute_loss(X, y)
self.loss_history.append(loss)
# 每100次迭代打印进度
if i % 100 == 0:
print(f"迭代{i}: 损失 = {loss:.2f}, w = {self.w:.2f}, b = {self.b:.2f}")
def predict(self, X):
return self.w * np.array(X) + self.b
# 使用梯度下降版本
gd_model = GradientDescentLinearRegression(learning_rate=0.001, n_iterations=1000)
gd_model.fit(areas, prices)
print(f"\n梯度下降结果:")
print(f"方程: y = {gd_model.w:.2f}x + {gd_model.b:.2f}")
# 绘制损失下降过程
plt.figure(figsize=(10, 4))
plt.plot(gd_model.loss_history)
plt.xlabel('迭代次数')
plt.ylabel('损失值')
plt.title('梯度下降优化过程')
plt.grid(True, alpha=0.3)
plt.show()
🧠 多变量线性回归
现实中,我们通常有多个特征影响结果:
房价预测的高级版本:
房价 = w₁×面积 + w₂×房间数 + w₃×地段评分 + b
# 多变量数据:面积、房间数、地段评分 -> 房价
X_multi = np.array([
[120, 3, 8], # 房子1
[80, 2, 6], # 房子2
[150, 4, 9], # 房子3
[90, 2, 7], # 房子4
[110, 3, 7], # 房子5
[200, 5, 9] # 房子6
])
y_multi = np.array([300, 180, 450, 220, 280, 520]) # 对应房价
# 使用sklearn的多变量线性回归
multi_model = LinearRegression()
multi_model.fit(X_multi, y_multi)
print("多变量线性回归结果:")
print(f"权重 (面积, 房间数, 地段): {multi_model.coef_}")
print(f"偏置: {multi_model.intercept_:.2f}")
print(f"方程: 房价 = {multi_model.coef_[0]:.2f}×面积 + {multi_model.coef_[1]:.2f}×房间数 + {multi_model.coef_[2]:.2f}×地段 + {multi_model.intercept_:.2f}")
# 预测新房子
new_house = np.array([[100, 2, 7]]) # 100㎡, 2室, 地段7分
predicted_price = multi_model.predict(new_house)[0]
print(f"\n预测新房子价格: {predicted_price:.1f}万")
⚠️ 线性回归的局限性
1️⃣ 只能捕捉线性关系
如果真实关系是曲线的,线性回归就不行了:
# 非线性数据示例
np.random.seed(42)
X_nonlinear = np.linspace(0, 10, 100)
y_nonlinear = 2 * X_nonlinear + 3 * X_nonlinear**2 + np.random.normal(0, 10, 100)
# 用线性回归拟合非线性数据
linear_model = LinearRegression()
linear_model.fit(X_nonlinear.reshape(-1, 1), y_nonlinear)
# 可视化对比
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.scatter(X_nonlinear, y_nonlinear, alpha=0.6, label='真实数据')
plt.plot(X_nonlinear, linear_model.predict(X_nonlinear.reshape(-1, 1)),
color='red', label='线性拟合')
plt.legend()
plt.title('线性回归拟合非线性数据(效果差)')
# 多项式回归效果更好
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
poly_model = Pipeline([
('poly', PolynomialFeatures(degree=2)),
('linear', LinearRegression())
])
poly_model.fit(X_nonlinear.reshape(-1, 1), y_nonlinear)
plt.subplot(1, 2, 2)
plt.scatter(X_nonlinear, y_nonlinear, alpha=0.6, label='真实数据')
plt.plot(X_nonlinear, poly_model.predict(X_nonlinear.reshape(-1, 1)),
color='green', label='多项式拟合')
plt.legend()
plt.title('多项式回归拟合非线性数据(效果好)')
plt.tight_layout()
plt.show()
2️⃣ 对异常值敏感
# 加入异常值的影响
normal_areas = [50, 80, 100, 120, 150, 180, 200]
normal_prices = [80, 120, 150, 180, 220, 260, 290]
# 加入一个异常值:面积很小但价格极高
outlier_areas = normal_areas + [60] # 多加一个点
outlier_prices = normal_prices + [1000] # 这个房子60㎡却卖1000万!
# 分别训练模型
normal_model = LinearRegression().fit(
np.array(normal_areas).reshape(-1, 1), normal_prices)
outlier_model = LinearRegression().fit(
np.array(outlier_areas).reshape(-1, 1), outlier_prices)
# 可视化对比
test_x = np.linspace(40, 220, 100).reshape(-1, 1)
plt.figure(figsize=(10, 6))
plt.scatter(normal_areas, normal_prices, color='blue', s=50, label='正常数据')
plt.scatter([60], [1000], color='red', s=100, marker='x', label='异常值')
plt.plot(test_x, normal_model.predict(test_x), 'b-', label='正常数据拟合')
plt.plot(test_x, outlier_model.predict(test_x), 'r--', label='含异常值拟合')
plt.xlabel('面积(㎡)')
plt.ylabel('价格(万)')
plt.legend()
plt.title('异常值对线性回归的影响')
plt.grid(True, alpha=0.3)
plt.show()
print("正常数据模型的斜率:", normal_model.coef_[0])
print("含异常值模型的斜率:", outlier_model.coef_[0])
🤖 为什么线性回归是机器学习的基石?
1️⃣ 简单有效
- 容易理解和实现
- 计算速度快
- 在小数据集上往往效果不错
2️⃣ 理论基础扎实
- 统计性质明确
- 可以进行显著性检验
- 是更复杂模型的基础
3️⃣ 可解释性强
# 解释模型结果
print("=== 模型解释 ===")
print(f"面积每增加1㎡,房价平均增加{multi_model.coef_[0]:.1f}万")
print(f"房间数每增加1间,房价平均增加{multi_model.coef_[1]:.1f}万")
print(f"地段评分每增加1分,房价平均增加{multi_model.coef_[2]:.1f}万")
print(f"即使什么都没有(面积=0),基础房价是{multi_model.intercept_:.1f}万")
📝 本篇小结
- 线性回归找直线:用直线 y = wx + b 预测数值
- 最小二乘法:让所有数据点到直线的距离平方和最小
- 梯度下降:复杂情况下的参数优化方法
- 多变量扩展:可以有多个特征同时影响结果
- 局限性:只能处理线性关系,对异常值敏感
- 重要性:是理解更复杂机器学习算法的基础
🎯 练习题
- 手工计算:给定数据点 (1,2), (2,3), (3,5),用手工方法计算线性回归的参数w和b
- 实际数据:找一组你感兴趣的数据(比如学习时间与考试成绩),用线性回归分析它们的关系
- 改进模型:尝试给房价数据加入"装修程度"特征,看看预测效果是否提升
- 异常值处理:思考如何处理数据中的异常值,让模型更稳健?
🔮 下一篇预告
第5篇:逻辑回归——不只是预测数字,还能分类
线性回归只能预测连续数值,但现实中我们经常需要分类:
- 这封邮件是垃圾邮件还是正常邮件?
- 这张图片是猫还是狗?
- 这个用户会购买产品还是不会?
逻辑回归就是解决这类问题的利器!我们将学习如何让AI学会"做选择题"。
准备好进入分类的世界了吗? 🚀


被折叠的 条评论
为什么被折叠?



