深入浅出自然语义处理原理并构建自然语义处理(NLP)模型GPT2
NLP自然语言处理,GPT2模型
1、词向量
在图像的处理中,我们无需对图像进行特殊的处理,因为图像本身就是由矩阵来表示的。而处理自然语言的时候,语言是由每一个字、词组成的。而字、词是通过编码存储在计算机当中的。所以我们可以通过将字、词编码成为向量的形式,如此就可以输入进深度学习网络模型中。
但是我们应该如何去编码呢?
像做图像分类那样,使用one—hot的形式编码?
但是这样会存在一个问题,在自然语言中,存在着词和词之间的关系,字和字之间的关系。例如近义词,反义词,同属性的词语。
例如:‘beijing’,‘china’,'tokyo’这三个词语之间的关系是如何的?
很显然,beijing是属于china 的,相比于tokyo,beijing离china的关系应该是要更近的才行。
看一看pytorch已经训练好的词向量,来解决这样一个问题。
安装torchtext。
pip install torchtext
运行下列程序:
import torch
import torchtext
from torchtext import vocab"""实例化词向量对象"""
gv = torchtext.vocab.GloVe(name='6B')"""打印词的长度"""
print(len(gv.vectors))"""打印词的形状"""
print(gv.vectors.shape)"""查询词索引位置"""
index = gv.stoi['tokyo']
print(index)"""打印词向量"""
vector_tokyo = gv.vectors[index]
print(vector_tokyo)"""由索引,查找词"""
print(gv.itos[index])
打印以下类容:
400000
torch.Size([400000, 300])
1363
tensor([ 0.0986, 0.2744, -0.1910, -0.4745, 0.3238, 0.0363, -0.1794, 0.0715,-0.1600, -1.3565, 0.0544, 0.0586, 0.9632, 0.6459, 0.3183, -0.2209,-0.3294, 0.2590, 0.0383, 0.0368, -0.0728, -0.8611, -0.1433, -0.0682,0.1370, 0.3474, 0.6794, -0.3918, -0.1797, -0.3086, 0.0509, -0.6783,0.2079, 0.0570, -0.0109, -0.4524, 0.0618, -0.4837, -0.4535, 0.3663,0.1987, 0.5068, 0.0085, 0.2570, -0.5934, 0.5397, -0.0467, 0.1591,-0.6192, 0.7122, 0.1573, 0.0781, 0.0654, 0.0127, -0.1181, 0.0454,0.1191, 0.3135, -0.3338, -0.7205, 0.1635, 0.3757, 0.2461, -0.1986,0.3314, -0.0696, 0.0323, -0.0119, 0.0461, -0.5783, 0.2841, -0.3058,-0.1039, -0.5089, 0.2029, -0.5188, 0.1908, 0.9081, -0.1614, -0.5558,-0.2981, 0.0113, -0.6955, 0.3706, -0.2457, 0.6815, -0.0221, -0.5354,-0.2667, -0.4546, 0.5362, -0.4829, -0.0112, -0.4637, -0.0534, -0.1134,-0.3340, 0.0190, 0.1398, -0.2753, -0.2229, -0.9672, -0.3900, 0.6600,-0.1395, -0.2849, 0.4003, -0.4742, 0.1142, 0.5477, -0.5486, -0.4966,-0.1614, -0.0464, 0.5475, 0.3730, 0.1716, 0.0252, -0.0163, -0.8848,0.6577, -0.7852, 0.0250, -0.2150, -0.4689, 0.1600, -0.1755, -0.2799,-0.3763, -0.1656, -0.3830, 1.1125, 0.7755, 0.2812, 0.5062, 0.1783,0.1184, 0.0525, 0.5988, 0.6151, 0.1548, 0.0550, 0.3621, -0.3447,0.2023, -0.3025, 0.0443, 0.2394, 0.1108, -0.1181, 0.9393, 0.2026,0.2374, 0.8568, 0.6142, 0.5347, -0.8022, -0.3214, -0.0874, 0.0590,0.1219, -0.0198, -0.2513, -0.5628, 0.6591, 0.0719, 0.3806, -0.0970,0.2537, -0.1051, -0.3114, -1.2763, -0.5952, -0.1996, -0.4410, -0.1974,0.4121, 0.5094, 0.0537, 0.9708, 0.1140, 0.2382, -1.1227, 0.2767,0.1361, 0.7891, 0.1975, -0.0671, -0.2377, -0.2153, 0.5068, -0.3815,-0.0401, -0.2702, -0.6019, -0.4694, 0.0836, -0.0187, -0.5859, 0.5743,1.0775, 0.2871, -0.1479, 0.7543, -1.1862, 0.8951, -0.2454, -0.2608,0.3586, -0.3043, -0.2555, -0.2138, -0.1634, -0.1754, -0.3832, 0.0035,-0.1285, 0.0648, -0.4690, 0.2399, 0.8058, -0.2286, 0.0707, 0.0218,-0.4434, 0.3778, -0.8856, 0.0924, -0.4961, 0.3073, 0.3822, -0.3354,0.1413, 0.2973, 0.6780, 0.2839, 0.4161, 0.4181, 0.5403, 0.7092,0.0378, -0.3367, -0.2768, 0.5240, -0.1976, -0.2343, -0.1787, -0.3622,-0.1782, -0.2002, 0.4667, -0.2682, -0.0780, 0.8032, -0.7729, -0.4938,-0.3711, 0.5108, 0.5503, -0.2175, -0.0640, -0.2579, -0.4843, 0.4356,0.5931, -0.1293, -0.3471, 0.3159, 0.2683, -0.5112, -0.4244, 0.0833,0.3387, -0.0699, -0.0656, 0.1321, -1.1871, -0.1551, 0.7677, -0.3515,-0.4988, 0.3188, 0.1130, -1.1187, -0.6493, -0.2563, -0.3067, 0.6126,-0.3617, -0.4735, 0.4456, 0.0256, -0.1027, -0.0352, 0.3227, 0.6737,0.0972, 0.1478, -0.0172, -0.2390])
tokyo
接着,
运行以下代码,通过向量的余弦相似度,来寻找和它关系最近的一条词。
import torch
import torchtext
from torchtext import vocab"""实例化词向量对象"""
gv = vocab.GloVe(name='6B',dim=50)def get_word_vector(word):"""取出词的向量:param word: 词:return: 词向量"""index = gv.stoi[word]return gv.vectors[index]def sim_10(word, n=10, way='cosine_similarity'):"""取出这个词向量,拿这个向量去遍历所有的向量,求距离,拉出10个最近的词:param way: 衡量方法:param word: 词向量:param n: 范围:return: 最相似的词向量"""if way == 'cosine_similarity':func = torch.cosine_similarityreverse = Trueelse:func = torch.distreverse = Falseall_cosine_similarity = []for i, w in enumerate(gv.vectors):if reverse:temp = func(word, w, dim=0)else:temp = func(word, w)all_cosine_similarity.append((gv.itos[i],temp))return sorted(all_cosine_similarity,key=lambda t:t[1],reverse=reverse)[:n]def answer(word1, word2, word3):print(f'{word1}:{word2}=={word3}:?')"""word1 - word2 = word3 - word4""""""word4 = word3 - word1 + word2"""word4 = get_word_vector(word3)-get_word_vector(word1)+get_word_vector(word2)return sim_10(word4,way='dist')[0]print(answer('beijing','china','tokyo'))
打印结果:
beijing:china==tokyo:?
('japan', tensor(2.7869))
已经训练好的词向量,和tokyo距离最近的为japan,这是正确的。
那么如何训练这样的词向量?
通过下图的方式:
找到一堆的语料数据,文章、对话、之类的。将一个词的前两个词的词向量wt−2、wt−1w_{t-2}、w_{t-1}wt−2、wt−1,和该词的后两个词的词向量wt+1、wt+2w_{t+1}、w_{t+2}wt+1、wt+2这是个词向量,做加法(对应位置数字相加),然后得到一个新的词向量w′w^{'}w′,将这个w′w^{'}w′和文章的词向量www之间做损失(loss=MSE(w′−w)loss = MSE(w^{'}-w)loss=MSE(w′−w)),即可,然后更新词向量,即可完成训练。
这便是word2vec中的CBOW。
\
2、传统encoder-decoder模型
如上图所示,传统的自然语言的处理采用RNN的方式,RNN处理序列,得到一个总体的概要,再通过概要输出序列。
但即使是改进成下图结构:
\
编码器得到语义信息c的过程中,会丢失大量的信息,使得模型无法关注语言的细节。
\
3、seq2seq with attention
于是在基于2的seq2seq基础上,RNN加入了attention。
见上图,输入一句话,(x1,x2,x3,x4)(x_{1},x_{2},x_{3},x_{4})(x1,x2,x3,x4)通过RNN处理后,得到总体的概要C,以及每一次输入一个词进入RNN后得到的(x1′,x2′,x3′,x4′)(x_{1}^{'},x_{2}^{'},x_{3}^{'},x_{4}^{'})(x1′,x2′,x3′,x4′)。
那么在我们现在输出第一个词的时候,会将rnn输出的第一个词,和(x1′,x2′,x3′,x4′)(x_{1}^{'},x_{2}^{'},x_{3}^{'},x_{4}^{'})(x1′,x2′,x3′,x4′)每一做向量的内积。
s1=x1′⋅y1s2=x2′⋅y1s3=x3′⋅y1s4=x4′⋅y1s_{1} =x_{1}^{'}\cdot y_{1}\\ s_{2} =x_{2}^{'}\cdot y_{1}\\ s_{3} =x_{3}^{'}\cdot y_{1}\\ s_{4} =x_{4}^{'}\cdot y_{1} s1=x1′⋅y1s2=x2′⋅y1s3=x3′⋅y1s4=x4′⋅y1
然后得到s的向量(s1,s2,s3,s4)(s_{1},s_{2},s_{3},s_{4})(s1,s2,s3,s4),经过softmax激活。
再将得到的s得分的乘上各自的词向量x′x^{'}x′,的到新的向量v:
v=s1∗x1′+s2∗x2′+s3∗x3′+s4∗x4′v = s_{1}*x_{1}^{'}+s_{2}*x_{2}^{'}+s_{3}*x_{3}^{'}+s_{4}*x_{4}^{'} v=s1∗x1′+s2∗x2′+s3∗x3′+s4∗x4′
将v和y1y_{1}y1,cat在一起。通过一层网络输出即可。
第二个单词的输出也是同样如此操着。这样就引入了原文的细节,得到较好的效果。
\
4、transformer模型
由编码器和解码器构成。而GPT2模型使用到的是transformer的解码器部分。在下一节详细解释。
\
5、GPT2
\
5.1、结构
GPT2的基本组成单元,就是这样一个结构,本质是输入一句话(几个词),然后预测下一个词。
输入通过自注意力后,再经过全连接神经网络。输出。
\
5.2、自注意力
在输入一句话,’我有一只猫‘,输入的是每一个词的词向量。
那么是如何做自己注意力的呢?
(s1,s2,s3,s4)=sotfmax((x1⋅x1,x1⋅x2,x1⋅x3,x1⋅x4))y1=s1∗x1+s2∗x2+s3∗x3+s4∗x4(s_1,s_2,s_3,s_4) = sotfmax((x_1\cdot x_1,\ x_1\cdot x_2,\ x_1\cdot x3,\ x_1\cdot x_4))\\ y1 = s_1*x_1+s_2*x_2+s_3*x_3+s_4*x_4\\ (s1,s2,s3,s4)=sotfmax((x1⋅x1,x1⋅x2,x1⋅x3,x1⋅x4))y1=s1∗x1+s2∗x2+s3∗x3+s4∗x4
首先是’我‘的词向量x1x_1x1和这句话的每一个词做内积,得到它和每一个词的关系。然后softmax归一化至总和为1.
之后再将,每一个得分和每一个词的向量做乘法操作,再将向量相加,得到输出y
之后的y2y_2y2同样操作:
(s1,s2,s3,s4)=sotfmax((x2⋅x1,x2⋅x2,x2⋅x3,x2⋅x4))y2=s1∗x1+s2∗x2+s3∗x3+s4∗x4(s_1,s_2,s_3,s_4) = sotfmax((x_2\cdot x_1,\ x_2\cdot x_2,\ x_2\cdot x3,\ x_2\cdot x_4))\\ y_2 = s_1*x_1+s_2*x_2+s_3*x_3+s_4*x_4 (s1,s2,s3,s4)=sotfmax((x2⋅x1,x2⋅x2,x2⋅x3,x2⋅x4))y2=s1∗x1+s2∗x2+s3∗x3+s4∗x4
如此完成了自注意力的操作。
\
5.3、多头自注意力
多头注意力,在上面的操作中,是将每个词向量,通过不同的网络层,线性变换后,再做自注意力的。然后将每一个自注意力的结果,cat在一起,通过一个网络层,变换维度后输出。
\
5.4、多头自注意力代码实现
构建GPT2模型时,首先需要构建的是自注意力模块。
from torch import nn
import torchclass SelfAttention(nn.Module):def __init__(self, embed_dim, num_head, is_mask=True):super(SelfAttention, self).__init__()def forward(self, x):pass
首先编写SelfAttention的类,该类在初始化的时候,应传入三个参数,词向量的维度,多头注意力的头数,以及是否使用掩码屏蔽每个词后面的词。
添加的掩码为一个下三角矩阵,这样操作,可以让网络只能让每个词和他前面的词相做注意力,而无法看到后面的词语。类似于人,阅读文字的时候,是从前往后,一个字一个字地阅读的。
详细操作如下图:
query和key运算后,先做masked,然后再softmax后与value运算。
然后按照多头注意力,创建两个线性层。
class SelfAttention(nn.Module):def __init__(self, embed_dim, num_head, is_mask=True):super(SelfAttention, self).__init__()assert embed_dim % num_head == 0self.num_head = num_headself.is_mask = is_maskself.linear1 = nn.Linear(embed_dim, 3 * embed_dim)self.linear2 = nn.Linear(embed_dim, embed_dim)def forward(self, x):pass
首先,我们需要将词向量的维度上,分出若干头来,故需要输入的词向量维度数和头数,能够整除。
同时我们将要从中分出query, key, value三个向量出来,故通过一层线性层扩增至三倍。
在多头自注意力,每一头,应当是不同的线性成来做线性变换,这里的全连接是同样的效果,只要从中分出来,就是等价的了。
具体前线推理如下:
class SelfAttention(nn.Module):def __init__(self, embed_dim, num_head, is_mask=True):super(SelfAttention, self).__init__()"""......"""def forward(self, x):'''x 形状 N,S,V'''x = self.linear1(x) # 形状变换为N,S,3Vn, s, v = x.shape"""分出头来,形状变换为 N,S,H,V"""x = x.reshape(n, s, self.num_head, -1)"""换轴,形状变换至 N,H,S,V"""x = torch.transpose(x, 1, 2)
直接reshape一下,变换形状至(N,S,H,V)然后换轴,至(N,H,S,V)即分出头来,
然后从最后一个维度切出query, key, value,开始计算自注意力。
class SelfAttention(nn.Module):def __init__(self, embed_dim, num_head, is_mask=True):super(SelfAttention, self).__init__()"""......"""def forward(self, x):"""......"""'''分出Q,K,V'''query, key, value = torch.chunk(x, 3, -1)dk = value.shape[-1] ** 0.5'''计算自注意力'''w = torch.matmul(query, key.transpose(-1, -2)) / dk # w 形状 N,H,S,Sif self.is_mask:"""生成掩码"""mask = torch.tril(torch.ones(w.shape[-1], w.shape[-1])).to(w.device)w = w * mask - 1e10 * (1 - mask)w = torch.softmax(w, dim=-1) # softmax归一化attention = torch.matmul(w, value) # 各个向量根据得分合并合并, 形状 N,H,S,V
attention(Q,K,V)=softmax(QKTdk)Vattention(Q, K, V) =softmax(\frac{QK^{T}}{\sqrt{d_{k}}})V attention(Q,K,V)=softmax(dk
根据上式计算,得到attention
其中在做注意力的时候,对其加掩码的时候,是w = w * mask - 1e10 * (1 - mask)
操作的。
主要是因为,在做softmax的时候,避免出现问题。对需要屏蔽的区域,应对其置为零,而且不影响其他位的softmax操纵,则应该的数值为负无穷。
最后变换形状,合并多头的结果,输出。完整代码如下:
class SelfAttention(nn.Module):r"""多头自注意力Args:embed_dim: 词向量的特征数。num_head: 多头注意力的头数。is_mask: 是否添加掩码。是,则网络只能看到每个词前的内容,而无法看到后面的内容。Shape:- Input: N,S,V (批次,序列数,词向量特征数)- Output:和输入同样的形状Examples::# >>> m = SelfAttention(720, 12)# >>> x = torch.randn(4, 13, 720)# >>> output = m(x)# >>> print(output.shape)# torch.Size([4, 13, 720])"""def __init__(self, embed_dim, num_head, is_mask=True):super(SelfAttention, self).__init__()assert embed_dim % num_head == 0self.num_head = num_headself.is_mask = is_maskself.linear1 = nn.Linear(embed_dim, 3 * embed_dim)self.linear2 = nn.Linear(embed_dim, embed_dim)def forward(self, x):x = self.linear1(x)n, s, v = x.shapex = x.reshape(n, s, self.num_head, -1)x = torch.transpose(x, 1, 2)query, key, value = torch.chunk(x, 3, -1)dk = value.shape[-1] ** 0.5w = torch.matmul(query, key.transpose(-1, -2)) / dkif self.is_mask:mask = torch.tril(torch.ones(w.shape[-1], w.shape[-1])).to(w.device)w = w * mask - 1e10 * (1 - mask)w = torch.softmax(w, dim=-1)attention = torch.matmul(w, value)attention = attention.permute(0, 2, 1, 3)n, s, h, v = attention.shapeattention = attention.reshape(n, s, h * v)return self.linear2(attention)
值得注意的是,这里的所有网络层,都是线性的,未加激活。
5.5、GPT2网络模型的解码器块
GPT2的一个基本单元见上图所示。
class Block(nn.Module):def __init__(self, embed_dim, num_head, is_mask):super(Block, self).__init__()self.ln_1 = nn.LayerNorm(embed_dim)self.attention = SelfAttention(embed_dim, num_head, is_mask)self.ln_2 = nn.LayerNorm(embed_dim)self.feed_forward = nn.Sequential(nn.Linear(embed_dim, embed_dim * 4),nn.GELU(),nn.Linear(embed_dim * 4, embed_dim))def forward(self, x):pass
同样构建这样的一个类。在实例化它的时候,应该有这三个参数,词向量的维度,多头注意力的头数,注意力时是否使用掩码。
同时定义出上图所示的,多头自注意力结构,两层层归一化结构,和一个前馈网络。
值得注意的是,该块的网络使用的是GELU激活。GELU在激活中引入了随机正则的思想,是一种对神经元输入的概率描述,直观上更符合自然的认识。
表达式如下:
GELU(x)=xP(X<=x)=xΦ(x)GELU(x)=xP(X<=x)=xΦ(x) GELU(x)=xP(X<=x)=xΦ(x)
这里Φ(x)\Phi(x)Φ(x)是正太分布的概率函数
然后根据计算流程,写出forward方法:
class Block(nn.Module):def __init__(self, embed_dim, num_head, is_mask):super(Block, self).__init__()'''......'''def forward(self, x):'''计算多头自注意力'''attention = self.attention(x)'''残差'''x = attention + xx = self.ln_1(x)'''计算feed forward部分'''h = self.feed_forward(x)x = h + x # 残差计算return self.ln_2(x)
完成总的块定义如下:
class Block(nn.Module):r"""GPT2块Args:embed_dim: 词向量的特征数。num_head: 多头注意力的头数。is_mask: 是否添加掩码。是,则网络只能看到每个词前的内容,而无法看到后面的内容。Shape:- Input: N,S,V (批次,序列数,词向量特征数)- Output:same shape as the inputExamples::# >>> m = Block(720, 12)# >>> x = torch.randn(4, 13, 720)# >>> output = m(x)# >>> print(output.shape)# torch.Size([4, 13, 720])"""def __init__(self, embed_dim, num_head, is_mask):super(Block, self).__init__()self.ln_1 = nn.LayerNorm(embed_dim)self.attention = SelfAttention(embed_dim, num_head, is_mask)self.ln_2 = nn.LayerNorm(embed_dim)self.feed_forward = nn.Sequential(nn.Linear(embed_dim, embed_dim * 4),nn.GELU(),nn.Linear(embed_dim * 4, embed_dim))def forward(self, x):attention = self.attention(x)x = attention + xx = self.ln_1(x)h = self.feed_forward(x)x = h + xreturn self.ln_2(x)
5.6、GPT2网络模型
于是由上构建出
class GPT2(nn.Module):r"""GPT2网咯模型Args:num_vocab:词库的个数embed_dim:词向量的特征数num_position:支持最大输出序列数num_block=12:解码器块的个数num_head=12:多头注意力的头数is_mask:注意力是否添加掩码Shape:- Input:N,Sinput_ids:输入文本的每个词的编码值position_ids:每个词的位置编码值- Output:预测的值,N,S,CExamples::# >>> m = GPT2(5000, 720, 1024)# >>> input_ids = input_ids = torch.randint(low=0, high=5000,size=(2,1024),dtype=torch.long)# >>> position_ids = torch.arange(0,input_ids.shape[-1])# >>> output = m(input_ids,position_ids)# >>> print(output.shape)# torch.Size([2, 1024, 5000])"""def __init__(self, num_vocab, embed_dim, num_position, num_block=12, num_head=12, is_mask=True):super(GPT2, self).__init__()'''构建词编码'''self.vocab = nn.Embedding(num_vocab, embed_dim)'''构建位置编码'''self.position = nn.Embedding(num_position, embed_dim)'''构建网络层'''blocks = []for i in range(num_block):blocks.append(Block(embed_dim, num_head, is_mask))self.net = nn.Sequential(*blocks)'''构建最后的输出层,分类层'''self.out_layer = nn.Linear(embed_dim, num_vocab)def forward(self, input_ids, position_ids):e = self.vocab(input_ids) # 取得词向量p = self.position(position_ids) # 取得位置向量h = self.net(e + p) # 输入网络return self.out_layer(h) # 由输出层输出
5.7、模芯的训练
首先考虑的是数据如何输入的问题。
以斗破苍穹为例:
首先是统计一共有那些字,和符号。符号也同样可以作为字输入网络。网络是可以学习这些标点符号的。
得到上图这样的文字,文件为vocab.txt。前五个字符是作为特殊字符处理的。
让后在通过这样的字典将我们文章进行编码。
斗破苍穹小说就变成了上图所示的样子,文件保存为token.txt。每一个数字对应的都是在vocab中的字的位置。
那么如何将文章加载进网络呢?
class MyDataset(Dataset):def __init__(self):self.dataset = []"""将每一句话都加载进入self.dataset中存放"""def __len__(self):return len(self.dataset)def __getitem__(self, index):data = torch.tensor(self.dataset[index])'''取出一句话''''''x为data[0:-1],不包含追后一个字,y为data[1:],不包含最后一个字。'''return data[0:-1], data[1:]
训练的过程中,一句话有n个字,那么就是让网络,输入前n-1个字,然后预测后n-1个字。
position_ids = torch.arange(0,x.shape[-1])
_y = m(x, position_ids ).reshape(-1, embed_dim)
y = y.reshape(-1)
loss = F.cross_entropy(_y, y)
如此计算损失进行优化。
5.8、网络的使用
y = net(x, p)
y = y[:, -1:]
# 所有字中,选概率最大的10个
v, y = torch.topk(y, 10, dim=int(-1))
v, y = v.reshape(-1, 10), y.reshape(-1, 10)
# 在8个候选字中通过概率去选一个, 增加文章的随机性
v = torch.multinomial(torch.softmax(v, dim=-1), 1)
在输入网络后,得到向量,选择概率最大的若干个,通过概率来选择。
如果只是选择概率最大的一个,会出现问题-----就像如果持续点击输入法推荐单词的第一个,它可能会陷入推荐同一个词的循环中,只有你点击第二或第三个推荐词,才能跳出这种循环。同样的,GPT-2 也有一个叫做「top-k」的参数,模型会从概率前 k 大的单词中抽样选取下一个单词。显然,在之前的情况下,top-k = 最好不要设置为1。
然后将现在得到的话继续输入网络中,得到下一个字。直到输出的字符是end为止。
5.9、训练效果
给网络先看两个字,让后让他直接写:
输入
萧炎喷出一口老血
得到输出:
萧炎喷出一口老血液往其喉咙,最后凝成一枚拳头大小。
这一招,无疑并没有令得范痨的形状,在体内若隐若现的血腥气似乎随时都会如此反复,后者也是会颇为心急速下来,但是地魔老鬼与那凶悍仅仅只能与其勉强办到的两者抗衡一拳。几乎他这个令人极为的女人产生相互,若是稍稍稍出现差一点差错。定要一些感到极为不择手忙脚乱。
身体轻轻颤,浓郁的血色能量似乎随随随意的挥动,似乎没有丝毫的迟疑,毕竟在能量膜之中不断的爆发出强横能量压压,偶尔有着连退缩的趋势,仅仅十几米不到距离的距离时,还逃得飞速,甚至是连空间都出现了一些痕迹,虽然先前那便短暂的接触者,可那头余斯只能炼制到高空尽头的萧炎,也是完全被撕裂了一些,而且,当空地都是在此刻在某一处,经过白日的那番大战后,损失惨重,这才成为真正的完全的一面攻,将三名斗皇强者拦住。
望着场中突然间变化的萧炎,范痨手一挥,一股雄浑斗气匹练猛然自其手掌中暴涌而出,然后狠狠的击打在手掌之上,顿时,一道惊天斗气匹练直接轰击而出,旋即手臂一抖,便是极为刁钻的对着萧炎裂缝隙击而去,最后嘭的一声,犹如擎天之地般,爆炸响,噼里啪啦的扩散在场中响了脑袋一般。
“破!”
微眯着双眼望着如同针刺般在自能量膜的萧炎影人影,范痨阴冷一笑,手中长剑,顿时爆发出极准的锵锵音响,声音盘在空中,将近百人几乎全部都是猛的反应了起来。
淡淡的瞥着场地之上近十几米,萧炎略微一怔,一些体内流亡的人长剑不由得多抽搐一阵抽搐,这些人类形类型的斗气大别,想要攻击杀连接周围的防御,怕是不可能的。
在萧炎手中两项斗技之后,范痨背着一对淡淡青色斗气双翼缓缓扇动,身体犹如风旋一般在范痨即将猛然暴增的几丈猛然一距离,顿时,尖锐的劲风在身后响起,犹如风暴一般,铺天盖地的对着萧炎暴射而去。
突如其来的攻击令,让得萧炎身体几乎是同时刻间变得明白了许多,而就在先前一拳之际,双方,那对巨大的阴影,却依然是让得其后出现了一条长长的深渊
在萧炎心中暗叫着失败与死之时,范痨也是诡异浮现,身形闪动间,目光阴寒的望着天空上的萧炎,嘴巴短了一下,便是收拳之不及,身形闪掠到范痨身后,手中重尺再度一握,身体犹如落地的黑球一般,猛然一抖,顿时,凶悍无匹的劲风铺天盖地的暴涌而出,足以令得他措手不及防御。
“停下了范痨的命,还有何人?!”
范痨手臂陡变化,厉喝道,在雄浑斗气的交锋处半空,犹如交接的波荡在一起一般。
“嘭!”
怖的暗劲犹如无形空的炮弹一般急速蔓延而出,将附近的一朵早已初得接触的强猛劲力轰得清虚弱,那正在接触萧炎的柳擎以及呼吸停滞的柳擎,都是在这一霎覆盖了下去,好强烈的劲风,反反而是被压得仅仅如一个弯,显然,因为力量的对碰,又是增强了上下去。
深入浅出自然语义处理原理并构建自然语义处理(NLP)模型GPT2相关推荐
- 深入浅出 Laravel 路由执行原理
本文首发于「深入浅出 Laravel 路由执行原理」,转载请注明出处. 这篇文章我们将学习 Laravel 项目中一个很重要的主题 --「路由」. 可以说几乎所有的框架都会涉及到「路由」的处理,简单一 ...
- 深入浅出图神经网络|GNN原理解析☄学习笔记(四)表示学习
深入浅出图神经网络|GNN原理解析☄学习笔记(四)表示学习 文章目录 深入浅出图神经网络|GNN原理解析☄学习笔记(四)表示学习 表示学习 表示学习的意义 离散表示与分布式表示 端到端学习 基于重构损 ...
- HDMapNet:高精度语义地图的动态构建
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 编辑丨算法邦 今天和大家分享工作的是自动驾驶中高精度语义地图的动态构建.内容主要是解读我们组最新的论文 ...
- 深入浅出,ARCore开发原理 1
作者:李超 前"跟谁学"直播研发高级经理 原文:深入浅出,ARCore开发原理 - SegmentFault 思否 其实关注 ARCore也蛮久了,但一直没有腾出时间来写个总结.正 ...
- 自然辩证法与计算机科学与技术,自然辩证法和科学技术有什么关系
自然辨证法在科学技术的具体学科和马克思主义哲学的普遍原理之间,是处于一种中间的位置.正是由于自然辩证法自身特殊的位置,与其他哲学相比,它和自然科学的关系更值得研究.自然辨证法是马克思主义的重要组成部分 ...
- python原理书籍_python书籍推荐:《深入浅出深度学习:原理剖析与Python实践》
在过去的这十年,深度学习已经席卷了整个科技界和工业界,2016年谷歌阿尔法狗打败围棋世界冠军李世石,更是使其成为备受瞩目的技术焦点. 今日,小编就为大家推荐一本能让初学者和"老司机" ...
- php获取当前日期所在自然周周一周末以及前后自然周始末
php获取当前日期所在自然周周一周末以及前后自然周始末 首先,获取当前时间,date函数,方法较多,展示一种: $present = date('y-m-d',time());//当前日期 然后获取当 ...
- 赫夫曼树的原理和构建
赫夫曼树的原理和构建 1. 赫夫曼树的构造 给定N个权值分别为w1, w2, -, Wn的节点.构造赫夫曼树的算法描述如下: 1)将这N个结点分别作为N棵树仅含一个结点的二叉树,构成森林F. ...
- 图像语义分割原理及常用方法
1图像语义分割的概念 1.1图像语义分割的概念与原理 图像语义分割可以说是图像理解的基石性技术,在自动驾驶系统(具体为街景识别与理解).无人机应用(着陆点判断)以及穿戴式设备应用中举足轻重.我们都知道 ...
最新文章
- Spring @Resource、@Autowired、@Qualifier区别
- 阿里云主机安装Memcached扩展优化WordPress
- cron表达式详解 Elastic-Job名次解释
- Linux下ctrl+c,ctrl+z,ctrl+d的区别
- 达尔豪西大学 计算机科学,达尔豪西大学计算机科学硕士专业.pdf
- akoj-1153-p次方求和
- Android Service被系统回收的解决方法
- 微博机器学习平台架构及在微博推荐中的应用
- 软件测试必读的七本书
- Scaled Exponential Linear Unit
- JavaScript小数运算出现多位的解决办法
- php高级编程 薛忠胜_2019年,最值得学习的编程语言是?
- Jsp Layout 布局页
- 皮尔逊相关系数和斯皮尔曼相关系数
- DM8整合java的jpa框架(附整合源码)
- javascript计算两个时间差
- 解决ueditor编辑器图片在线管理图片无法显示
- mall-swarm微服务商城系统
- GPIO口 多引脚操作
- 如何创建一个 react 项目及如何运行?