资讯动态

线性回归从原理到工程:梯度下降、特征归一化与正规方程实战解析

发布时间:2026/10/13 12:00:22 来源:尧图企业网站定制
1. 项目概述这不是“抄答案”而是一次对线性回归底层逻辑的重新校准“吴恩达机器学习第二周编程作业ex1答案”——这个标题在各大技术社区、高校课程讨论区和自学群组里几乎每年开学季都会高频出现。但我要先说清楚如果你点进来是想找一份能直接复制粘贴、一键提交、蒙混过关的“标准答案”那这篇内容可能让你失望。它不是解压包里的.py文件也不是GitHub上star数过千的gist链接它是一份以ex1为切口对线性回归建模全流程进行手术刀式拆解的实操手记。核心关键词——单变量线性回归、代价函数、梯度下降、特征归一化、正规方程——每一个都不是孤立的术语而是环环相扣的工程决策点。我带过的某高校暑期实训班里有位A同学第一次跑通ex1后兴奋地截图发群结果第二天就被导师当堂追问“你写的gradientDescent函数里alpha0.01这个值是怎么定的如果换成0.1会怎样为什么cost曲线在迭代500次后还没收敛”——问题一出满屏沉默。这恰恰说明ex1的价值从来不在“跑通”而在“跑懂”。它面向的是所有刚推开机器学习大门的人可能是计算机专业大三学生正在啃《统计学习方法》的研究生或是转行做数据分析的职场人。只要你手头有Python环境、numpy基础、以及愿意花两小时盯着cost值一点点下降的耐心这篇内容就能帮你把“公式推导”和“代码实现”之间的那层毛玻璃彻底擦干净。它不承诺速成但保证你下次再写theta theta - alpha * (1/m) * X.T (X theta - y)时脑子里浮现的不再是符号而是数据点在二维平面上被一条直线温柔牵引的真实画面。2. 内容整体设计与思路拆解为什么ex1必须分“单变量”与“多变量”两套方案ex1的官方结构看似简单前半部分用单变量房屋面积→房价练手后半部分升级到多变量面积房间数楼层数→房价。但这个“升级”背后藏着一个被初学者普遍忽略的关键设计逻辑特征尺度差异对梯度下降收敛性的致命影响。我曾用同一组真实房价数据做过对比实验——当面积单位是“平方米”数值范围0-300房间数是“个”1-6楼层数是“层”1-30时若不做任何处理直接喂给梯度下降代价函数J(θ)的等高线会呈现极度扁长的椭圆状。此时梯度方向几乎平行于长轴算法不得不沿着锯齿形路径缓慢爬行收敛速度暴跌。而ex1的精妙之处就在于它用最朴素的方式揭示了这个原理单变量部分刻意回避了归一化因为只有一个特征尺度问题不凸显而多变量部分则强制引入featureNormalize函数。这不是教学偷懒而是刻意为之的认知阶梯。它逼着你亲手计算mean和std亲手写X_norm (X - mu) / sigma再亲眼看到归一化前后cost曲线收敛步数从1500骤减至400以内。这种“动手即见效果”的设计比十页PPT讲理论更直击要害。另一个常被忽视的设计点是两种求解路径的并置梯度下降 vs 正规方程。ex1要求你分别实现两者并比较结果。这绝非为了增加工作量。正规方程θ(X^T X)^{-1} X^T y给出的是解析解一步到位但它要求X^T X可逆且计算复杂度为O(n^3)梯度下降则是迭代解需调参α, 迭代次数但内存友好可扩展至百万级特征。我在某公司处理用户行为日志时就因误用正规方程求解10万维稀疏特征导致矩阵求逆直接OOM崩溃最后切回随机梯度下降才救场。ex1用一个几十行的脚本提前十年给你埋下了这个坑。所以整个作业的骨架本质是构建一个“可控的微缩战场”在这里你能安全地试错、观察、验证把那些在真实项目中可能引发线上事故的底层假设提前掰开揉碎。2.1 单变量线性回归为什么从“画图”开始比写代码更重要很多初学者一打开ex1就急着冲向computeCost.m或gradientDescent.m。但官方starter code里第一行注释写着“Plot the data to see what it looks like”。这句话轻描淡写却是整个作业的锚点。我坚持认为可视化是理解单变量线性回归不可跳过的前置步骤。原因有三其一它能瞬间暴露数据异常。比如某次带学生调试时一位同学的plot显示所有点都挤在y轴附近呈垂直分布后来发现是数据加载时列索引搞反把标签当成了特征。其二它建立直观的“拟合感”。当你看到散点图上那条手工画的粗略直线和最终算法输出的蓝色拟合线重叠时“最小化误差”就不再是抽象概念而是视觉上可衡量的差距。其三它为后续调参提供基准。在未运行任何算法前你可以目测估计斜率θ1应在[0.5, 2.0]区间截距θ0应在[-5, 10]之间——这个粗糙范围就是你初始化theta的黄金依据。我见过太多人直接theta np.zeros((2,1))结果在α0.01时cost不降反升只因初始点离最优解太远梯度方向“拐错了弯”。正确的做法是先用plt.scatter(X, y)再用plt.plot(X, theta0 theta1*X, r-)画一条你认为合理的线哪怕只是凭感觉。这个动作耗时不到两分钟却能避免后续半小时的盲目调试。它提醒你机器学习不是魔法而是人在数据与模型之间架设的理性桥梁。2.2 多变量线性回归特征归一化的数学本质与实操陷阱进入多变量部分featureNormalize函数成为绕不开的坎。它的代码只有四五行但背后的数学逻辑常被简化为“让数据变小”。这很危险。让我用一个生活化类比解释想象你要指挥一支由不同兵种组成的军队步兵、骑兵、炮兵协同进攻。步兵移动慢特征值小骑兵快特征值中炮兵射程远但装填慢特征值大。如果不统一指挥节奏即归一化命令“前进100步”对步兵是全力冲刺对骑兵是闲庭信步对炮兵却是原地打转——整个系统必然失序。特征归一化正是这个“统一指挥节奏”的过程。其数学本质是将每个特征映射到均值为0、标准差为1的标准正态分布公式为x_norm (x - μ) / σ。这里有两个极易踩的坑第一μ和σ必须仅从训练集计算且必须复用到测试集。我曾见有人在交叉验证时对每折数据单独计算μ/σ导致模型在验证集上表现虚高上线后惨败。第二归一化必须在添加偏置项X01之前完成。因为X0是常数列其标准差为0若强行归一化会导致除零错误。正确顺序是加载原始X → 计算mu/sigma → 归一化X → 最后np.hstack([np.ones((m,1)), X_norm])。这个顺序错一点整个流程就崩。另外很多人忽略了一个细节归一化后的X_norm其第一列对应θ0不再是全1而是全0因为(1-1)/σ0。这意味着θ0此时代表的是“当所有特征取均值时的预测值”而非传统意义上的y轴截距。这个语义变化在解释模型时至关重要——它意味着归一化不仅是为了算法收敛更是为了赋予参数可解释性。3. 核心细节解析与实操要点从公式到代码的每一行注释现在我们沉入代码细节。ex1的核心函数computeCost和gradientDescent表面看只是几行矩阵运算但每一行都承载着关键决策。我将以Python numpy实现为例逐行拆解其物理意义与实操要点。3.1 computeCost函数代价函数的三种等价视角def computeCost(X, y, theta): m len(y) # 样本数这是所有向量化操作的基石 J 0 # 初始化代价注意此处J是标量非向量 # 方法一显式循环教学用不推荐 # for i in range(m): # h theta[0] theta[1]*X[i,1] # 预测值 # J (h - y[i])**2 # J J / (2*m) # 方法二向量化核心推荐 h X theta # (m,2) (2,1) - (m,1)所有样本预测值 error h - y # (m,1) 预测误差向量 J np.sum(error**2) / (2*m) # 平方误差均值的一半 return J这段代码有三个必须掌握的视角几何视角——J是m个数据点到拟合直线的垂直距离平方和统计视角——J是均方误差MSE的1/2倍省去1/2是为了求导时消去系数计算视角——X theta是向量化精髓它用一次矩阵乘法替代m次循环效率提升百倍。这里有个隐藏技巧error**2是按元素平方而非矩阵平方这是numpy广播机制的功劳。若你误写成error error.T得到的是误差向量的内积一个标量结果相同但逻辑错误——前者是∑(e_i²)后者是e·e虽数值等价但前者可读性与泛化性更强。另外2*m中的2是公式固有系数不能省略否则梯度下降步长会系统性偏大。3.2 gradientDescent函数梯度更新的原子操作与稳定性保障def gradientDescent(X, y, theta, alpha, num_iters): m len(y) J_history np.zeros(num_iters) # 记录每次迭代的J值用于诊断 for iter in range(num_iters): h X theta error h - y # 关键梯度计算注意X.T error的维度链 # X.T: (2,m), error: (m,1) - X.T error: (2,1) 恰好是∂J/∂θ的形状 gradient (1/m) * X.T error # 原子更新theta theta - alpha * gradient theta theta - alpha * gradient # 记录代价 J_history[iter] computeCost(X, y, theta) return theta, J_history这段代码的“心脏”是gradient (1/m) * X.T error。为什么是X.T因为我们要计算∂J/∂θ_j根据链式法则∂J/∂θ_j (1/m) * ∑(h_i - y_i) * x_ij。而X.T的第j行正是所有样本的x_ij组成的向量与error向量点乘完美实现求和。这就是矩阵运算如何优雅封装求和逻辑。实操中最大的陷阱是alpha学习率的选择。它不是超参数而是算法的“油门踏板”。太大如α1.0cost会剧烈震荡甚至发散太小如α1e-6收敛慢如蜗牛。ex1的默认α0.01是经验值但必须配合J_history曲线验证。我教学生时必做的一件事让他们画出不同α下的J_history对比图。当α0.001时曲线平缓下降α0.01时快速收敛α0.03时后期轻微震荡α0.1时cost值像坐过山车最终飙升。这个实验比任何理论都深刻。另外theta theta - alpha * gradient必须是原子操作——不能写成theta - alpha * gradient虽然结果相同但前者更清晰体现“更新”意图避免与增量赋值混淆。3.3 正规方程实现何时该放弃迭代拥抱解析解def normalEqn(X, y): # θ (X^T X)^{-1} X^T y # 注意X已包含偏置列X01无需额外处理 theta np.linalg.inv(X.T X) X.T y return theta这段代码简洁得令人不安但藏着两个生死攸关的条件第一X.T X必须可逆。在实际项目中当特征存在强共线性如同时加入“年龄”和“出生年份”或样本数m小于特征数n时矩阵会奇异np.linalg.inv直接报错。此时必须用伪逆np.linalg.pinv替代。第二计算复杂度爆炸。X.T X是n×n矩阵求逆复杂度O(n³)。当n10000时O(1e12)次运算普通服务器需数小时。而梯度下降的单次迭代仅为O(mn)可轻松应对海量特征。因此正规方程的适用场景非常明确小规模数据n10000、特征独立、且追求精确解。我在处理某实验室的基因表达数据n500, m200时就果断选用正规方程3秒出解而处理电商用户画像n50000, m1e6时则必须用随机梯度下降。ex1通过对比两者结果应高度一致让你亲身体验解析解的优雅与迭代解的务实本就是一枚硬币的两面。4. 实操过程与核心环节实现从零开始的完整复现记录现在让我们以“完全新手”视角走一遍ex1的完整实操流程。我会记录每一个关键决策点、遇到的典型问题及解决过程确保你拿到的不是结论而是可复现的路径。4.1 环境准备与数据加载避开编码格式的隐形杀手第一步永远是环境。我推荐使用Anaconda创建纯净环境conda create -n ml-ex1 python3.8。安装核心库pip install numpy matplotlib scipy。数据加载看似简单却是第一个雷区。ex1的数据是txt格式用np.loadtxt(ex1data1.txt, delimiter,)即可。但注意文件编码必须是UTF-8无BOM。某次帮学生debug发现cost值始终为nan排查两小时才发现数据文件是Windows记事本保存的ANSI编码中文路径名导致numpy读取乱码X和y变成全nan。解决方案用VS Code打开txt文件右下角点击编码选择“Save with Encoding” → “UTF-8”。另一个细节np.loadtxt默认返回二维数组但ex1的y是列向量。必须显式reshapey data[:, 1].reshape(-1, 1)。若忘记reshapey.shape为(m,)与theta.shape(2,1)做矩阵运算时numpy会触发广播产生难以察觉的维度错误导致cost计算错误。这个坑我踩过三次。4.2 单变量线性回归全流程从绘图到预测的七步闭环以ex1data1.txt面积→房价为例执行以下七步加载并探索数据data np.loadtxt(ex1data1.txt, delimiter,); X data[:,0].reshape(-1,1); y data[:,1].reshape(-1,1); print(fX shape: {X.shape}, y shape: {y.shape})可视化初探plt.scatter(X, y, cred, markerx); plt.xlabel(Population); plt.ylabel(Profit); plt.show()——确认数据分布合理。添加偏置项X np.hstack([np.ones((len(X),1)), X])—— 此时X.shape为(m,2)第一列为全1。初始化参数theta np.array([[0],[0]])—— 不要np.zeros(2)那会是(2,)一维数组维度错。设置超参数alpha 0.01; iterations 1500—— ex1默认值足够收敛。执行梯度下降theta, J_history gradientDescent(X, y, theta, alpha, iterations)可视化结果plt.plot(X[:,1], X theta, b-); plt.scatter(X[:,1], y, cred, markerx)—— 蓝线应穿过红点云中心。这七步中第3步和第4步的维度处理是成败关键。我曾见有人写X np.c_[np.ones(m), X]结果X变成(m,3)因为原始X是(m,1)np.c_拼接后多了一维。正确做法永远是np.hstack配reshape。另外第6步后务必检查J_history[-1]是否远小于J_history[0]若差距不足10%说明α太小或迭代不足。4.3 多变量线性回归进阶归一化、预测与结果解读切换到ex1data2.txt面积房间数→房价流程升级加载数据data np.loadtxt(ex1data2.txt, delimiter,); X data[:,0:2]; y data[:,2].reshape(-1,1)特征归一化def featureNormalize(X): mu np.mean(X, axis0) # 按列求均值shape(2,) sigma np.std(X, axis0) # 按列求标准差shape(2,) X_norm (X - mu) / sigma return X_norm, mu, sigma X_norm, mu, sigma featureNormalize(X) # X_norm shape(m,2)添加偏置项X np.hstack([np.ones((len(X_norm),1)), X_norm])—— 注意这里是X_norm不是原始X。初始化与训练theta np.zeros((3,1)); theta, J_history gradientDescent(X, y, theta, 0.1, 400)—— α增大到0.1因已归一化。预测新样本# 预测面积1650房间数3的房子 x_test np.array([1650, 3]) # 先归一化用训练集的mu/sigma非测试集 x_test_norm (x_test - mu) / sigma # 添加偏置转列向量 x_test_full np.hstack([1, x_test_norm]).reshape(-1,1) price x_test_full.T theta # 结果为标量结果解读打印price并对比正规方程结果theta_normal normalEqn(X, y)。两者应相差1e-5。若差异大检查归一化是否应用到X非X_norm或mu/sigma是否用错。这里的关键心得是预测时的归一化必须复用训练阶段的mu和sigma。我曾见有人写x_test_norm (x_test - np.mean(x_test)) / np.std(x_test)这完全错误——单个样本的均值恒为自身标准差为0直接崩溃。记住归一化参数是数据集的统计属性不是单个样本的。5. 常见问题与排查技巧实录那些文档里不会写的血泪教训在带教数十期学员和自己反复调试ex1的过程中我整理出一份高频问题速查表。这些问题90%的初学者都会撞上而官方文档只字不提。问题现象根本原因排查技巧终极解决方案J_history曲线不下降甚至上升α过大或梯度计算错误打印前10次的J_history看是否单调递减检查gradient (1/m) * X.T error中X是否含偏置列将α减半如0.01→0.005或检查X维度X必须是(m,n1)X.T是(n1,m)computeCost返回nanX或y含nan值或theta初始化为infprint(np.isnan(X).any(), np.isnan(y).any(), np.isnan(theta).any())重新加载数据theta np.zeros((n1,1))勿用np.random.randngradientDescent报错ValueError: operands could not be broadcast togetherX和theta维度不匹配print(X.shape, theta.shape, y.shape)—— X应为(m,2)theta为(2,1)y为(m,1)theta theta.reshape(-1,1)或X X.reshape(m,-1)强制规范维度归一化后预测结果严重偏离测试样本归一化时用了错误的mu/sigma在预测前加print(mu, sigma, x_test)确认数值合理显式写出x_test_norm (x_test - mu) / sigma禁止任何简写正规方程np.linalg.inv报错LinAlgError: Singular matrixX存在线性相关列或m nprint(np.linalg.matrix_rank(X), X.shape)—— 若秩 列数说明相关改用theta np.linalg.pinv(X.T X) X.T y或删除冗余特征除了表格还有几个独家避坑技巧“三色打印法”调试梯度下降在gradientDescent循环内每100次迭代打印print(fIter {iter}: J{J_history[iter]:.4f}, theta{theta.ravel()})。用不同颜色标记J值绿色、theta0蓝色、theta1红色。当看到J稳定下降而theta剧烈跳动立刻怀疑α过大。“维度断言”防御式编程在每个函数开头加断言assert X.shape[0] y.shape[0], X and y must have same rows。这能在错误发生前就捕获问题。“双轨验证”保底策略无论用梯度下降还是正规方程最后都用computeCost(X, y, theta)计算最终J值。两者J值应高度一致1e-8否则必有实现错误。最后分享一个真实案例某学员在多变量部分用alpha0.01死活不收敛J_history在1000次后仍波动。我让他检查mu和sigma发现sigma中有一个值为0——原来他误将偏置列全1也纳入了归一化修正为X data[:,0:2]后一切正常。这个教训刻骨铭心归一化只针对原始特征永远排除人工添加的常数列。6. 工具选型与性能优化当ex1遇上真实数据规模ex1的数据量极小m≈100但它的代码结构是工业级项目的微缩模型。当我们将这套范式迁移到真实场景时工具选型和性能优化就变得至关重要。这里没有银弹只有基于场景的务实选择。6.1 向量化 vs 循环为什么绝不手写for循环ex1的computeCost函数提供了显式循环版本已注释。有人觉得它更易懂便在真实项目中沿用。这是巨大误区。我用真实房价数据m10000做过基准测试向量化X theta耗时0.002秒显式循环for i in range(m)耗时1.8秒性能差距达900倍原因在于numpy的向量化操作调用的是底层C/Fortran优化的BLAS库而Python循环是解释执行每轮都有对象创建、类型检查等开销。更隐蔽的风险是循环版本无法利用GPU加速。当你的数据量升至百万级循环版本可能需要数小时而向量化版本在GPU上只需数秒。因此ex1的教学价值之一就是强制你建立“向量化思维”——看到求和、点积、矩阵乘第一反应是找numpy的对应函数而非for循环。6.2 学习率自适应从手动调参到Adam的平滑过渡ex1要求手动设置α这在教学中无可厚非。但在真实项目中为每个新任务调α是低效的。此时应自然过渡到自适应优化器。以Adam为例它结合了动量Momentum和RMSProp的优点动量项累积历史梯度方向加速收敛RMSProp项自适应调整每个参数的学习率缓解特征尺度差异。其核心更新公式为m_t β1 * m_{t-1} (1-β1) * g_t一阶矩估计v_t β2 * v_{t-1} (1-β2) * g_t²二阶矩估计theta theta - α * m_t / (sqrt(v_t) ε)其中β10.9, β20.999, ε1e-8是默认值。你会发现Adam几乎不需要调α——0.001是安全起点。我在某金融风控模型中用Adam替代手动调参的SGD模型收敛速度提升3倍AUC提升0.005。ex1虽不涉及但它为你理解这些高级优化器奠定了坚实的梯度下降直觉。6.3 内存优化当数据大到放不下RAM时ex1的数据可全量载入内存但真实场景常遇“数据大于内存”。此时必须采用在线学习Online Learning策略。核心思想是不加载全部数据而是分批mini-batch读取、计算梯度、更新参数。伪代码如下for epoch in range(num_epochs): for batch_X, batch_y in get_next_batch(large_data.csv, batch_size1000): # 对当前batch执行梯度下降 grad compute_gradient(batch_X, batch_y, theta) theta theta - alpha * grad关键点在于get_next_batch函数它应使用生成器yield实现流式读取避免一次性加载。pandas的pd.read_csv(..., chunksize1000)是理想选择。我处理过10GB的日志文件用此方法在8GB内存的机器上20分钟完成训练。ex1虽小但它教会你的gradient (1/m) * X.T error正是mini-batch梯度下降的原子单元——只是m从总样本数变成了当前批次大小。7. 项目延展与工程实践从ex1到生产环境的五步跃迁完成ex1只是万里长征第一步。真正的价值在于如何将这个玩具模型演变为可落地的工程系统。以下是基于ex1的五个关键跃迁方向每一步都对应真实项目中的痛点。7.1 数据预处理自动化构建可复用的Pipelineex1的手动归一化是教学必需但生产中必须自动化。解决方案是scikit-learn的Pipelinefrom sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression pipeline Pipeline([ (scaler, StandardScaler()), # 自动计算mu/sigma并存储 (regressor, LinearRegression()) # 自动调用正规方程 ]) pipeline.fit(X_train, y_train) # 训练时自动归一化 y_pred pipeline.predict(X_test) # 预测时自动用相同参数归一化这个Pipeline会将StandardScaler的mu/sigma参数持久化确保训练与预测一致性。某公司曾因手动归一化参数未保存导致模型上线后预测全错损失数十万。Pipeline是防错的第一道防火墙。7.2 模型评估体系化超越单一J值的多维审视ex1只用J(θ)评估但真实场景需多维指标训练集J vs 验证集J若训练J很小验证J很大说明过拟合残差图Residual Plotplt.scatter(y_pred, y_pred - y_true)理想状态是点均匀分布在y0线附近若呈漏斗状说明方差非齐性R²分数1 - SS_res / SS_tot解释模型捕获变异的比例业务指标如房价预测关注绝对误差中位数MAE而非均方误差MSE因MSE对异常值敏感。我在某房产平台项目中就因只看R²0.85忽略MAE高达15万上线后用户投诉“价格不准”后改用MAE优化用户体验显著提升。7.3 模型部署轻量化从.py到API的无缝转换ex1的模型是.py文件但生产需要API。最简方案是Flaskfrom flask import Flask, request, jsonify import joblib app Flask(__name__) model joblib.load(linear_model.pkl) # 保存的Pipeline app.route(/predict, methods[POST]) def predict(): data request.json X np.array([[data[area], data[rooms]]]) pred model.predict(X)[0][0] return jsonify({price: float(pred)}) if __name__ __main__: app.run(host0.0.0.0:5000)用joblib.dump(pipeline, linear_model.pkl)保存训练好的PipelineAPI启动后即可接收HTTP请求。某初创团队用此方案3天内将ex1级模型上线为内部工具支撑销售团队实时估价。7.4 持续监控与反馈闭环让模型活起来模型上线不是终点而是起点。必须建立监控数据漂移Data Drift定期计算新数据的mu/sigma与训练集对比若差异10%触发告警性能衰减Performance Decay每日计算线上预测的MAE若连续3天上升启动模型重训反馈收集在API响应中加入feedback_url: https://.../feedback?predxxxactualyyy收集用户纠错。某教育平台通过此闭环发现模型对“学区房”预测偏差大补充特征后准确率提升12%。ex1教会你建模而闭环教会你让模型持续进化。7.5 伦理与可解释性当线性回归遇见XAI线性回归常被视为“可解释模型”但ex1并未深挖。真实项目中必须回答“为什么预测这个价格”解决方案是SHAPSHapley Additive exPlanationsimport shap explainer shap.LinearExplainer(model.named_steps[regressor], model.named_steps[scaler].transform(X_train)) shap_values explainer.shap_values(X_test.iloc[0:1]) shap.plots.waterfall(shap_values[0]) # 可视化各特征贡献这张瀑布图会清晰显示面积贡献85万房间数贡献-12万最终预测1230万。这不仅是技术需求更是合规要求——欧盟GDPR规定用户有权获知自动化决策的理由。ex1的θ向量正是这一切的起点。8. 个人实操体会那些年在ex1里悟到的朴素真理写到这里我想分享几个在反复调试ex1过程中沉淀下来的体会。它们没有出现在任何教材里却比公式更接近机器学习的本质。第一个体会“收敛”不是目标而是副产品。初学时我 obsessively盯着J_history曲线追求它光滑下降至平坦。直到某次我把α设得极小1e-5J曲线美得像教科书但theta值在迭代10000次后仍在微调。我突然意识到我们真正需要的不是J无限趋近于某个极小值而是J下降到一个“业务可接受”的阈值比如MAE5万且theta不再发生实质性变化。在真实项目中我常设early stopping当连续100次迭代J下降1e-6就主动终止。这省下90%的计算时间结果几乎无损。ex1教会我工程思维的第一课是定义什么是“足够好”。第二个体会维度是敌人也是朋友。ex1的单变量部分X是(m,2)多变量是(m,3)看起来差别不大。但当我第一次处理1000维的文本特征时才真正理解“维度灾难”。那时X.T X是一个1000×1000矩阵内存占用2MB尚可接受但当维度升至10000就是200MB且求逆时间指数增长。ex1用温和的方式让我敬畏维度——它不恐吓你

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑