文章目录

  • 1. Introduction
  • 2.Natural Language Processing
    • 2.1 什么是NLP
    • 2.2 NLP为何很难
  • 3.Transformers可以做什么
    • 3.1 Working with pipelines
    • 3.2 Zero-shot classification(零样本分类)
    • 3.3 Text generation
    • 3.4 在pipeline中使用来自Hub的模型
    • 3.5 Mask filling
    • 3.6 NER
    • 3.7 QA(Question answering)
    • 3.8 Summarization
    • 3.9 Translation
  • 4.Transformers如何工作
    • 4.1 Transformer的历史
    • 4.2 Transformer是语言模型
    • 4.3 Transformer是大模型
    • 4.4 迁移学习
    • 4.5 Introduction of Transformer
    • 4.6 Attention layers(注意力层)of Transformer
    • 4.7 Transformer原始架构
    • 4.8 Architectures vs. checkpoints
  • 5.Encoder模型
  • 6.Decoder模型
  • 7.Sequence-to-Sequence模型(Seq2Seq)
  • 8.Bias and limitations
  • 9.总结

1. Introduction

  • Transformer models
  • Transformers使用
  • Fine-tuning 预训练模型
  • Sharing model and tokenizers

在Introduction中,将会包含以上四项内容的介绍。

在下边这些章节中,将会学习如下:

  • 使用pipeline()函数解决NLP任务,比如文本生成和文本分类
  • Transformer架构
  • 如何区分encoderdecoderencoder-decoder架构及其使用案例

2.Natural Language Processing

介绍Transformer模型之前,先对NLP做一个简要概述。

2.1 什么是NLP

简单来说,NLP任务就是要理解人类所表达的内容,包括语言、文字、语音等内容。常见的NLP任务如下:

  • Classifying whole sentences(文本分类):句子情绪识别,垃圾邮件检测,段落间是否相关
  • Classifying each word in a sentence(分词):辨别句子中的成分(名词、动词、形容词)、命名实体识别(人物、位置、组织)
  • Generating text content(文本生成):提示内容补全、文本填充
  • Extracting an answer from a text(信息提取):基于上下文,提取有关问题的答案
  • Generating a new sentence from an input text(翻译):文本翻译

NLP并不局限于文本领域,在语音识别和计算机视觉中也有其身影,比如:根据图像生成文本内容的描述。

2.2 NLP为何很难

    计算机处理信息的方式不同于人类大脑。人类所说的语言可能有多种含义,我们可以轻松地排除,确定其所要表达的内涵,而对于机器学习模型来说,想要准确理解语言所表达的内容是很困难的,即语义理解极为困难,这也是当前NLP领域面临的一大难题。

3.Transformers可以做什么

Transformer模型广泛应用于各种NLP任务当中,比如2.1节中提到的任务。

3.1 Working with pipelines

pipeline()函数是Transformers library最基础的对象,其将模型和必要的预处理和后处理步骤连接起来,允许我们直接输入文本得到清晰明确的结果。如下:

from transformers import pipeline# 创建分类器对象
classifier=pipeline('sentiment-analysis')
classifier("I've been waiting for a HuggingFace course my whole life.")

[{‘label’: ‘POSITIVE’, ‘score’: 0.9598050713539124}]

也可以输入多个句子

classifier(["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"]
)

[{‘label’: ‘POSITIVE’, ‘score’: 0.9598050713539124},
{‘label’: ‘NEGATIVE’, ‘score’: 0.9994558691978455}]

    这里,选择已经预训练好的模型,并且在英语sentiment analysis(情感分析)上进行了微调。创建分类器对象时下载并缓存模型,如果重新执行该语句,将使用缓存的模型,无需再次下载。
将输入文本传递到pipeline时主要涉及如下三个步骤:

  • 文本被预处理成模型可以理解的格式
  • 预处理的输入被传递给模型
  • 模型的预测也是经过处理的,可以很好理解

在这里可获得pipelines如下:

  • feature-extraction(特征提取,得到文本的向量表示)
  • fill-mask
  • ner(命名实体识别)
  • question-answering(问答)
  • sentiment-analysis(情感分析)
  • summarization(摘要)
  • text-generation(文本生成)
  • translation(翻译)
  • zero-shot-classification

3.2 Zero-shot classification(零样本分类)

    这里从对尚未标记的样本进行分类任务开始,这是实际当中最常见的场景,因为标注不仅需要专业领域知识,而且时间、人力成本都很高。
    在这个例子中,zero-shot-classification pipeline非常强大,允许指定用于分类的标签,所以不必依赖于预训练模型的标签。在sentiment-analysis中,可以把文本分类为positive 或negative,而这里,可以使用任何喜欢的标签集对文本进行分类。

classifier=pipeline("zero-shot-classification")
classifier("This is a course about the Transformers library",candidate_labels=["education","politics","business"]
)

{‘sequence’: ‘This is a course about the Transformers library’,
‘labels’: [‘education’, ‘business’, ‘politics’],
‘scores’: [0.8445963859558105, 0.111976258456707, 0.043427448719739914]}

pipeline调用zero-shot,无需根据数据微调模型,并且直接返回想要的任何标签列表的概率分数。

3.3 Text generation

这里使用pipeline()生成文本,主要思想就是提供一个prompt,模型通过生成剩余的文本对其进行补全。文本生成涉及到随机性,所以生成的结果可能和如下不一致。

generator=pipeline("text-generation")
generator("In this course,We will teach you how to")

[{‘generated_text’: ‘In this course,We will teach you how to use the following technologies in a self defense weapon, to use their abilities effectively. We will be discussing the use of 3rd person perspective. We will have more examples of some of the concepts described above’}]

也可以使用参数num_return_sequences控制生成多少个不同的序列以及使用参数max_length控制输出文本的总长度。

3.4 在pipeline中使用来自Hub的模型

上边的示例使用了默认模型,但也可以从Hub中选择特定模型用于pipeline,例如文本生成任务。到Model Hub中点击左侧对应标签会展示支持该任务的模型,如下图:

这里使用distilgpt2模型,下面是使用pipeline()distilgpt2的加载。

generator=pipeline("text-generation",model="distilgpt2")
generator("In this course, we will teach you how to",max_length=30,num_return_sequences=2,
)

[{‘generated_text’: “In this course, we will teach you how to make a better value system for you. Each lesson will be based on the interests of your clients’”},
{‘generated_text’: ‘In this course, we will teach you how to identify and identify the many common problems with your project. Please note, though, that we are not’}]

这里也可以通过点击language标签来优化对模型的搜索,然后选择一个模型以用来生成另一种语言的文本。Model Hub包含支持多种语言的多语言模型检查点。

3.5 Mask filling

unmasker=pipeline("fill-mask")
unmasker("This course will teach you all about <mask> models.",top_k=2)

[{‘score’: 0.1961972862482071,
‘token’: 30412,
‘token_str’: ’ mathematical’,
‘sequence’: ‘This course will teach you all about mathematical models.’},
{‘score’: 0.04052707925438881,
‘token’: 38163,
‘token_str’: ’ computational’,
‘sequence’: ‘This course will teach you all about computational models.’}]

top_k参数控制想要显示几种可能性结果。注意,这里对于空缺的位置填充了<mask>,称之为掩码标记。其他的mask-filling模型或许有不同的掩码标记,在探索其他模型时,验证正确的mask词总是有益的。

3.6 NER

NER(命名实体识别)是一项给定输入文本,找出其中对应的实体,比如人、位置或组织类别的实体。

from transformers import pipeline, AutoModelForTokenClassification, AutoTokenizermodel = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
ner=pipeline("ner", model=model, tokenizer=tokenizer,grouped_entities=True)
ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")

[{‘entity_group’: ‘PER’,
‘score’: 0.9981694,
‘word’: ‘Sylvain’,
‘start’: 11,
‘end’: 18},
{‘entity_group’: ‘ORG’,
‘score’: 0.9796019,
‘word’: ‘Hugging Face’,
‘start’: 33,
‘end’: 45},
{‘entity_group’: ‘LOC’,
‘score’: 0.9932106,
‘word’: ‘Brooklyn’,
‘start’: 49,
‘end’: 57}]

模型识别出Sylvain 是人(PER),Hugging Face是一个组织(ORG),Brooklyn是一个位置(LOC)。

    通过在pipeline()中添加grouped_entities=True将句子中对应于同一实体的部分重新组合在一起,这里将"Hugging"和“Face”重组为一个组织。
事实上,后面小结中,预处理就可以将一些单词分为更小的部分。例如,Sylvain可以分为四部分:S,##yl,##va,和##in。后处理步骤中,pipeline成功将这些pieces(片)组合。

3.7 QA(Question answering)

QA pipeline使用从上下文获取的信息来回答问题。

from transformers import pipeline
qa=pipeline("question-answering")
qa(question="Where do I work?",context="My name is Sylvain and I work at Hugging Face in Brooklyn"
)

{‘score’: 0.6949760913848877, ‘start’: 33, ‘end’: 45, ‘answer’: ‘Hugging Face’}

注意到,pipeline是从提供的上下文中提取信息的,并不生成答案。

3.8 Summarization

Summarization将文本缩减为更短的文本,同时保留文本中重要内容信息。

from transformers import pipelinesummarizer=pipeline("summarization")
summarizer("""America has changed dramatically during recent years. Not only has the number ofgraduates in traditional engineering disciplines such as mechanical, civil,electrical, chemical, and aeronautical engineering declined, but in most ofthe premier American universities engineering curricula now concentrate onand encourage largely the study of engineering science. As a result, thereare declining offerings in engineering subjects dealing with infrastructure,the environment, and related issues, and greater concentration on hightechnology subjects, largely supporting increasingly complex scientificdevelopments. While the latter is important, it should not be at the expenseof more traditional engineering.Rapidly developing economies such as China and India, as well as otherindustrial countries in Europe and Asia, continue to encourage and advancethe teaching of engineering. Both China and India, respectively, graduatesix and eight times as many traditional engineers as does the United States.Other industrial countries at minimum maintain their output, while Americasuffers an increasingly serious decline in the number of engineering graduatesand a lack of well-educated engineers."""
)

[{‘summary_text’: ’ China and India graduate six and eight times as many traditional engineers as the U.S. as does other industrial countries . America suffers an increasingly serious decline in the number of engineering graduates and a lack of well-educated engineers . There are declining offerings in engineering subjects dealing with infrastructure, infrastructure, the environment, and related issues .'}]

类似于text generation,可以指定结果的max_length或min_length

3.9 Translation

这里使用Model Hub中的Helsinki-NLP/opus-mt-zh-en模型来完成翻译任务。

from transformers import pipelinetranslator = pipeline("translation", model="Helsinki-NLP/opus-mt-zh-en")
translator("我叫舒城,我住在上海松江区。")

[{‘translation_text’: ‘My name is Shu City. I live in Songjiang District in Shanghai.’}]

类似于text generatiosummarization,也可以指定max_lengthmin_length

pipeline()的基本用法就如上述,下边将深入介绍pipeline()功能。

4.Transformers如何工作

这里,简要介绍Transformer模型架构。

4.1 Transformer的历史


Transformer架构诞生于2017年,最初其被应用于翻译任务。以下是应用Transformer架构的一些模型:

  • 2018年7月:GPT,首个预训练Transformer模型,在多种NLP任务上微调取得了SOTA。
  • 2018年10月:BERT,大规模预训练模型,旨在产生更好的句子摘要。
  • 2019年2月:GPT2,改进版GPT(参数规模更大)。
  • 2019年10月:DistilBERT,BERT的提炼版本,速度提高60%,内存减少40%,但仍保留BERT性能的97%。
  • 2019年10月:BART和T5,和原始Transformer采用同样架构的两个大规模预训练模型。
  • 2020年5月:GPT3,比GPT2参数规模更大的预训练模型,在很多任务上即使不需要fine-tuning表现仍然很好(称之为zero-shot learning)。

以上模型并不是全部,广义上讲,可以将这些模型分为三个类别:

  • GPT-like(也称作auto-regressive Transformer models,自回归Transformer模型)
  • BERT-like(也称作auto-encoding Transformer models,自编码Transformer模型)
  • BART/T5-like(也称作sequence-to-sequence Transformer models ,序列-to-序列Transformer模型)

4.2 Transformer是语言模型

    以上涉及到的所有Transformer模型均为语言模型。这意味着这些模型以self-supervised(自监督)方式在大量原始文本上进行了训练。所谓自监督就是一种训练类型,其目标是根据模型输入自动计算的,不需要人类对数据进行标注。这些类型的语言模型可以对其训练过的语言产生好的理解,但对于特定的实际任务并不是很有用,因此,一般预训练模型都会经过一个称之为迁移学习的过程,在此过程中,模型以监督方式在给定标签的特定数据集上进行微调,即预训练+微调范式。

    一个任务的例子就是根据先前阅读的n个单词,预测下一个单词是什么。这称之为causal language modeling,因为输出取决于过去和当前输入,而不是未来的输入。


另一个例子就是masked language modeling(遮蔽语言建模),即预测一个句子中被掩盖的单词是什么。

4.3 Transformer是大模型

DistliBERT之外,要使模型获得更好的性能一般性策略就是增加模型大小以及预训练使用的数据量。

不幸的是,训练一个大模型,需要大量数据,这在时间和计算资源上都很昂贵。这甚至可以转化为对环境的影响,如下图所示:

该图展示了一个一个由团队领导的大型模型项目,团队有意识地减少预训练对环境的影响,可以看到,运行大量实验以获得最佳超参数其二氧化碳排放量会更多。

可以想象,如果研究团队、学生组织或公司想要训练一个模型,都是从头开始的,这势必会导致巨大的、不必要的时间和计算成本的浪费。

这也是为什么共享语言模型如此重要:共享经过训练的权重,可以降低训练成本,减少对环境的影响。

4.4 迁移学习

预训练是从零开始训练一个模型:权重随机初始化、训练开始时没有任何先验知识。

另一方面,Fine-tuning是在模型预训练之后的训练。首先需要获得一个预训练语言模型,然后使用特定任务的带有标签的数据集进行额外训练,即fine-tuning。这里解释一下为什么要分两步进行,而不是一步到位直接训练达到目的。

  • 第一,预训练模型已经在同fine-tuning数据集相似的大规模数据集上进行初步训练。因此,fine-tuning过程可以利用模型预训练期间获得的知识,一方面,可以作为先验知识,另一方面,加快训练推理速度。
  • 第二,预训练模型已经在大量数据上进行了训练,fine-tuning期间只需要很少的数据和时间就可以获得不错的结果。
  • 第三,对于同样的推理任务,获得良好结果所需要的时间和资源要少得多。

例如,可以利用经过英语训练的预训练模型,在arXiv语料库上对齐进行fine-tuning,从而生成基于科学/研究的模型。fine-tuning只需要少量数据:预训练模型获得的知识是可以迁移的,因此称之为迁移学习。

因此,fine-tuning模型具有更少的时间、数据、钱和环境成本。迭代不同的fine-tuning方案也更快、更容易,于完整的预训练相比,训练的约束条件更少。

4.5 Introduction of Transformer

Transformer主要由两个blocks组成:

  • Encoder(左):encoder接收输入并构建其特征表示,这意味着模型经过优化,可以获得更好的特征表示。
  • Decoder(右):decoder使用encoder的特征表示以及其他输入来生成目标序列,意味着可以对输出进行优化。

encoder和decoder都可以独立使用,具体取决于任务。

  • Encoder-only models: 适用于需要理解输入的任务,例如句子分类和命名实体识别
  • Decoder-only models: 适用于生成类任务,比如文本生成
  • Encoder-decoder models or sequence-to-sequence models: 适用于生成任务,并要求有输入,比如翻译和概括类任务

4.6 Attention layers(注意力层)of Transformer

    Transformer模型的一个关键特性就是由一个称之为attention layer的特殊层所构建。详细内容可在其原始论文"Attention is All You Need!"查阅。现在,我们需要知道的是,在处理每个单词的表示时,该层会告诉模型特别注意传递给它的句子中的某些单词(或多或少的忽略其他单词)(类似于人的注意力,集中于感兴趣的地方)。

    这里举一个例子,考虑文本从英语翻译成法语的任务。给定输入”You like this course",翻译模型需要关注相邻的词"You"来获得"like"这个词的正确翻译,因为在法语中,动词"like"的变位方式不同,具体取决于主题。然而,对于该词的翻译没有用处。同样,在翻译"this"时,模型还需要注意"course"这个词,因为"this"的翻译取决于相关连的名词是男性还是女性,同样,句子中的其他词对于"this"的翻译无关紧要。对于复杂的句子(复杂的语法规则),模型需要特别注意可能出现在句子中更远的单词,以正确翻译每个单词。

    相同的概念适用于自然语言相关的其他任何任务:一个词本身具有含义,但也受到上下文影响,上下文可以是当前的词或之前/之后的任何其他词(或多个词)。

4.7 Transformer原始架构

    Transformer架构最初是为翻译任务而设计。训练期间,编码器接收某种语言的输入(句子),解码器接收目标语言的相同句子。在编码器中,注意力层可以使用句子中的所有单词(给定单词的翻译可能取决于句子中的前后内容)。然而,解码器是按顺序工作的,只能关注到已经翻译部分的单词。例如,当预测了翻译目标的前三个词时,将它们提供给解码器,然后解码器使用编码器的所有输入来尝试预测第四个词。
    为加速训练过程(模型可以访问目标句子),将整个目标句子输入到decoder,但不允许使用未来的单词(如果在尝试预测位置2处的单词可以访问位置2处的单词,就相当于考试作弊)。例如,当尝试预测第四个单词时,注意力层只能访问位置1到3的单词。
    原始Transformer架构如下,左侧为Encoder,右侧为Decoder。

    注意到,解码器块中的第一个注意力层关注解码器过去所有输入,但第二个注意力层使用编码器的输出。因此,它可以访问整个句子以最好的预测当前单词。这非常有用,因为不同语言其语法规则不同,单词的顺序也不尽相同。有助于根据上下文确定单词的最佳翻译。
    注意力掩码也在encoder/decoder中使用,以防止模型注意到某些特殊词。例如,在批处理句子时,特殊填充词用于使 所有输入句子具有相同的长度。

4.8 Architectures vs. checkpoints

这里,对Architectures和checkpoints两个术语进行一下说明,

  • Architectures :模型的骨架——模型中每层及每个操作的定义
  • Checkpoints:给定Architectures中加载的权重
  • Model:这是一个总称,不像"Architectures"或"Checkpoints"那么准确,但可以同时表示两者。

例如,BERT是一种架构,而Bert-base-cased(Google团队为BERT第一个版本训练的一组权重)是一个checkpoints。但是,可以说"BERT模型"和"基于BERT的模型“。

5.Encoder模型

    Encoder模型仅使用Transformer模型的编码器。在每个阶段,attention layer可以访问初始句子中的所有单词。这些模型通常被描述为具有“bi-directional”(双向)注意力,通常将其称为auto-encoding(自编码器)模型。
    Encoder模型的预训练通常围绕以某种方式破坏给定的句子(例如,随机掩盖句子中的单词)并让模型找到被掩盖的单词或重建原始句子
    编码器模型最适合于需要理解整个句子的任务,比如句子分类、命名实体识别以及抽取式问答等。典型的模型代表如下:

  • ALBERT
  • BERT
  • DistilBERT
  • ELECTRA
  • RoBERTa

6.Decoder模型

    Decoder模型只包含Transformer模型中的decoder部分。在每个阶段,对于给定的单词,attention layer只能访问句子中位于该次前边的单词,这些模型通常称之为auto-regressive(自回归)模型。
    Decoder模型的预训练通常围绕预测句子中的下一个单词进行。其最适合于文本生成类任务。Decoder模型的典型代表有如下:

  • CTRL
  • GPT
  • GPT-2
  • TransformerXL

7.Sequence-to-Sequence模型(Seq2Seq)

    Encoder-Decoder模型(也称作sequence-to-sequence模型)使用Transformer架构的两部分。每个阶段,编码器的注意力层可以访问初始句子的所有单词,而解码器的注意力层只能访问输入中给定单词之前的单词。

8.Bias and limitations

    尽管预训练模型使用超大规模数据进行训练,参数规模也极大,所学习到的知识是极为丰富的,但不可避免的存在一定的局限性。

unmasker=pipeline("fill-mask",model="bert-base-uncased")
result=unmasker("This man works as a [MASK]")print([r["token_str"] for r in result])result=unmasker("This woman works as a [MASK]")
print([r["token_str"] for r in result])

[‘lawyer’, ‘carpenter’, ‘doctor’, ‘waiter’, ‘mechanic’]
[‘nurse’, ‘waitress’, ‘teacher’, ‘maid’, ‘prostitute’]

当填写这两个句子中的缺失词时,模型只给出了一个不区分性别的答案(waiter/waitress)。其他则是通常与一种特定性别相关的工作职业,prostitute最终成为"women"和”work"相联系起来的一种可能性,这显然不是模型的想要的目标。即使经过预训练+微调之后,这种缺陷仍然不能避免。

9.总结

    在这里,了解了Transformers中的pipeline()函数的使用,可以用来处理不同的NLP任务。同时我们也讨论了迁移学习和微调的重要性,以及如何根据任务需要选择不同的模型架构,总结如下表:

Model Example Tasks
Encoder ALBERT,BERT,DistilBERT,ELECTRA,RoBERTa Sentence classification,NER,extractive question answering
Decoder CTRL,GPT,GPT-2,TransformerXL Text generation
Encoder-Decoder BART,T5,Marian,mBART Summarization,translation,generative question answering

Hugging Face(1)——Transformer Models相关推荐

  1. PyTorch深度学习(23)Transformer及网络结构ViT

    Transformer 一.Transformer 1.简介 创新.模型效果 通用的模块 注意力机制 应用领域:cv nlp 信号处理 视觉.文本.语音.信号 核心: 提特征的方法  提的更好 应用N ...

  2. SnapKit 源码解读(五):Models

    Models 里面的所有文件,都是用来对约束建模使用的. Typealiases Typealiases 为跨平台能力定义了一套公用的类. #if os(iOS) || os(tvOS)import ...

  3. 全民 Transformer (二): Transformer在深度学习和NLP中如何发挥作用

    <How Transformers work in deep learning and NLP: an intuitive introduction>   2020年的确是 Transfo ...

  4. 随笔-关系抽取(三) — Dependency-based Models

    关系抽取(三) - Dependency-based Models Improved Relation Classification by Deep Recurrent Neural Networks ...

  5. PRML学习总结(8)——Graphical Models

    PRML学习总结(8)--Graphical Models 8.1 Bayesian Networks 8.1.1 Example: Polynomial regression 8.1.2 Gener ...

  6. 深度学习之图像分类(十七)-- Transformer中Self-Attention以及Multi-Head Attention详解

    深度学习之图像分类(十七)Transformer中Self-Attention以及Multi-Head Attention详解 目录 深度学习之图像分类(十七)Transformer中Self-Att ...

  7. Coursera吴恩达《序列模型》课程笔记(3)-- Sequence models Attention mechanism

    红色石头的个人网站:redstonewill.com <Recurrent Neural Networks>是Andrw Ng深度学习专项课程中的第五门课,也是最后一门课.这门课主要介绍循 ...

  8. 李宏毅机器学习(五)Transformer

    学习内容 前情提要 Sequence-to-sequence(Seq2Seq) 输入是一个句子,输出长度不定: 下面的第一个是语音辨识,第二个是机器翻译,第三个是语音翻译.这三个都是独立的任务. 第三 ...

  9. 【NLP】毕设学习笔记(二)transformer

    文章目录 transformer组成 encoder/decoder组成 1.self-Attenion 背景 概念 attention函数计算 2.Feed Forward Neural Netwo ...

最新文章

  1. 五. python的日历模块
  2. 新搭建mysql容易出现问题
  3. 使用scikit-learn进行机器学习的简易教程
  4. phpMyFAQ 3.0.3 中文版
  5. 手把手教我班小姐姐学java之多态
  6. python 新式类和旧式类_python新式类和旧式类区别
  7. android studio进度条的应用,Android Studio实现进度条效果
  8. Apache POI TXT转成EXCEL(XLSX)
  9. windows自带黑体_Windows自带的宋体、黑体、楷体、仿宋体等能免费商用吗?
  10. 威纶触摸屏485轮询通讯_威纶通触摸屏与PLC实现一机多屏通讯方法
  11. VMware Workstation 启动报错
  12. 蓝桥杯_等差素数列_java
  13. ADS1110输入阻抗
  14. 2016大学计算机陈春丽,2016级计算机类专业分流结果公示.PDF
  15. [坑]微信支付首次支付成功,第二次调用失败
  16. 合影效果java_【蚂蚁课堂】四十三:如何拍酷炫集体照?
  17. 关于xds100仿真器的ftdi驱动无法使用的问题
  18. redis 解决key是乱码问题,并清理
  19. 渗透测试工具:跨站脚本漏洞检测---Xsser
  20. Android各种img文件作用以及系统启动过程

热门文章

  1. python调用ironpython_在.NET中嵌入IronPython 交互
  2. initramfs/initrd
  3. 数商云B2B分销商城系统:助力企业加快分销速度,构建高效智能B2B网上分销平台
  4. 外公家的猫-八年级作文
  5. iOS 一一 触摸事件和手势
  6. Kubectl 好用的命令行工具:oh-my-zsh 技巧和窍门
  7. 互联网公司的主要角色以及其职责
  8. 1187:统计字符数
  9. EventLoop(回顾)
  10. 最牛的商业模式,化肥厂利用买化肥送车,一年总利润600多万?