1. 线性回归解决的第一个问题:把"猜"变成"算"
很多初学者看到"线性回归"这四个字,第一反应是"又要画一条直线了",然后就开始套公式、调库、跑结果。但如果你只是停留在"用 sklearn 调一下 LinearRegression"这个层面,那和用计算器算平均数没区别。真正有价值的是搞清楚一个问题:线性回归到底在解决什么本质问题?
先抛一个反直觉的结论:线性回归从头到尾都不是在"画线",而是在估计参数。它假设输入特征和输出之间存在一种线性关系,而我们要做的,是找到一组参数,让这种假设尽可能贴合已有的数据。你以为你在拟合曲线,实际上你在求解一个参数向量。
举个特别朴素的例子。假设你要根据一套房子的面积预测价格,你有 50 条历史成交记录。如果没有线性回归,你怎么办?靠经验拍脑袋:面积大的贵一点,小的便宜一点,但这不叫模型,这叫感觉。线性回归做的事情,是把"感觉"拆解成"面积每增加 1 平米,价格平均上涨多少"这样一个数值,然后通过历史数据把这个数值算出来。
这个过程背后的思维方式值得展开说。我们不是在寻找一条穿过所有数据点的线——现实中的数据几乎不可能完美落在一条直线上,总会有噪声、误差、未纳入模型的变量。线性回归的真正目标,是找一条整体误差最小的线,让它能代表数据的一般趋势。这个"整体误差最小"的度量方式,就是后文会细说的损失函数。
另一个容易忽略的点是:线性回归之所以叫"线性",本质上是对参数线性,而不是对特征线性。这句话新手很难一次消化。用人话解释就是:模型允许输入特征是 (x^2)、(\sin(x))、(x_1 x_2) 这种非线性组合,只要模型表达式是关于参数 (\theta) 的一次函数,它仍然是线性回归。很多人一听到"线性"就觉得只能拟合直线,这是天大的误解。利用这个性质,线性回归可以拟合曲线——只要你自己构造出非线性特征,比如把面积取平方、把楼层做交叉相乘,喂给线性模型,它照样能拟合出弯弯曲曲的形状。这就是"线性模型 + 特征工程 = 非线性拟合能力"的底层逻辑。
学习这个内容的适合人群,我建议是三类:一是刚入门机器学习、想真正理解模型而不是只会调库的同学;二是准备期末考试的本科生,东西本身不难,但考得细;三是做数据分析、想从统计学角度理解回归本质的从业者。这篇文章会跳过调库的部分,直接从原理到代码、从数学到实战,把这个经典的算法讲透。
2. 最小二乘法与梯度下降:两条完全不同的求参路线
2.1 为什么损失函数要选"误差平方"而不是"误差绝对值"
前面说了,模型要"整体误差最小",但具体怎么定义"误差",学问很大。最常见的定义是均方误差(Mean Squared Error, MSE),公式长这样:
[ J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 ]
新手通常会问:为什么误差要平方?直接用绝对误差不行吗?这背后有两个非常实际的原因。
第一个原因是数学性质上的。平方函数在整个实数域上是连续可导的,而且导数是线性的 2 倍残差,方便求导和优化。而绝对值函数在零点不可导,用梯度下降的时候会遇到"导数不存在"的尴尬局面。虽然后续发展出了 Huber Loss 这类分段函数来缓解这个问题,但经典最小二乘法选平方误差,最重要的动机就是便于求导、有解析解。
第二个原因在统计学上更深刻。当我们假设误差服从正态分布时,均方误差恰好是极大似然估计的自然结果。也就是说,你用最小二乘法求出来的参数,在"误差服从正态分布"这个假设下,是概率意义上最优的估计。这里不过度展开,但你可以记一个结论:最小二乘法不是拍脑袋选的,它和极大似然估计在正态假设下是等价的。
那这个前头的 1/2 是怎么回事?纯粹是为了求导时把 2 消掉,让公式更整洁。很多人看到这个系数会疑惑,其实没有任何实际意义,就是为了数学上的便利。在很多深度学习框架的损失函数里,你也能看到类似"多此一举"的常数项,都是同一个道理。
2.2 正规方程:一步到位的解析解法
有了损失函数,接下来的问题就是:怎么找到让 (J(\theta)) 最小的 (\theta)?
最直接的做法是走解析路线。既然 (J(\theta)) 是关于 (\theta) 的二次函数,而二次函数是凸函数,那么它的导数为零的点就是全局最小值点。直接令梯度等于零,解出 (\theta),这就是正规方程(Normal Equation):
[ \theta = (X^T X)^{-1} X^T y ]
这个公式看起来简单,但有几个坑必须说清楚。
第一个坑是 (X^T X) 可能不可逆。最典型的情况是特征之间存在多重共线性——比如你同时把"面积(平方米)"和"面积(平方英尺)"作为两个特征放进去,它们本质上是同一个信息,导致矩阵奇异。解决办法主要是删除冗余特征,或者用岭回归(加一个 (\lambda I) 项)来保证可逆性。
第二个坑是计算复杂度。正规方程需要计算一个 (n \times n) 矩阵的逆,其中 (n) 是特征数量。当特征维度上万甚至更高时,这个矩阵求逆的复杂度是 (O(n^3)),计算代价极高。所以正规方程适合特征维度不太高的场景,如果特征有几百万维,还是老老实实走梯度下降吧。
还有一个初学者容易踩的坑:一定要记得在特征矩阵 (X) 前面加一列全 1,用来对应偏置项(截距)。如果不加,模型被迫穿过原点,相当于强行让"零面积"的房子价格为零,这在实际问题中几乎总是错的。很多人用 numpy 手写正规方程时预测结果离谱,排查半天发现就是忘了加这一列。
2.3 梯度下降:面对大数据集的迭代求解方案
正规方程固然漂亮,但碰到大数据集就力不从心了。这时候就需要梯度下降出场。它的思路很简单:从某个初始参数出发,沿着损失函数下降最快的方向——也就是负梯度方向——迈一小步,然后重复这个过程,直到收敛。
参数更新规则如下:
[ \theta_j := \theta_j - \alpha \frac{\partial J(\theta)}{\partial \theta_j} ]
其中 (\alpha) 是学习率,控制每次迈多大步子。这里必须展开讲几个关键细节。
第一,学习率的选择是个细活。(\alpha) 太大,参数会在最优点附近来回震荡,甚至直接发散,损失函数越跑越大;(\alpha) 太小,收敛速度慢得要命,训练跑半天还在原地踏步。常见做法是从 (0.01) 这类值开始试,观察损失曲线:如果损失震荡不下降,说明学习率大了;如果下降得极其缓慢,说明学习率小了。没有万能的学习率,必须针对具体问题调。
第二,特征缩放对梯度下降的影响极大。如果某个特征的取值范围是 0 到 100000,另一个特征只有 0 到 1,那么损失函数的等高线会变成非常狭长的椭圆,梯度下降会在椭圆的长轴和短轴之间来回震荡,收敛极慢。解决办法是把所有特征都缩放到相近的范围内,常用的有标准化(减去均值除以标准差)、归一化(缩放到 0 到 1 区间)。这个细节太重要了,我见过太多人跑梯度下降不收敛,最后发现是没做特征缩放。
第三,批量梯度下降、随机梯度下降、小批量梯度下降的选择。批量梯度下降每轮迭代用全量数据计算梯度,准但慢;随机梯度下降每个样本更新一次,快但震荡剧烈;小批量梯度下降取折中,每轮用一小批(比如 32 或 128 个样本)计算梯度,是实际工程中最常用的方案。在算法的学习阶段,建议先从批量梯度下降理解原理,再用小批量做实际训练。
3. 从连续到离散:线性分类的本质是找决策边界
3.1 为什么不能直接把回归结果当作分类结果
线性回归解决的是连续值预测问题,比如房价、温度、销售额。但现实里还有一类问题是离散的,比如一封邮件是垃圾邮件还是正常邮件、一个肿瘤是良性还是恶性、一张图片里是猫还是狗。这类问题统称为分类问题。那么问题来了:能不能直接训练一个线性回归,把输出值大于 0.5 的判为类别 1,小于 0.5 的判为类别 0?
很多教材直接告诉你"不行",但没讲清楚为什么不行。这里我花点篇幅说透。
假设你用线性回归做二分类,类别标签设为 0 和 1。训练数据中,类别 0 的样本集中在特征值较小的区域,类别 1 的样本集中在特征值较大的区域。线性回归为了最小化平方误差,会试图让所有类别 0 的预测值接近 0、所有类别 1 的预测值接近 1。这看起来没什么问题,但一旦数据里出现极端离群点,比如某个类别 1 的样本特征值特别大,为了让这个点的预测值接近 1,回归线会被强行拉斜,导致决策边界偏移,大量正常样本被误分类。换句话说,回归模型对离群点太敏感,而这种敏感性在分类任务中是不可接受的。
更深层的问题是:线性回归输出的是一个无界的实数值,可能是 -3,也可能是 8。你没法给"预测值是 2.5"赋予一个有意义的概率解释。而分类问题的输出应该是一个概率——"有 87% 的把握这是一只猫"。于是我们需要一个函数,把任意实数压缩到 0 到 1 之间,并且压缩过程要平滑可导,方便优化。这个函数就是 sigmoid 函数:
[ \sigma(z) = \frac{1}{1 + e^{-z}} ]
3.2 逻辑回归:在线性函数外套一层 sigmoid
逻辑回归的名字里有"回归"两个字,但它本质上是分类算法,这又是初学者最容易困惑的一个点。它的想法非常直接:先算一个线性组合 (z = \theta^T x),再用 sigmoid 函数把它映射成概率:
[ h_\theta(x) = \sigma(\theta^T x) = \frac{1}{1 + e^{-\theta^T x}} ]
然后设定一个阈值(通常是 0.5):如果 (h_\theta(x) \ge 0.5),预测为正类,否则预测为负类。这里的 0.5 其实就是决策边界。因为 sigmoid 函数是单调递增的,(h_\theta(x) = 0.5) 等价于 (\theta^T x = 0),所以逻辑回归的决策边界本质上是特征空间中的一个线性超平面。比如二维特征空间中,决策边界就是一条直线;三维空间中是一个平面;更高维就是超平面。
有个非常重要的直觉需要建立:逻辑回归学到的不是决策边界本身,而是决策边界的参数。训练过程就是在找一组参数,让正类样本经过 sigmoid 映射后的概率尽量接近 1,负类样本尽量接近 0。只是在决策的时候,我们把这个连续概率硬截断成一个离散类别。
还有一个点值得提:逻辑回归输出的"概率"并不总是校准良好的。也就是说,模型输出 0.7,并不代表这类样本真的有 70% 的概率属于正类。这是因为逻辑回归是在有限训练数据上拟合的,并且对特征分布有假设。如果你的应用场景需要概率校准(比如风控领域计算违约概率),通常还要额外做校准(比如 Platt scaling 或 Isotonic regression)。这在吴恩达的课程里没细讲,但实际工作中是个大坑。
3.3 从决策边界角度看线性分类的局限性
弄清楚了决策边界的本质,也就自然理解了线性分类的局限性:如果两类数据在特征空间中无法用一个线性超平面分开,那线性分类器无论怎么调参都不可能完全正确。经典的例子是 XOR 问题——两个特征取值进行异或运算作为类别标签,这种情况下数据分布呈对角线交叉形态,任何一条直线都无法将两类分开。
但这不代表线性分类器没用。恰恰相反,线性分类器是很多复杂模型的基础组件。神经网络中的每一个神经元,本质上就是一个线性分类器加一个非线性激活函数;支持向量机的核技巧,也是先把数据映射到高维空间再用线性超平面分割。你甚至可以认为,深度学习就是在做"自动学习特征表示 + 线性分类"这两件事的组合。理解好线性分类,等于给后面学所有复杂模型打地基。
4. 过拟合、欠拟合与正则化:线性模型最常见的翻车点
4.1 用房价预测理解偏差和方差
学完前面的内容,你可能会觉得线性回归和逻辑回归都很简单:一个求解析解,一个梯度下降,完事了。但实际使用时,你会发现模型在训练集上表现很好,一上测试集就拉垮。这是机器学习里最经典的问题——过拟合。要理解过拟合,必须先建立"偏差"和"方差"这两个概念。
偏差(Bias)衡量模型的预测值与真实值之间的系统性偏差。高偏差意味着模型过于简单,连训练数据的基本趋势都捕捉不到,这就是欠拟合。打个比方,你用一个恒定值去预测所有房价,预测结果可能平均来看接近真实值,但对每个具体样本都差得远。
方差(Variance)衡量模型对训练数据波动的敏感程度。高方差意味着模型过度拟合了训练数据中的噪声,换了另一批训练数据,学到的模型参数可能天差地别,这就是过拟合。相当于你把训练集里的每一个细节都记下来了,包括噪声和异常点,一旦遇到新的数据就完全失效。
线性模型中,这两种情况分别对应什么?欠拟合通常发生在特征太少了,模型根本表达不了数据的复杂关系;过拟合则通常发生在特征太多、或者构造了太多非线性特征组合时,模型有足够的能力把训练数据"背"下来。这里有个很实用的判断方法:训练集误差大、测试集误差也大,是欠拟合;训练集误差小、测试集误差大,是过拟合;两个误差都大且接近,可能是数据本身质量差或特征没做好。
4.2 正则化:给参数加"紧箍咒"
既然过拟合的根源是模型太自由、参数值可以随意变大来完美拟合数据,那自然的想法就是限制参数的大小。这就是正则化的核心思想:在损失函数后面加一个惩罚项,让参数不能太大。
线性回归加 L2 正则化后就是岭回归(Ridge Regression),目标函数变成:
[ J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 + \lambda \sum_{j=1}^{n} \theta_j^2 ]
加 L1 正则化后就是Lasso 回归,惩罚项变成 (\lambda \sum_{j=1}^{n} |\theta_j|)。这两者的行为差异非常大,值得掰开说。
L2 正则化(岭回归)的效果是让所有参数都往 0 收缩,但不会精确等于 0。它适合大多数场景,尤其是特征之间有一定相关性的情况,能稳定参数估计。L1 正则化(Lasso)的效果则更激进:它可以让一部分参数精确等于 0,相当于自动帮你做了特征选择,把不重要的特征直接丢弃。这在地震数据、基因数据这类高维稀疏场景中特别有用。实际工作中,很多人直接上 ElasticNet,也就是 L1 + L2 混合,兼顾两者优点。
那 (\lambda) 怎么选?(\lambda) 太小,正则化没效果,过拟合依旧;(\lambda) 太大,把所有参数都压得接近 0,模型退化成"预测值 ≈ 常数",欠拟合。通常的做法是画正则化路径图,观察不同 (\lambda) 下参数的收缩情况,然后用交叉验证选出泛化性能最好的 (\lambda)。sklearn 里RidgeCV和LassoCV就是干这个的,能自动在给定范围内搜索最优 (\lambda)。
4.3 逻辑回归的正则化与分类任务的评估指标
正则化同样适用于逻辑回归,而且在实际项目中几乎是必开的。因为逻辑回归做分类时,如果特征维度很高(比如文本分类中 TF-IDF 向量动辄上十万维),不过正则化的话模型非常容易过拟合。逻辑回归在 sklearn 中的实现LogisticRegression默认就带 L2 正则化,参数C控制正则化强度——注意,这里的C是正则化强度的倒数,C越小正则化越强,和岭回归的 (\lambda) 方向完全相反,很多人第一次用都会搞混。
另外,分类任务的评估不能只看准确率。在线性分类这个场景下,我强烈建议关注precision、recall 和 F1-score。尤其是正负样本不平衡的问题:假设 99% 的样本是负类,那模型什么都不学,全预测负类,准确率就有 99%,但这个模型毫无用处。此时应该看 confusion matrix,分析模型在正类上的表现。此外,ROC 曲线和 AUC 值也是评估分类模型好坏的经典工具。这个知识点期末考试特别喜欢考,面试也常问。
5. 手写一个线性回归和逻辑回归:不依赖框架的实现
5.1 用 numpy 从零实现线性回归
讲了这么多理论,现在进入实操环节。我打算先实现纯 Python + numpy 版本的线性回归,不用 sklearn,因为只有从零写一遍,你才能真正理解前面说的那些公式到底在计算什么。
首先是数据准备。我们用最简单的模拟数据:假设真实的关系是 (y = 4x + 3 + \text{噪声}),生成 100 个样本点。
import numpy as np np.random.seed(42) X = np.random.rand(100, 1) * 4 # 特征值范围 0~4 true_w, true_b = 4.0, 3.0 y = true_w * X + true_b + np.random.randn(100, 1) * 0.5 # 加噪声然后写正规方程的代码。记得要给 X 加上一列 1,对应偏置项:
X_b = np.c_[np.ones((100, 1)), X] # 加一列全 1 # 正规方程: theta = (X^T X)^(-1) X^T y theta = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y print("求解结果:", theta) # 应该接近 [[3], [4]]这里有个实用的小技巧:当矩阵维度较大时,直接求逆可能数值不稳定,更稳妥的做法是用np.linalg.lstsq(X_b, y, rcond=None)或者np.linalg.solve(X_b.T @ X_b, X_b.T @ y)。后者用 LU 分解而不是显式求逆,数值稳定性更好。
再写梯度下降版本,帮助理解迭代过程:
def gradient_descent(X_b, y, lr=0.01, n_iter=1000): m = len(X_b) theta = np.random.randn(X_b.shape[1], 1) history = [] for _ in range(n_iter): gradient = (1/m) * X_b.T @ (X_b @ theta - y) theta = theta - lr * gradient loss = (1/(2*m)) * np.sum((X_b @ theta - y) ** 2) history.append(loss) return theta, history theta_gd, loss_history = gradient_descent(X_b, y, lr=0.1)运行之后你会发现,即使学习率只设 0.1,损失函数的下降曲线也会很平滑。如果把学习率改成 1.5,损失就会震荡甚至爆炸——你可以亲手试一下,这个"失控"的过程能帮你建立对学习率的直觉。
5.2 手写逻辑回归:理解交叉熵损失与梯度更新
逻辑回归的实现比线性回归多两个关键点:一是用 sigmoid 函数做映射,二是损失函数从均方误差换成交叉熵(对数损失)。为什么不能用均方误差?因为逻辑回归的输出经过 sigmoid 压缩后,均方误差作为损失函数是非凸的,存在多个局部极小值,梯度下降容易陷入局部最优。而交叉熵损失关于参数是凸函数,能保证收敛到全局最优。
逻辑回归的损失函数长这样:
[ J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} [y^{(i)} \log(h_\theta(x^{(i)})) + (1 - y^{(i)}) \log(1 - h_\theta(x^{(i)}))] ]
理解这个公式的关键在于"对数"的作用:当真实标签 (y=1) 时,损失只有第一项起作用,如果预测概率越接近 1,损失越小;预测概率越接近 0,(\log(0)) 趋于负无穷,损失会急剧增大。换句话说,交叉熵对"错误且自信"的预测施加了极其严厉的惩罚。这种不对称的惩罚力度,是它在分类问题上远优于均方误差的根本原因。
手写实现如下:
def sigmoid(z): return 1 / (1 + np.exp(-z)) def logistic_regression(X, y, lr=0.01, n_iter=1000): m, n = X.shape X_b = np.c_[np.ones((m, 1)), X] theta = np.zeros((n + 1, 1)) for _ in range(n_iter): z = X_b @ theta h = sigmoid(z) gradient = (1/m) * X_b.T @ (h - y) theta = theta - lr * gradient return theta注意一个细节:梯度更新的表达式和线性回归的梯度形式几乎一模一样,都是 (X^T (h - y)),区别只是 (h) 的表达式不同——线性回归中 (h = X\theta),逻辑回归中 (h = \text{sigmoid}(X\theta))。这个"巧合"是广义线性模型的统一性质,理解了这一点,你对很多机器学习模型的认知会拔高一个层次。
5.3 把代码跑起来:用模拟数据验证两类模型
为了验证实现是否正确,我们构造一个线性可分的二分类数据集,用上面的逻辑回归训练并观察决策边界:
from sklearn.datasets import make_classification X_cls, y_cls = make_classification( n_samples=200, n_features=2, n_redundant=0, n_clusters_per_class=1, random_state=42 ) theta_cls = logistic_regression(X_cls, y_cls, lr=0.5, n_iter=2000) # 决策边界: theta0 + theta1*x1 + theta2*x2 = 0 x1_vals = np.linspace(X_cls[:, 0].min(), X_cls[:, 0].max(), 100) x2_vals = -(theta_cls[0] + theta_cls[1] * x1_vals) / theta_cls[2]这里有个实操中非常容易踩的坑:如果数据特征取值范围差异很大,逻辑回归的梯度下降会收敛得极其缓慢,甚至震荡。我在自己第一次写逻辑回归时吃过这个亏——在某个数据集上怎么调学习率都不收敛,最后把所有特征做标准化,问题立刻解决。标准化的代码就一行:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_cls_scaled = scaler.fit_transform(X_cls)你可能会问:正规方程不需要特征缩放,为什么梯度下降就要?因为正规方程是一步到位求解,不涉及迭代路径;而梯度下降是"沿着陡峭方向一步步挪",如果各个方向的坡度差异巨大,挪动路径就会像在狭长山谷里来回弹跳。这就是特征缩放必要的根本原因。
6. 期末复习高频考点与新手最容易忽略的细节
6.1 西电、山大等高校期末真题中反复出现的题型
从热搜词里能看到,"西电机器学习期末"、"山东大学机器学习期末"、"国科大机器学习"这些搜索量都很高,说明不少读者正在备考。我结合这些课程常见的考试风格,把线性回归和线性分类的考点做一个梳理。
第一类是概念辨析题。典型问法:"什么是欠拟合和过拟合?如何解决?"答题要点是三板斧:欠拟合增加特征或提高模型复杂度;过拟合增加训练数据、降低模型复杂度、加入正则化。注意考试时最好结合公式说明正则化的作用机制,只说"加正则化"不给公式不给解释,得分会打折扣。
第二类是公式推导题。最常见的是推导线性回归的正规方程。完整步骤是:写出损失函数 (J(\theta) = \frac{1}{2}(X\theta - y)^T(X\theta - y)),对 (\theta) 求偏导并令其为零:(\nabla_\theta J(\theta) = X^T(X\theta - y) = 0),解得 (\theta = (X^T X)^{-1} X^T y)。推导过程中要特别注意矩阵求导的规则,这是很多人的失分点。同样是推导逻辑回归的梯度更新公式,题设通常会给出 sigmoid 函数的导数性质 ( \sigma'(z) = \sigma(z)(1 - \sigma(z)) ),利用链式法则一步步推。
第三类是计算题。给几个训练样本,要求用梯度下降手动迭代一步或两步,更新参数。这里需要注意的是:题目给的学习率、初始参数、样本值,计算时必须仔细,尤其是交叉熵损失里的 log 计算,很多同学在这里算错小数点。我的建议是做题时保留至少 4 位小数,避免累积误差。
还有一类容易被忽视的考点是线性回归的统计性质。比如"在高斯-马尔可夫假设下,最小二乘估计是 BLUE(最优线性无偏估计)"这个结论,几乎每个学校都会考到,但少有人真正理解。它说的是:在线性回归的所有线性无偏估计中,最小二乘估计的方差最小。这是线性回归在统计学中的"王者"地位的由来,但机器学习角度对其关注较少。备考时记住结论并说出Gauss-Markov假设的四个条件即可。
6.2 容易被忽略但实际非常重要的细节
除了考试,我再分享几个实际工作中容易出问题的小细节。第一个是数据的顺序效应。如果你在训练逻辑回归之前对数据做了排序,比如按时间排,那么梯度下降迭代过程中每个 batch 的样本分布会偏向某一类,导致训练不稳定。解决方法是每次迭代前 shuffle 一下数据。sklearn 的SGDClassifier和很多框架默认会做这件事,但自己手写实现时要记得。
第二个是特征的量纲统一。线性回归和逻辑回归对特征的量纲敏感——一个特征如果是"平方厘米"量级,另一个是"立方米"量级,数值差异可能达几个数量级,这会让模型对数值大的特征赋予不合理的权重解释。在实际建模之前做探索性数据分析,查看特征分布和量纲,是每个 ML 项目的第一步。
第三个是模型的可解释性与可视化。线性模型最大的优势就是可解释性好——你可以直接说"面积每增加 1 平米,房价平均上涨 X 元",这在金融、医疗等领域是硬性需求。建议大家在做项目时把学到的参数打印出来,结合业务含义去解读,你会发现很多有意思的信息。比如逻辑回归学到的权重中,哪个特征贡献最大,哪个特征有负向影响,这些完全可以作为项目报告中的亮点输出。
6.3 一个完整的建模流程总结
最后,我把用线性回归或逻辑回归解决实际问题的标准流程串一遍,这个流程适用于绝大多数入门级机器学习任务:
- 明确问题:搞清楚这是回归问题还是分类问题,评估指标是什么(回归用 MSE/MAE,分类用 accuracy 或 F1-score)。
- 数据探索与清洗:查看缺失值、异常值,画特征分布图和散点图,直观感受数据形态。
- 特征工程:构造有意义的特征,做特征缩放,处理类别特征(独热编码等)。
- 划分数据集:训练集/测试集划分,比例通常 7:3 或 8:2,并设置随机种子保证可复现。
- 训练与调参:先跑一个基线模型,观察训练集和测试集的损失曲线,判断是否欠拟合或过拟合,再调整正则化强度、学习率等超参数。
- 评估与迭代:用测试集做最终评估,输出各项指标。如果效果不佳,回到第 3 步重新做特征工程,或者尝试更复杂的模型。
- 部署与监控:把模型导出保存,在新数据上持续监控表现。数据分布会随时间漂移,模型需要定期重新训练。
我强烈建议新手哪怕用 sklearn 已经很方便,也至少要自己从零手写一遍线性回归和逻辑回归。这个过程会逼着你把每个公式、每次矩阵运算都搞明白。我当年就是这么过来的,手写了一轮之后,再去看那些复杂的模型,感觉就如履平地了。而且面试时,面试官问你"线性回归的损失函数为什么选平方误差"、"逻辑回归为什么要用交叉熵",你能清晰说出来和背答案的差距,一瞬间就能体现出来。