ARTICLE DETAIL

资讯详情

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

ELM极限学习机分类器:从随机映射原理到调参实战指南

ELM极限学习机分类器:从随机映射原理到调参实战指南 简介面向机器学习初学者的ELM分类器MATLAB实现包适用于需要快速完成分类任务且对训练速度有要求的场景可有效解决传统BP神经网络迭代慢、调参复杂的痛点。包内共5个文件其中3个.m脚本构成核心代码elmtrain.m负责模型训练elmpredict.m用于新样本预测elm.m集成封装接口另含2个.xlsx文件提供示例测试数据方便验证效果用户可自行替换数据以适配不同任务。压缩包仅14KB结构轻量开箱即用。当前已有581人学习尤其适合学生、科研人员及工程开发者快速上手极限学习机。借助这份资源用户可直接运行完整流程理解随机初始化隐藏层参数、激活函数选择及通过伪逆求解输出权重的关键原理并基于清晰注释进行二次开发与调参优化例如通过交叉验证选择节点数或加入正则化提升泛化能力极大节省建模时间。1. ELM这么火到底解决了什么问题很多工程师第一次听到ELM分类器会以为是什么新出的深度学习花活其实ELM极限学习机Extreme Learning Machine把单隐层前馈神经网络的训练简化到了极致输入层到隐藏层的权重矩阵随机生成后直接固定隐藏层把样本映射到高维空间输出层权重用最小二乘一步解析解算出来连梯度下降都不用跑。训练耗时从分钟、小时级降到毫秒、秒级特别适合几千到十万条量级的小表格数据、实时预测和嵌入式场景。你可以用它快速搭Baseline、做特征筛选的验证也能直接作为生产分类器。它不适合超大原始图像或语音那是深度网络的阵地但处理结构化数据时ELM的性价比非常可观。2. ELM分类器原理拆解随机映射为什么不需要训练隐藏层2.1 看似“拍脑袋”的随机投影其实是高维特征变换ELM分类器的网络结构和你熟悉的神经网络一样分为输入层、隐藏层、输出层。真正让ELM接地气的地方在于训练方式。设输入矩阵为X维度是(n_samples, n_features)随机初始化输入层到隐藏层的权重矩阵W和偏置b这两个参数一经生成便不再更新。隐藏层的输出矩阵由激活函数g计算得到H g(X W b)H的维度是(n_samples, n_hidden)。到这里ELM扮演的角色和SVM使用核函数非常像——它把原始样本映射到一个高维特征空间。输入权重越随机映射越非线性样本在这个空间中线性可分的概率就越高。这就是ELM能work的直觉基础随机投影虽然看起来像黑匣子但只要隐藏层维度足够宽原本纠缠在一起的数据有很大概率在高维空间被拉开。数学上有Johnson-Lindenstrauss引理这类保距嵌入理论做支撑工程上则是大量实验验证了随机映射确实有效。理解这一点很重要因为它决定了你后续怎么调参数。ELM的隐藏层本质上不是在学习而是在产生一组随机的“特征工程”。它不需要反向传播来逐层修正权重是因为隐藏层的目的不是表达数据内部的层次语义而是提供一个高维线性分离的舞台。当样本数从几百涨到几万隐藏层宽度从几十涨到几百分类效果的变化规律都可以从这个视角去解释。2.2 输出权重的解析解从最小二乘到带正则化的求解网络里只剩最后一层输出权重β。它的维度是(n_hidden, n_classes)或(n_hidden, 1)二分类或回归时。ELM的训练目标只有一个——让Hβ尽可能接近目标矩阵T。T是标签矩阵分类任务中通常做one-hot编码维度是(n_samples, n_classes)。这是一个标准线性最小二乘问题min || H β - T ||²最优解为β H† T其中H†是H的Moore-Penrose广义逆常见的数值实现方式有SVD分解法也有通过求解正规方程得到的。当隐藏层节点数n_hidden小于样本数n_samples时正规方程形式为β (HᵀH)⁻¹ Hᵀ T但实际工程中HᵀH往往接近奇异直接求逆会得到数值上不稳定的解。因此更稳健的解法是加上一个正则项把问题改成带岭回归约束的优化目标β (HᵀH I / C)⁻¹ Hᵀ T这里的C是正则化参数I是单位矩阵。当C趋近无穷大时公式退化为普通最小二乘C越小对输出权重β的约束越强泛化性能越好和SVM的惩罚系数C在精神上是一致的。这个解析解的求解过程没有迭代、没有学习率、没有epoch概念一次矩阵运算就把输出层整明白。这也是ELM速度快到离谱的根本原因。如果你自己手推过这个解会发现它的计算复杂度主要来自两个部分一是计算HᵀH二是求解线性系统。前者是(n_features或n_hidden)维矩阵乘法后者是一个大小为n_hidden的线性方程组求解。当n_hidden在几百的数量级时即使样本量有几万条训练时间也基本在两三秒以内这在大规模正交实验或特征工程循环里优势非常突出。2.3 ELM、SVM、BP对比适用边界在哪里把ELM分类器和主流方案放到一张桌子上对比能更清晰地看出它适合哪些场景。对比维度ELMSVMBP神经网络训练方式随机映射解析解凸优化/二次规划梯度下降反向传播迭代次数0依赖SMO迭代几十到几百轮主要超参数隐藏节点数、激活函数、C核函数、核参数、C网络层数、神经元数、学习率、正则化训练速度毫秒到秒级千样本以上明显变慢最慢数据规模上限万级结构化数据千到万级百万级起可解释性输出权重可直接查看支持向量可以查看权重难解释从这张表能看出ELM的位置很特殊它比SVM训练快很多尤其在样本量上万、特征数上百的情况下SVM的二次规划求解会让人等到绝望ELM则几乎感觉不到计算压力。和BP网络比ELM既没有收敛性问题也没有学习率调参的痛苦训练过程完全没有随机梯度下降那种“调一晚上参数还是loss不降”的折磨。但ELM也有明显短板。首先是隐藏层随机映射不做任何数据自适应的调整要获得更强的表达能力必须把隐藏层做宽参数搜索空间比调节一个BP网络更粗。其次它对噪声和异常值比较敏感因为最小二乘准则本身不具备鲁棒性数据里混进极端离群点时输出权重会被拉偏。第三随机性带来不稳定同一份数据跑两次结果不一样必须在工程流程里用多重采样来兜底。理解了这三个边界你就知道ELM适合做快速原型验证、中小数据集的分类任务、以及需要低延迟推理的场景。不适合把它用在数据量极大、需要自动学习高层语义特征的深度学习任务里。3. 跑通第一个ELM分类器从NumPy手写到30行核心代码3.1 用最快路径写出一个能跑的ELM分类器直接上代码我习惯用NumPy把ELM分类器实现一遍而不是一开始就依赖封装库。原因很简单自己写一遍你才能真正理解那个解析解的每一步后面调包、调参才不会像盲人摸象。import numpy as np class ELMClassifier: def __init__(self, n_hidden100, activationsigmoid, C1.0, random_stateNone): self.n_hidden n_hidden self.activation activation self.C C self.random_state random_state def _activate(self, Z): if self.activation sigmoid: return 1.0 / (1.0 np.exp(-Z)) elif self.activation tanh: return np.tanh(Z) elif self.activation relu: return np.maximum(0, Z) else: raise ValueError(Unsupported activation) def fit(self, X, y): if self.random_state is not None: np.random.seed(self.random_state) n_samples, n_features X.shape # 随机初始化输入层权重与偏置范围取[-1, 1] self.W np.random.uniform(-1, 1, (n_features, self.n_hidden)) self.b np.random.uniform(-1, 1, (self.n_hidden,)) # 计算隐藏层输出矩阵 H H self._activate(X self.W self.b) # 分类任务把标签转成one-hot矩阵 self.classes_ np.unique(y) T np.zeros((n_samples, len(self.classes_))) for i, label in enumerate(y): T[i, np.where(self.classes_ label)[0]] 1 # 带岭正则化的解析解beta (H^T H I/C)^{-1} H^T T HtH H.T H I_norm np.eye(self.n_hidden) / self.C self.beta np.linalg.solve(HtH I_norm, H.T T) return self def predict_proba(self, X): H self._activate(X self.W self.b) scores H self.beta exp_scores np.exp(scores - np.max(scores, axis1, keepdimsTrue)) return exp_scores / np.sum(exp_scores, axis1, keepdimsTrue) def predict(self, X): probs self.predict_proba(X) return self.classes_[np.argmax(probs, axis1)]这段代码的核心逻辑有两个。第一输入权重W和偏置b用均匀分布随机生成后不再改变隐藏层矩阵H只是X的一次随机投影加非线性激活。第二输出权重β通过带正则化的解析解一步算出np.linalg.solve直接解线性方程组比显式求逆更快、数值上更稳定。I / self.C就是岭正则项C越大解越接近普通最小二乘C越小对权重的收缩越强。参数初始化范围有讲究。W取[-1, 1]配合标准化后的输入一般没问题但如果输入特征没做标准化某些特征的量纲很大完整的XW就会产生极大的绝对值sigmoid立刻饱和隐藏层输出出现大片全0或全1模型直接报废。所以用ELM前标准化数据不是建议是必须。均匀分布还是正态分布对结果影响不大我习惯用[-1, 1]均匀分布复现性更好。3.2 在开源数据集上跑Baseline不只贴精度还要看训练时间手写实现跑通之后最简单有效的验证是拿它和逻辑回归对比一轮精度和耗时。这里用手写数字数据集包含1797张8x8图像虽然像素维度不高但足够看出ELM的训练速度优势。from sklearn.datasets import load_digits from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression import time data load_digits() X, y data.data, data.target X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) scaler StandardScaler() X_train scaler.fit_transform(X_train) X_test scaler.transform(X_test) # ELM分类器 start time.time() elm ELMClassifier(n_hidden300, activationsigmoid, C1.0, random_state42) elm.fit(X_train, y_train) elm_time time.time() - start elm_acc (elm.predict(X_test) y_test).mean() # 逻辑回归做基线对比 start time.time() lr LogisticRegression(max_iter1000, random_state42) lr.fit(X_train, y_train) lr_time time.time() - start lr_acc (lr.predict(X_test) y_test).mean() print(fELM | 精度: {elm_acc:.4f} | 训练耗时: {elm_time:.4f}s) print(fLogReg | 精度: {lr_acc:.4f} | 训练耗时: {lr_time:.4f}s)这段代码选隐藏层300个节点sigmoid激活C1手写数字这种64维输入、10分类的任务对ELM来说压力不大。实际跑下来ELM的训练耗时通常比逻辑回归少一个数量级精度持平或略优。逻辑回归针对这类数据已经很强ELM赢在速度尤其当你需要在一个特征选择循环里训练几百次模型时ELM的优势会从“够用”变成“碾压”。参数方面提醒两点n_hidden300并不是随手填的。对64维输入300个隐藏节点大约是对数级别搜索范围的中位值效果一般已经有保障。C先取1.0跑通流程后续做网格搜索。random_state42能保证你第一次跑就有稳定的对比结果但正式实验时不能只看单次第5章会详细说随机性的坑。3.3 核ELM当普通随机映射不够时加一层核变换随机投影在高维空间把数据拉开但并不保证每类数据都能拉得足够开尤其当原始特征有复杂非线性关系时随机映射可能表现得不够好。常见做法是在随机映射之前先对输入做一次核变换这就是核ELM的思想。def rbf_kernel(X, gamma1.0): X2 np.square(X).sum(axis1, keepdimsTrue) dist2 -2 * (X X.T) X2 X2.T return np.exp(-gamma * dist2) K rbf_kernel(X_train, gamma0.1)核ELM不再直接使用X作为隐藏层的输入而是先构造一个RBF核矩阵K然后用K替换原始特征。核函数的作用是显式地把样本映射到极大维度甚至无穷维空间随机映射则是在这个核映射后的空间上再做一次投影。工程上核ELM通常比普通ELM更稳但核矩阵是n_samples x n_samples大小样本量超过两万时内存会顶不住这也是它的使用边界。如果你拿ELM做手写数字识别普通随机映射已经能拿到95%以上的准确率核ELM能把精度再往上抬代价是训练耗时从百分之一秒量级变成秒级。对中小数据集来说核ELM是一个值得放进候选池的方案尤其当普通ELM的精度卡在瓶颈时换核比单纯调隐藏节点数更有效。需要注意的是这里的K是训练数据和训练数据之间的核矩阵预测时需要分别计算新样本与训练样本的核距离这在实际部署时有点麻烦除非预先保留全部训练样本。4. ELM分类器三个必调参数隐藏节点数、激活函数与正则化C4.1 隐藏节点数玄学背后其实有搜索规律隐藏节点数n_hidden是ELM分类器最核心的超参数也是很多新手最拿不准的。它不像BP网络那样有“越大表达能力越强”的直觉因为ELM的随机投影并不保证节点越多一定越好。节点数太少高维映射空间不够宽不同类别的样本可能仍然纠缠在一起节点数太多隐藏层H的秩不会同步增长反而可能出现HᵀH近奇异、解被噪声主导的问题。我一般会先在log空间做网格粗搜n_hidden从16开始按2倍步长一直搜到1024甚至2048用交叉验证看精度的收敛曲线。你会发现曲线通常是先快速上升、然后趋于平台、最后略微下降。平台区和下降区的拐点就是你在生产环境应该选的节点数。经验规则是n_hidden取log2(n_samples)的5到10倍左右但不要超过n_samples的一半。比如1万条样本log2约14节点数取70到140是合理起点300到500在加正则的前提下也安全。隐藏节点数还直接影响训练时间和推理时间。推理阶段要做一次X W的矩阵乘法W的列数就是n_hidden所以隐藏节点数每翻一倍推理耗时也涨一倍。在嵌入式或实时场景里这个成本不可忽略你需要在精度和延迟之间找一个平衡点。我习惯做法是先在离线环境用大节点数摸清理论上限再逐步减半观察精度损失精度损失在1%以内就继续减直到找到性能边界。这样比一上来就固定节点数靠谱得多。4.2 激活函数怎么选sigmoid、tanh、relu、径向基对比ELM分类器对激活函数的选择比BP神经网络宽容得多因为不涉及梯度回传激活函数只需要提供非线性映射即可。不同激活函数的隐藏层输出范围不同直接影响H矩阵的数值分布。激活函数输出范围特点常用场景sigmoid(0, 1)单调饱和输出非负数据尺度适中做概率类映射tanh(-1, 1)零均值倾向于稳定大多数结构化数据默认选择ReLU[0, ∞)稀疏激活一半输出为0隐藏节点数较多时RBF核映射(0, 1]局部响应适合聚类分布特征尺度相似且类别中心分明sigmoid在ELM里有个特殊问题如果输入X的尺度没控制好W和b随机初始化后神经元的加权和可能落在sigmoid的饱和区H矩阵里出现大量接近0或接近1的值信息含量变低精度受限。tanh的输出以0为中心对数据标准化后的表现通常更稳定这也是我在实际项目里最常用的激活函数。ReLU的好处是计算快坏处是随机初始化下大约有一半神经元输出恒为0等效隐藏节点数缩水。如果选择ReLU建议把n_hidden上调30%到50%来补偿。RBF径向基函数在ELM里的用法不是直接作为激活函数作用于XW而是把原始样本作为中心点计算每个样本与中心点的欧氏距离后再做高斯变换。RBF对数据的局部结构敏感在聚类特征明显的数据集上效果突出但对高维稀疏数据表现很糟欧氏距离会变得没有区分度。选激活函数没有万能答案我一般会准备一个候选列表tanh、sigmoid、relu、rbf在同一个交叉验证框架下跑一遍用精度和方差做选择。这并不耗时ELM快就快在你可以肆无忌惮地穷举。4.3 正则化C过拟合与奇异矩阵的后悔药正则化C可能是ELM分类器里最容易被忽略的参数。很多教程手写ELM直接用np.linalg.pinv(H)求伪逆完全不提C这在隐藏节点数远小于样本数时问题不大一旦节点数逼近或超过样本数HᵀH就会变得奇异伪逆解出的β数值极大训练集拟合完美测试集一塌糊涂。这正是过拟合的典型症状。C的作用是给β加上一个权重收缩惩罚控制输出权重的范数。实际调参中C在0.001到100之间按对数均匀搜索观察不同C值下训练集和验证集精度变化。C过小β被压得太紧模型欠拟合C过大正则约等于零过拟合风险回升。最佳C值通常落在0.1到10之间但和数据集有关不能拍脑袋。from sklearn.model_selection import GridSearchCV from sklearn.base import BaseEstimator # 用前文的ELMClassifier包一层sklearn接口方便做网格搜索 param_grid { n_hidden: [64, 128, 256, 512], C: [0.001, 0.01, 0.1, 1, 10, 100], activation: [tanh, sigmoid, relu] } # 实际使用时建议配合K折交叉验证搜索 # grid GridSearchCV(ELMClassifier(random_state42), param_grid, cv5, scoringaccuracy) # grid.fit(X_train, y_train) # print(grid.best_params_)这段网格搜索代码展示了ELM调参的标准姿势。因为ELM训练足够快即使参数组合有60多种、5折交叉验证总训练次数300次左右在结构化数据上通常几秒到几十秒就能完成。作为对比BP网络做同样的网格搜索需要数小时甚至数天。ELM把超参数搜索的成本压到和单次BP训练接近这让你有底气把参数空间铺得更开。需要注意的坑是网格搜索时应固定random_state否则同一组参数因为随机种子不同会产生额外的精度波动干扰参数比较。更稳妥的做法是每组参数跑3到5个随机种子取平均精度作为搜索依据这部分内容在第6章会细说。5. ELM分类实战避坑5个让人翻车的经典现场5.1 数据没标准化精度直接崩在个位数现象用iris或某一个表格数据集跑ELM训练和测试精度都不到20%和随机猜测差不多。检查代码逻辑没毛病激活函数也换了好几个始终无效。原因数据集中某个特征量纲极大比如数值从0到10000另外几个特征范围在0到1之间。随机权重W初始化范围是[-1,1]量纲大的特征经过XW后产生极大绝对值sigmoid或tanh立刻饱和隐藏层输出全部变成相同的值。隐藏层H矩阵的列几乎线性相关HᵀH接近退化输出权重解出来没有任何区分能力。解决在进入ELM之前对每个特征做Z-score标准化均值为0、方差为1。标准化之后不同特征对随机投影的贡献才均衡W的取值范围和特征尺度才能匹配。手工实现代码里加入StandardScaler预测时也要用训练集拟合出的scaler做同样变换不能分别fit。这是ELM使用中翻车率最高的一条几乎成为本分类器社区里的老生常谈。5.2 同一份数据、同样参数每次跑精度差几个点现象同一个数据集同一个n_hidden和C第一次跑精度0.96第二次变成0.93第三次又回到0.95。开始怀疑代码有bug或者数据集出了问题。原因ELM的输入权重W和偏置b是随机生成的每跑一次都不一样。隐藏层特征空间不同输出权重自然不同精度波动是本质属性不是代码缺陷。这在数据集小、隐藏节点数小时尤其明显随机性的影响被放大。解决正式的实验和调参流程里绝不能只看单次结果。常见做法是固定random_state来复现单次实验但评估模型真实水平时要跑多个随机种子一般取5次或10次记录平均精度和标准差用均值和方差两个数字来评价模型。我在项目流程里会把“随机种子列表”设计成参数从[0,1,2,3,4]这类小集合开始时间允许就扩展到20个。能把标准差压到1%以内说明这个配置稳定否则继续调。5.3 训练集满分、测试集拉胯隐藏节点数设太大现象训练集精度高达0.999测试集只有0.85两者差距明显。反复调C也没法恢复到满意水平。原因隐藏节点数设置远超合理范围比如只有2000条样本n_hidden却设成了2000。隐藏层输出矩阵H的维度远大于样本数最小二乘解唯一地拟合了训练集的每一个细节包括噪声。HᵀH奇异或接近奇异β的范数爆炸模型完全丧失泛化能力。解决用验证集或者交叉验证观察训练集和验证集的精度差距。当差距超过3个百分点时优先减少n_hidden同时增大正则化系数C。我的经验值是n_hidden不超过样本数的1/3同时保持C在1左右做搜索。如果节点数已经减到合理范围但过拟合依旧考虑使用核ELM替代随机投影核映射的局部约束能力更强对噪声没那么敏感。5.4 矩阵奇异或预测值全是NaNC设成了0现象fit过程中np.linalg.solve报错提示matrix is singular或者模型能跑通但predict输出NaN精度直接没法看。原因C的含义是正则化强度的倒数C越大正则越弱。当C设为0或接近0时公式(HᵀH I/C)⁻¹里的I/C趋近无穷大理论上意味着完全不允许β有任何幅值实际上数值计算直接溢出。还有人会把C从1按习惯改成0以为“不设正则”结果就是上面说的数值崩溃。另一种情况是C非常大比如1e10I/C几乎为零HᵀH奇异时又回到伪逆的坑。解决C取0.001到100之间的正值不要取0或极端大数。如果你真的想做无正则求解用np.linalg.pinv(H) T而不是走正规方程SVD分解能处理奇异的H矩阵。但工程上建议永远保留小正则项它带来的精度损失往往远小于数值稳定性收益。记住一句话C是后悔药不要轻易戒掉。5.5 少数类被吞掉非平衡数据上的精度骗局现象二分类任务正类只占5%。模型精度95%看似优秀实际上把所有样本全部判为负类正类召回率是0。用accuracy评估会完全被骗。原因ELM的输出权重β通过最小二乘拟合one-hot目标矩阵各类别样本数量悬殊时最小二乘会优先拟合体量大的类别小类别的误差贡献被稀释。ELM对这个问题的敏感程度比逻辑回归还要高因为逻辑回归有概率校准机制ELM输出的只是类间距离没有天然的概率解释。解决先对少数类加权重在目标矩阵T中把少数类样本所在行的误差权重提高或者对训练集做SMOTE过采样。更简单的做法是改变分类决策阈值默认取argmax对所有类公平但实际生产中代价矩阵往往不对称。我用过最顺手的方式用ELM输出每个样本在各类别上的score在验证集上搜索最优决策阈值让F1分数最大化而不是accuracy最大化。评估指标从accuracy换成macro-F1或recall才能真正反映少数类的表现。6. 一份能交差的ELM评估流程重复运行、交叉验证与多指标看板很多ELM项目翻车不在算法而在评估方式太粗糙跑一次出个精度就觉得完事。ELM的随机性让单次精度的参考价值非常低我现在的标准流程会分成三步走。第一步数据切分固定为训练、验证、测试三段。训练集用来做交叉验证调参验证集用来做重复运行的最终模型筛选测试集只在模型定稿后碰一次防止验证集被反复使用后产生信息泄漏。第二步调参搜索阶段每个参数组合跑5个随机种子记录精度、macro-F1和标准差。第三步用测试集跑一次同时输出混淆矩阵看错误集中在哪些类别。from sklearn.model_selection import StratifiedKFold import numpy as np # 重复运行的ELM评估骨架 def evaluate_elm_repeated(X, y, n_hidden, C, activation, n_runs5, n_splits5): accs [] f1s [] for seed in range(n_runs): skf StratifiedKFold(n_splitsn_splits, shuffleTrue, random_stateseed) fold_accs [] for train_idx, val_idx in skf.split(X, y): model ELMClassifier( n_hiddenn_hidden, CC, activationactivation, random_stateseed ) model.fit(X[train_idx], y[train_idx]) fold_accs.append((model.predict(X[val_idx]) y[val_idx]).mean()) accs.append(np.mean(fold_accs)) return { mean_acc: np.mean(accs), std_acc: np.std(accs) }这段代码的核心是把随机种子和K折交叉验证揉在一起。每个随机种子对应一组不同的折切分5个种子乘5折就是25次独立训练得到的平均精度比单次结果有说服力得多。ELM训练快25次训练在中小型数据集上也就几秒钟这代价完全可以接受。标准差的含义比平均精度更值得关注标准差大说明模型对该参数的随机初始化敏感必须继续调参或增宽隐藏层。多指标看板是我交付模型前的最后工序不要只打印accuracy。分类任务至少要同时看macro-F1和混淆矩阵二分类还要看ROC-AUC。ELM分类器的输出score可以用softmax转成伪概率拿来画ROC曲线完全没问题。我在实际项目中遇到过精度96%但正类召回率只有30%的情况如果只看accuracy这个模型直接上线会出大事故。现在我做任何ELM实验默认动作都是固定随机种子、至少重跑5次取均值、输出混淆矩阵。单次精度只配在调试阶段看一眼靠它下结论就是自我安慰。ELM这个技术方向值不值得投入关键就看你能不能把它从“一个快但玄的算法”变成“一个可复现、可量化的工程工具”。它的训练成本和调参成本都极低你可以玩命地搜索参数、重复实验这种试错容错性是SVM和BP给不了的。希望帮到你。本文还有配套的精品资源点击获取
返回列表