course-nlp——8-translation-transformer

news2024/11/25 16:16:42

本文参考自https://github.com/fastai/course-nlp。

注意力机制和 Transformer

Nvidia AI 研究员 Chip Huyen 写了一篇很棒的文章《Top 8 trends from ICLR 2019》,其中的趋势之一是 RNN 正在失去研究人员的青睐。

这是有原因的,RNN 可能很麻烦:并行化可能很棘手,而且很难调试。 由于语言是递归的,RNN 似乎在概念上与 NLP 非常契合,但最近使用注意力的方法在 NLP 上取得了最先进的成果。

这仍然是一个非常活跃的研究领域,例如,最近的一篇论文《使用轻量级和动态卷积减少注意力》表明,卷积在某些任务上可以胜过注意力,包括英语到德语的翻译。 需要对 RNN、CNN 和 transformer/注意力的各种优势进行更多的研究,也许还需要研究如何将每种方法的优点结合起来。

from fastai.text import *
path = Config().data_path()/'giga-fren'
path.ls()
[PosixPath('/home/jhoward/.fastai/data/giga-fren/cc.en.300.bin'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/data_save.pkl'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/models'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/giga-fren.release2.fixed.en'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/giga-fren.release2.fixed.fr'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/questions_easy.csv'),
 PosixPath('/home/jhoward/.fastai/data/giga-fren/cc.fr.300.bin')]

加载数据

我们重复使用与翻译笔记本中相同的功能来加载我们的数据。

def seq2seq_collate(samples, pad_idx=1, pad_first=True, backwards=False):
    "Function that collect samples and adds padding. Flips token order if needed"
    samples = to_data(samples)
    max_len_x,max_len_y = max([len(s[0]) for s in samples]),max([len(s[1]) for s in samples])
    res_x = torch.zeros(len(samples), max_len_x).long() + pad_idx
    res_y = torch.zeros(len(samples), max_len_y).long() + pad_idx
    if backwards: pad_first = not pad_first
    for i,s in enumerate(samples):
        if pad_first: 
            res_x[i,-len(s[0]):],res_y[i,-len(s[1]):] = LongTensor(s[0]),LongTensor(s[1])
        else:         
            res_x[i, :len(s[0])],res_y[i, :len(s[1])] = LongTensor(s[0]),LongTensor(s[1])
    if backwards: res_x,res_y = res_x.flip(1),res_y.flip(1)
    return res_x, res_y
class Seq2SeqDataBunch(TextDataBunch):
    "Create a `TextDataBunch` suitable for training an RNN classifier."
    @classmethod
    def create(cls, train_ds, valid_ds, test_ds=None, path='.', bs=32, val_bs=None, pad_idx=1,
               dl_tfms=None, pad_first=False, device=None, no_check=False, backwards=False, **dl_kwargs):
        "Function that transform the `datasets` in a `DataBunch` for classification. Passes `**dl_kwargs` on to `DataLoader()`"
        datasets = cls._init_ds(train_ds, valid_ds, test_ds)
        val_bs = ifnone(val_bs, bs)
        collate_fn = partial(seq2seq_collate, pad_idx=pad_idx, pad_first=pad_first, backwards=backwards)
        train_sampler = SortishSampler(datasets[0].x, key=lambda t: len(datasets[0][t][0].data), bs=bs//2)
        train_dl = DataLoader(datasets[0], batch_size=bs, sampler=train_sampler, drop_last=True, **dl_kwargs)
        dataloaders = [train_dl]
        for ds in datasets[1:]:
            lengths = [len(t) for t in ds.x.items]
            sampler = SortSampler(ds.x, key=lengths.__getitem__)
            dataloaders.append(DataLoader(ds, batch_size=val_bs, sampler=sampler, **dl_kwargs))
        return cls(*dataloaders, path=path, device=device, collate_fn=collate_fn, no_check=no_check)
class Seq2SeqTextList(TextList):
    _bunch = Seq2SeqDataBunch
    _label_cls = TextList

请参阅笔记本 7-seq2seq-translation,了解我们用于创建、处理和保存此数据的代码。

data = load_data(path)
data.show_batch()

在这里插入图片描述

Transformer 模型在这里插入图片描述

转移(Shifting)

我们向数据加载器添加一个转换,将目标向右移动并在开头添加填充。

v = data.vocab
v.stoi['xxpad']
1
def shift_tfm(b):
    x,y = b
    y = F.pad(y, (1, 0), value=1)
    return [x,y[:,:-1]], y[:,1:]
data.add_tfm(shift_tfm)

嵌入(Embeddings)

输入和输出嵌入是传统的 PyTorch 嵌入(如果需要,我们可以使用预训练向量)。Transformer 模型不是循环模型,因此它不知道单词的相对位置。为了帮助它做到这一点,他们必须对输入嵌入进行位置编码,该编码是特定频率的余弦:

d = 30
torch.arange(0., d, 2.)/d
tensor([0.0000, 0.0667, 0.1333, 0.2000, 0.2667, 0.3333, 0.4000, 0.4667, 0.5333,
        0.6000, 0.6667, 0.7333, 0.8000, 0.8667, 0.9333])
class PositionalEncoding(nn.Module):
    "Encode the position with a sinusoid."
    def __init__(self, d):
        super().__init__()
        self.register_buffer('freq', 1 / (10000 ** (torch.arange(0., d, 2.)/d)))
    
    def forward(self, pos):
        inp = torch.ger(pos, self.freq)
        enc = torch.cat([inp.sin(), inp.cos()], dim=-1)
        return enc
tst_encoding = PositionalEncoding(20)
res = tst_encoding(torch.arange(0,100).float())
_, ax = plt.subplots(1,1)
for i in range(1,5): ax.plot(res[:,i])

在这里插入图片描述

res[:6,:6]

在这里插入图片描述

class TransformerEmbedding(nn.Module):
    "Embedding + positional encoding + dropout"
    def __init__(self, vocab_sz, emb_sz, inp_p=0.):
        super().__init__()
        self.emb_sz = emb_sz
        self.embed = embedding(vocab_sz, emb_sz)
        self.pos_enc = PositionalEncoding(emb_sz)
        self.drop = nn.Dropout(inp_p)
    
    def forward(self, inp): 
        pos = torch.arange(0, inp.size(1), device=inp.device).float()
        return self.drop(self.embed(inp) * math.sqrt(self.emb_sz) + self.pos_enc(pos))

前馈(Feed forward)

前馈单元很简单:它只是两个带有跳过连接和 LayerNorm 的线性层。

def feed_forward(d_model, d_ff, ff_p=0., double_drop=True):
    layers = [nn.Linear(d_model, d_ff), nn.ReLU()]
    if double_drop: layers.append(nn.Dropout(ff_p))
    return SequentialEx(*layers, nn.Linear(d_ff, d_model), nn.Dropout(ff_p), MergeLayer(), nn.LayerNorm(d_model))

多头注意力机制

在这里插入图片描述

class MultiHeadAttention(nn.Module):
    def __init__(self, n_heads, d_model, d_head=None, p=0., bias=True, scale=True):
        super().__init__()
        d_head = ifnone(d_head, d_model//n_heads)
        self.n_heads,self.d_head,self.scale = n_heads,d_head,scale
        self.q_wgt,self.k_wgt,self.v_wgt = [nn.Linear(
            d_model, n_heads * d_head, bias=bias) for o in range(3)]
        self.out = nn.Linear(n_heads * d_head, d_model, bias=bias)
        self.drop_att,self.drop_res = nn.Dropout(p),nn.Dropout(p)
        self.ln = nn.LayerNorm(d_model)
        
    def forward(self, q, kv, mask=None):
        return self.ln(q + self.drop_res(self.out(self._apply_attention(q, kv, mask=mask))))
    
    def create_attn_mat(self, x, layer, bs):
        return layer(x).view(bs, x.size(1), self.n_heads, self.d_head
                            ).permute(0, 2, 1, 3)
    
    def _apply_attention(self, q, kv, mask=None):
        bs,seq_len = q.size(0),q.size(1)
        wq,wk,wv = map(lambda o: self.create_attn_mat(*o,bs),
                       zip((q,kv,kv),(self.q_wgt,self.k_wgt,self.v_wgt)))
        attn_score = wq @ wk.transpose(2,3)
        if self.scale: attn_score /= math.sqrt(self.d_head)
        if mask is not None: 
            attn_score = attn_score.float().masked_fill(mask, -float('inf')).type_as(attn_score)
        attn_prob = self.drop_att(F.softmax(attn_score, dim=-1))
        attn_vec = attn_prob @ wv
        return attn_vec.permute(0, 2, 1, 3).contiguous().view(bs, seq_len, -1)

掩蔽(Masking)

注意层使用掩码来避免关注某些时间步骤。首先,我们并不希望网络真正关注填充,因此我们将对其进行掩码。其次,由于此模型不是循环的,因此我们需要(在输出中)掩码所有我们不应该看到的标记(否则就是作弊)。

def get_output_mask(inp, pad_idx=1):
    return torch.triu(inp.new_ones(inp.size(1),inp.size(1)), diagonal=1)[None,None].byte()
#     return ((inp == pad_idx)[:,None,:,None].long() + torch.triu(inp.new_ones(inp.size(1),inp.size(1)), diagonal=1)[None,None] != 0)

未来令牌的掩码示例:

torch.triu(torch.ones(10,10), diagonal=1).byte()
tensor([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [0, 0, 1, 1, 1, 1, 1, 1, 1, 1],
        [0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
        [0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
        [0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
        [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=torch.uint8)

编码器和解码器块

现在我们准备在模型图中添加的块中重新组合这些层:
在这里插入图片描述

class EncoderBlock(nn.Module):
    "Encoder block of a Transformer model."
    #Can't use Sequential directly cause more than one input...
    def __init__(self, n_heads, d_model, d_head, d_inner, p=0., bias=True, scale=True, double_drop=True):
        super().__init__()
        self.mha = MultiHeadAttention(n_heads, d_model, d_head, p=p, bias=bias, scale=scale)
        self.ff  = feed_forward(d_model, d_inner, ff_p=p, double_drop=double_drop)
    
    def forward(self, x, mask=None): return self.ff(self.mha(x, x, mask=mask))
class DecoderBlock(nn.Module):
    "Decoder block of a Transformer model."
    #Can't use Sequential directly cause more than one input...
    def __init__(self, n_heads, d_model, d_head, d_inner, p=0., bias=True, scale=True, double_drop=True):
        super().__init__()
        self.mha1 = MultiHeadAttention(n_heads, d_model, d_head, p=p, bias=bias, scale=scale)
        self.mha2 = MultiHeadAttention(n_heads, d_model, d_head, p=p, bias=bias, scale=scale)
        self.ff   = feed_forward(d_model, d_inner, ff_p=p, double_drop=double_drop)
    
    def forward(self, x, enc, mask_out=None): return self.ff(self.mha2(self.mha1(x, x, mask_out), enc))

整个模型

class Transformer(Module):
    def __init__(self, inp_vsz, out_vsz, n_layers=6, n_heads=8, d_model=256, d_head=32, 
                 d_inner=1024, p=0.1, bias=True, scale=True, double_drop=True, pad_idx=1):
        self.enc_emb = TransformerEmbedding(inp_vsz, d_model, p)
        self.dec_emb = TransformerEmbedding(out_vsz, d_model, 0.)
        args = (n_heads, d_model, d_head, d_inner, p, bias, scale, double_drop)
        self.encoder = nn.ModuleList([EncoderBlock(*args) for _ in range(n_layers)])
        self.decoder = nn.ModuleList([DecoderBlock(*args) for _ in range(n_layers)])
        self.out = nn.Linear(d_model, out_vsz)
        self.out.weight = self.dec_emb.embed.weight
        self.pad_idx = pad_idx
        
    def forward(self, inp, out):
        mask_out = get_output_mask(out, self.pad_idx)
        enc,out = self.enc_emb(inp),self.dec_emb(out)
        enc = compose(self.encoder)(enc)
        out = compose(self.decoder)(out, enc, mask_out)
        return self.out(out)

Bleu 度量(参见专用笔记本)

class NGram():
    def __init__(self, ngram, max_n=5000): self.ngram,self.max_n = ngram,max_n
    def __eq__(self, other):
        if len(self.ngram) != len(other.ngram): return False
        return np.all(np.array(self.ngram) == np.array(other.ngram))
    def __hash__(self): return int(sum([o * self.max_n**i for i,o in enumerate(self.ngram)]))
def get_grams(x, n, max_n=5000):
    return x if n==1 else [NGram(x[i:i+n], max_n=max_n) for i in range(len(x)-n+1)]
def get_correct_ngrams(pred, targ, n, max_n=5000):
    pred_grams,targ_grams = get_grams(pred, n, max_n=max_n),get_grams(targ, n, max_n=max_n)
    pred_cnt,targ_cnt = Counter(pred_grams),Counter(targ_grams)
    return sum([min(c, targ_cnt[g]) for g,c in pred_cnt.items()]),len(pred_grams)
class CorpusBLEU(Callback):
    def __init__(self, vocab_sz):
        self.vocab_sz = vocab_sz
        self.name = 'bleu'
    
    def on_epoch_begin(self, **kwargs):
        self.pred_len,self.targ_len,self.corrects,self.counts = 0,0,[0]*4,[0]*4
    
    def on_batch_end(self, last_output, last_target, **kwargs):
        last_output = last_output.argmax(dim=-1)
        for pred,targ in zip(last_output.cpu().numpy(),last_target.cpu().numpy()):
            self.pred_len += len(pred)
            self.targ_len += len(targ)
            for i in range(4):
                c,t = get_correct_ngrams(pred, targ, i+1, max_n=self.vocab_sz)
                self.corrects[i] += c
                self.counts[i]   += t
    
    def on_epoch_end(self, last_metrics, **kwargs):
        precs = [c/t for c,t in zip(self.corrects,self.counts)]
        len_penalty = exp(1 - self.targ_len/self.pred_len) if self.pred_len < self.targ_len else 1
        bleu = len_penalty * ((precs[0]*precs[1]*precs[2]*precs[3]) ** 0.25)
        return add_metrics(last_metrics, bleu)

训练

n_x_vocab,n_y_vocab = len(data.train_ds.x.vocab.itos), len(data.train_ds.y.vocab.itos)

model = Transformer(n_x_vocab, n_y_vocab, d_model=256)
learn = Learner(data, model, metrics=[accuracy, CorpusBLEU(n_y_vocab)], loss_func = CrossEntropyFlat())
learn.lr_find()
learn.recorder.plot()

在这里插入图片描述

learn.fit_one_cycle(8, 5e-4, div_factor=5)

在这里插入图片描述

def get_predictions(learn, ds_type=DatasetType.Valid):
    learn.model.eval()
    inputs, targets, outputs = [],[],[]
    with torch.no_grad():
        for xb,yb in progress_bar(learn.dl(ds_type)):
            out = learn.model(*xb)
            for x,y,z in zip(xb[0],xb[1],out):
                inputs.append(learn.data.train_ds.x.reconstruct(x))
                targets.append(learn.data.train_ds.y.reconstruct(y))
                outputs.append(learn.data.train_ds.y.reconstruct(z.argmax(1)))
    return inputs, targets, outputs
inputs, targets, outputs = get_predictions(learn)
inputs[10],targets[10],outputs[10]
(Text xxbos xxmaj pendant que xxunk les activités requises pour maintenir mon xxunk physique , est - ce que je xxunk de la protection d’un régime d’assurance ou de pension ?,
 Text xxbos xxmaj while i go about maintaining this high degree of fitness , am i protected under an insurance or pension plan ?,
 Text xxbos xxmaj while i do to the my physical physical of physical , do i aware by the pension plan service plan ?)
inputs[700],targets[700],outputs[700]
(Text xxbos xxmaj quelles sont les conséquences sur la recherche , la mise en pratique et les politiques en ce qui a trait à l'ac ?,
 Text xxbos xxmaj what are the xxunk for xxup kt research , practice / policy ?,
 Text xxbos xxmaj what are the implications implications research kt , , policy and policies in)
inputs[701],targets[701],outputs[701]
(Text xxbos xxmaj quelle est la position des xxmaj états - xxmaj unis , du xxmaj canada et de la xxup xxunk à ce propos ?,
 Text xxbos xxmaj where do the xxup us , xxmaj canada and xxup xxunk stand ?,
 Text xxbos xxmaj what is xxmaj xxup us xxmaj xxmaj united and the xxunk fit in)
inputs[2500],targets[2500],outputs[2500]
(Text xxbos xxmaj quels sont les atouts particuliers du xxmaj canada en recherche sur l'obésité sur la scène internationale ?,
 Text xxbos xxmaj what are the unique xxmaj canadian strengths in obesity research that set xxmaj canada apart on an international front ?,
 Text xxbos xxmaj what are xxmaj specific strengths canada strengths in obesity - ? are up canada ? from international international stage ?)

inputs[4002],targets[4002],outputs[4002]
(Text xxbos xxmaj quelles sont les répercussions politiques à long terme de cette révolution scientifique mondiale ?,
 Text xxbos xxmaj what are some of the long - term policy implications of this global knowledge revolution ?,
 Text xxbos xxmaj what are the long the long - term policies implications of this global scientific ? ?)

标签平滑(Label smoothing)

他们在论文中指出,使用标签平滑有助于获得更好的 BLEU/准确度,即使它会使损失变得更糟。

model = Transformer(len(data.train_ds.x.vocab.itos), len(data.train_ds.y.vocab.itos), d_model=256)
learn = Learner(data, model, metrics=[accuracy, CorpusBLEU(len(data.train_ds.y.vocab.itos))], 
                loss_func=FlattenedLoss(LabelSmoothingCrossEntropy, axis=-1))
learn.fit_one_cycle(8, 5e-4, div_factor=5)

在这里插入图片描述

learn.fit_one_cycle(8, 5e-4, div_factor=5)
print("Quels sont les atouts particuliers du Canada en recherche sur l'obésité sur la scène internationale ?")
print("What are Specific strengths canada strengths in obesity - ? are up canada ? from international international stage ?")
print("Quelles sont les répercussions politiques à long terme de cette révolution scientifique mondiale ?")
print("What are the long the long - term policies implications of this global scientific ? ?")
Quels sont les atouts particuliers du Canada en recherche sur l'obésité sur la scène internationale ?
What are Specific strengths canada strengths in obesity - ? are up canada ? from international international stage ?
Quelles sont les répercussions politiques à long terme de cette révolution scientifique mondiale ?
What are the long the long - term policies implications of this global scientific ? ?
inputs[10],targets[10],outputs[10]
(Text xxbos xxmaj quelle distance y a - t - il entre le point le plus rapproché de la surface à xxunk et la position d’utilisation habituelle du tube radiogène ?,
 Text xxbos xxmaj what is the distance between the nearest point of the area to be shielded and the usual operational position of the x - ray tube ?,
 Text xxbos xxmaj what is the xxmaj between the xxmaj and of the xxmaj ? the ? and the most ? ? of the xxmaj - ray tube ?)
inputs[700],targets[700],outputs[700]
(Text xxbos xxmaj quels types de présentations xxmaj santé xxmaj canada xxunk - t - il dans le format ectd à compter du 1er septembre ?,
 Text xxbos xxmaj what kind of submission types will xxmaj health xxmaj canada accept on xxmaj september 1 , 2004 in ectd format ?,
 Text xxbos xxmaj what is of information is of be canadian xxmaj canada take ? the canadian ? , and ? the format ?)
inputs[701],targets[701],outputs[701]
(Text xxbos xxmaj quelles sont les trois caractéristiques qui vous incitent le plus à investir dans votre région ( xxup nommez - xxup les ) ?,
 Text xxbos xxmaj what are the three most attractive features about investing in your region ( xxup name xxup it ) ?,
 Text xxbos xxmaj what is the main main important concerns of the in the country ? xxup xxunk , xxunk ) ?)
inputs[4001],targets[4001],outputs[4001]
(Text xxbos xxmaj quelles actions avez - vous prises et quel en a été le résultat ?,
 Text xxbos xxmaj what were your actions and the outcomes ?,
 Text xxbos xxmaj what is the targets ? how main of)

测试泄露(Test leakage)

如果我们改变位置 n 处目标中的标记,它不应该影响之前的预测。

learn.model.eval();
xb,yb = data.one_batch(cpu=False)
inp1,out1 = xb[0][:1],xb[1][:1]
inp2,out2 = inp1.clone(),out1.clone()
out2[0,15] = 10
y1 = learn.model(inp1, out1)
y2 = learn.model(inp2, out2)
(y1[0,:15] - y2[0,:15]).abs().mean()
tensor(0., device='cuda:0', grad_fn=<MeanBackward1>)

在这里插入图片描述

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

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

相关文章

2938. 区分黑球与白球

题目 桌子上有 n 个球&#xff0c;每个球的颜色不是黑色&#xff0c;就是白色。 给你一个长度为 n 、下标从 0 开始的二进制字符串 s&#xff0c;其中 1 和 0 分别代表黑色和白色的球。 在每一步中&#xff0c;你可以选择两个相邻的球并交换它们。 返回「将所有黑色球都移到…

网工内推 | 网络运维工程师,H3CIE认证优先,13薪,享股票期权

01 畅读 &#x1f537;招聘岗位&#xff1a;高级网络运维工程师 &#x1f537;职责描述&#xff1a; 1.负责线上业务网络技术运维工作&#xff0c;保障并优化线上网络质量&#xff1b; 2.规划并构建公司线上业务网络架构&#xff1b; 3.规划线上业务网络质量评估与监控体系&…

信号:干扰类别及特征提取

目录 第一部分&#xff1a;干扰类别 1.压制干扰 1.1噪声调幅瞄准式干扰(单音干扰) 1.2噪声调频阻塞式干扰&#xff08;宽带噪声干扰&#xff09; 1.3噪声调频扫频式干扰&#xff08;线性调频&#xff09; 2.欺骗干扰 2.1距离欺骗干扰&#xff08;幅度调制干扰&#xff0…

关于main函数参数列表的那些事

写在最前面&#xff1a; 本篇博客所写代码&#xff0c;全部都依赖于Linux环境。 在开始之前&#xff0c;我们先问自己几个问题&#xff1a; main函数可以传参吗?如果main函数可以传参&#xff0c;最多可以传几个参数。main函数传递的参数具体作用是什么&#xff1f; 一.是否…

java小游戏-坦克大战1.0

文章目录 游戏界面样式游戏需求分析设计类过程1&#xff1a;初始化界面过程2&#xff1a;用面向对象思想设置功能过程3&#xff1a;调用类实例化对象过程4&#xff1a;联合调试 项目代码下载&#xff1a; CSDN_java小游戏-坦克大战1.0 来源&#xff1a;该游戏来自尚学堂~&…

神了,Suno创作的《不期待》三个版本,你最喜欢哪一个?

Suno AI 最近尝试了下 Suno AI 的v3.5模型&#xff0c;有点惊艳 做了三首版本的AI歌曲&#xff0c;词是我写的&#xff0c;其他全都交给Suno了&#xff0c;欢迎大家来听听 B站链接 Youtube链接

源码文章上传无忧,论坛小程序支持

前言 在数字化时代&#xff0c;知识的分享与传播显得愈发重要。为了满足广大创作者和求知者的需求&#xff0c;我们推出了全新的论坛小程序&#xff0c;不仅支持文章、源码、链接等多样化内容的上传&#xff0c;还实现了付费观看功能&#xff0c;为创作者们提供了一个展示才华…

flask 之JWT认证实现

目录 1、JWT 1.1、JWT概述 1.2、token的生成 1.3、token校验 1.4、flask项目中实现JWT认证 1、JWT 1.1、JWT概述 JWT&#xff08;JSON Web Token&#xff09;是一种用于身份验证和授权的开放标准。它由三部分组成&#xff0c;分别是头部、负载和签名。 头部&#xff0…

第三方软件测试机构与CMA、CNAS资质

第三方软件测试机构 随着信息技术的快速发展&#xff0c;软件在各个领域的应用越来越广泛&#xff0c;软件的质量和安全性成为人们关注的焦点。为了确保软件的质量和安全性&#xff0c;第三方软件测试机构和CMA、CNAS资质成为了重要的保障。 第三方软件测试机构是独立于软件开…

python调用excel的demo

在本地安装Pycharm之后&#xff0c;新建工程&#xff0c;在main.py中键入如下代码,即可实现Python调用excel&#xff1a; import pandas as pd sheet pd.read_excel(test.xlsx) data sheet.loc[0].values print("读取指定行的数据:\n{0}".format(data)) 第一次编…

如何将 MySQL 数据库共享给他人?

文章目录 共享所有数据库给他人1. 连接到 MySQL 数据库2. 选择要使用的数据库3. 修改连接所需的 host4. 刷新权限 共享部分数据库给他人1. 创建用户2. 授权3. 刷新权限 结语 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是I…

JVMの静、动态绑定异常捕获JIT即时编译

在说明静态绑定和动态绑定之前&#xff0c;我们首先要了解在字节码指令的层面&#xff0c;JVM是如何调用方法的&#xff1a; 例如我有以下的代码&#xff0c;很简单就是在main方法中调用了另一个静态方法&#xff1a; public class MethodTest {public static void main(Strin…

git clone 文件名中文、有冒号等问题 fatal: repository ‘***/r/鏍″洯鏅烘収椋熷爞/.git/‘ not found

记录一个git问题&#xff0c;比较有意思&#xff0c;也比较难找。 背景 首先把代码拉下来&#xff0c;发现给我报错。 怀疑 刚开始以为是仓库地址变了&#xff0c;但是发现仓库地址并没有变过。 交流 然后寻找解决方案。因为同事也遇到过&#xff0c;同事交了我一招&…

数据结构第三篇【链表的相关知识点一及在线OJ习题】

数据结构第三篇【链表的相关知识点一及在线OJ习题】 链表链表的实现链表OJ习题顺序表和链表的区别和联系 本文章主要讲解关于链表的相关知识&#xff0c;喜欢的可以三连喔 &#x1f600;&#x1f603;&#x1f604;&#x1f604;&#x1f60a;&#x1f60a;&#x1f643;&#…

【iOS】——Runtime学习

文章目录 一、Runtime介绍二、Runtime消息传递三、实例对象、类对象、元类对象四、isa_t结构体的具体实现五、cache_t的具体实现六、class_data_bits_t的具体实现七、Runtime消息转发动态方法解析备用接收者完整消息转发 一、Runtime介绍 iOS的Runtime&#xff0c;通常称为Obj…

GitHub飙升!京东认证的“Python编程入门三剑客”究竟好在哪?

Python凭借着简单易学、功能强大&#xff0c;已经跃居TIOB编程语言榜首&#xff0c;并且已经开始了它的霸榜之旅。如何选择一套适合自己的Python学习教程&#xff0c;是每个Python爱好者面临的首要问题。 今天给小伙伴们带来的是图灵&京东认证的“Python编程入门三剑客”&…

项目:仿RabbitMQ实现的消息队列组件

文章目录 写在前面开源仓库和项目上线其他文档说明 需求分析BrokerServer交换机类型持久化消息应答 模块划分服务端模块客户端模块交换机数据管理模块队列数据管理模块绑定数据管理模块消息数据管理模块队列信息管理模块虚拟机数据管理模块路由匹配模块消费者管理模块信道管理模…

gomail发送邮件的参数如何设置?如何使用?

gomail发送邮件的认证方式有哪些&#xff1f;怎么设置邮件发信&#xff1f; Gomail是一个常用的Go语言邮件发送库&#xff0c;它提供了简单易用的接口&#xff0c;使得邮件发送变得非常方便。AokSend将详细介绍如何设置gomail发送邮件的参数&#xff0c;帮助开发者更好地理解和…

Java实现经纬度坐标转换

一、坐标系统简介 坐标系统&#xff0c;是描述物质存在的空间位置&#xff08;坐标&#xff09;的参照系&#xff0c;通过定义特定基准及其参数形式来实现。 坐标是描述位置的一组数值&#xff0c;按坐标的维度一般分为一维坐标&#xff08;公路里程碑&#xff09;和二维坐标…

申请HTTPS证书的具体步骤是什么?

在当今数字化时代&#xff0c;网络安全已成为企业和个人关注的焦点。HTTPS证书作为网络安全的重要组成部分&#xff0c;不仅象征着网站的安全性&#xff0c;更是数据保护和用户信任的基石。本文将详细阐述HTTPS证书的重要性以及如何申请和配置HTTPS证书&#xff0c;以帮助网站所…