手撕Transformer!!从每一模块原理讲解到代码实现【超详细!】

news2024/11/19 0:34:58

文章目录

    • 一、位置编码
      • 位置编码的原理
      • 代码解释
    • 二、多头注意力
    • 三、前馈神经网络(FeedForward)和层归一化(NormLayer)
      • FeedForward 模块
        • 代码解析
      • NormLayer 模块
        • 代码解析
    • 四、Encoder
      • Encoder 类
      • EncoderLayer 类
      • 前向传播过程
    • 五、Decoder
      • Decoder 类
      • DecoderLayer 类
      • 前向传播过程
    • 六、Transformer整体框架
    • 参考资料

一、位置编码

位置编码(Positional Encoding)是Transformer模型中的一个重要组成部分,用于在序列数据中引入位置信息。由于Transformer模型本身不具备处理序列顺序的能力(因为它完全基于自注意力机制,没有递归或卷积结构),位置编码的引入使得模型能够利用序列的顺序信息。

位置编码的原理

位置编码通过在输入嵌入向量中添加一个与位置相关的向量来实现。具体来说,对于每个位置 ( pos ) 和每个维度 ( i ),位置编码向量 ( PE(pos, 2i) ) 和 ( PE(pos, 2i+1) ) 分别由以下公式计算:

代码解释

以下是 PositionalEncoder 类的详细解释:

import torch
import torch.nn as nn
import math

class PositionalEncoder(nn.Module):

    def __init__(self, d_model, max_seq_len=80):
        super().__init__()
        self.d_model = d_model
        # 创建一个常量 PE 矩阵
        pe = torch.zeros(max_seq_len, d_model)
        for pos in range(max_seq_len):
            for i in range(0, d_model, 2):
                pe[pos, i] = math.sin(pos / (10000**((2 * i) / d_model)))
                pe[pos, i + 1] = math.cos(pos / (10000**((2 * (i + 1)) / d_model)))
        pe = pe.unsqueeze(0)
        self.register_buffer('pe', pe)

    def forward(self, x):
        # 使得单词嵌入表示相对大一些
        x = x * math.sqrt(self.d_model)
        # 增加位置常量到单词嵌入表示中
        seq_len = x.size(1)
        x = x + self.pe[:, :seq_len]
        return x
  1. 初始化

    • d_model:模型的维度。
    • max_seq_len:序列的最大长度。
    • pe:一个大小为 (max_seq_len, d_model) 的零矩阵,用于存储位置编码。
  2. 计算位置编码

    • 对于每个位置 pos 和每个维度 i,计算 sincos 值,并将其存储在 pe 矩阵中。
    • pe 矩阵通过 unsqueeze(0) 增加一个批次维度,使其形状为 (1, max_seq_len, d_model)
  3. 注册缓冲区

    • self.register_buffer('pe', pe):将 pe 注册为一个缓冲区,这样它会在模型保存和加载时被保存,但不会被优化器更新。
  4. 前向传播

    • x = x * math.sqrt(self.d_model):将输入嵌入向量 x 放大,以确保嵌入向量的值不会被位置编码淹没。
    • x = x + self.pe[:, :seq_len]:将位置编码添加到输入嵌入向量中,其中 seq_len 是输入序列的实际长度。

二、多头注意力

多头注意力机制(Multi-Head Attention)是Transformer模型中的一个关键组件,用于处理序列数据,特别是在自然语言处理任务中。它的主要思想是将输入的查询(Query)、键(Key)和值(Value)通过多个独立的注意力头(Attention Heads)进行处理,然后将这些头的输出拼接起来并通过一个线性层进行整合。这种机制可以捕捉序列中不同位置的多种复杂关系。

以下是对多头注意力机制的详细解释:

  1. 初始化

    • d_model:输入和输出的维度。
    • heads:注意力头的数量。
    • d_k:每个注意力头的维度,计算方式为 d_model // heads
    • 线性层:用于将输入的查询、键和值分别映射到 d_model 维度。
    • 丢弃层(Dropout):用于防止过拟合。
    • 输出线性层:用于将拼接后的多头注意力输出映射回 d_model 维度。
  2. 注意力计算

    • attention 方法计算注意力分数。首先,通过矩阵乘法计算查询和键的点积,然后除以 sqrt(d_k) 进行缩放,以防止梯度消失或爆炸。
    • 如果提供了掩码(mask),则将掩码中为0的位置对应的分数设置为一个非常小的值(如 -1e9),以确保这些位置在softmax后为0。
    • 对分数进行softmax操作,使其成为一个概率分布。
    • 应用丢弃层(Dropout)。
    • 通过矩阵乘法将注意力分数与值相乘,得到加权的值。
  3. 前向传播

    • 对输入的查询、键和值分别进行线性变换,然后重塑为多头形式。
    • 将这些张量进行转置,以便在注意力计算中正确对齐。
    • 调用 attention 方法计算多头注意力。
    • 将多头注意力的输出进行转置和拼接,然后通过输出线性层进行整合。

以下是完整的代码实现:

import torch
import torch.nn as nn
import torch.nn.functional as F
import math

class MultiHeadAttention(nn.Module):

    def __init__(self, heads, d_model, dropout=0.1):
        super().__init__()
        self.d_model = d_model
        self.d_k = d_model // heads
        self.h = heads
        self.q_linear = nn.Linear(d_model, d_model)
        self.v_linear = nn.Linear(d_model, d_model)
        self.k_linear = nn.Linear(d_model, d_model)
        self.dropout = nn.Dropout(dropout)
        self.out = nn.Linear(d_model, d_model)

    def attention(self, q, k, v, d_k, mask=None, dropout=None):
        scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)
        if mask is not None:
            mask = mask.unsqueeze(1)
            scores = scores.masked_fill(mask == 0, -1e9)
        scores = F.softmax(scores, dim=-1)
        if dropout is not None:
            scores = dropout(scores)
        output = torch.matmul(scores, v)
        return output

    def forward(self, q, k, v, mask=None):
        bs = q.size(0)
        k = self.k_linear(k).view(bs, -1, self.h, self.d_k).transpose(1, 2)
        q = self.q_linear(q).view(bs, -1, self.h, self.d_k).transpose(1, 2)
        v = self.v_linear(v).view(bs, -1, self.h, self.d_k).transpose(1, 2)
        scores = self.attention(q, k, v, self.d_k, mask, self.dropout)
        concat = scores.transpose(1, 2).contiguous().view(bs, -1, self.d_model)
        output = self.out(concat)
        return output

转置操作 .transpose(1, 2) 是为了在多头注意力计算中正确对齐每个头的查询、键和值,指的是,矩阵计算在sequence_length, d_k这两个维度上进行。

三、前馈神经网络(FeedForward)和层归一化(NormLayer)

FeedForward 模块

FeedForward 模块是一个简单的前馈神经网络,通常紧跟在多头注意力机制之后。它由两个线性层和一个激活函数组成,中间包含一个丢弃层(Dropout)以防止过拟合。

代码解析
class FeedForward(nn.Module):

    def __init__(self, d_model, d_ff=2048, dropout=0.1):
        super().__init__()
        # d_ff 默认设置为 2048
        self.linear_1 = nn.Linear(d_model, d_ff)
        self.dropout = nn.Dropout(dropout)
        self.linear_2 = nn.Linear(d_ff, d_model)

    def forward(self, x):
        x = self.dropout(F.relu(self.linear_1(x)))
        x = self.linear_2(x)
        return x
  • 初始化

    • d_model:输入和输出的维度。
    • d_ff:中间层的维度,默认设置为 2048。
    • dropout:丢弃层的丢弃率,默认设置为 0.1。
    • self.linear_1:第一个线性层,将输入从 d_model 维度映射到 d_ff 维度。
    • self.dropout:丢弃层,用于防止过拟合。
    • self.linear_2:第二个线性层,将输入从 d_ff 维度映射回 d_model 维度。
  • 前向传播

    • self.linear_1(x):将输入 xd_model 维度映射到 d_ff 维度。
    • F.relu(self.linear_1(x)):应用 ReLU 激活函数。
    • self.dropout(F.relu(self.linear_1(x))):应用丢弃层。
    • self.linear_2(x):将输入从 d_ff 维度映射回 d_model 维度。

NormLayer 模块

NormLayer 模块是一个层归一化层,用于对输入进行归一化处理。层归一化通过对每个样本的所有特征进行归一化,使得每个样本的特征具有相同的均值和标准差。
在这里插入图片描述

代码解析
class NormLayer(nn.Module):

    def __init__(self, d_model, eps=1e-6):
        super().__init__()
        self.size = d_model
        # 层归一化包含两个可以学习的参数
        self.alpha = nn.Parameter(torch.ones(self.size))
        self.bias = nn.Parameter(torch.zeros(self.size))
        self.eps = eps

    def forward(self, x):
        norm = self.alpha * (x - x.mean(dim=-1, keepdim=True)) \
        / (x.std(dim=-1, keepdim=True) + self.eps) + self.bias
        return norm
  • 初始化

    • d_model:输入和输出的维度。
    • eps:一个很小的数,用于防止除零错误,默认设置为 1e-6。
    • self.alpha:一个可学习的缩放参数,初始化为全1。
    • self.bias:一个可学习的偏移参数,初始化为全0。
  • 前向传播

    • x.mean(dim=-1, keepdim=True):计算输入 x 在最后一个维度上的均值。
    • x.std(dim=-1, keepdim=True):计算输入 x 在最后一个维度上的标准差。
    • (x - x.mean(dim=-1, keepdim=True)) / (x.std(dim=-1, keepdim=True) + self.eps):对输入 x 进行归一化处理。
    • self.alpha * ... + self.bias:应用可学习的缩放和偏移参数。

这两个模块在Transformer模型中通常一起使用,FeedForward 模块用于增加模型的非线性能力,而 NormLayer 模块用于稳定训练过程和加速收敛。

四、Encoder

这里的 Encoder 类是 Transformer 模型中的编码器部分。编码器的主要作用是将输入序列(例如一段文本)转换成一系列高维特征向量,这些特征向量可以被解码器用来生成输出序列。下面是对 Encoder 类及其组成部分的详细解释:

Encoder 类

Encoder 类是整个编码器的主要结构,它包含了以下几个部分:

  1. 嵌入层 (self.embed)

    • 将输入的词汇索引序列(src)转换为对应的词嵌入向量。每个词汇索引对应一个 d_model 维的向量。
  2. 位置编码器 (self.pe)

    • 由于 Transformer 模型没有递归和卷积结构,无法自然地利用序列的顺序信息。位置编码器通过在词嵌入向量中添加位置信息来解决这个问题。位置编码可以是固定的(如正弦和余弦函数),也可以是可学习的。
  3. 编码器层 (self.layers)

    • 这是一个由 NEncoderLayer 组成的列表。每个 EncoderLayer 包含一个多头注意力机制和一个前馈神经网络,以及相应的归一化层和丢弃层。
  4. 归一化层 (self.norm)

    • 在所有编码器层之后,对输出进行层归一化,以稳定训练过程。
class Encoder(nn.Module):

    def __init__(self, vocab_size, d_model, N, heads, dropout):
        super().__init__()
        self.N = N
        self.embed = nn.Embedding(vocab_size, d_model)
        self.pe = PositionalEncoder(d_model)
        self.layers = nn.ModuleList([EncoderLayer(d_model, heads, dropout) for _ in range(N)])
        self.norm = NormLayer(d_model)

    def forward(self, src, mask):
        x = self.embed(src)
        x = self.pe(x)
        for layer in self.layers:
            x = layer(x, mask)
        return self.norm(x)

EncoderLayer 类

EncoderLayer 类是编码器的基本组成单元,每个 EncoderLayer 包含以下几个部分:

  1. 归一化层 (self.norm_1self.norm_2)

    • 在多头注意力机制和前馈神经网络之前,对输入进行层归一化。
  2. 多头注意力机制 (self.attn)

    • 计算输入序列的自注意力表示。自注意力机制允许模型在处理每个位置的输入时,考虑到序列中所有其他位置的信息。
  3. 前馈神经网络 (self.ff)

    • 一个简单的两层全连接神经网络,用于对每个位置的输入进行非线性变换。
  4. 丢弃层 (self.dropout_1self.dropout_2)

    • 在多头注意力机制和前馈神经网络的输出上应用丢弃操作,以防止过拟合。
class EncoderLayer(nn.Module):

    def __init__(self, d_model, heads, dropout=0.1):
        super().__init__()
        self.norm_1 = NormLayer(d_model)
        self.norm_2 = NormLayer(d_model)
        self.attn = MultiHeadAttention(heads, d_model, dropout=dropout)
        self.ff = FeedForward(d_model, dropout=dropout)
        self.dropout_1 = nn.Dropout(dropout)
        self.dropout_2 = nn.Dropout(dropout)

    def forward(self, x, mask):
        x2 = self.norm_1(x)
        x = x + self.dropout_1(self.attn(x2, x2, x2, mask))
        x2 = self.norm_2(x)
        x = x + self.dropout_2(self.ff(x2))
        return x

前向传播过程

  1. 嵌入和位置编码

    • 输入序列 src 首先通过嵌入层转换为词嵌入向量,然后通过位置编码器添加位置信息。
  2. 编码器层处理

    • 将添加了位置信息的词嵌入向量输入到第一个编码器层。每个编码器层的输出作为下一个编码器层的输入,依次经过所有 N 个编码器层。
  3. 归一化

    • 在所有编码器层处理完毕后,对最终的输出进行层归一化。

五、Decoder

这个 Decoder 类是 Transformer 模型中的解码器部分。解码器的主要作用是生成输出序列,例如在机器翻译任务中,解码器负责生成目标语言的句子。下面是对 Decoder 类及其组成部分的详细解释:

Decoder 类

Decoder 类是整个解码器的主要结构,它包含了以下几个部分:

  1. 嵌入层 (self.embed)

    • 将输入的目标语言词汇索引序列(trg)转换为对应的词嵌入向量。每个词汇索引对应一个 d_model 维的向量。
  2. 位置编码器 (self.pe)

    • 由于 Transformer 模型没有递归和卷积结构,无法自然地利用序列的顺序信息。位置编码器通过在词嵌入向量中添加位置信息来解决这个问题。位置编码可以是固定的(如正弦和余弦函数),也可以是可学习的。
  3. 解码器层 (self.layers)

    • 这是一个由 NDecoderLayer 组成的列表。每个 DecoderLayer 包含两个多头注意力机制和一个前馈神经网络,以及相应的归一化层和丢弃层。
  4. 归一化层 (self.norm)

    • 在所有解码器层之后,对输出进行层归一化,以稳定训练过程。
class Decoder(nn.Module):

    def __init__(self, vocab_size, d_model, N, heads, dropout):
        super().__init__()
        self.N = N
        self.embed = nn.Embedding(vocab_size, d_model)
        self.pe = PositionalEncoder(d_model)
        self.layers = nn.ModuleList([DecoderLayer(d_model, heads, dropout) for _ in range(N)])
        self.norm = NormLayer(d_model)

    def forward(self, trg, e_outputs, src_mask, trg_mask):
        x = self.embed(trg)
        x = self.pe(x)
        for layer in self.layers:
            x = layer(x, e_outputs, src_mask, trg_mask)
        return self.norm(x)

DecoderLayer 类

DecoderLayer 类是解码器的基本组成单元,每个 DecoderLayer 包含以下几个部分:

  1. 归一化层 (self.norm_1, self.norm_2, self.norm_3)

    • 在多头注意力机制和前馈神经网络之前,对输入进行层归一化。
  2. 丢弃层 (self.dropout_1, self.dropout_2, self.dropout_3)

    • 在多头注意力机制和前馈神经网络的输出上应用丢弃操作,以防止过拟合。
  3. 多头注意力机制 (self.attn_1, self.attn_2)

    • self.attn_1 是自注意力机制,计算输入序列的自注意力表示。自注意力机制允许模型在处理每个位置的输入时,考虑到序列中所有其他位置的信息。
    • self.attn_2 是编码器-解码器注意力机制,允许解码器在生成每个位置的输出时,考虑到编码器的输出(即源语言的上下文信息)。
  4. 前馈神经网络 (self.ff)

    • 一个简单的两层全连接神经网络,用于对每个位置的输入进行非线性变换。
class DecoderLayer(nn.Module):

    def __init__(self, d_model, heads, dropout=0.1):
        super().__init__()
        self.norm_1 = NormLayer(d_model)
        self.norm_2 = NormLayer(d_model)
        self.norm_3 = NormLayer(d_model)
        self.dropout_1 = nn.Dropout(dropout)
        self.dropout_2 = nn.Dropout(dropout)
        self.dropout_3 = nn.Dropout(dropout)
        self.attn_1 = MultiHeadAttention(heads, d_model, dropout=dropout)
        self.attn_2 = MultiHeadAttention(heads, d_model, dropout=dropout)
        self.ff = FeedForward(d_model, dropout=dropout)

    def forward(self, x, e_outputs, src_mask, trg_mask):
        x2 = self.norm_1(x)
        x = x + self.dropout_1(self.attn_1(x2, x2, x2, trg_mask))
        x2 = self.norm_2(x)
        x = x + self.dropout_2(self.attn_2(x2, e_outputs, e_outputs, src_mask))
        x2 = self.norm_3(x)
        x = x + self.dropout_3(self.ff(x2))
        return x

前向传播过程

  1. 嵌入和位置编码

    • 输入序列 trg 首先通过嵌入层转换为词嵌入向量,然后通过位置编码器添加位置信息。
  2. 解码器层处理

    • 将添加了位置信息的词嵌入向量输入到第一个解码器层。每个解码器层的输出作为下一个解码器层的输入,依次经过所有 N 个解码器层。
    • 在每个解码器层中,首先进行自注意力机制计算,然后进行编码器-解码器注意力机制计算,最后进行前馈神经网络计算。
  3. 归一化

    • 在所有解码器层处理完毕后,对最终的输出进行层归一化。

六、Transformer整体框架

在这里插入图片描述

class Transformer(nn.Module):

    def __init__(self, src_vocab, trg_vocab, d_model, N, heads, dropout):
        super().__init__()
        self.encoder = Encoder(src_vocab, d_model, N, heads, dropout)
        self.decoder = Decoder(trg_vocab, d_model, N, heads, dropout)
        self.out = nn.Linear(d_model, trg_vocab)

    def forward(self, src, trg, src_mask, trg_mask):
        e_outputs = self.encoder(src, src_mask)
        d_output = self.decoder(trg, e_outputs, src_mask, trg_mask)
        output = self.out(d_output)
        return output

参考资料

https://zhuanlan.zhihu.com/p/657456977
《Attention is all you need》

版权声明
本博客内容仅供学习交流,转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1882302.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

喜提一等奖!白鲸开源在“创业北京”创业创新大赛海淀区选拔赛决赛表现亮眼

6月25日,第七届“创业北京”创业创新大赛海淀区选拔赛决赛在中关村东升国际科学园成功举办。本次活动由海淀区人力资源和社会保障局、中关村科学城管委会主办,以“创响新时代 共圆中国梦”为主题,活动现场主体赛先进制造赛道和主体赛现代服务…

网络安全在2024好入行吗?

前言 024年的今天,慎重进入网安行业吧,目前来说信息安全方向的就业对于学历的容忍度比软件开发要大得多,还有很多高中被挖过来的大佬。 理由很简单,目前来说,信息安全的圈子人少,985、211院校很多都才建立…

网站提示不安全怎么办

当您访问一个网站时,如果浏览器提示该网站不安全,这通常意味着以下几个问题之一,以及相应的解决办法: 一、未启用HTTPS协议: 解决方法:确保网站启用了HTTPS协议。这意味着您需要为您的网站部署一个有效的…

2024年最适合Python小白的零基础入门教程!

伴随着云计算、大数据、AI等技术的迅速崛起,市场对Python人才的需求和市场人才的匮乏,让长期沉默的Python语言一下子备受众人的关注,再加上简单易学,使得Python一跃成为TIOBE排行榜的第一。 准备学Python或者想学Python的小伙伴们…

1.linux操作系统CPU负载

目录 概述CPU平均负载查看平均负载结束 概述 CPU 使用率 和CPU 平均使用率。 CPU平均负载 单位时间内系统处于 [可运行状态] 和 [不可中断状态] 的平均进程数,就是平均活跃进程数,和CPU使用率并没有直接关系 可运行状态 正在使用CPU或者正等待CPU的进…

ITK-读取/写入图像

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 绪论 在本文中,将介绍如何使用ITK(Insight Segmentation and Registration Toolkit)库来读取…

【毕业一年,聊聊什么】

毕业一年,聊聊什么 一,引子 武汉,大雨连连,大雨如柱,大雨倾盆,任性的,傲娇的,一点没有想停的样子。 下雨天,好适合Emo啊,该我了,请允许。 二&…

Meilisearch 安装和使用教程

如今搜索功能已成为几乎所有应用不可或缺的一部分。无论是电商平台、内容管理系统,还是企业内部知识库,用户都期待能够快速、准确地找到他们需要的信息。然而,传统的搜索解决方案往往面临着诸多挑战:响应速度慢、相关性差、难以适…

分享值得推荐的6大磁力搜索器平台,亲测有效!

昨天晚上,隔壁出租屋的小美私信阿星,问哪里能下载到有趣的资源,比如漫画、影音、学习资料等等。 这直接问到了阿星的强项了!其实网络上,高手和小白之间,只差一个搜索引擎。 今天阿星想和大家分享几款好用…

常用图片处理操作

静态图片文件转base64 import base64 with open(1.png, rb) as f:source f.read() base64_img base64.b64encode(source)base64转静态图片文件 imgdata base64.b64decode(base64_img)# 将图片保存为文件 with open("new.png", wb) as f:f.write(imgdata)PS:这里…

IT运维管理与运营管理的创新与实践

IT运维管理与运营管理的创新与实践 在信息化飞速发展的今天,IT运维管理与运营管理已成为企业保障业务连续性和提升运营效率的关键环节。随着数字化转型的深入,企业对IT运维管理的要求不断提高。本文结合《IT运维管理与运营管理》文档的内容,…

海南云亿商务咨询有限公司引领抖音电商新纪元

在数字化浪潮汹涌的今天,电商行业迎来了前所未有的发展机遇。作为电商服务领域的佼佼者,海南云亿商务咨询有限公司凭借其专业的团队和丰富的经验,专注于抖音电商服务,助力企业快速布局市场,实现销售增长和品牌提升。 …

基于x86+FPGA+AI轴承缺陷视觉检测系统,摇枕弹簧智能检测系统

一、承缺陷视觉检测系统 应用场景 轴类零件自动检测设备,集光、机、软件、硬件,智能图像处理等先进技术于一体,利用轮廓特征匹配,目标与定位,区域选取,边缘提取,模糊运算等算法实现人工智能高…

运算放大器重要参数详解

运算放大器是一种用于放大电压并实现信号处理和放大的电子设备。以下是运算放大器的一些重要参数及其详解: 增益(Gain): 定义:增益是运算放大器输出电压与输入电压之比,表示运算放大器在输入信号上的放大倍数。重要性:增益决定了信号的放大程度,是运算放大器的基本功能…

工程师这几招降低电机EMI的方法,提高系统电磁兼容性能

通过在电机端子之间放置陶瓷电容器、工模滤波器或BDL滤波器均可抑制差模和共模噪声,以提高系统的EMC性能。工程师在本文详细介绍这几种降低电机EMI的方法。 EMC和EMI背景 电磁干扰(EMI)是系统上的电磁噪声的辐射或感应。与大多数电磁电路组件一样,直流…

用易查分下发《致家长一封信》,支持在线手写签名,一键导出PDF!

暑假来临之际,学校通常需要下发致家长信,以正式、书面的形式向家长传达重要的通知或建议。传统的发放方式如家长签字后学生将回执单上交,容易存在丢失、遗忘的问题。 那么如何更高效、便捷、安全地将致家长一封信送达给每位家长呢&#xff1f…

3-数据提取方法1(json)(6节课学会爬虫)

3-数据提取方法1(json)(6节课学会爬虫) 1,Json2,哪里会返回json的数据(值得尝试的操作)3,Json字符串转换成字典或python类型进行数据提取(1)Json.…

使用热力图表示联邦学习场景中的客户端数据分布

用于生成热力图,记录过程,方便之后直接使用。 使用场景:联邦学习中显示客户端数据分布,或者显示数据分布的各类其他场景 文章目录 一、代码hot.py使用方法 二、参数解释三、样图关键词 一、代码 写这段代码时主要考虑联邦学习中显…

短视频抓取:成都柏煜文化传媒有限公司

短视频抓取:技术挑战、法律边界与未来趋势 随着移动互联网的迅猛发展,短视频平台如雨后春笋般涌现,成为现代人生活娱乐的重要组成部分。然而,在海量短视频内容中,如何高效、准确地抓取目标视频,成为了一个…

JUC工具类: Semaphore详解

Semaphore底层是基于AbstractQueuedSynchronizer来实现的。Semaphore称为计数信号量,它允许n个任务同时访问某个资源,可以将信号量看做是在向外分发使用资源的许可证,只有成功获取许可证,才能使用资源。立刀旁 目录 # 带着BAT大厂…