文章目录

  • 角度1
    • 缺乏可用于训练的数据
    • 过拟合
    • 欠拟合
    • 训练时间长
  • 角度2
    • 从数据上提升性能
    • 从算法上提升性能
    • 从算法调优上提升性能
    • 从模型融合上提升性能

角度1

缺乏可用于训练的数据

一般来说,数据越多,模型的性能就越好。缺乏数据的问题是,我们的深度学习模型可能无法从数据中学习模式或功能,因此它可能无法在未看到的数据上提供良好的性能。

我们可以利用数据增强技术来代替花费数天时间来收集数据。

数据增强是在不实际收集新数据的情况下,生成新数据或增加数据以训练模型的过程。

图像数据有多种数据增强技术,常用的增强技术有旋转、剪切、翻转等。

过拟合

当一个模型在训练集上执行得非常好,但是在验证集(或不可见的数据)上性能下降时,就会被认为是过拟合。


上图中蓝色标记的部分是过拟合模型,因为训练误差非常小并且测试误差非常高。过拟合的原因是该模型甚至从训练数据中学习了不必要的信息,因此它在训练集上的表现非常好。
但是,当引入新数据时,它将无法执行。我们可以向模型的架构中引入Dropout,以解决过拟合的问题。
使用Dropout,我们随机关闭神经网络的某些神经元。假设我们在最初有20个神经元的图层上添加了概率为0.5的Dropout层,因此,这20个神经元中的10个将被抑制,我们最终得到了一个不太复杂的体系结构。
因此,该模型将不会学习过于复杂的模式,可以避免过拟合。

欠拟合

欠拟合是指模型无法从训练数据本身中学习模式,因此训练集上的性能较低。

为了克服欠拟合的问题,你可以尝试以下解决方案:

  • 增加训练数据
  • 制作一个复杂的模型
  • 增加训练的epoch
    对于我们的问题,欠拟合不是问题,因此,我们将继续研究提高深度学习模型性能的下一种方法。

训练时间长

有些情况下,你可能会发现你的神经网络需要花很多时间来收敛。这背后的主要原因是输入到神经网络层的分布发生了变化。
在训练过程中,神经网络各层的权值发生变化,激活也随之变化。现在,这些激活是下一层的输入,因此每一次连续的迭代都会改变分布。
由于这种分布的变化,每一层都必须适应不断变化的输入—这就是为什么训练时间增加的原因。
为了克服这一问题,我们可以应用批处理标准化(batch normalization),其中我们正常化的激活隐藏层,并试图作出相同的分布。

角度2

从数据上提升性能

  1. 收集更多的数据
  2. 产生更多的数据
  3. 对数据做缩放
  4. 对数据做变换
  5. 特征选择
  6. 重新定义问题
    1)收集更多的数据
    你还能收集到更多的训练数据吗?你的模型的质量往往取决于你的训练数据的质量。你需要确保使用的数据是针对问题最有效的数据。你还希望数据尽可能多。深度学习和其它现代的非线性机器学习模型在大数据集上的效果更好,尤其是深度学习。这也是深度学习方法令人兴奋的主要原因之一。


数据集压倒算法
多数情况下,数据集越多越好

2)产生更多的数据
深度学习算法往往在数据量大的时候效果好。我们在上一节已经提到过这一点。如果由于某些原因你得不到更多的数据,也可以制造一些数据。

  • 如果你的数据是数值型的向量,那么随机生成已有向量的变形向量。
  • 如果你的数据是图像,用已有的图像随机生成相似图像。
  • 如果你的数据是文本,做法你懂得……
    这类做法通常被称为数据扩展或是数据生成。你可以使用生成模型,也可以用一些简单的小技巧。举个例子,若是用图像数据,简单地随机选择和平移已有的图像就能取得很大的提升。它能提升模型的泛化能力,如果新的数据中包含这类变换就能得到很好的处理。有时候是往数据中增加噪声,这相当于是一种规则方法,避免过拟合训练数据

深度学习中的图像数据扩充
训练有噪声的数据

3)对数据做缩放此方法简单有效。
使用神经网络模型的一条经验法宝就是:将数据缩放到激活函数的阈值范围。

  • 如果你使用sigmoid激活函数,将数据缩放到0-1之间。
  • 如果选用tanh激活函数,将值域控制在-1~1之间。输入、输出数据都经过同样的变换。比如,如果在输出层有一个sigmoid函数将输出值转换为二值数据,则将输出的y归一化为二进制。
  • 如果选用的是softmax函数,对y进行归一化还是有效的。我还建议你将训练数据扩展生成多个不同的版本:
    · 归一化到0 ~ 1
    · 归一化到-1 ~ 1
    · 标准化

然后在每个数据集上测试模型的性能,选用最好的一组生成数据。如果更换了激活函数,最好重复做一次这个小实验。在模型中不适合计算大的数值。此外,还有许多其它方法来压缩模型中的数据,比如对权重和激活值做归一。

输入数据标准化?
Scikt-Learn准备输入数据

4) 对数据做变换
与上一节的方法相关,但是需要更多的工作量。你必须真正了解所用到的数据。数据可视化,然后挑出异常值。先猜测每一列数据的分布

  • 这一列数据是不是倾斜的高斯分布,若是如此,尝试用Box-Cox方法纠正倾斜
  • 这一列数据是不是指数分布,若是如此,则进行对数变换
  • 这一列数据是不是存在某些特性,但是难以直观地发现,尝试一下对数据平方或者开方
  • 是否可以将特征离散化,以便更好地强调一些特征

凭你的直觉,尝试几种方法

  • 是否可以用投影的方法对数据预处理,比如PCA?
  • 是否可以将多个属性合并为单个值?
  • 是否可以发掘某个新的属性,用布尔值表示?
  • 是否可以在时间尺度或是其它维度上有些新发现?

神经网络有特征学习的功能,它们能够完成这些事情。不过你若是可以将问题的结构更好地呈现出来,网络模型学习的速度就会更快。在训练集上快速尝试各种变换方法,看看哪些方法有些,而哪些不起作用。
如何定义机器学习问题
特征挖取工程
如何用Scikit-Learn准备输入的数据

5) 特征选择
神经网络受不相关数据的影响很小。它们会对此赋予一个趋近于0的权重,几乎忽略此特征对预测值的贡献。你是否可以移除训练数据的某些属性呢?我们有许多的特征选择方法和特征重要性方法来鉴别哪些特征可以保留,哪些特征需要移除。动手试一试,试一试所有的方法。如果你的时间充裕,我还是建议在相同的神经网络模型上选择尝试多个方法,看看它们的效果分别如何。

  • 也许用更少的特征也能得到同样的、甚至更好的效果。
  • 也许所有的特征选择方法都选择抛弃同一部分特征属性。那么就真应该好好审视这些无用的特征。
  • 也许选出的这部分特征给你带来了新的启发,构建出更多的新特征。

特征选择入门介绍
基于Pytrhon的机器学习中的特征选择问题

6)问题重构

在回到你问题的定义上来。你所收集到的这些观测数据是描述问题的唯一途径吗也许还有其它的途径。也许其它途径能更清晰地将问题的结构暴露出来。我自己非常喜欢这种练习,因为它强迫我们拓宽思路。很难做好。尤其是当你已经投入大量的时间、精力、金钱在现有的方法上。即使你列举了3 ~ 5种不同的方式,至少你对最后所选用的方式有充足的信心。

  • 也许你可以将时间元素融入到一个窗口之中。
  • 也许你的分类问题可以转化为回归问题,反之亦然。也许可以把二值类型的输出转化为softmax的输出
  • 也许你可以对子问题建模。

深入思考问题是一个好习惯,最好在选择工具下手之前先完成上述步骤,以减少无效的精力投入。无论如何,如果你正束手无策,这个简单的连续能让你思如泉涌。另外,你也不必抛弃前期的大量工作。

如何定义机器学习问题

从算法上提升性能

  1. 算法的筛选
  2. 从文献中学习
  3. 重采样的方法

你事先不可能知道哪种算法对你的问题效果最好。如果你已经知道,你可能也就不需要机器学习了。你有哪些证据可以证明现在已经采用的方法是最佳选择呢?我们来想想这个难题。

当在所有可能出现的问题上进行效果评测时,没有哪一项单独的算法效果会好于其它算法。所有的算法都是平等的。这就是天下没有免费的午餐理论的要点。

也许你选择的算法并不是最适合你的问题。现在,我们不指望解决所有的问题,但当前的热门算法也许并不适合你的数据集。我的建议是先收集证据,先假设有其它的合适算法适用于你的问题。

筛选一些常用的算法,挑出其中适用的几个。

  • 尝试一些线性算法,比如逻辑回归和线性判别分析
  • 尝试一些树模型,比如CART、随机森林和梯度提升
  • 尝试SVM和kNN等算法
  • 尝试其它的神经网络模型,比如LVQ、MLP、CNN、LSTM等等

采纳效果较好的几种方法,然后精细调解参数和数据来进一步提升效果。将你所选用的深度学习方法与上述这些方法比较,看看是否能击败他们?也许你可以放弃深度学习模型转而选择更简单模型,训练的速度也会更快,而且模型易于理解。

一种数据驱动的机器学习方法
面对机器学习问题为何需要筛选算法
用scikit-learn筛选机器学习的分类算法

2) 从文献中学习
从文献中“窃取”思路是一条捷径。其它人是否已经做过和你类似的问题,他们使用的是什么方法。阅读论文、书籍、问答网站、教程以及Google给你提供的一切信息。记下所有的思路,然后沿着这些方向继续探索。这并不是重复研究,这是帮助你发现新的思路。
优先选择已经发表的论文

3) 重采样的方法

你必须明白自己模型的效果如何。你估计的模型效果是否可靠呢?深度学习模型的训练速度很慢。

  • 这就意味着我们不能用标准的黄金法则来评判模型的效果,比如k折交叉验证。
  • 也许你只是简单地把数据分为训练集和测试集。如果是这样,就需要保证切分后的数据分布保持不变。单变量统计和数据可视化是不错的方法。
  • 也许你们可以扩展硬件来提升效果。举个例子,如果你有一个集群或是AWS的账号,我们可以并行训练n个模型,然后选用它们的均值和方差来获取更稳定的效果。
  • 也许你可以选择一部分数据做交叉验证(对于early stopping非常有效)。
  • 也许你可以完全独立地保留一部分数据用于模型的验证。另一方面,也可以让数据集变得更小,采用更强的重采样方法。
  • 也许你会看到在采样后的数据集上训练得到的模型效果与在全体数据集上训练得到的效果有很强的相关性。那么,你就可以用小数据集进行模型的选择,然后把最终选定的方法应用于全体数据集上。
  • 也许你可以任意限制数据集的规模,采样一部分数据,用它们完成所有的训练任务。

用Keras评估深度学习模型的效果
用重采样的方法评估机器学习算法的效果

从算法调优上提升性能

你通过算法筛选往往总能找出一到两个效果不错的算法。但想要达到这些算法的最佳状态需要耗费数日、数周甚至数月。下面是一些想法,在调参时能有助于提升算法的性能。

  1. 模型可诊断性
  2. 权重的初始化
  3. 学习率
  4. 激活函数
  5. 网络结构
  6. batch和epoch
  7. 正则项
  8. 优化目标
  9. 提早结束训练

你可能需要指定参数来多次(3-10次甚至更多)训练模型,以得到预计效果最好的一组参数。对每个参数都要不断的尝试。有一篇关于超参数最优化的优质博客:如何用Keras网格搜索深度学习模型的超参数

1) 可诊断性
只有知道为何模型的性能不再有提升了,才能达到最好的效果。是因为模型过拟合呢,还是欠拟合呢?千万牢记这个问题。千万

模型总是处于这两种状态之间,只是程度不同罢了。一种快速查看模型性能的方法就是每一步计算模型在训练集和验证集上的表现,将结果绘制成图表。

在训练集和验证集上测试模型的准确率

  • 如果训练集的效果好于验证集,说明可能存在过拟合的现象,试一试增加正则项。
  • 如果训练集和验证集的准确率都很低,说明可能存在欠拟合,你可以继续提升模型的能力,延长训练步骤。
  • 如果训练集和验证集的曲线有一个焦点,可能需要用到early stopping的技巧了。经常绘制类似的图表,深入研究并比较不同的方法,以提高模型的性能。

这些图表也许是你最有价值的诊断工具。
另一种有效的诊断方法是研究模型正确预测或是错误预测的样本。在某些场景下,这种方法能给你提供一些思路。

  • 也许你需要更多的难预测的样本数据。
  • 也许你可以从训练集中删去那些容易被学习的样本。
  • 也许你可以有针对性地对不同类型的输入数据训练不同的模型
    用Keras展现深度学习模型的训练过程
    机器学习算法的过拟合和欠拟合

2) 权重的初始化
有一条经验规则:**用小的随机数初始化权重。**事实上,这可能已经足够了。但是这是你网络模型的最佳选择吗?不同的激活函数也可以有不同的应对策略,但我不记得在实践中存在什么显著的差异。保持你的模型结构不变,试一试不同的初始化策略。记住,权重值就是你模型需要训练的参数。几组不同的权重值都能取得不错的效果,但你想得到更好的效果。

  • 尝试所有的初始化方法,找出最好的一组初始化值。
  • 试一试用非监督式方法预学习,比如自动编码机。
  • 尝试用一组现有的模型权重参数,然后重新训练输入和输出层(迁移学习)。

记住,修改权重初始化值的方法与修改激活函数或者目标函数的效果相当。
深度网络模型的初始化

3) 学习率调节
学习率也能带来效果提升。这里也有一些探索的思路:

  • 尝试非常大、非常小的学习率。
  • 根据参考文献,在常规值附近用网格化搜索。· 尝试使用逐步减小的学习率。
  • 尝试每隔固定训练步骤衰减的学习率。
  • 尝试增加一个向量值,然后用网格搜索。

大的网络模型需要更多的训练步骤,反之亦然。如果你添加了更多的神经节点和网络层,请加大学习率。学习率与训练步骤、batch大小和优化方法都有耦合关系。
使用Keras对深度学习模型进行学习率调节
反向传播算法该选用什么学习率?

4) 激活函数
也许你应该选用ReLU激活函数。仅仅因为它们的效果更好。

在ReLU之前流行sigmoid和tanh,然后是输出层的softmax、线性和sigmoid函数。除此之外,我不建议尝试其它的选择。这三种函数都试一试,记得把输入数据归一化到它们的值域范围。

显然,你需要根据输出内容的形式选择转移函数。比方说,将二值分类的sigmoid函数改为回归问题的线性函数,然后对输出值进行再处理。同时,可能需要调整合适的损失函数。在数据转换章节去寻找更多的思路吧。
为何使用激活函数

5) 网络拓扑结构
调整网络的拓扑结构也会有一些帮助。
你需要设计多少个节点,需要几层网络呢?别打听了,鬼知道是多少。你必须自己找到一组合理的参数配置。

  • 试一试加一层有许多节点的隐藏层(拓宽)。
  • 试一试一个深层的神经网络,每层节点较少(纵深)。
  • 尝试将上面两种组合。
  • 尝试模仿近期发表的问题类似的论文。
  • 尝试拓扑模式。

这是一个难题。越大的网络模型有越强的表达能力,也许你就需要这样一个。

更多层的结构提供了抽象特征的更多结构化组合的可能,也许你也需要这样一个网络。后期的网络模型需要更多的训练过程,需要不断地调节训练步长和学习率。

我的网络模型该设计几层呢
我的网络模型该设计几个节点呢

6) batch和epoch
batch的大小决定了梯度值,以及权重更新的频率。一个epoch指的是训练集的所有样本都参与了一轮训练,以batch为序。你尝试过不同的batch大小和epoch的次数吗?在前文中,我们已经讨论了学习率、网络大小和epoch次数的关系。深度学习模型常用小的batch和大的epoch以及反复多次的训练。这或许对你的问题会有帮助。

  • 尝试将batch大小设置为全体训练集的大小(batch learning)。‘
  • 尝试将batch大小设置为1(online learning)。
  • 用网格搜索尝试不同大小的mini-batch(8,16,32,…)
  • 尝试再训练几轮epoch,然后继续训练很多轮epoch。
  • 尝试设置一个近似于无限大的epoch次数,然后快照一些中间结果,寻找效果最好的模型。有些模型结构对batch的大小很敏感。我觉得多层感知器对batch的大小很不敏感,而LSTM和CNN则非常敏感,但这都是仁者见仁。
    什么是批量学习、增量学习和在线学习?

7) 正则项
正则化是克服训练数据过拟合的好方法。最近热门的正则化方法是dropout,你试过吗?Dropout方法在训练过程中随机地略过一些神经节点,强制让同一层的其它节点接管。简单却有效的方法。

  • 权重衰减来惩罚大的权重值。
  • 激活限制来惩罚大的激活函数值。尝试用各种惩罚措施和惩罚项进行实验,比如L1、L2和两者之和。

使用Keras对深度学习模型做dropout正则化
权值衰减

8) 优化方法和损失函数
以往主要的求解方法是随机梯度下降,然而现在有许许多多的优化器。你尝试过不同的优化策略吗?随机梯度下降是默认的方法。先用它得到一个结果,然后调节不同的学习率、动量值进行优化。许多更高级的优化方法都用到更多的参数,结构更复杂,收敛速度更快。这取决于你的问题,各有利弊吧。

为了压榨现有方法的更多潜力,你真的需要深入钻研每个参数,然后用网格搜索法测试不同的取值。过程很艰辛,很花时间,但值得去尝试。

我发现更新/更流行的方法收敛速度更快,能够快速了解某个网络拓扑的潜力,例如:ADAM RMSprop

你也可以探索其它的优化算法,例如更传统的算法(Levenberg-Marquardt)和比较新的算法(基因算法)。其它方法能给SGD创造好的开端,便于后续调优。待优化的损失函数则与你需要解决的问题更相关。

不过,也有一些常用的伎俩(比如回归问题常用MSE和MAE),换个损失函数有时也会带来意外收获。同样,这可能也与你输入数据的尺度以及所使用的激活函数相关。

相关阅读:
1)梯度下降优化算法概览
2)什么是共轭梯度和Levenberg-Marquardt? 3)深度学习的优化方法,2011

9) Early Stopping
你可以在模型性能开始下降的时候停止训练。这帮我们节省了大量时间,也许因此就能使用更精细的重采样方法来评价模型了。early stopping也是防止数据过拟合的一种正则化方法,需要你在每轮训练结束后观察模型在训练集和验证集上的效果。

一旦模型在验证集上的效果下降了,则可以停止训练。你也可以设置检查点,保存当时的状态,然后模型可以继续学习。

相关阅读:
1)如何在Keras给深度学习模型设置check-point
2)什么是early stopping?

从模型融合上提升性能

你可以将多个模型的预测结果融合。继模型调优之后,这是另一个大的提升领域。事实上,往往将几个效果还可以的模型的预测结果融合,取得的效果要比多个精细调优的模型分别预测的效果好。我们来看一下模型融合的三个主要方向:

  1. 模型融合
  2. 视角融合
  3. stacking

1) 模型融合
不必挑选出一个模型,而是将它们集成。如果你训练了多个深度学习模型,每一个的效果都不错,则将它们的预测结果取均值。模型的差异越大,效果越好。举个例子,你可以使用差异很大的网络拓扑和技巧。如果每个模型都独立且有效,那么集成后的结果效果更稳定。相反的,你也可以反过来做实验。每次训练网络模型时,都以不同的方式初始化,最后的权重也收敛到不同的值。多次重复这个过程生成多个网络模型,然后集成这些模型的预测结果。它们的预测结果会高度相关,但对于比较难预测的样本也许会有一点提升。
相关阅读:
1) 用scikit-learn集成机器学习算法
2)如何提升机器学习的效果

2) 视角融合
如上一节提到的,以不同的角度来训练模型,或是重新刻画问题。我们的目的还是得到有用的模型,但是方式不同(如不相关的预测结果)。你可以根据上文中提到的方法,对训练数据采取完全不同的缩放和变换技巧。所选用的变化方式和问题的刻画角度差异越大,效果提升的可能性也越大。简单地对预测结果取均值是一个不错的方式。

3)stacking你还可以学习如何将各个模型的预测结果相融合。这被称作是stacked泛化,或者简称为stacking。通常,可以用简单的线性回归的方式学习各个模型预测值的权重。把各个模型预测结果取均值的方法作为baseline,用带权重的融合作为实验组。Stacked Generalization (Stacking)

深度学习模型提升性能的策略相关推荐

  1. 手动/自动/交叉验证评估Keras深度学习模型的性能

    Keras是Python中一个的强大而易用的库,主要用于深度学习. 在设计和配置你的深度学习模型时,需要做很多决策.大多数决定必须通过反复试错的方法来解决,并在真实的数据上进行评估. 因此,有一个可靠 ...

  2. 【AI不惑境】网络的宽度如何影响深度学习模型的性能?

    大家好,这是专栏<AI不惑境>的第三篇文章,讲述模型宽度与模型性能的关系. 进入到不惑境界,就是向高手迈进的开始了,在这个境界需要自己独立思考.如果说学习是一个从模仿,到追随,到创造的过程 ...

  3. Roofline Model与深度学习模型的性能分析

    作者:Michael Yuan 链接:hhttps://zhuanlan.zhihu.com/p/34204282 本文转载自知乎,作者已授权,未经许可请勿二次转载 最近在不同的计算平台上验证几种经典 ...

  4. 调参:深度学习模型24种优化策略

    [时间序列预测/分类] 全系列60篇由浅入深的博文汇总:传送门 文章目录 1. 深度学习模型面临的挑战 1.1 神经网络学习映射功能 1.2 学习网络权重很困难 1.3 求解非凸误差面 1.4 学习算 ...

  5. 网络的宽度如何影响深度学习模型的性能?

    大家好,这是专栏<AI不惑境>的第三篇文章,讲述模型宽度与模型性能的关系. 进入到不惑境界,就是向高手迈进的开始了,在这个境界需要自己独立思考.如果说学习是一个从模仿,到追随,到创造的过程 ...

  6. 网络的宽度对深度学习模型的性能影响

    目录 1 为什么需要足够的宽度 2,经典网络的第一层的宽度 3,宽度对模型性能的影响 4 如何更加有效地利用宽度 4.1 提高每一层通道的利用率 4.2 用其他通道的信息来补偿 5 经典网络模型宽度设 ...

  7. 深度学习模型提升模型效果的常见方法

    在训练集上表现不好,需要降低bias: 调整超参数,如设置更深更宽的网络 训练更长的时间 选择其它特征学习函数(CNN.RNN.LSTM.GRU等) 在验证集上表现不好,需要降低方差: 引入正则化(如 ...

  8. 提升深度学习模型的表现,你需要这20个技巧

    选自machielearningmastery 机器之心编译 作者:Jason Brownlee 参与:杜夏德.陈晨.吴攀.Terrence.李亚洲 本文原文的作者 Jason Brownlee 是一 ...

  9. 4个提高深度学习模型性能的技巧

    点击上方"AI遇见机器学习",选择"星标"公众号 原创干货,第一时间送达 深度学习是一个广阔的领域,但我们大多数人在构建模型时都面临一些共同的难题 在这里,我们 ...

  10. Jetson Xavier、Jetson TX2、 1080(Ti)、2080显卡运行深度学习模型性能对比(英伟达开发平台VS常用显卡)

    前言:         英伟达的Jetson TX2使得很多人认为深度学习模型终于可以像嵌入式开发平台那样做到小型化了,不用再跑在高配计算机或者服务器上面了,但是实际上Jetson TX2开发板的性能 ...

最新文章

  1. 我国医疗机器人产业发展特征分析
  2. Android 中文 API (90) —— WindowManager
  3. oracle数据加载控制文件格式,oracle数据加载的几种常用方法
  4. Ubuntu16.04安装docker
  5. Docker精华问答 | Consul是什么?
  6. HTML学习笔记--HTML的语法【1】
  7. 【资源】《可解释的机器学习》,让机器学习不再神秘!
  8. Echarts双纵轴分隔线合并解决方案
  9. 一生都学不完的计谋(经典)
  10. 第八章 (一)分治 练习题
  11. django中collectstatic的使用
  12. 埃文科技教你如何验证IP地址定位的准确率
  13. 小福利,介绍excel高阶函数2
  14. f28335的c语言结构体,TMS320F28335程序SVPWM源程序
  15. yocto编译错误:ERROR: libtinyxml2-XXX do_fetch: Fetcher failure for URL
  16. 2019年第十一届蓝桥杯国赛JavaB组第H题——“大胖子走迷宫”题目及解析
  17. 2022茶艺师(中级)考试题模拟考试题库及模拟考试
  18. Win10系统安装CUDA10.0和cuDNN
  19. Decimal.quantize
  20. 2017黑加传智java_传智黑马 Java在职加薪课 学成在线

热门文章

  1. 网页资源不知道如何下载,我来教你
  2. 手把手教你编写网页图形验证码识别工具
  3. ObjectARX标注公差简单实例
  4. 做前端网页需要用网页框架吗
  5. 服务端渲染技术之Nuxt.js的详细使用
  6. Spring publishevent事件处理
  7. linux: 未知的名称或服务 Caused by: java.net.UnknownHostException: smn01: Name or service not known
  8. 13年android手机top,2013年安卓ROOT工具大盘点(一键ROOT工具Top10)
  9. 苹果 iOS 15.5更新了哪些功能 苹果 iOS 15.5值得更新吗
  10. linux pkg文件,pkg文件结构详细解释(转)