Task 4: Contextual Word Embeddings

目录

  • Task 4: Contextual Word Embeddings
    • 词向量的表示
    • 一、Peters et al. (2017): TagLM – “Pre-ELMo”
    • 二、Peters et al. (2018): ELMo: Embeddings from Language Models
    • 三、ULMfit
    • 四、Transformer
      • 1.Encoder
      • 2.Decoder
      • 3.Positional Encoding
    • 五、BERT
    • 六、补充知识点:GPT
      • 1.OpenAI GPT(开放式GPT)
        • 1)OpenAI GPT
        • 2)Transformer decoder作为语言模型
        • 3)BPE(Byte Pair Encoding)
        • 4)有监督的微调
        • 5)总结
      • 2.OpenAI GPT-2
        • 1)Zero-Shot Transfer
        • 2)字节序列上的BPE介绍
        • 3)模型修改
    • 七、总结
    • 实战
    • 【参考资料】

理论部分:

  • 回顾 Word2Vec, GloVe, fastText 模型
  • 介绍contextual word representation
  • 介绍 ELMO,GPT与BERT模型

词向量的表示

  目前为止,我们已经学过了Word2vec, GloVe, fastText等词向量的表示。通过这些词向量能在神经网络的训练中起到一个很好的效果,如图所示:


  但是这三个方法都普遍存在在一些问题,就是无法解决一词多义的问题,即对于同一个词无论上下文的词是否相同,训练出来的词向量都是一样的
  当我们语料不足时,训练出来的词向量效果不会很理想,这时我们可以使用其他人已经训练好的词向量,并且以预训练的词向量来作为初始值,在训练过程中进行微调。下图是2011年Collobert, Weston等人使用预训练的词向量进行NLP任务的精度和F1值,模型使用了预训练词向量之后,得分得到了提升:


  但是,我们训练好的词向量是不可能涵盖所有词的(这里主要有两个原因,一是训练语料中本来就不存在这些词,二是这些词在训练语料中出现次数过少),这就会存在一个未知词(unknown words)的问题,遇到这个问题的时候我们怎么处理呢?
  常见的解决方案是:

  • 首先,最简单和最普遍的解决方法就是将所有未知词映射为,并且为它训练一个词向量。但是这种方法存在缺点,它把这些未知词都视为相同,不能区分它们的区别。
  • 训练字符级词向量
  • 此外,你可以将其视为新的词,并为其分配一个随机向量,将它们添加到你的词汇表。

  不过,对于这样的解决方案存在着一定的问题,即:我们没有办法区分不同的unknown words。此外,还有一些问题,比如词向量唯一表示词而不考虑词在文章中出现的位置,比如一个词在不同的句子中有不同的含义等。
  针对这些问题,有人想到词向量表示应该结合词所在的句子进行考虑。但是标准的RNN训练只在 task-labeled 的小数据上,后来有人想能不能用词向量的编码,比如LSTM的编码来表示单词,并且在大型的无标签的数据上进行训练,于是就产生了Contextual Word Representations。如图:

一、Peters et al. (2017): TagLM – “Pre-ELMo”

论文地址:https://arxiv.org/pdf/1705.00108.pdf

  核心思想:通过上下文中获取单词的含义,但只在task-labeled的任务(例如,NER)上使用RNN来进行训练算法的核心步骤如下:

  • 在未标记的数据上预训练词向量和语言模型
  • 在输入序列中准备好单词嵌入和语言模型嵌入。
  • 在序列标记模型中同时使用单词嵌入和语言模型嵌入。

  模型结构图如下:


  详细的过程如图所示:


  论文得出的结论如下:

  • 通过对语言模型观察我们得出:使用有监督数据集来训练的语言模型效果甚微,使用双向语言模型仅对向前有利,网络结构越复杂效果越好。
  • 通过对任务特定Bi-LSTM观察可知:仅使用LM嵌入来预测并不好。

二、Peters et al. (2018): ELMo: Embeddings from Language Models

论文名称及地址:
Deep contextualized word representations. NAACL 2018.
https://arxiv.org/abs/1802.05365

  在2018年,Peters等人提出的ELMo模型在非常多的NLP任务上都提高了state-of-the-art 方法的performance, 被一些人称为新的word2vec。这篇文章同时被ICLR 2018 和NAACL 2018 接收, 后来获得了NAACL best paper award
  ELMo是第一个使用双向语言模型来获得词向量的方法。这里使用长上下文而不是上下文窗口学习词标记向量,使用双向的深层NLM进行训练并使用其所有层进行预测。
  我们来简要介绍下这个模型:首先,它训练了一个双向的语言模型,其次,其性能很好并且模型不大。具体步骤——使用2个Bi-LSTM层,使用字符级的CNN建立初始单词表示(2048 char n-gram过滤器和2个HighWay层,512 dim投影),使用4096 dim hidden/cell LSTM状态,512dim投影到下一个输入,使用残差网络连接token输入和输出(SoftMax)的参数,并将这些参数连接在正向和反向语言模型之间。
  具体如图所示:


  ELMo模型一个比较重要的特点是,它不仅使用了LSTM最上面的一层隐藏层,也使用其他隐藏层,对所有的隐藏层做一个权重的求和,得到ebeding的结果,公式如图所示:


  使用ELMo完成task

  1. 首先,预训练bi-LM模型得到单词的 representations
  2. 冻结上一步得到的bi-LM的参数
  3. 将得到的ELMo权重应用于特定的任务

  以下给出了将ELMo模型应与sequence tagger任务,如图所示:


  ELMo模型在NLP的很多应用都取得很好的效果,对普通的基准模型,应用了ELMo后,都取得了一定水平的提升,如图所示:


  ELMo的bi-LSTM NLM层各有特点,也适合不同的NLP任务:低层的权重更适合低层次的语法任务,比如词性标注、句法依赖、NER等;高层的权重更适合层次更好的语义任务,比如情感分析、语义角色标注、问答、SN等

三、ULMfit

论文名称及地址:
Deep contextualized word representations. NAACL 2018.
https://arxiv.org/abs/1802.05365

  Howard and Ruder (2018)提出了== Universal Language Model Fine-tuning for Text Classification==。ULMfit主要是使用迁移学习来进行文本分类迁移学习示意图如下:


  对于模型的处理,UML采用了如下三步:

  1. 首先,在一个非常大的数据集(和任务数据集不相关)上训练一个LM模型。
  2. 接着,使用任务相关的数据集,对模型进行fine-tune(进行训练,在前一个模型的基础上对参数进行微调)
  3. 使用classifier任务继续fine-tune

  模型结构图如下:


  ULMfit取得的效果也非常的明显,如图:


  该模型在训练时有一些细节:

  • 每层使用不同的学习率,即Slanted triangular learning rate (STLR) schedule,开始学习率逐渐增大,后面逐渐变小
  • 在学习分类器时逐步解冻并且采用STLR策略
  • 分类时使用下图拼接的方法:

  这其中迁移学习的方法在NLP中开了一个头,从此网络越来越复杂,训练的规模也越来越大

四、Transformer

  transformer的出现主要是为了利用纯attention来解决RNN系列网络无法并行计算的问题模型结构图如下所示:

  • 使用非循环结构的encoder-decoder模型
  • 可以进行并行的机器翻译的计算
  • 预测每一个翻译的word
  • 代价函数是标准的softmax输出下的交叉熵代价函数

如果我们要详细地了解transformer,可以参考下面地资源:
http://nlp.seas.harvard.edu/2018/04/03/attention.html
这是一个使用pytorch在jupyter notebook上来解释transformer的教程。

  我们从图中可以看到:和大多数seq2seq模型一样,transformer的结构也是由encoder和decoder组成。最初应用于使用并行语料库进行机器翻译并预测每个单词的翻译。

1.Encoder

  Encoder由N=6个相同的layer组成,layer指的就是上图左侧的单元,最左边有个“Nx”,这里是x6个。每个Layer由两个sub-layer组成,分别是multi-head self-attention mechanism和fully connected feed-forward network。其中每个sub-layer都加了residual connection和normalisation,因此可以将sub-layer的输出表示为:


  首先我们先看一下Multi-head self-attention。对于普通的attention机制,可以用以下形式表示:


  multi-head attention则是通过h个不同的线性变换对Q,K,V进行投影,最后将不同的attention结果拼接起来并通过线性层传输,可以用以下公式表达:


  与CNN和传统的Attention相比,Multi-head attention还是有很多特性的。下面以这句话为例子:The cat stuck out its tongue and licked its owner当使用CNN处理这段话时,体现的是相对位置的不同线性变换。


  当使用普通的Attention时,体现的是权重的平均,如下图所示:


  当使用Multi-Attention时,在输入和输出上具有不同线性变换的并行行Attention层,如下图所示:


  其次是Position-wise feed-forward networks。这层主要是提供非线性变换。

2.Decoder

  Decoder和Encoder的结构差不多,但是多了一个attention的sub-layer,这里先明确一下decoder的输入输出和解码过程:

  • 输入:encoder的输出和对应i-1位置decoder的输出。所以中间的attention不是self-attention,它的K,V来自encoder,Q来自上一位置decoder的输出
  • 输出:对应i位置的输出词的概率分布
  • 解码:这里要特别注意一下,编码可以并行计算,一次性全部encoding出来,但解码不是一次把所有序列解出来的,而是像RNN一样一个一个解出来的,因为要用上一个位置的输入当作attention的query

  明确了解码过程之后最上面的图就很好懂了,这里主要的不同就是新加的另外要说一下新加的attention多加了一个mask,因为训练时的output都是ground truth,这样可以确保预测第i个位置时不会接触到未来的信息。

3.Positional Encoding

  截止目前为止,我们介绍的Transformer模型并没有捕捉顺序序列的能力,也就是说无论句子的结构怎么打乱,Transformer都会得到类似的结果。换句话说,Transformer只是一个功能更强大的词袋模型而已
  为了解决这个问题,论文中在编码词向量时引入了位置编码(Position Embedding)的特征。具体地说,位置编码会在词向量中加入了单词的位置信息,这样Transformer就能区分不同位置的单词了。那么怎么编码这个位置信息呢?常见的模式有:a. 根据数据学习;b. 自己设计编码规则。在这里作者采用了第二种方式。那么这个位置编码该是什么样子呢?通常位置编码是一个特征向量,这样便于和词向量进行单位加的操作。论文给出的编码公式如下:


  在上式中,pos表示单词的位置,i表示单词的维度。关于位置编码的实现可在Google开源的算法中get_timing_signal_1d()函数找到对应的代码。
  作者这么设计的原因是考虑到在NLP任务重,除了单词的绝对位置,单词的相对位置也非常重要。根据公式sin(α+β)=sinαcosβ+cosαsinβ以及cos(α+β)=cosαcosβ-sinαsinβ,这表明位置k+p的位置向量可以表示为位置k的特征向量的线性变化,这为模型捕捉单词之间的相对位置关系提供了非常大的便利。
  Transformer是第一个用纯attention搭建的模型,算法的并行性非常好,并且在翻译任务上也获得了更好的结果,因此Transformer也可以用在NLP的其他任务上。但是,Transformer一味的去除掉了RNN,因此RNN和Transformer的结合也许会更好

五、BERT

论文地址: https://arxiv.org/abs/1810.04805

  Bert模型是Google在2018年10月发布的语言表示模型,全称:Bidirectional Encoder Representations from Transformers,它采用双向的transformer结构,进行Encoder Representations。Bert在NLP领域横扫了11项任务的最优结果,可以说是最近NLP中最重要的突破。
  语言模型通常是单向的,通常由左到右或者从右到左进行,但是语言的理解通常是一个双向的过程。所以需要建立一个双向的网络,但是通常的双向编码是会造成Words “see themselves”,如图所示:


  这样会造成上层进行编码的效果不是很好,针对这个问题,BERT在预训练时,对数据进行mask操作,如图所示:


  BERT模型的目标是利用大规模无标注语料训练、获得文本的包含丰富语义信息的Representation,即:文本的语义表示,然后将文本的语义表示在特定NLP任务中作微调,最终应用于该NLP任务


  BERT模型的主要输入是文本中各个字/词的原始词向量,该向量既可以随机初始化,也可以利用Word2Vector等算法进行预训练以作为初始值;输出是文本中各个字/词融合了全文语义信息后的向量表示
  BERT将多个transformer编码器堆叠在一起。BERT卓越的性能基于两点。首先创新预训练任务Masked Language Model (MLM)以及Next Sentence Prediction (NSP);其次训练BERT使用了大量数据和算力
  MLM使得BERT能够从文本中进行双向学习,也就是说这种方式允许模型从单词的前后单词中学习其上下文关系。此前的模型这是做不到的。此前最优的算法称为Generative Pre-training (GPT) ,该方法采用了从左到右的训练方式,另外ELMo 采用浅双向学习(shallow bidirectionality)
 &emsp**;BERT和ELMo和GPT三种结构**如图所示:


  ELMo采用的是双向的LSTM,GPT采用的是单向的transformer,BERT采用的是双向的transformer
  BERT complication: Next sentence prediction:BERT为了在预训练是更好的获得句子间的关系,不仅仅进行mask词汇的预测,还预测句子,预测一句子是否会紧挨着另外一个句子出现,如图所示:


  sentence pair encoding:BERT提供了多种encoding的方式,如图所示:


  Bert只学习一个建立在顶层的分类器,微调每个任务,如图所示:


  而近日,百度提出知识增强的语义表示模型== ERNIE==(Enhanced Representation from kNowledge IntEgration),并发布了基于 PaddlePaddle 的开源代码与模型,在语言推断、语义相似度、命名实体识别、情感分析、问答匹配等自然语言处理(NLP)各类中文任务上的验证显示,模型效果全面超越 BERT。由此可以看出,预训练模型已成为近来NLP领域的潮流

六、补充知识点:GPT

1.OpenAI GPT(开放式GPT)

论文地址:
Improving Language Understanding by Generative Pre-Training(Radford等人,2018年)
https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf

  与ELMo的想法类似,OpenAI GPT,Generative Pre-training Transformer的缩写,通过在大量免费文本语料库上进行训练,将无监督语言模型扩展到更大的规模。

1)OpenAI GPT

  GPT与ELMo有两个主要区别:

  • 模型体系结构不同:ELMO模型通过独立训练的从左到右和从右到左多层LSTMs的简单级联构成,而GPT是一个多层单向的Transformer
    decoder。
  • 在下游任务使用带上下文信息的Embedding的方式不同:ELMO需要为特定的任务训练特定模型,然后把embedding当作特征提供给特地任务使用,而GPT对所有任务都是相同的模型。

2)Transformer decoder作为语言模型

  与传统的Transformer架构相比,Transformer解码器模型丢弃了encoder部分,因此模型只有一个输入。输入句子embedding经过多层Transfomer处理。每一层都由一个multi-head self-attention层和一个pointwise feed-forward层构成。最终经过softmax层输出在目标词条上的概率分布。


  Loss是负对数似然度(negative log-likelihood),与ELMO相同,但没有反向计算(序列从后往前的计算)。比方说,k大小的上下文窗口位于目标单词之前,损失如下:

3)BPE(Byte Pair Encoding)

 &emsp**;字节对编码(BPE)用于编码输入序列。 BPE最初在20世纪90年代被提出作为数据压缩算法,然后被用来解决机器翻译中的开放词汇问题**,因为在翻译成新语言时很容易遇到罕见和未知的单词。受到由于稀有和未知单词通常可以分解为多个子词的情况所启发,BPE通过迭代和贪婪地合并频繁的字符对来找到最佳的单词分词。

4)有监督的微调

  OpenAI GPT提出的最实质性的升级是摆脱task-specific模型,直接使用预先训练的语言模型!
  以分类为例。比方说,在带标签的数据集中,每个输入都有n个标签,x=(x1,…,xn),还有一个标签y。GPT首先通过预先训练的Transformer解码器处理输入序列x,最后一个tokenxn的最后一层输出是hL(n)。然后,只有一个新的可训练权重矩阵Wy,它可以预测类别标签上的分布。


  Loss是最小化真实标签的负对数似然度。此外,添加LMloss作为辅助loss被认为是有益的,因为:

  • 它有助于在训练期间加快收敛速度。
  • 有望提高监督模型的泛化能力。


  基于类似的设计,对于其他任何下游任务不需要更改网络结构。如果任务输入包含多个句子,则在每对句子之间添加一个特殊的分隔符( $ )。这个定界符标签的embedding是一个我们需要学习的新参数,但是它应该非常小。
  对于句子相似性任务,因为排序无关紧要,所以两个排序都包括在内。对于多项选择任务,上下文与每个答案候选项配对

5)总结

  OpenAI GPT在第一阶段,语言模型的生成性预训练可以吸收尽可能多的自由文本(free text)。然后在第二个阶段,利用小的带标注数据集和一组最小的新参数对模型进行微调,以适应特定的任务
  GPT的一个局限性是它的单向特性—该模型只被训练来预测未来left-to-right context,这限制了GPT的学习能力。

2.OpenAI GPT-2

论文地址: Language Models are Unsupervised Multitask Learners
https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf

  OpenAI GPT-2语言模型是GPT的直接继承者。与GPT-2与GPT-1相比,模型结构基本一致,任然采用多层单向Transformer模型,主要是在训练数据方面有很大不同

  • 数据量更大、更广泛的训练数据,Reddit上抓取了800万各种类型的数据。
  • 对训练数据进行筛选,选择更高质量的数据训练网络。
  • GPT-2层数增加一倍,有1.5B的参数,比原始GPT多10倍,并且在Zero-Shot Transfer场景下,在8个测试语言建模数据集中的7个数据集上,获得了SOTA结果。
  • 一些细微的网络结构上的修改。

  正是因为拥有了更加丰富、更大量的训练数据,模型结构也比GPT-1更加复杂,学习到的Feature更加广泛和准确。因此,OpenAI GPT-2的巨大改进在小数据集和用于测量长期相关性的数据集上尤为显著

1)Zero-Shot Transfer

  GPT-2的预训练任务仅仅包含第一步预训练语言模型。所有下游语言任务都被构建为预测条件概率,没有任务特定的微调。
  LM模型非常适合处理文本生成任务(Text Generation)。

  • 机器翻译任务,比如,从英语到汉语,被构造出如下的条件LM:“英语句子=汉语句子”和“目标英语句子=”。 例如,条件概率的预测看起来像: P (?|I like green apples. =我喜欢绿苹果。A cat meows at him. =一只猫对他喵。It is
    raining cats and dogs. = " )
  • QA任务的格式与机器翻译类似,把问题和答案放在一起构成Context。
  • 摘要抽取任务是在抽取完文章的上下文信息之后,通过添加 TL:DR: 来触发的。

2)字节序列上的BPE介绍

  与最初的GPT相同,GPT-2输入采用BPE处理使用UTF-8字节序列。每个字节可以在8bits中表示256个不同的值,而UTF-8中一个字符最多可以使用4个字节,总共支持最多2的31次方个字符。因此,对于字节序列表示,只需要大小为256的词汇表,不需要担心预处理、分词等。尽管有这些好处,当前字节级(byte-level)的LMs与SOTA词级别(word-level)的LMs的性能差距仍然不可忽略
  BPE通过贪心的方式合并频繁共现的字节对。以防止它生成多个版本的常用词(比如对于dog,生成dog. dog! dog?),GPT-2防止BPE跨类别合并字符(因此dog不会与标点符号合并,如。,!还有?)。这些技巧有助于提高最终字节分段的质量。
  使用字节序列表示,GPT-2能够为任何Unicode字符串分配概率,而不需要任何预处理步骤。

3)模型修改

  与GPT相比,GPT-2除了具有更多的Transformer层和参数之外,只包含了很少的架构修改:

  • Layer normalization被移动到每个sub-block的输入,类似于一种“building block”类型的残差单元(不同于原始类型“bottleneck”,它在weight layers之前先进行batch
    normalization)。
  • 在最终的自self-attention块之后添加了额外的layer normalization。
  • 初始化被修改为与模型深度相关的函数。
  • Residual layer的参数最初按 1/N 的系数缩放,其中N是残余层的数量。
  • 使用更大的词汇量和上下文大小。

七、总结

  现有流行Contextual-Based LM的对比:

实战

【参考资料】

1.斯坦福cs224n-2019链接:https://web.stanford.edu/class/archive/cs/cs224n/cs224n.1194/
2.bilibili 视频:https://www.bilibili.com/video/BV1s4411N7fC?p=2
3.Generalized Language Models:https://lilianweng.github.io/lil-log/2019/01/31/generalized-language-models.html

Task 4: Contextual Word Embeddings (附代码)(Stanford CS224N NLP with Deep Learning Winter 2019)相关推荐

  1. Task 5: Homework(附代码)(Stanford CS224N NLP with Deep Learning Winter 2019)

    Task 5: Homework--英文词向量的探索 目录 Task 5: Homework--英文词向量的探索 词向量 本项目需要下载的包 Part 1:基于计数的词向量 问题1.1:实现不同单词 ...

  2. Task 2: Word Vectors and Word Senses (附代码)(Stanford CS224N NLP with Deep Learning Winter 2019)

    Task 2: Word Vectors and Word Senses 目录 Task 2: Word Vectors and Word Senses 一.词向量计算方法 1 回顾word2vec的 ...

  3. Task 3: Subword Models (附代码)(Stanford CS224N NLP with Deep Learning Winter 2019)

    Task 3: Subword Models 目录 Task 3: Subword Models 回顾:Word2vec & Glove 一.人类语言声音:语音学和音系学 二.字符级模型(Ch ...

  4. Task 4: Contextual Word Embeddings

    Contextual Word Embeddings 最想学习哪些内容,汇总如下: 变压器 (Transformers) BERT 问题解答 (QA) 文本生成和摘要 预训练的词向量:早年的Collo ...

  5. 【cs224n学习作业】Assignment 1 - Exploring Word Vectors【附代码】

    前言 这篇文章是CS224N课程的第一个大作业, 主要是对词向量做了一个探索, 并直观的感受了一下词嵌入或者词向量的效果.这里简单的记录一下我探索的一个过程. 这一下几篇文章基于这次作业的笔记理论: ...

  6. 【CTR模型】TensorFlow2.0 的 DCN(Deep Cross Network) 实现与实战(附代码+数据)

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  7. 【CTR模型】TensorFlow2.0 的 xDeepFM 实现与实战(附代码+数据)

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  8. 【CTR模型】TensorFlow2.0 的 DeepFM 实现与实战(附代码+数据)

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  9. 【论文精读 | 细节分析 | 代码实现】PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation

    文章目录 声明 引文 1.点云数据格式 2. 点云的特点 2.1.1 点云的置换不变性 2.1.2 点云的相互关系 2.1.3 点云的旋转不变性 3. 传统处理方式 Abstract 点云数据的特性补 ...

最新文章

  1. 第十七届第一场智能车竞速校内赛,比往年来的早一些
  2. SVN之文件同步更新
  3. C++Wiggle Sort摆动排序的实现算法(附完整源码)
  4. java 最少使用(lru)置换算法_一篇文章学会如何基于LRU-K算法设计本地缓存实现流量削峰...
  5. 阅读量PHP设计,zblogPHP如何修改文章阅读量
  6. iOS多线程编程之锁的理解
  7. python分析nginx日志_利用python分析nginx日志
  8. php文档头,头部文档(header.php)
  9. JVM监控及诊断工具GUI篇之Arthas(一):基础指令
  10. 新闻管理系统(增删改查+分页+阅读+发布评论+删除评论+数据库)
  11. Docker引擎客户端工具docker的总结
  12. Arduino DY-SV17F自动语音播报
  13. mysql dual表用法_详解Oracle数据库中DUAL表的使用
  14. 阿里巴巴“新六脉神剑”背后的故事
  15. nc65右键生成菜单_NC65管理员层级管控
  16. Debian - Add the checking mail notification - mutt
  17. Visual Studio Code 代码显示空格等空白符的方法
  18. 如何利用华硕Mesh系统路由器在780平方公尺大的场域架设可靠的WiFi系统?
  19. 使用Charles做弱网测试入门篇
  20. 查看tomcat的线程数

热门文章

  1. 笛卡尔空间轨迹规划(直线、圆弧)
  2. 什么cpu适合matlab,是不是AMD的CPU不适合MATLAB?
  3. 系统架构师考试需求大纲
  4. 大屏幕-全屏、退出全屏
  5. 计算机会计研究生学校排名2015,2015年会计学研究生院校排名介绍
  6. 安装SSL证书遇到困难怎么办?
  7. Spark 优化加速
  8. SQL优化一键命中索引
  9. 第九周 oj 三,切面条
  10. VSCode生成 自定义代码块