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

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

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

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

1. 线性回归问题

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

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

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

<math xmlns="http://www.w3.org/1998/Math/MathML"> y = 10 x y = 10x </math>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 学习之路(四)- 逻辑回归问题

相关推荐
IT猿手2 小时前
2025最新群智能优化算法:山羊优化算法(Goat Optimization Algorithm, GOA)求解23个经典函数测试集,MATLAB
人工智能·python·算法·数学建模·matlab·智能优化算法
Jet45053 小时前
玩转ChatGPT:GPT 深入研究功能
人工智能·gpt·chatgpt·deep research·深入研究
毕加锁3 小时前
chatgpt完成python提取PDF简历指定内容的案例
人工智能·chatgpt
Wis4e5 小时前
基于PyTorch的深度学习3——基于autograd的反向传播
人工智能·pytorch·深度学习
西猫雷婶6 小时前
神经网络|(十四)|霍普菲尔德神经网络-Hebbian训练
人工智能·深度学习·神经网络
梦丶晓羽6 小时前
自然语言处理:文本分类
人工智能·python·自然语言处理·文本分类·朴素贝叶斯·逻辑斯谛回归
SuperCreators6 小时前
DeepSeek与浏览器自动化AI Agent构建指南
人工智能·自动化
美狐美颜sdk7 小时前
什么是美颜SDK?从几何变换到深度学习驱动的美颜算法详解
人工智能·深度学习·算法·美颜sdk·第三方美颜sdk·视频美颜sdk·美颜api
訾博ZiBo7 小时前
AI日报 - 2025年3月10日
人工智能
waicsdn_haha7 小时前
Postman v11 安装与API测试入门教程(Windows平台)
人工智能·windows·测试工具·mysql·postman·dbeaver·rest