🐸 青蛙编程网
首页 / AI / 机器学习 / 5. 实战:房价预测

实战:房价预测

这是什么:线性回归(Linear Regression) = 用一条直线把特征和标签连起来,专门解决"预测一个数字"的回归问题。

为什么用:终章实战!前几章你用 K 近邻解决了分类(判断品种),这次换线性回归给房子估价。麻雀虽小五脏俱全,这就是一个完整的机器学习项目。

如何用:本章拿 15 套房的数据开练:拆出特征和标签、训练模型,再让它给一套没见过的房估个价。

任务与数据

任务:根据面积和房龄预测房价——特征 2 个,标签 1 个连续数字,是标准的回归问题。数据集自己造:15 套房的记录,小小一份,方便你逐行验证。

真实项目通常用 Pandas 从 CSV 读数据,思路完全一样,只是数据来源不同。

完整代码

from sklearn.linear_model import LinearRegression

# 1. 造数据:15 套房 [面积(㎡), 房龄(年), 价格(万元)]
data = [
    [50, 1, 127],  [55, 2, 134],  [60, 1, 147],  [60, 5, 135],
    [65, 3, 151],  [70, 2, 164],  [70, 8, 146],  [75, 4, 168],
    [80, 1, 187],  [85, 6, 182],  [90, 3, 201],  [95, 5, 205],
    [100, 2, 224], [105, 7, 219], [110, 1, 247],
]

# 2. 拆出特征 X 和标签 y
X = [[row[0], row[1]] for row in data]   # 面积、房龄
y = [row[2] for row in data]             # 价格

# 3. 创建模型并训练
model = LinearRegression()
model.fit(X, y)

# 4. 看看模型学到的规律
print("每平米:", round(model.coef_[0], 4), "万")
print("每年折旧:", round(model.coef_[1], 4), "万")
print("基础价:", round(model.intercept_, 4), "万")

# 5. 预测一套没见过的房:90㎡、房龄 5 年
pred = model.predict([[90, 5]])
print("90㎡、房龄 5 年 → 预测:", round(pred[0], 2), "万")

你会看到:

每平米: 2.0 万
每年折旧: -3.0 万
基础价: 30.0 万
90㎡、房龄 5 年 → 预测: 195.0 万

模型学到了什么

线性回归学到的是一条公式:房价 = 2 × 面积 − 3 × 房龄 + 30。

翻译成人话:每平米 2 万,房子每老一年贬值 3 万,新房基础价 30 万。预测 90㎡、5 年房龄:2×90 − 3×5 + 30 = 195 万——和模型算的一致,你可以口算验算!

这套数据是照公式造的,所以模型学得分毫不差;真实数据有噪音(装修、学区、楼王位置……),模型只能学出"大概规律",学得好不好,就靠《模型评估》那套方法来验收。

代码 在干什么
LinearRegression() 创建线性回归模型
model.fit(X, y) 用 15 套房学习规律
model.coef_ 学到的系数 [2, -3]:每个特征的影响力度
model.intercept_ 学到的截距 30:基础价
model.predict([[90, 5]]) 给新房估价

记忆口诀:回归就是找公式,系数是影响力,截距是底价。

回归 vs 分类:一张表看清区别

维度 分类(classification) 回归(regression)
标签类型 类别(如"是/否"、"猫/狗") 连续数字(如房价、气温)
常用算法 KNN 分类器、逻辑回归、决策树 线性回归、岭回归、随机森林回归
评估指标 准确率、查全率、查准率 MSE、MAE、R²
本章例子 鸢尾花品种 房价预测

❓ 常见问题

Q1:为什么不划分训练集/测试集?

本章数据只有 15 套房,太少了,拆分后每份样本太少,模型学不到稳定规律。入门演示用全部数据训练即可;真实项目一定要拆分,并在测试集上验证。

Q2:model.coef_ 是 [2, -3],为什么房龄是负数?

负系数表示负相关:房龄越大,价格越低。每多一年房龄,价格下降 3 万,其他条件不变。

Q3:预测结果总是比真实房价低/高怎么办?

说明数据和模型假设不匹配。可能原因:特征不够(缺少地段、学区)、数据量太小、关系不是线性的。尝试加更多特征,或换更复杂的模型。

⚠️ 新手翻车现场

翻车一:把标签 y 造成二维列表

# 错误:y 是 [[127], [134], ...],LinearRegression 期望一维
y = [[row[2]] for row in data]
model.fit(X, y)  # 报错或结果异常

问题:sklearn 的回归器期望 y 是一维数组(每样本一个标签),不是嵌套列表。

修正:y = [row[2] for row in data],直接是扁平列表。

翻车二:预测时传入一维数组而非二维

# 错误:predict 期望 [[90, 5]],不是 [90, 5]
model.predict([90, 5])  # 报错:Expected 2D array, got 1D array instead

问题:predict 的输入必须是二维(即使只预测一条,也要包一层列表),表示"一批样本,每条 2 个特征"。

修正:model.predict([[90, 5]]),外层一层括号。

🎯 什么时候用线性回归

  • 要预测的是连续数字(房价、气温、销量、股价)
  • 特征与标签之间大致呈线性关系
  • 需要模型结果可解释("每平米多少钱"这样的系数很直观)
  • 作为回归任务的基准,先跑线性回归看看效果

📝 本章小结

  • 线性回归学的是一个线性公式:标签 = 特征 × 系数 + 截距
  • coef_ 是每个特征的影响力,intercept_ 是基础价
  • predict 输入必须是二维,即使只预测一条
  • 数据量太少时(如本章 15 套房)可暂不拆分训练/测试集,真实项目必须拆分
  • 记忆口诀:回归就是找公式,系数是影响力,截距是底价。

动手改

  1. 让模型给"60㎡、房龄 10 年"的房子估价,先口算(2×60 − 3×10 + 30)再运行,对得上吗?
  2. 往 data 里再加 2 套房(价格按公式自己算),看系数还准不准
  3. 把 LinearRegression() 换成 from sklearn.tree import DecisionTreeRegressor(),看预测结果是否变化
  4. 思考:真实房价还要考虑地段、学区……一个简单公式还撑得住吗?

机器学习毕业 🎉 下一站 LLM,认识当下最火的大模型 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。