ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

斯坦福CS229机器学习课程精讲:从线性回归到逻辑回归的数学原理与Python实现

斯坦福CS229机器学习课程精讲:从线性回归到逻辑回归的数学原理与Python实现 最近在整理机器学习学习资料时发现很多同学都在寻找系统、权威且能跟得上时代的课程。斯坦福大学的 CS229《机器学习》课程无疑是该领域的经典与标杆。无论是准备期末考试的学生还是希望夯实理论基础、深入理解算法本质的开发者这门课都提供了无与伦比的深度和广度。然而网上流传的版本众多找到一套完整、清晰且最新的中文学习资源并不容易。本文旨在为大家系统梳理斯坦福 CS2292026年夏季课程的核心内容与学习路径。我们将不仅概述课程大纲更会深入拆解几个关键机器学习算法的数学原理与实现思想并提供配套的学习建议和资源指引。无论你是机器学习入门者还是希望温故知新的从业者都能通过本文构建一个清晰的学习框架并掌握课程中的精华部分。1. 课程背景与核心价值斯坦福 CS229《机器学习》是人工智能领域最负盛名的课程之一由机器学习领域的先驱 Andrew Ng吴恩达教授创立并长期主讲。这门课不同于一些侧重工具使用的实践课它从概率统计、线性代数和优化理论的基础出发严谨地推导各种机器学习算法的来龙去脉旨在培养学生对机器学习“第一性原理”的深刻理解。为什么 CS229 至今仍被奉为经典理论基础扎实课程不满足于“调用API”而是深入算法背后的数学原理如最大似然估计、梯度下降的收敛性、支持向量机的对偶问题等。这能让你真正理解算法为何有效以及其局限性所在。知识体系完整课程覆盖了监督学习线性回归、逻辑回归、神经网络、支持向量机、无监督学习聚类、降维、深度学习基础以及学习理论偏差/方差、正则化等核心模块构建了完整的知识图谱。思维方法培养课程强调将实际问题抽象为数学模型并选择合适的算法进行求解的完整流程。这种“建模-求解-评估”的思维模式是解决真实世界机器学习问题的关键。对于中文学习者而言找到一套带有精准中英字幕的完结课程视频配合完整的讲义和作业能够极大降低学习门槛提升学习效率。2026年夏季的最新版本意味着课程内容可能融入了近年来一些重要的基础概念更新或教学表述优化更具学习价值。2. 学习环境与前置知识准备学习 CS229 并不仅仅是观看视频更重要的是完成课后作业和编程实践。因此一个合适的学习环境至关重要。2.1 编程语言与工具课程官方作业通常使用MATLAB或Octave一种开源兼容MATLAB的软件。这是因为在课程创立之初这些工具能让学生更专注于算法本身而非编程语法。但对于现代开发者我们完全可以用更流行的语言来复现算法。推荐选择Python当前机器学习领域的事实标准。使用NumPy进行矩阵运算Matplotlib进行绘图可以完美复现课程所有算法。本文后续示例也将使用 Python。MATLAB/Octave为了原汁原味体验课程作业可以使用它们。Octave 是免费的开源软件。集成开发环境IDEJupyter Notebook非常适合交互式学习和演示能分段运行代码并即时显示图表和结果。PyCharm / VS Code功能强大的通用代码编辑器适合构建更大的项目。2.2 核心前置数学知识CS229 对数学有一定要求。在开始前建议复习以下内容线性代数向量、矩阵乘法、转置、逆、特征值/特征向量。这是理解所有模型尤其是线性回归、PCA的基础。概率论与统计随机变量、概率分布高斯分布、伯努利分布、期望、方差、最大似然估计、贝叶斯定理。微积分偏导数、梯度、多元函数的优化。这是理解梯度下降等优化算法的关键。优化理论基础了解凸函数、拉格朗日乘子法对理解SVM至关重要。如果某些数学知识生疏不必畏惧可以在学习到相关部分时同步查阅资料。课程讲义本身也会包含必要的数学附录。2.3 示例项目结构为了更好地跟随本文进行实践建议建立如下目录结构cs229_study/ │ ├── notes/ # 存放课程讲义、学习笔记 ├── assignments/ # 编程作业目录 │ └── ps1/ # 第一次作业 │ ├── data/ # 数据集 │ ├── utils.py # 工具函数 │ └── linear_regression.py # 线性回归实现 ├── algorithms/ # 算法实现代码库 │ ├── linear_regression.py │ ├── logistic_regression.py │ ├── svm.py │ └── pca.py └── main.py # 主程序用于测试算法3. 核心算法原理拆解以线性回归与逻辑回归为例CS229 课程内容浩瀚我们选取监督学习中最基础、最重要的两个模型——线性回归和逻辑回归来深入剖析其原理这也是课程初期的重点。3.1 线性回归从最小二乘法到概率解释问题定义给定训练集{(x^(i), y^(i)); i 1,..., m}其中x^(i) ∈ R^ny^(i) ∈ R。目标是学习一个线性函数h(x) θ^T x假设x_0 1故θ^T x包含截距项使得h(x)能很好地预测y。1. 最小二乘法Ordinary Least Squares最直观的方法是让预测值与真实值的平方差最小。定义代价函数Cost Function为J(θ) (1/2m) * Σ (h_θ(x^(i)) - y^(i))^2我们的目标是找到参数θ使得J(θ)最小化。代数解法正规方程通过令代价函数对θ的导数为零可以直接得到解析解θ (X^T X)^(-1) X^T y其中X是m x (n1)的设计矩阵y是m x 1的目标值向量。当特征维度n很大或X^T X不可逆时此方法计算代价高或不适用。迭代解法梯度下降这是更通用的优化方法。参数更新规则为θ_j : θ_j - α * (∂J(θ)/∂θ_j)对于线性回归偏导数为(1/m) * Σ (h_θ(x^(i)) - y^(i)) * x_j^(i)。α是学习率控制每一步更新的幅度。2. 概率解释Probabilistic Interpretation为什么使用最小二乘CS229 给出了一个漂亮的概率视角。我们假设目标变量y与输入x的关系为y^(i) θ^T x^(i) ε^(i)其中误差项ε^(i)服从均值为0方差为σ^2的高斯分布正态分布即ε^(i) ~ N(0, σ^2)。这意味着p(y^(i) | x^(i); θ) N(θ^T x^(i), σ^2)在给定X和θ的情况下数据y的似然函数为L(θ) Π p(y^(i) | x^(i); θ)最大化似然函数MLE等价于最小化最小二乘代价函数。这个解释将线性回归纳入了统计学习的框架为其奠定了坚实的理论基础。3.2 逻辑回归分类问题的概率模型当输出y是离散值如0或1时线性回归不再适用。逻辑回归是解决二分类问题的经典线性模型。1. 假设函数Hypothesis逻辑回归使用Sigmoid 函数或 Logistic 函数将线性组合θ^T x映射到(0, 1)区间将其解释为概率h_θ(x) g(θ^T x) 1 / (1 exp(-θ^T x))其中g(z) 1/(1e^{-z})是 Sigmoid 函数。h_θ(x)表示P(y1 | x; θ)。2. 代价函数交叉熵损失如果沿用线性回归的平方误差代价函数J(θ)将是一个非凸函数难以优化。逻辑回归从最大似然估计出发推导出交叉熵损失Cross-Entropy Loss。 对于单个样本其概率为P(y | x; θ) (h_θ(x))^y * (1 - h_θ(x))^(1-y)取对数似然并希望最大化它等价于最小化负对数似然从而得到代价函数J(θ) - (1/m) [ Σ y^(i) log(h_θ(x^(i))) (1-y^(i)) log(1 - h_θ(x^(i))) ]这个函数是凸的保证了梯度下降能找到全局最优解在适当的学习率下。3. 参数更新对代价函数求导得到的梯度形式非常简洁∂J(θ)/∂θ_j (1/m) Σ (h_θ(x^(i)) - y^(i)) x_j^(i)注意这个更新公式在形式上与线性回归完全一样但本质不同因为这里的h_θ(x)是 Sigmoid 函数。这体现了数学形式上的优美统一。4. 完整实战案例Python实现线性回归与逻辑回归理论需要代码来巩固。下面我们使用 Python 和 NumPy 从头实现这两个算法并在经典数据集上进行测试。4.1 环境与数据准备首先确保安装必要的库并准备数据。# 在终端中运行 pip install numpy matplotlib scikit-learn我们使用scikit-learn自带的波士顿房价数据集回归和鸢尾花数据集分类我们只取两类作为示例。4.2 线性回归实现创建文件algorithms/linear_regression.py。# algorithms/linear_regression.py import numpy as np class LinearRegression: def __init__(self, learning_rate0.01, n_iters1000): 初始化线性回归模型。 :param learning_rate: 学习率 :param n_iters: 梯度下降迭代次数 self.lr learning_rate self.n_iters n_iters self.weights None self.bias None self.cost_history [] # 记录每次迭代的代价用于可视化 def fit(self, X, y): 使用梯度下降法训练模型。 :param X: 训练特征形状 (m_samples, n_features) :param y: 训练标签形状 (m_samples,) m_samples, n_features X.shape # 初始化参数 self.weights np.zeros(n_features) self.bias 0 # 梯度下降 for _ in range(self.n_iters): # 计算预测值 y_predicted np.dot(X, self.weights) self.bias # 计算梯度 # dw (1/m) * X^T (y_pred - y) dw (1 / m_samples) * np.dot(X.T, (y_predicted - y)) # db (1/m) * sum(y_pred - y) db (1 / m_samples) * np.sum(y_predicted - y) # 更新参数 self.weights - self.lr * dw self.bias - self.lr * db # 记录当前代价可选用于调试 cost (1/(2*m_samples)) * np.sum((y_predicted - y)**2) self.cost_history.append(cost) def predict(self, X): 预测 return np.dot(X, self.weights) self.bias def get_params(self): 返回模型参数 return self.weights, self.bias4.3 逻辑回归实现创建文件algorithms/logistic_regression.py。# algorithms/logistic_regression.py import numpy as np class LogisticRegression: def __init__(self, learning_rate0.01, n_iters1000): self.lr learning_rate self.n_iters n_iters self.weights None self.bias None self.cost_history [] def _sigmoid(self, z): Sigmoid 激活函数 # 防止溢出 z np.clip(z, -500, 500) return 1 / (1 np.exp(-z)) def fit(self, X, y): m_samples, n_features X.shape self.weights np.zeros(n_features) self.bias 0 for _ in range(self.n_iters): # 线性组合 linear_model np.dot(X, self.weights) self.bias # 通过sigmoid得到预测概率 y_predicted self._sigmoid(linear_model) # 计算梯度 (与线性回归形式一致但y_predicted含义不同) dw (1 / m_samples) * np.dot(X.T, (y_predicted - y)) db (1 / m_samples) * np.sum(y_predicted - y) # 更新参数 self.weights - self.lr * dw self.bias - self.lr * db # 计算交叉熵损失并记录 # 避免 log(0) 的情况 epsilon 1e-15 y_predicted_clipped np.clip(y_predicted, epsilon, 1 - epsilon) cost - (1/m_samples) * np.sum(y * np.log(y_predicted_clipped) (1-y) * np.log(1-y_predicted_clipped)) self.cost_history.append(cost) def predict_proba(self, X): 预测为正类的概率 linear_model np.dot(X, self.weights) self.bias return self._sigmoid(linear_model) def predict(self, X, threshold0.5): 根据阈值进行类别预测 probabilities self.predict_proba(X) return (probabilities threshold).astype(int)4.4 运行与验证创建主测试文件main.py。# main.py import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_boston, load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from algorithms.linear_regression import LinearRegression from algorithms.logistic_regression import LogisticRegression def demo_linear_regression(): print( 线性回归演示 ) # 加载数据 boston load_boston() X, y boston.data, boston.target # 只使用一个特征方便可视化这里选第5个特征RM-房间数 X_rm X[:, 5].reshape(-1, 1) # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split(X_rm, y, test_size0.2, random_state42) # 特征标准化 (非常重要尤其是对于梯度下降) scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 训练模型 model LinearRegression(learning_rate0.1, n_iters2000) model.fit(X_train_scaled, y_train) w, b model.get_params() print(f学习到的参数: 权重 w {w[0]:.4f}, 偏置 b {b:.4f}) # 预测 y_pred model.predict(X_test_scaled) # 计算均方误差 mse np.mean((y_pred - y_test) ** 2) print(f测试集均方误差(MSE): {mse:.4f}) # 可视化 plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.scatter(X_train_scaled, y_train, colorblue, label训练数据, alpha0.5) plt.plot(X_train_scaled, model.predict(X_train_scaled), colorred, linewidth2, label回归线) plt.xlabel(标准化后的房间数 (RM)) plt.ylabel(房价 (MEDV)) plt.title(线性回归拟合) plt.legend() plt.subplot(1, 2, 2) plt.plot(range(len(model.cost_history)), model.cost_history) plt.xlabel(迭代次数) plt.ylabel(代价 (J)) plt.title(梯度下降收敛过程) plt.tight_layout() plt.show() def demo_logistic_regression(): print(\n 逻辑回归演示 ) # 加载鸢尾花数据集只取两类Setosa和Versicolor和两个特征 iris load_iris() X iris.data[0:100, :2] # 只取前100个样本前两个特征萼片长度和宽度 y iris.target[0:100] # 将标签转换为0和1 y np.where(y 0, 0, 1) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 训练模型 model LogisticRegression(learning_rate0.1, n_iters3000) model.fit(X_train_scaled, y_train) # 预测 y_pred model.predict(X_test_scaled) accuracy np.mean(y_pred y_test) print(f测试集准确率: {accuracy:.4f}) # 可视化决策边界 plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) # 绘制训练数据点 plt.scatter(X_train_scaled[y_train0, 0], X_train_scaled[y_train0, 1], colorred, label类别 0, alpha0.7) plt.scatter(X_train_scaled[y_train1, 0], X_train_scaled[y_train1, 1], colorblue, label类别 1, alpha0.7) # 生成网格点以绘制决策边界 x_min, x_max X_train_scaled[:, 0].min() - 1, X_train_scaled[:, 0].max() 1 y_min, y_max X_train_scaled[:, 1].min() - 1, X_train_scaled[:, 1].max() 1 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) Z model.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) plt.contourf(xx, yy, Z, alpha0.3, cmapplt.cm.RdBu) plt.xlabel(特征1 (标准化)) plt.ylabel(特征2 (标准化)) plt.title(逻辑回归决策边界) plt.legend() plt.subplot(1, 2, 2) plt.plot(range(len(model.cost_history)), model.cost_history) plt.xlabel(迭代次数) plt.ylabel(交叉熵损失) plt.title(损失函数下降过程) plt.tight_layout() plt.show() if __name__ __main__: demo_linear_regression() demo_logistic_regression()4.5 结果说明运行python main.py你将看到线性回归部分输出学习到的权重和偏置以及测试集的均方误差。图表会显示数据点、拟合的直线以及梯度下降过程中代价函数的下降曲线直观展示算法收敛过程。逻辑回归部分输出模型在测试集上的分类准确率。图表会显示两类数据的分布、模型学习到的决策边界一条直线以及交叉熵损失随迭代下降的过程。通过这个实战你不仅实现了算法核心还完成了数据预处理、模型训练、评估和可视化的完整流程这正是 CS229 作业所要求的核心能力。5. 学习CS229的常见问题与排查思路在学习 CS229 和实现算法过程中你可能会遇到以下典型问题问题现象可能原因解决思路梯度下降不收敛代价函数爆炸或震荡1. 学习率α设置过大。2. 特征未标准化归一化。3. 代码中存在 bug如梯度计算错误。1. 尝试减小学习率如 0.01, 0.001。2. 对特征进行标准化(x - mean)/std。3. 使用数值梯度检验Gradient Checking来验证梯度计算是否正确。这是 CS229 作业中强调的重要调试技巧。逻辑回归预测概率全是 0 或 11. 特征尺度差异巨大导致θ^T x数值过大或过小Sigmoid 函数饱和。2. 学习率太大导致参数更新跳过最优解。1.务必进行特征标准化。2. 在_sigmoid函数中对输入z进行裁剪np.clip防止数值溢出。3. 检查并减小学习率。正规方程求解时出现奇异矩阵错误矩阵X^T X不可逆奇异。原因可能是1. 特征之间存在线性相关冗余。2. 特征数量n大于样本数量m。1. 检查并移除冗余特征如高度相关的特征。2. 使用正则化如岭回归在X^T X上加上一个小的常数 λI使其可逆。3. 使用伪逆np.linalg.pinv代替逆。理解不了讲义中的数学推导前置数学知识线性代数、概率论不牢固。1.不要死磕。先接受结论尝试从几何或直觉上理解。2. 同步复习相关数学知识。Coursera 上 Andrew Ng 的《机器学习》课程数学要求相对较低可作为先导。3. 多看几遍视频关注教授解释概念的直觉部分。编程作业无从下手对问题转换、算法实现到代码的映射不熟悉。1. 仔细阅读作业 PDF 中的说明和提示。2. 先完成课程提供的“填空式”代码文件如果有。3. 将数学公式如梯度公式逐行翻译成代码使用向量化操作NumPy避免低效循环。课程视频节奏快跟不上课程信息密度极高。1.善用暂停和回放。记下关键步骤和疑问。2.讲义Notes是核心。视频是讲解讲义是精炼的教科书。以讲义为主线视频为辅。3. 组建学习小组讨论难点。6. 高效学习CS229的最佳实践与工程建议掌握了具体算法后如何将 CS229 的知识体系转化为解决实际问题的能力以下是一些工程实践上的建议。6.1 学习路径规划按顺序推进严格跟随课程大纲顺序监督学习 - 学习理论 - 无监督学习 - 深度学习/强化学习。前面的内容是后面的基础。“三位一体”学习法看视频理解直观解释和动机。读讲义精读数学推导这是知识的锚点。尝试自己推导一遍。做作业这是将知识内化为能力的关键。独立完成即使耗时很长。主动输出学完一个章节后尝试用白板或笔记软件在不看资料的情况下复述核心思想、算法步骤和关键公式。6.2 代码实现规范向量化编程CS229 强调使用 MATLAB/Octave 的向量化操作。在 Python 中就是熟练使用NumPy避免显式的for循环。这能极大提升代码效率和简洁性。# 低效使用循环 dw np.zeros(n_features) for j in range(n_features): for i in range(m_samples): dw[j] (h[i] - y[i]) * X[i, j] dw[j] / m_samples # 高效向量化 (这正是我们实现中使用的) dw (1 / m_samples) * np.dot(X.T, (h - y))模块化设计像我们实战案例中那样将每个算法封装成类fit,predict。这有利于代码复用、测试和集成到更大项目中。数值稳定性在实现涉及指数、对数的运算时如Sigmoid、交叉熵损失必须考虑数值溢出/下溢问题使用np.clip等函数进行保护。6.3 超越课程作业项目实践完成课程作业后是时候进行综合应用了复现经典算法尝试不参考任何代码仅根据讲义中的算法描述独立实现 K-Means、PCA、高斯判别分析GDA等。参加 Kaggle 入门竞赛例如Titanic: Machine Learning from Disaster或House Prices: Advanced Regression Techniques。运用从 CS229 学到的特征工程、模型选择线性回归、逻辑回归、正则化、交叉验证等全套流程。阅读经典论文课程会引用多篇奠基性论文如 SVM 的原始论文。挑战自己阅读这些论文看看理论是如何被提出的。6.4 知识串联与深化CS229 的知识不是孤立的线性回归 vs. 逻辑回归思考它们代价函数梯度形式的一致性以及为何一个用平方误差一个用交叉熵。生成模型 vs. 判别模型比较高斯判别分析GDA生成模型和逻辑回归判别模型在假设和性能上的异同。偏差与方差用这个框架去分析你实现的模型是过拟合还是欠拟合并思考如何通过增加数据、调整模型复杂度如正则化来改进。学习斯坦福 CS229 是一次对机器学习根基的深度挖掘。它可能充满挑战但回报是巨大的——你将获得一种透过现象看本质的能力能够理解并驾驭层出不穷的新模型、新框架而不仅仅是调用它们。建议你以本文为地图结合最新的中英字幕课程视频、官方讲义和作业踏踏实实地走完这段旅程。过程中遇到的每一个数学难点和编程卡点都是你能力成长的基石。当你能够清晰地推导出算法公式并优雅地将其转化为运行的代码时你就真正掌握了机器学习的核心语言。
返回列表