自然语言处理: 第七章GPT的搭建

这篇具有很好参考价值的文章主要介绍了自然语言处理: 第七章GPT的搭建。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

自然语言处理: 第七章GPT的搭建

理论基础

在以transformer架构为框架的大模型遍地开花后,大模型的方向基本分成了三类分别是:

  • decoder-only架构 , 其中以GPT系列为代表
  • encoder-only架构,其中以BERT系列为代表
  • encoder-decoder架构,标准的transformer架构以BART和T5为代表

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能

大模型的使用方法如下: 分解成pre-train 和fine-tuning ,其中pre-train是收集大量的高质量的文本(或者其他多模态的输入)去让模型拥有文本理解的泛化能力,而fine-tuing则是对应各自的下游任务将pre-train好的model在下游任务中作微调,从而适应不同的任务头。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能



那么为什么基于transformer的架构为什么需要可以分成上面的三个分支呢?除了最基本的encoder-decoder架构,这种能普遍处理好各种任务外,那么decoder-only 和 encoder-only的区别在哪?下面以BERT和GPT为代表来分别解释这两种架构的代表,而其中最主要的区别就是二者的预训练目标的区别: 我们由之前Seq2Seq的模型知道,

  • BERT全称是Bidirectional Encoder Representation from Transformers,可以看到它是一个双向的模型,而编码器的作用主要是将输入的全部文本信息压缩至一个定长的向量,然后再给下游任务作fine_tuning,所以BERT这种Encoder-only的架构的预训练任务更像是一个填空题,以下图的例子为例,BERT的任务就是给一个完整的文本, 一(二)三四五,上山(打)老虎,需要去预测括号里的内容,而且BERT本身是一个双向的网络,所以在预测括号里的内容时候,他是已经看过全文的,所以这种encoder-only的架构它更具有推理和理解上下文的能力,所以用来做文本分类,关系抽取与命名实体识别的任务有更好的效果,这种预训练的模式叫做MLM(masked language model)。
  • 而GPT作为decoder-only,它拥有更好的文本生成能力,它的预训练任务就更加贴合我们传统理解的NLP任务,同样如下图的例子,GPT的预训练过程是老虎没打到,(抓到小松鼠),通过上文去预测下文,所以它是一个单向的,也就是更像一个问答题,所以它具有更好的文本生成能力所以就更适合用来作聊天机器人。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能




因此,GPT的生成式预训练如,内容如下: 输入是上文,输出是下文,并且是单向的decoder结构,所以相比于传统的transformer结构,GPT结构更加的轻量了。除此之外还需要注意的是,在训练阶段由于保证运行效率,直接就由文本在前端加一个 <sos>, 但是在inference阶段需要没生成一个字,连同之前的上文一起再输入给下一次作为输入。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能




因此这种decorder-only的结构,除了去除了encoder结构之外,自身的decoder基本跟transfor的decoder结构一致,但是去掉了encoder-decoder的self-attention这部分,transformer基本的结构可以参考上文第六章Transformer- 现代大模型的基石: 分解的结构如下图:

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能




还有一种解释是是从对模型的期望来解释BERT 和GPT的区别,根据前文我们可以知道BERT的预训练的模式是作填空题,所以它本身并不具备生成文字内容的能力,但是它具有更好的理解上下文的能力,所以对应不同的任务,只需要BERT + Head(任务头) 就可以针对不同的任务,所以这就导致了BERT更适合成为专才。而GPT由于预训练是做的问答题,而其实所有的NLP任务都可以看成是问答的任务,比如说机器翻译,你只要给GPT下一个prompt 请帮我将下列句子翻译成英文这样GPT就可以翻译成英文了。对于其他任务也是一样的,只需要下对应的prompt,所以GPT是更像一个通才,无需加单独的任务头,便可以完成不同的任务。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能

代码实现

1. 多头注意力

class ScaledDotProductAttention(nn.Module):
    def __init__(self):
        super(ScaledDotProductAttention, self).__init__()  
    def forward(self, Q, K, V, attn_mask):  
        # Q K V [batch_size, n_heads, len_q/k/v, dim_q=k/v] (dim_q=dim_k)
        # 计算注意力分数(原始权重)[batch_size,n_heads,len_q,len_k]
        scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) 
        # 使用注意力掩码,将attn_mask中值为1的位置的权重替换为极小值
        # attn_mask [batch_size,n_heads,len_q,len_k],形状和scores相同
        scores.masked_fill_(attn_mask.to(torch.bool), -1e9) 
        # 对注意力分数进行softmax
        weights = nn.Softmax(dim=-1)(scores)
        # 计算上下文向量(也就是注意力的输出), 是上下文信息的紧凑表示
        context = torch.matmul(weights, V)
        return context, weights # 返回上下文向量和注意力分数
  
# 定义多头注意力类
d_embedding = 512  # Embedding Size
n_heads = 8  # number of heads in Multi-Head Attention
batch_size = 3 # 每一批数据量
class MultiHeadAttention(nn.Module):
    def __init__(self):
        super(MultiHeadAttention, self).__init__()
        self.W_Q = nn.Linear(d_embedding, d_k * n_heads) # Q的线性变换层
        self.W_K = nn.Linear(d_embedding, d_k * n_heads) # K的线性变换层
        self.W_V = nn.Linear(d_embedding, d_v * n_heads) # V的线性变换层
        self.linear = nn.Linear(n_heads * d_v, d_embedding)
        self.layer_norm = nn.LayerNorm(d_embedding)

    def forward(self, Q, K, V, attn_mask): 
        # Q K V [batch_size,len_q/k/v,embedding_dim]  
        residual, batch_size = Q, Q.size(0) # 保留残差连接
        # 将输入进行线性变换和重塑,以便后续处理
        # q_s k_s v_s: [batch_size,n_heads.,len_q/k/v,d_q=k/v]
        q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2)  
        k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2)
        v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2)
        # 将注意力掩码复制到多头 [batch_size,n_heads,len_q,len_k]
        attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1)
        # 使用缩放点积注意力计算上下文和注意力权重
        context, weights = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
        # 重塑上下文向量并进行线性变换,[batch_size,len_q,n_heads * dim_v]
        context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) 
        output = self.linear(context)
        # 与输入(Q)进行残差链接,并进行层归一化后输出[batch_size, len_q, embedding_dim]
        output = self.layer_norm(output + residual)
        return output, weights # 返回层归一化的输出和注意力权重

2. 逐位置前馈网络

# 定义逐位置前向传播网络类
class PoswiseFeedForwardNet(nn.Module):
    def __init__(self):
        super(PoswiseFeedForwardNet, self).__init__()
        # 定义一维卷积层1,用于将输入映射到更高维度
        self.conv1 = nn.Conv1d(in_channels=d_embedding, out_channels=2048, kernel_size=1)
        # 定义一维卷积层2,用于将输入映射回原始维度
        self.conv2 = nn.Conv1d(in_channels=2048, out_channels=d_embedding, kernel_size=1)
        # 定义层归一化
        self.layer_norm = nn.LayerNorm(d_embedding)

    def forward(self, inputs): 
        # inputs: [batch_size, len_q, embedding_dim]  
        residual = inputs  # 保留残差连接
        # 在卷积层1后使用ReLU激活函数
        output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))
        # 使用卷积层2进行降维
        output = self.conv2(output).transpose(1, 2)
        # 与输入进行残差链接,并进行层归一化,[batch_size, len_q, embedding_dim]
        output = self.layer_norm(output + residual)
        return output # 返回层归一化后的输出加上残差连接的结果

3. 正弦位置编码表

def get_sin_enc_table(n_position, embedding_dim):
    # 根据位置和维度信息,初始化正弦位置编码表
    sinusoid_table = np.zeros((n_position, embedding_dim))  
    # 遍历所有位置和维度,计算角度值
    for pos_i in range(n_position):
        for hid_j in range(embedding_dim):
            angle = pos_i / np.power(10000, 2 * (hid_j // 2) / embedding_dim)
            sinusoid_table[pos_i, hid_j] = angle  
    # 计算正弦和余弦值
    sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  # dim 2i 偶数维
    sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2])  # dim 2i+1 奇数维  
    return torch.FloatTensor(sinusoid_table)

4. 填充位置掩码

# 生成填充注意力掩码的函数,用于在多头自注意力计算中忽略填充部分
def get_attn_pad_mask(seq_q, seq_k):
    batch_size, len_q = seq_q.size()
    batch_size, len_k = seq_k.size()
    # 生成布尔类型张量[batch_size,1,len_k(=len_q)]
    pad_attn_mask = seq_k.data.eq(0).unsqueeze(1)  #<PAD> Token的编码值为0 
    # 变形为何注意力分数相同形状的张量 [batch_size,len_q,len_k]
    pad_attn_mask = pad_attn_mask.expand(batch_size, len_q, len_k) 
    return pad_attn_mask # 形状[batch_size,len_q,len_k]

5. 后续位置掩码

# 生成后续注意力掩码的函数,用于在多头自注意力计算中忽略未来信息
def get_attn_subsequent_mask(seq):
    # 获取输入序列的形状 [batch_size, seq_len(len_q), seq_len(len_k)]
    attn_shape = [seq.size(0), seq.size(1), seq.size(1)]
    # 使用numpy创建一个上三角矩阵(triu = triangle upper)
    subsequent_mask = np.triu(np.ones(attn_shape), k=1)
    # 将numpy数组转换为PyTorch张量,并将数据类型设置为byte(布尔值)
    subsequent_mask = torch.from_numpy(subsequent_mask).byte()
    return subsequent_mask # [batch_size, seq_len(len_q), seq_len(len_k)]

6. 解码器

# 构建解码器层
class DecoderLayer(nn.Module):
    def __init__(self):
        super(DecoderLayer, self).__init__()
        self.self_attn = MultiHeadAttention()  # 多头自注意力层
        self.feed_forward = PoswiseFeedForwardNet()  # 位置前馈神经网络层
        self.norm1 = nn.LayerNorm(d_embedding)  # 第一个层归一化
        self.norm2 = nn.LayerNorm(d_embedding)  # 第二个层归一化

    def forward(self, dec_inputs, attn_mask=None):
        # 使用多头自注意力处理输入
        attn_output, _ = self.self_attn(dec_inputs, dec_inputs, dec_inputs, attn_mask)
        # 将注意力输出与输入相加并进行第一个层归一化
        norm1_outputs = self.norm1(dec_inputs + attn_output)
        # 将归一化后的输出输入到位置前馈神经网络
        ff_outputs = self.feed_forward(norm1_outputs)
        # 将前馈神经网络输出与第一次归一化后的输出相加并进行第二个层归一化
        dec_outputs = self.norm2(norm1_outputs + ff_outputs)
        return dec_outputs
  
# 构建解码器
n_layers = 6  # 设置Encoder/Decoder的层数
class Decoder(nn.Module):
    def __init__(self, corpus):
        super(Decoder, self).__init__()
        self.src_emb = nn.Embedding(corpus.vocab_size, d_embedding)  # 词嵌入层(参数为词典维度)
        self.pos_emb = nn.Embedding(corpus.seq_len, d_embedding)  # 位置编码层(参数为序列长度)  
        self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)]) # 初始化N个解码器层

    def forward(self, dec_inputs):  
        positions = torch.arange(len(dec_inputs), device=dec_inputs.device).unsqueeze(-1) # 位置信息  
        inputs_embedding = self.src_emb(dec_inputs) + self.pos_emb(positions) # 词嵌入与位置编码相加  
        attn_mask = get_attn_subsequent_mask(inputs_embedding).to(dec_inputs.device) # 生成自注意力掩码
        dec_outputs =  inputs_embedding # 初始化解码器输入,这是第一层解码器层的输入  
        for layer in self.layers:
            # 每个解码器层接收前一层的输出作为输入,并生成新的输出
            # 对于第一层解码器层,其输入是dec_outputs,即词嵌入和位置编码的和
            # 对于后续的解码器层,其输入是前一层解码器层的输出  
            dec_outputs = layer(dec_outputs, attn_mask) # 将输入数据传递给解码器层
        return dec_outputs # 返回最后一个解码器层的输出,作为整个解码器的输出

7. GPT

class GPT(nn.Module):
    def __init__(self, corpus):
        super(GPT, self).__init__()
        self.corpus = corpus
        self.decoder = Decoder(corpus) # 解码器,用于学习文本生成能力
        self.projection = nn.Linear(d_embedding, corpus.vocab_size)  # 全连接层,输出预测结果

    def forward(self, dec_inputs):  
        dec_outputs = self.decoder(dec_inputs) # 将输入数据传递给解码器
        logits = self.projection(dec_outputs) # 传递给全连接层以生成预测
        return logits #返回预测结果
  
    def decode(self, input_str, strategy='greedy', **kwargs):
        if strategy == 'greedy': # 贪心解码函数
            return generate_text_greedy_search(self, input_str, **kwargs)
        elif strategy == 'beam_search': # 集束解码函数
            return generate_text_beam_search(self, input_str, **kwargs)
        else:
            raise ValueError(f"Unknown decoding strategy: {strategy}")

8. Greedy_search & Beam_search

def generate_text_beam_search(model, input_str, max_len=5, beam_width=5, repetition_penalty=1.2):
    # 将模型设置为评估(测试)模式,关闭dropout和batch normalization等训练相关的层
    model.eval()
    # 让NLTK工具帮忙分一下词
    input_str = word_tokenize(input_str)
    # 将输入字符串中的每个token转换为其在词汇表中的索引, 如果输入的词不再词表里面,就忽略这个词
    input_tokens = [model.corpus.vocab[token] for token in input_str if token in model.corpus.vocab]
    # 检查输入的有意义的词汇长度是否为0
    if len(input_tokens) == 0:
        return   
    # 创建一个列表,用于存储候选序列,初始候选序列只包含输入tokens
    candidates = [(input_tokens, 0.0)]  
    # 创建一个列表,用于存储所有生成的序列及其得分
    final_results = []
    # 禁用梯度计算,以节省内存并加速测试过程
    with torch.no_grad():
        # 生成最多max_len个tokens
        for _ in range(max_len):
            # 创建一个新的候选列表,用于存储当前时间步生成的候选序列
            new_candidates = []    
            # 遍历当前候选序列
            for candidate, candidate_score in candidates:
                # 将当前候选序列转换为torch张量并将其传递给模型
                device = "cuda" if torch.cuda.is_available() else "cpu"
                inputs = torch.LongTensor(candidate).unsqueeze(0).to(device)
                outputs = model(inputs)        
                # 只关心最后一个时间步(即最新生成的token)的logits
                logits = outputs[:, -1, :]
                # 应用重复惩罚:为已经生成的词汇应用惩罚,降低它们再次被选择的概率
                for token in set(candidate):
                    logits[0, token] /= repetition_penalty
                # 将<pad>标记的得分设置为一个很大的负数,以避免选择它
                logits[0, model.corpus.vocab["<pad>"]] = -1e9        
                # 找到具有最高分数的前beam_width个tokens
                scores, next_tokens = torch.topk(logits, beam_width, dim=-1)
                # 遍历生成的tokens及其得分
                for score, next_token in zip(scores.squeeze(), next_tokens.squeeze()):
                    # 将生成的token添加到当前候选序列
                    new_candidate = candidate + [next_token.item()]            
                    # 更新候选序列得分
                    new_score = candidate_score - score.item()            
                    # 如果生成的token是EOS(结束符),将其添加到最终结果中
                    if next_token.item() == model.corpus.vocab["<eos>"]:
                        final_results.append((new_candidate, new_score))
                    else:
                        # 将新生成的候选序列添加到新候选列表中
                        new_candidates.append((new_candidate, new_score))
            # 从新候选列表中选择得分最高的beam_width个序列
            candidates = sorted(new_candidates, key=lambda x: x[1], reverse=True)[:beam_width]
    # 选择得分最高的候选序列,如果final_results为空,选择当前得分最高的候选序列
    if final_results:
        best_candidate, _ = sorted(final_results, key=lambda x: x[1])[0]
    else:
        best_candidate, _ = sorted(candidates, key=lambda x: x[1])[0]
    # 将输出 token 转换回文本字符串
    output_str = " ".join([model.corpus.idx2word[token] for token in best_candidate])
    return output_str

def generate_text_greedy_search(model, input_str, max_len=5):
    # 将模型设置为评估(测试)模式,关闭dropout和batch normalization等训练相关的层
    model.eval()
    # 使用NLTK工具进行词汇切分
    input_str = word_tokenize(input_str)
    # 将输入字符串中的每个token转换为其在词汇表中的索引, 如果输入的词不在词表里面,就忽略这个词
    input_tokens = [model.corpus.vocab[token] for token in input_str if token in model.corpus.vocab]
    # 检查输入的有意义的词汇长度是否为0
    if len(input_tokens) == 0:
        return   
    # 创建一个列表,用于存储生成的词汇
    output_tokens = input_tokens
    # 禁用梯度计算,以节省内存并加速测试过程
    with torch.no_grad():
        # 生成最多max_len个tokens
        for _ in range(max_len):
            # 将当前生成的tokens转换为torch张量并将其传递给模型
            device = "cuda" if torch.cuda.is_available() else "cpu"
            inputs = torch.LongTensor(output_tokens).unsqueeze(0).to(device)
            outputs = model(inputs)        
            # 只关心最后一个时间步(即最新生成的token)的logits
            logits = outputs[:, -1, :]
            # 找到具有最高分数的token
            _, next_token = torch.topk(logits, 1, dim=-1)
            # 如果生成的token是EOS(结束符),则停止生成
            if next_token.item() == model.corpus.vocab["<eos>"]:
                break
            # 否则,将生成的token添加到生成的词汇列表中
            output_tokens.append(next_token.item())
    # 将输出 tokens 转换回文本字符串
    output_str = " ".join([model.corpus.idx2word[token] for token in output_tokens])
    return output_str



结果

本次实验设置了三个对照组,分别是baseline(N_head = 8 , n_layer = 6), N_head = 32 , n_layer = 18,可以看到训练10000个step之后得loss分别如下图:

从收敛程度上来看,18层layer得transformer 完全没有收敛,这个可能是因为深度神经网络的梯度消失,所以我们设置的网络如果没有残差链接的话,尽量不要太深。然后再看多头,可以看到头的数量好像也不是越多越好,但是其实二者都收敛了,具体结果我们可以结合一下inference的结果看看。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能
自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能
自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能


可以看到两种解码得方式,greedy_search在大部分时候由于设置了惩罚项所以现在大部分时候是两个单词无限循环,相比之下beam_search得结果就好得多,更像一句话。

其次对比一下三个对照组得结果,正如loss的结果一样,深层次GPT架构无论是beam_search还是greedy_search翻译的结果都非常的差,出现了很多标点,这应该就是没有收敛的结果。然后对比下不同的head数量,这里看上去也是n_head越少的效果越好。

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能

自然语言处理: 第七章GPT的搭建,自然语言处理,自然语言处理,gpt,人工智能文章来源地址https://www.toymoban.com/news/detail-636628.html

到了这里,关于自然语言处理: 第七章GPT的搭建的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 『C语言初阶』第七章 -初识指针

    🔥 博客主页 : 小羊失眠啦. 🔖 系列专栏 : C语言 🌥️ 每日语录 : 苦难是化了妆的祝福。 ❤️ 感谢大家点赞👍收藏⭐评论✍️ 时隔多日小羊又来给铁汁们更新C语言之初识指针,指针是C语言中一个关键且强大的概念,理解和掌握指针对于编写高效、灵活的程序至关重要

    2024年02月13日
    浏览(38)
  • 第七章 C语言语句的机器级表示

    2023年04月12日
    浏览(55)
  • 【鸿蒙开发】第七章 ArkTS语言UI范式-基础语法

    通过前面的章节,我们基本清楚鸿蒙应用开发用到的语言和项目基本结构,在【鸿蒙开发】第四章 Stage应用模型及项目结构也提到过ArkTS的UI范式的 基本语法 、 状态管理 、 渲染控制 等能力,简要介绍如下: 基本语法 : ArkTS 定义了 声明式UI描述 、 自定义组件 和 动态扩展

    2024年02月03日
    浏览(64)
  • 基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理

    Transformer正在颠覆AI领域。市面上有这么平台和Transformer模型。本书将引导你使用Hugging Face从头开始预训练一个RoBERTa模型,包括构建数据集、定义数据整理器以及训练模型等。将引领你进入Transformer的世界,将讲述不同模型和平台的优势,指出如何消除模型的缺点和问题。 《基

    2024年02月03日
    浏览(67)
  • 图像处理与计算机视觉--第七章-神经网络-单层感知器

      下图是一个简单的感知器模型图:                 在输出层的每一个节点上接受来自输入层的加权和作为输出层的净输入如下所示: n e t j ′ = ∑ i = 1 n w i j x i mathrm{net}_{j}^{prime}=sum_{i=1}^{n}w_{ij}x_{i} net j ′ ​ = i = 1 ∑ n ​ w ij ​ x i ​ 输出的值由激活

    2024年02月06日
    浏览(39)
  • Transformer、BERT和GPT 自然语言处理领域的重要模型

    Transformer、BERT和GPT都是自然语言处理领域的重要模型,它们之间有一些区别和联系。 区别: 架构:Transformer是一种基于自注意力机制的神经网络架构,用于编码输入序列和解码输出序列。BERT(Bidirectional Encoder Representations from Transformers)是基于Transformer架构的双向编码模型,

    2024年03月09日
    浏览(57)
  • 解析GPT-3、GPT-4和ChatGPT关系-迈向自然语言处理的新高度“

    Hello,小索奇!很高兴为你拓展关于GPT-3、GPT-4、ChatGPT之间关系的信息,以及解释自然语言模型和Transformer的区别。 首先,GPT-3、GPT-4、ChatGPT都是建立在GPT系列技术基础上的自然语言处理模型。它们在不同的代数、性能和应用场景下展现了自然语言处理领域的不断发展。 GPT是生

    2024年01月25日
    浏览(55)
  • GPT-3和自然语言处理的前沿:思考AI大模型的发展

    自然语言处理(NLP)是人工智能(AI)领域中最富有挑战性和活跃的研究领域之一。近年来,随着深度学习技术的发展和计算能力的提高,大型语言模型,尤其是OpenAI的GPT-3,已成为推动该领域进步的核心力量。本文将详细探讨GPT-3模型的架构、应用和对NLP的影响,同时思考

    2024年04月24日
    浏览(76)
  • 《自然语言处理(NLP)的最新进展:Transformers与GPT-4的浅析》

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月08日
    浏览(53)
  • (数字图像处理MATLAB+Python)第七章图像锐化-第三节:高斯滤波与边缘检测

    高斯函数 :是一种常见的连续函数,通常用符号 G ( x ) G(x) G ( x ) 表示。它可以用下面的公式定义 G ( x ) = 1 σ 2 π e − x 2 2 σ 2 G(x)=frac{1}{sigma sqrt{ 2pi }}e^{-frac{x^{2}}{2sigma^{2}}} G ( x ) = σ 2 π ​ 1 ​ e − 2 σ 2 x 2 ​ 其中, x x x 是自变量, σ sigma σ 是一个正实数,表示高斯函

    2024年02月06日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包