AI 学习之路(三)- 线性回归问题

今天是学习 AI 的第三天,装环境就不再赘述了,太简单了。

安装了环境,也装了一些 AI 算法库,比如 TensorFlow 、PyTorch 等,不过暂时都用不上。

根据 AI 制定的计划,3,4,5 天的内容一起。写下这篇文章,如何利用机器学习解决线性回归问题。

1. 线性回归问题

什么是线性回归问题呢?举个房价的简单例子。

房屋面积(平方米) 价格(万元)
30 300
40 400
50 500

如上所示,不同的房屋面积,对应了不同的价格,我们可以很轻松的发现,上述表格包含的规律为

y = 10 x y = 10x y=10x

这样,我们就可以推测,当房屋面积为 60 平方米时,价格为 600 万元。

然而现实生活中,不可能会有这么有规律的数据,有可能会出现下面这种情况。

房屋面积(平方米) 价格(万元)
30 280
40 410
50 490

这个时候,再让我们预测 60 平方米,价格是多少,就没有那么容易了,这个问题就不单是一个线性问题,而可以看作是一个线性回归问题。

通常这种情况下,我们会通过最小二乘法来得到一条里所有的点都最近的曲线。

ini 复制代码
import numpy as np

# 定义面积数据(自变量)
x = np.array([30, 40, 50])
# 定义房价数据(因变量)
y = np.array([280, 410, 490])

# 计算 x 和 y 的均值
x_mean = np.mean(x)
y_mean = np.mean(y)

# 计算斜率 beta_1
numerator = np.sum((x - x_mean) * (y - y_mean))
denominator = np.sum((x - x_mean) ** 2)
beta_1 = numerator / denominator

# 计算截距 beta_0
beta_0 = y_mean - beta_1 * x_mean

# 定义要预测的面积
x_to_predict = 60

# 进行预测
predicted_price = beta_0 + beta_1 * x_to_predict

print(f"预测 60 平米的房价为: {predicted_price:.2f} 万元")

下面这幅图,可以形象的说明最小二乘法在找一个什么样的线性关系

2. 多变量的线性回归问题

上面这个例子比较简单,而实际中房价并不单单依靠面积决定,如果有多个变量,应该怎么找到对应的线性关系呢,在此基础上,拓展表格如下。

房屋面积(平方米) 装修金额(万元) 价格(万元)
30 5 280
40 25 410
50 50 540

可以看到我们增加了装修这个纬度,而且可以目测装修金额越高,最终价格也越高。那么到底如何找到预测的线性关系呢,为了不去了解复杂的计算过程,我们直接使用 sklearn 中的方法,来解决这个问题。

ini 复制代码
import numpy as np
from sklearn.linear_model import LinearRegression

# 数据准备
X = np.array([[30, 5], [40, 25], [50, 50]])  # 特征矩阵,每一行是一个样本,每一列是一个特征
y = np.array([280, 410, 540])  # 因变量

# 创建并拟合模型
model = LinearRegression()
model.fit(X, y)

# 查看系数和截距
beta_1 = model.coef_  # 自变量系数
beta_0 = model.intercept_  # 截距
print(f"自变量系数: {beta_1}")
print(f"截距: {beta_0}")

# 预测新数据
new_X = np.array([[60, 30]])  # 假设要预测的房屋面积为 60 平方米,装修金额为 30 万元
predicted_price = model.predict(new_X)
print(f"预测的房价为: {predicted_price[0]:.2f} 万元")

这里面的数学原理涉及到到如何计算多变量的最小误差平方和,需要用到矩阵、转置矩阵,求导的知识才能够算出来,比较复杂,感谢封装好的 LinearRegression 模型。

3. 模型评估

在刚才的例子里,由于数据没有真实性,所以不具备评估的条件。正确的做法应该是,采集数据时,将数据分为训练集和测试集,以下以波士顿房价预测为例。

python 复制代码
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['STHeiti']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 加载波士顿房价数据集
# 注意:从scikit-learn 1.2版本开始,波士顿房价数据集已被移除
# 这里使用兼容的替代方式
try:
    data_url = "http://lib.stat.cmu.edu/datasets/boston"
    raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
    data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
    target = raw_df.values[1::2, 2]
except Exception as e:
    print(f"数据加载出错: {e}")
    raise

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=42)

# 创建线性回归模型
model = LinearRegression()

# 训练模型
model.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = model.predict(X_test)

# 评估模型
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")

使用训练集训练后,测验集的X_test,用训练好的模型预测得到 y_pred , 最终用均方误差(MSE)和决定系数(R²)来评判模型是否预测准确。

均方误差很好理解:假设共预测 n 项,将每一项的 (预测值 - 实际值) 平方后求和,再除以 n 就可以了。

决定系数稍微复杂点:将设实际值的平均值为 10,使用 (实际值 - 10) 平方后求和作为分母,再使用 (预测值 - 10) 平方后求和作为分子,再拿 1 - (预测值 - 实际值) 平方后求和 / (实际值 - 10) 平方后求和

MSE 要越接近 0 ,R² 要越接近 1 时才能说明这是个好模型

上述代码运行结果为

均方误差 (MSE): 24.291119474973048

决定系数 (R²): 0.6687594935356385

是个不太理想的数值,所以我们需要对模型进行优化。

4. 模型优化

在不更换模型时(线性回归),优化有这些常用的方式:特征缩放、特征选择、处理异常值、特征组合等方法,优化的代码(部分)如下。

ini 复制代码
# 特征缩放
from sklearn.preprocessing import StandardScaler

# 创建标准化器
scaler = StandardScaler()# 对训练集和测试集的特征进行标准化
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
ini 复制代码
# 特征选择
from sklearn.feature_selection import SelectKBest, f_regression

# 选择相关性最高的前k个特征
selector = SelectKBest(score_func=f_regression, k=5)
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)
ini 复制代码
# 处理异常值

# 计算每个特征的Z-score
z_scores = np.abs((data - np.mean(data, axis=0)) / np.std(data, axis=0))# 设定阈值,例如3
threshold = 3
outliers = np.where(z_scores > threshold)# 移除异常值
data_cleaned = np.delete(data, outliers[0], axis=0)
target_cleaned = np.delete(target, outliers[0], axis=0)
ini 复制代码
# 特征组合

from sklearn.preprocessing import PolynomialFeatures

# 创建多项式特征
poly = PolynomialFeatures(degree=2)
X_train_poly = poly.fit_transform(X_train)
X_test_poly = poly.transform(X_test)

上面的例子使用 处理异常值 和 特征组合 ,可以将均方误差和决定系数改进为:

均方误差 (MSE): 8.196982138149128

决定系数 (R²): 0.827221026062241

由于波士顿房价数据,特征值特别多,所以下面用一个简化的数据来说明,什么情况应该采用怎么样的优化方法。

行号 房屋房龄(年) 房屋面积(平方英尺) 卧室数量 小区绿化覆盖率 周边商场距离(公里) 房屋价格(千美元)
1 2.5 1500 3.2 12 0.2 250
2 3 1800 3.5 15 0.3 300
3 2.2 1600 3 10 0.25 230
4 1.8 1400 2.8 8 0.18 200
5 3.5 2000 4 20 0.4 350
6 4 2200 4.5 22 0.5 400
7 1.5 1200 2.5 6 0.15 180
8 2.8 1700 3.3 13 0.22 260
9 50 1900 3.8 18 0.35 320
10 3.2 1850 3.6 16 0.32 310

1. 特征缩放

  • 数据特征:各特征的取值范围差异很大。例如 "房屋房龄(年)" 取值在 1.5 - 50 之间,而 "房屋面积(平方英尺)" 取值在 1200 - 2200 之间。

  • 适用原因:在使用一些基于距离计算的算法(如 K - 近邻算法)或者梯度下降优化算法(如线性回归使用梯度下降求解参数)时,取值范围大的特征会在距离计算或者梯度更新中占据主导地位,影响模型的训练效果和收敛速度。通过特征缩放(如标准化或归一化),可以将各特征统一到相近的尺度,使模型能够更公平地对待每个特征,提升训练效率和准确性。

2. 特征选择

  • 数据特征:特征之间存在冗余或者某些特征与目标变量(房屋价格)的相关性极低。比如 "小区绿化覆盖率" 和 "周边商场距离(公里)" 可能存在一定的相关性,同时 "周边商场距离(公里)" 与 "房屋价格(千美元)" 的相关性经计算发现非常弱。

  • 适用原因:过多的特征会增加模型的复杂度,导致训练时间变长,并且容易出现过拟合现象。通过特征选择方法(如相关性分析、方差分析等),可以筛选出对目标变量影响较大的特征,去除冗余和无关特征,简化模型,提高模型的泛化能力。

3. 处理异常值

  • 数据特征:数据中存在明显偏离其他数据点的值。例如第 9 行的 "房屋房龄(年)" 为 50,远高于其他行的房龄数据,这可能是数据录入错误或者特殊情况导致的异常值。

  • 适用原因:异常值会对模型的训练和拟合产生较大干扰,使模型的参数估计出现偏差,降低模型的预测准确性。通过识别并处理异常值(如使用箱线图确定异常值范围,然后删除异常值或者进行修正),可以使模型更好地拟合正常数据,提高预测的稳定性和准确性。

4. 特征组合

  • 数据特征:单个特征与目标变量的关系不明显,但特征之间组合可能产生新的有价值信息。例如 "房屋面积(平方英尺)" 和 "卧室数量" 单独来看与 "房屋价格(千美元)" 的关系不是特别清晰,但将它们组合成 "单位卧室面积(平方英尺 / 个)" 这个新特征,可能会与房屋价格有更显著的相关性。
  • 适用原因:特征组合可以挖掘数据中潜在的信息和模式,创造出更具解释性和预测能力的新特征。新的特征组合可能能够更好地反映数据的内在规律,从而提升模型对目标变量的预测效果。

5. 挑战竞赛

想成为真正的预言家吗,可以参与 kaggle 举办的房价预测大赛,我让 deepseek 帮我写了一个默认的房价预测程序,获得了 3606 名的成绩。可见机器学习算法的学习依然任重道远。

ini 复制代码
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.impute import SimpleImputer

# 1. 加载数据
train_data = pd.read_csv('./train.csv')
test_data = pd.read_csv('./test.csv')

# 2. 初步数据探索
print("训练集形状:", train_data.shape)
print("测试集形状:", test_data.shape)
print("训练集缺失值统计:\n", train_data.isnull().sum().sort_values(ascending=False).head(10))

# 3. 特征选择(示例选取部分特征)
selected_features = [
    'OverallQual', 'GrLivArea', 'TotalBsmtSF', '1stFlrSF', 
    'YearBuilt', 'GarageCars', 'FullBath', 'TotRmsAbvGrd'
]

# 4. 处理缺失值
# 对数值型特征用中位数填充,分类特征用众数填充(此处简化处理)
numerical_features = selected_features
categorical_features = []  # 此示例未选分类特征

# 训练集处理
X_train = train_data[selected_features]
y_train = train_data['SalePrice']
imputer = SimpleImputer(strategy='median')
X_train_imputed = pd.DataFrame(imputer.fit_transform(X_train), columns=X_train.columns)

# 测试集处理
X_test = test_data[selected_features]
X_test_imputed = pd.DataFrame(imputer.transform(X_test), columns=X_test.columns)

# 5. 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train_imputed)
X_test_scaled = scaler.transform(X_test_imputed)

# 6. 训练模型
model = LinearRegression()
model.fit(X_train_scaled, y_train)

# 7. 验证模型(使用训练集划分验证集)
X_train_part, X_val, y_train_part, y_val = train_test_split(
    X_train_scaled, y_train, test_size=0.2, random_state=42
)
val_pred = model.predict(X_val)
rmse = np.sqrt(mean_squared_error(y_val, val_pred))
print(f"验证集RMSE: {rmse:.2f}")

# 8. 预测测试集并生成提交文件
test_pred = model.predict(X_test_scaled)
submission = pd.DataFrame({'Id': test_data['Id'], 'SalePrice': test_pred})
submission.to_csv('submission.csv', index=False)
print("提交文件已生成!")

6. 总结

通过这篇文章,我们从最简单的单变量线性回归出发,逐步探讨了多变量场景下的模型构建、评估与优化方法,并结合实战案例展示了线性回归的应用潜力。希望这些内容能帮助你:

  1. 理解核心概念:从数据规律到最小二乘法,掌握线性回归的本质。
  2. 快速上手实践 :通过代码示例熟悉 sklearn 的建模流程。
  3. 优化模型性能:学会特征工程与模型调优的常用技巧。
  4. 挑战真实问题:用 Kaggle 竞赛检验学习成果。

学习线性回归是踏入机器学习的第一步,但真正的提升还需动手实践与持续思考。如果这篇文章对你有所启发,欢迎点赞❤️收藏⭐️支持!也欢迎在评论区分享你的学习心得或疑问,我们一起进步!

下期预告:AI 学习之路(四)- 逻辑回归问题

相关推荐
2501_938140071 小时前
做内容很省心,2026好用AI笔记,支持抖音小红书视频无水印保存
人工智能
sell-cloud4 小时前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国6 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI6 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区6 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris8 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy8 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V8 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI8 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技9 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人