什么是 LoRA 模型

LoRA 的全称是 LoRA: Low-Rank Adaptation of Large Language Models,是一种以极低资源微调大模型的方法,其来自于论文 LoRA: Low-Rank Adaptation of Large Language Models ¹。

LoRA 的核心思想是冻结预训练的模型权重,并将可训练的秩分解矩阵注入 Transformer 架构的每一层,从而大大减少了下游任务的可训练参数数量。相比于完全微调,LoRA 可以节省显存、提高训练速度、减少推理延迟,并且保持或提升模型质量。

LoRA 可以应用于自回归模型(如 GPT 系列)和 Encoder-Decoder 模型(如 T5),并且可以与不同规模的预训练模型(如 RoBERTa, DeBERTa, GPT-2, GPT-3)兼容。

LoRA 的原理和实现

大模型微调的困境

随着模型规模的不断扩大,模型会“涌现”出各种能力。特别是对大语言模型 (LLM) 来说,随着规模的扩大其在 zero-shot、常识推理等能力上会有大幅度的提高。

但是,大模型的微调成本和部署成本也非常高。例如,GPT-3 175B 模型微调需要 1.2TB 的显存。此外,若针对不同下游任务微调多个模型,那么就需要为每个下游任务保存一份模型权重,成本非常高。在某些场景下,甚至可能需要针对不同的用户微调不同的模型,那么模型微调和部署的成本将不可接受。

因此,如何降低大模型微调和部署成本,将是大模型商用的重要一环。

LoRA 之前的方法

在 LoRA 方法提出之前,也有很多方法尝试解决大模型微调困境的问题。其中有两个主要的方向:

  • 添加 adapter 层;
  • 使用 prefix-tuning。

但是这两种方法都有局限性:

  • Adapter 层会引入推理时延。简单来说,它的主要思想是在预训练模型的每一层 Transformer 中插入一个小的可训练的模块,称为 adapter。这样可以保持预训练模型的权重不变,只更新 adapter 的参数,从而实现参数高效和灵活的迁移学习12。
  • Prefix-tuning 难以优化。prefix-tuning 方法是受语言模型 in-context learning 能力的启发,只要有合适的上下文则语言模型可以很好地解决自然语言任务。但是,针对特定的任务找到离散 token 的前缀需要花费很长时间,prefix-tuning 提出使用连续的 virtual token embedding 来替换离散 token。这些 virtual token embedding 需要作为可训练参数进行优化,而且会减少下游任务的序列长度。

LoRA 的方法

LoRA 为了更加参数高效,使用相对非常小的参数 Θ \Theta Θ 来表示任务相关的参数增量 Δ Φ = Δ Φ ( Θ ) \Delta\Phi=\Delta\Phi (\Theta) ΔΦ=ΔΦ(Θ) ,其中 ∣ Θ ∣ ≪ ∣ Φ 0 ∣ |\Theta|\ll |\Phi_0| ∣Θ∣Φ0 。寻找 Δ Φ \Delta\Phi ΔΦ 的任务就变成对 Θ \Theta Θ 的优化:

max ⁡ Θ ∑ ( x , y ) ∈ Z ∑ t = 1 ∣ y ∣ log ⁡ ( p Φ 0 + Δ Φ ( Θ ) ( y t ∣ x , y < t ) ) \max_ {\Theta}\sum_ { (x,y)\in\mathcal {Z}}\sum_ {t=1}^ {|y|}\log (p_ {\Phi_0+\Delta\Phi (\Theta)} (y_t|x,y_ {<t})) Θmax(x,y)Zt=1ylog(pΦ0+ΔΦ(Θ)(ytx,y<t))

LoRA 将会使用低秩表示来编码 Δ Φ \Delta\Phi ΔΦ ,同时实现计算高效和存储高效。当预训练模型是 175B GPT-3,可训练参数 ∣ Θ ∣ |\Theta| ∣Θ∣ 可以小至 ∣ Φ 0 ∣ |\Phi_0| Φ0 的 0.01% 。

对于预训练权重矩阵 W 0 ∈ R d × k W_0\in\mathbb {R}^ {d\times k} W0Rd×k ,可以通过低秩分解来表示其更新 W 0 + Δ W = W 0 + B A , B ∈ R d × r , A ∈ R r × k W_0+\Delta W=W_0+BA,B\in\mathbb {R}^ {d\times r},A\in\mathbb {R}^ {r\times k} W0+ΔW=W0+BABRd×r,ARr×k 且秩 r ≪ min ⁡ ( d , k ) r\ll\min (d,k) rmin(d,k) 。在训练过程中, W 0 W_0 W0 被冻结且不接受梯度更新, A A AB B B 则是可训练参数。注意, W 0 W_0 W0Δ W = B A \Delta W=BA ΔW=BA 都会乘以相同的输入。对于 h = W 0 x h=W_0x h=W0x ,前向传播变为:

h = W 0 x + Δ W x = W 0 x + B A x h=W_0x+\Delta Wx=W_0x+BAx h=W0x+ΔWx=W0x+BAx

对矩阵 A A A 使用随机高斯初始化,对矩阵 B B B 使用 0 进行初始化,因此 Δ W = B A \Delta W=BA ΔW=BA 在训练的开始为 0。使用 α r \frac {\alpha} {r} rα 来缩放 Δ W x \Delta Wx ΔWx 。当使用 Adam 优化时,经过适当的缩放初始化,调优 α \alpha α 与调优学习率大致相同。

当进行部署时,以显式的计算和存储 W = W 0 + B A W=W_0+BA W=W0+BA ,并正常执行推理。 W 0 W_0 W0B A BA BA 都是 R d × k \mathbb {R}^ {d\times k} Rd×k 。当需要转换至另一个下游任务,可以通过减去 B A BA BA 来恢复 W 0 W_0 W0 ,然后添加不同的 B ′ A ′ B'A' BA

LoRA 的实验结果和分析

LoRA 的实验设置

论文中使用了四种不同规模的预训练模型:RoBERTa-base, DeBERTa-base, GPT-2-medium, GPT-3-175B。其中前两种是 Encoder 模型,后两种是 Decoder 模型。

论文中使用了八个下游任务:SQuAD v1.1, SQuAD v2.0, CoQA, RACE, MNLI, SST-2, QQP, QNLI。其中前四个是机器阅读理解任务,后四个是 GLUE 任务。

论文中将 LoRA 与以下方法进行了比较:

  • Full fine-tuning:完全微调所有参数;
  • Adapter:在每一层 Transformer 中添加 adapter 层;
  • Prefix-tuning:在每一层 Transformer 中添加 virtual token embedding;
  • Freeze:冻结所有参数,只微调输出层。

论文中使用了两种评价指标:模型质量和推理时延。模型质量使用 F1 或者准确率来衡量。推理时延使用单个 GPU 上的推理时间来衡量。

LoRA 的实验结果

论文中给出了各种方法在不同任务上的模型质量和推理时延的结果。这里只展示部分结果,完整结果可以参考原论文。

RoBERTa-base 在 GLUE 上的结果

LoRA 在模型质量上与 full fine-tuning 相当或者更好,并且远超过其他方法。同时,LoRA 的推理时延与 full fine-tuning 和 freeze 相同,并且比 adapter 和 prefix-tuning 小很多。

LoRA 的分析和讨论

论文中还对 LoRA 的一些性质和特点进行了分析和讨论,这里只简要介绍一些,完整内容可以参考原论文。

  • LoRA 的秩选择。论文中发现,对于不同的预训练模型和下游任务,LoRA 的最优秩是不同的。一般来说,秩越大,模型质量越高,但是也会增加计算和存储的开销。论文中提供了一些经验性的秩选择方法,例如根据预训练模型的层数或者下游任务的难度来选择秩。
  • LoRA 的初始化。论文中发现,对于 LoRA 的低秩矩阵 A A AB B B,使用随机高斯初始化 A A A,使用 0 初始化 B B B 是比较合理的。这样可以保证 Δ W = B A \Delta W=BA ΔW=BA 在训练开始时为 0,不会影响预训练模型的权重。同时,使用 α r \frac {\alpha} {r} rα 来缩放 Δ W x \Delta Wx ΔWx 可以避免过大或过小的梯度更新。
  • LoRA 的有效性。论文中通过实验发现,预训练模型在适应下游任务时,其权重更新具有低秩的特性。也就是说,只需要少量的参数就可以实现较大的性能提升。这也说明了 LoRA 的设计思想是合理的。

LoRA 的优缺点

根据论文和网上的一些资料²³,我们可以总结出 LoRA 模型的一些优缺点:

优点

  • 参数高效。LoRA 只需要少量的可训练参数就可以实现与完全微调相当或更好的模型质量。这样可以节省显存、提高训练速度、减少存储空间。
  • 推理高效。LoRA 不会增加额外的推理时延,因为它只是在预训练模型的权重上加上一个低秩矩阵,并不改变模型的结构和计算流程。
  • 通用性强。LoRA 可以应用于自回归模型和 Encoder-Decoder 模型,并且可以与不同规模的预训练模型兼容。
  • 灵活性强。LoRA 可以通过调整低秩矩阵的秩来平衡模型质量和计算开销。同时,LoRA 可以通过减去低秩矩阵来恢复预训练模型的权重,并添加不同的低秩矩阵来适应不同的下游任务。

缺点

  • 秩选择困难。LoRA 的低秩矩阵的秩对于模型质量和计算开销都有影响,但是没有一个统一的方法来确定最优的秩。需要根据不同的预训练模型和下游任务进行尝试和调整。
  • 初始化敏感。LoRA 的低秩矩阵的初始化对于模型的收敛和性能都有影响,需要使用合适的初始化方法和缩放因子。如果初始化不当,可能会导致模型无法收敛或者性能下降。
  • 低秩假设不一定成立。LoRA 的设计基于一个假设,即预训练模型在适应下游任务时,其权重更新具有低秩的特性。这个假设在一些实验中得到了验证,但是也可能存在一些反例,即需要较高秩的权重更新才能实现较好的模型质量。

LoRA 的应用场景

LoRA 模型作为一种以极低资源微调大模型的方法,可以应用于以下一些场景:

  • 需要使用大规模预训练语言模型来解决特定的自然语言处理任务,例如机器阅读理解、文本摘要、文本分类等,但是又受限于硬件资源或者成本预算的场景。
  • 需要根据不同的用户或者领域来定制化大规模预训练语言模型的生成风格或者内容,例如对话系统、文本生成、文本风格转换等,但是又不想为每个用户或者领域保存一份完整微调的模型的场景。
  • 需要在不同的下游任务之间快速切换大规模预训练语言模型的能力,例如多任务学习、元学习、迁移学习等,但是又不想重新训练或者加载完整微调的模型的场景。

LoRA 的代码实现

论文中提供了一个开源的代码库,可以方便地将 LoRA 集成到 PyTorch 模型中,并提供了 RoBERTa, DeBERTa, 和 GPT-2 的实现和模型检查点。代码库的地址是:https://github.com/microsoft/LoRA

代码库中包含了以下几个部分:

  • lora.py:包含了 LoRA 的核心实现,即低秩矩阵注入和参数恢复等功能。
  • models.py:包含了 RoBERTa, DeBERTa, 和 GPT-2 的 LoRA 版本的实现。
  • run_glue.py:包含了在 GLUE 任务上使用 RoBERTa 或者 DeBERTa 的 LoRA 版本进行微调和评估的脚本。
  • run_squad.py:包含了在 SQuAD 任务上使用 RoBERTa 或者 DeBERTa 的 LoRA 版本进行微调和评估的脚本。
  • run_race.py:包含了在 RACE 任务上使用 RoBERTa 或者 DeBERTa 的 LoRA 版本进行微调和评估的脚本。
  • run_coqa.py:包含了在 CoQA 任务上使用 GPT-2 或者 GPT-3 的 LoRA 版本进行微调和评估的脚本。

代码库中还提供了一些使用说明和示例命令,可以参考 README.md 文件。

Source: Conversation with Bing, 2023/6/12
(1) 你真的会用LORA吗?超详细讲解LORA分层控制 - 知乎. https://zhuanlan.zhihu.com/p/621260240.
(2) LoRA 指南 - 知乎. https://zhuanlan.zhihu.com/p/600628691.
(3) 什么是LoRA模型,如何使用和训练LoRA模型?你想要的都在这!. https://zhuanlan.zhihu.com/p/624230991.

Source: Conversation with Bing, 2023/6/12
(1) LoRA: Low-Rank Adaptation of Large Language Models. https://arxiv.org/abs/2106.09685.
(2) 【自然语言处理】【大模型】极低资源微调大模型方法LoRA … https://zhuanlan.zhihu.com/p/618073170.
(3) 论文阅读:LORA-大型语言模型的低秩适应 - 知乎. https://zhuanlan.zhihu.com/p/611557340.

补充

具体说说 lora 是怎么实现将可训练的秩分解矩阵注入 Transformer 架构的每一层,举个具体的例子

  • LoRA 的基本思想是对于预训练模型的权重矩阵 W 0 W_0 W0,使用一个低秩矩阵 Δ W = B A \Delta W=BA ΔW=BA 来表示其更新,其中 B B BA A A 是可训练的参数,而 W 0 W_0 W0 是固定的。这样可以保证 Δ W \Delta W ΔW 的参数数量远小于 W 0 W_0 W0 的参数数量,从而实现参数高效。
  • LoRA 可以应用于 Transformer 架构的不同部分,例如自注意力、交叉注意力、前馈网络等。具体来说,LoRA 可以将低秩矩阵注入到这些部分的输入或输出端,或者在这些部分的中间添加一个低秩矩阵。
  • 举个例子,假设我们要对一个自注意力层进行 LoRA 微调,该层的输入为 Q , K , V Q, K, V Q,K,V,输出为 Z Z Z。我们可以在输入端注入低秩矩阵 Δ Q \Delta Q ΔQ, Δ K \Delta K ΔK, Δ V \Delta V ΔV,即:

Q ′ = Q + Δ Q = Q + B Q A Q Q'=Q+\Delta Q=Q+B_QA_Q Q=Q+ΔQ=Q+BQAQ

K ′ = K + Δ K = K + B K A K K'=K+\Delta K=K+B_KA_K K=K+ΔK=K+BKAK

V ′ = V + Δ V = V + B V A V V'=V+\Delta V=V+B_VA_V V=V+ΔV=V+BVAV

然后使用 Q ′ Q' Q, K ′ K' K, V ′ V' V 来计算自注意力的输出 Z Z Z。这样相当于在输入端增加了一个残差连接。

  • 我们也可以在输出端注入低秩矩阵 Δ Z \Delta Z ΔZ,即:

Z ′ = Z + Δ Z = Z + B A Z'=Z+\Delta Z=Z+BA Z=Z+ΔZ=Z+BA

然后使用 Z ′ Z' Z 作为自注意力的输出。这样相当于在输出端增加了一个残差连接。

  • 我们还可以在自注意力的中间添加一个低秩矩阵 Δ A \Delta A ΔA,即:

A = s o f t m a x ( Q K T d k ) + Δ A = s o f t m a x ( Q K T d k ) + B A A=\mathrm {softmax} (\frac {QK^T} {\sqrt {d_k}})+\Delta A=\mathrm {softmax} (\frac {QK^T} {\sqrt {d_k}})+BA A=softmax(dk

QKT)+ΔA=softmax(dk

QKT
)+
BA

然后使用 A A A 来计算自注意力的输出 Z Z Z。这样相当于在自注意力的中间增加了一个残差连接。

  • 这些方法都可以实现将可训练的秩分解矩阵注入 Transformer 架构的每一层,从而实现 LoRA 微调。

Source: Conversation with Bing, 2023/6/12
(1) Using LoRA for Efficient Stable Diffusion Fine-Tuning … https://huggingface.co/blog/lora.
(2) Picotest-J2101A Injection Transformer 10Hz - 45MHz. https://www.picotest.com/products_J2101A.html.
(3) GitHub - Blealtan/RWKV-LM-LoRA: RWKV is a RNN with … https://github.com/Blealtan/RWKV-LM-LoRA.

为什么 adapter 会引入时延?

  • adapter 的基本形式是一个两层的前馈网络,其中第一层将输入从 hidden_size 降维到 bottleneck_size,第二层将输出从 bottleneck_size 升维到 hidden_size。这样可以保证 adapter 的输出与原始 Transformer 层的输出具有相同的维度,从而可以进行残差连接¹²。
  • 举个例子,假设我们要对一个自注意力层进行 adapter 微调,该层的输入为 Q Q Q, K K K, V V V,输出为 Z Z Z。我们可以在输入端或者输出端插入一个 adapter 层,例如:

Q ′ = Q + a d a p t e r ( Q ) Q'=Q+\mathrm {adapter} (Q) Q=Q+adapter(Q)

K ′ = K + a d a p t e r ( K ) K'=K+\mathrm {adapter} (K) K=K+adapter(K)

V ′ = V + a d a p t e r ( V ) V'=V+\mathrm {adapter} (V) V=V+adapter(V)

然后使用 Q ′ Q' Q, K ′ K' K, V ′ V' V 来计算自注意力的输出 Z Z Z。或者:

Z ′ = Z + a d a p t e r ( Z ) Z'=Z+\mathrm {adapter} (Z) Z=Z+adapter(Z)

然后使用 Z ′ Z' Z 作为自注意力的输出。

  • 这些方法都会引入推理时延,因为 adapter 层需要额外的计算和通信。具体来说,adapter 层需要计算两次矩阵乘法和两次激活函数,并且需要与原始 Transformer 层进行残差连接。这些操作都会增加推理时延,尤其是在大规模的预训练模型和下游任务上。

¹: Houlsby, N., Giurgiu, A., Jastrzebski, S., Morrone, B., de Laroussilhe, Q., Gesmundo, A., … & Gelly, S. (2019). Parameter-efficient transfer learning for NLP. arXiv preprint arXiv:1902.00751.

²: Pfeiffer, J., Rücklé, A., Eger, S., & Gurevych, I. (2020). AdapterHub: A framework for adapting transformers. arXiv preprint arXiv:2007.07779.

Source: Conversation with Bing, 2023/6/12
(1) Compacter: Efficient Low-Rank Hypercomplex Adapter Layers. https://arxiv.org/abs/2106.04647.
(2) Parameter-Efficient Transfer Learning for NLP - arXiv.org. https://arxiv.org/pdf/1902.00751.pdf.
(3) Adapters for Generative and Seq2Seq Models in NLP. https://adapterhub.ml/blog/2021/04/adapters-for-generative-and-seq2seq-models-in-nlp/.
(4) Adapters: A Compact and Extensible Transfer Learning … https://medium.com/dair-ai/adapters-a-compact-and-extensible-transfer-learning-method-for-nlp-6d18c2399f62.

那 lora 是不是也会引入推理时延?

不会。LoRA 是不会引入推理时延的,因为 LoRA 不会改变预训练模型的结构和计算流程。具体来说,LoRA 只是在预训练模型的权重矩阵上加上一个低秩矩阵,而这个低秩矩阵可以在训练时就计算好,并且与原始权重矩阵相加,得到一个新的权重矩阵。这样,在推理时,就不需要额外的计算和通信,只需要使用新的权重矩阵进行原始 Transformer 层的计算即可。因此,LoRA 是不会引入推理时延的,这也是它与 adapter 的一个优势。

lora 相对于只微调模型最后的输出层(freeze)的异同

  • LoRA 是在预训练模型的每一层 Transformer 中注入可训练的低秩矩阵,而 freeze 是只在预训练模型的最后一层添加一个可训练的输出层。
  • LoRA 的可训练参数数量取决于低秩矩阵的秩,而 freeze 的可训练参数数量取决于输出层的大小。一般来说,LoRA 的可训练参数数量会比 freeze 少很多。
  • LoRA 的模型质量与完全微调相当或者更好,而 freeze 的模型质量通常会比完全微调差很多。这是因为 LoRA 可以更好地利用预训练模型的各层信息,而 freeze 只能利用预训练模型的最后一层信息。
  • LoRA 的推理时延与完全微调和 freeze 相同,而 adapter 和 prefix-tuning 的推理时延会比完全微调和 freeze 大很多。这是因为 LoRA 不会改变预训练模型的结构和计算流程,而 adapter 和 prefix-tuning 会增加额外的计算和通信。

  • LoRA 和 freeze 都是为了降低大模型微调和部署的成本,使得大模型可以在有限的硬件资源和预算下适应特定的下游任务或者领域。
  • LoRA 和 freeze 都是基于一个假设,即预训练模型在适应下游任务时,其权重更新具有低秩或者稀疏的特性。也就是说,只需要少量的参数就可以实现较大的性能提升。

Source: Conversation with Bing, 2023/6/12
(1) Using LoRA for Efficient Stable Diffusion Fine-Tuning … https://huggingface.co/blog/lora.
(2) What is the difference between LoRa and LoRaWAN … https://www.techtarget.com/searchnetworking/answer/What-is-the-difference-between-LoRa-and-LoRaWAN.
(3) LoRA: Low-Rank Adaptation of Large Language Models. https://github.com/microsoft/LoRA.

LoRA 的学习笔记相关推荐

  1. LoRa 节点侧学习笔记_汇总

    LoRa在今年(2016年)应该是最火的物联网技术,Semtech不停攻城略地,七大洲,哦,除了南极洲,所有地区都宣布要建立国家级的LoRa网络.虽然,我大中国的运营商要做NB-IoT,但是不乏中兴. ...

  2. LoRaWan协议1.1 ClassB部分学习笔记

    LoRaWan协议1.1 ClassB部分学习笔记 目录 8.对Class B的介绍 9.同步网络发起下行的原理(class b独有) 10.Class B上行帧 11. 下行ping包格式(clas ...

  3. 【物联网学习笔记——人人学IoT系列】二、IoT平台,能力开放

    目录 1. 解锁物联网平台,与OceanConnect相识 1.1 物联网发展的挑战 1.1.1 新业务上线周期长 1.1.2 标准不统一.集成困难 1.1.3 网络联接复杂 1.2 应对挑战的方案 ...

  4. 【物联网学习笔记——人人学IoT系列】一、初识物联网

    目录 1. 物联网初探 1.1 物联网(Internet of Things)早期概念定义 1.2 物联网概念发展历程 1.3 发展历史时期划分 1.3.1 概念期 1.3.2 发展期 1.3.3 成 ...

  5. 【物联网学习笔记——人人学IoT系列】三、窄带无线,海量物联

    目录 1. NB-IoT 1.1 NB-IoT背景知识 1.2 NB-IoT的网络总体架构 2. NB-IoT中的Niubility技术 2.1 NB-IoT物理层 2.1.1 NB-IoT上行技术 ...

  6. 《物联网开发实战》09 边缘中心:物联网网关有多重要?(学习笔记)

    仅作为本人学习<物联网开发实战>的学习笔记,原课程链接:极客时间<物联网开发实战>--郭朝斌 不是所有的设备都使用 Wi-Fi 这类可以直接接入互联网从而与云平台通信的通信技术 ...

  7. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  8. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  9. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

最新文章

  1. C#中切割字符串之正则表达式应用
  2. 面试碰到这个算法:字母异位词分组
  3. 造轮子是什么意思_程序员发文质疑阿里天启为kpi项目,重复造轮子,阿里回应:诽谤...
  4. 如何让在JAVA中定义常量池
  5. heroku_本月风味– Neo4j和Heroku
  6. 复制K2流程图实现记录
  7. docker搭建zookeeper集群
  8. 使用NodeJS连接到MySQL数据库Client does not support authentication protocol requested by server; consider upg
  9. Flash制作空战游戏
  10. 软件测试02_软件生命周期软件测试流程
  11. IPv4到IPv6的改造转换方案(上):IPv6和IPv4优势对比
  12. 全国计算机科学与技术讲师电话,计算机科学与技术学院
  13. 码畜 码奴 码农 IT民工和IT其他工种的划分定义
  14. 用python画一个机器猫歌词_Python实现海贼王的歌词组成词云图
  15. juniper防火墙定义策略生效时间
  16. ehvierwer登录与不登录_微信上不去了怎么办,峰哥教你微信登录不上去的办法
  17. MAC更新系统网络连接中断
  18. [Codeup]1814 问题 A: 剩下的树
  19. 基于ArcGIS JS API实现的两种距离和面积测量方式
  20. office2019卸载组件_office2019软件安装教程

热门文章

  1. 将一些好看的图片变成素描画
  2. 为什么很多程序员喜欢用 Kindle ?
  3. STM32F103 4*4薄膜键盘代码分享
  4. 入行物联网8年后的自白,机智云系“物联网创业者”的希望承载者
  5. 你真的了解Cadence吗?
  6. java计算机毕业设计健身俱乐部管理系统(附源码、数据库)
  7. mysql 管理数据库和管理表笔记
  8. nginx使用二级路径反向代理不同IP和端口
  9. 架构一个数据交换与信息共享平台
  10. Android 项目架构设计深入浅出