transformer入门学习(二)

import torch# pytorch
import torch.nn as nn# 模型工具包
import torch.nn.functional as F# 函数运算工具包
from torch.autograd import Variable# 变量处理包
import math
import matplotlib.pyplot as pyp
import numpy as np
import copy
import math
# embedding
class Embedding(nn.Module):
    def __init__(self,d_model,max_words):# 词向量维度,多少个单词或词语要做词向量
        super(Embedding,self).__init__()#调用父类初始化方法
        self.lut=nn.Embedding(max_words,d_model)#embedding层
        self.d_model=d_model
    def forward(self,x):#正向传播,(batch_size,max_len),单词别写错
        print('x形状:{},系数:{}'.format(x.shape,math.sqrt(self.d_model)))
        return self.lut(x)*math.sqrt(self.d_model)
# 位置编码层
class PositionEncoding(nn.Module):#位置编码
    # cxl_len,一个序列中某个单元(可以是单词,词组)对应的向量维度,seq_len:序列的长度
    def __init__(self,cxl_len,dropout,seq_len=1000):#假设词向量100维
        super(PositionEncoding,self).__init__()
        self.dropout=nn.Dropout(dropout)#定义dropout层,dropout,里面参数置0的比例
        # 定义的句子(序列)到向量的映射,是序列的向量表示
        seq_cxl_=torch.zeros(seq_len,cxl_len)# 初始化容器(200,100)
        seq_inx=torch.arange(seq_len).unsqueeze(1)# 序列的索引化表示(200,1)
        # ,unsqueeze(1)指在1轴增加维度
        temp_fz=torch.exp(torch.arange(0,cxl_len,2)\
                          *-(math.log(10000.0)/cxl_len))# 步长2,偶数列(1*50)
        # 第一个:指锁定所有行,第二个::2指锁定所有列,不过步长是2,其实选定的是偶数列
        # 因为选定偶数列,所以seq_cxl_[:,::2]形状是(200,50)==(200,1)*(1*50)
        # 偶数列向量值被赋正弦值,奇数列向量值被赋余弦值
        seq_cxl_[:,::2]=torch.sin(seq_inx*temp_fz)
        seq_cxl_[:,1::2]=torch.cos(seq_inx*temp_fz)
        seq_cxl_=seq_cxl_.unsqueeze(0)# 在0轴增加维度
        # 将词向量矩阵注册成模型的buffer,不随优化器同步更新参数,注册后,在模型保存后,和模型一起加载
        self.register_buffer('seq_cxl',seq_cxl_)
    def forward(self,x):# x形状(batch_size,seq_len),截取列到和x形状一样
        x=x+Variable(self.seq_cxl[:,:x.size(1)],requires_grad=False)
        return self.dropout(x)
def get_mask_tensor(size):# 构建掩码张量
    mask_shape=(1,size,size)#size指的是序列长度
    subseq_mask=np.triu(np.ones(mask_shape),k=1).astype('uint8')
    return torch.from_numpy(1-subseq_mask)# 得到下三角矩阵
# key,query,value代表注意力的三个输入张量,mask:掩码,dropout:Dropout对象
def attention(key,query,value,mask=None,dropout=None):# 比如key=query=value形状(2,4,512)
    cxl_dim=query.size(-1)# cxl_dim=512
    # 对query和key的转置做矩阵乘法,key最后两个轴做转置,除以一个缩放因子
    # (2,4,512)@(2,512,4)==(2,4,4),除了一个512的开方,相当于把数据变小处理
    # 这行代码的深层次意义就是构造了一个(seq_len,seq_len)的方阵,是为了遮掩,
    # 这样序列后边的信息才不会提前泄露,第一个词汇的向量会依次和整个序列的每一个词汇
    # 的向量做点乘,之后放到第一个词汇的一行(一共4(保存的是相关性)个信息),之后依次类推
    # 第二个词汇和整个序列的每个词汇做点乘,也有4个信息(保存的是第二个词汇和序列中每个词汇的相关性)
    # 最后就形成了一个方阵.最后除的那个是常数,只是为了把数据变小(2,8,4,64)@(2,8,64,4)=(2,8,4,4)
    scores=torch.matmul(query,key.transpose(-2,-1))/math.sqrt(cxl_dim)
    print('scores形状:',scores.shape)
    if mask is not None:# 如果有掩码
        #将scores中mask值为0的部分替换成一个很小的值,1的部分不变
        #mask形状和scores一致,mask中1的部分起了遮掩的作用
        print('mask',mask.shape)
        scores=scores.masked_fill(mask==0,1e-9)
    #对scores的最后一个维度做softmax操作,求概率,scores形状(2,4,4),在其上最后一维做softmax
    # 操作,返回形状也应该是(2,4,4),返回的是概率对应的标签
    p_attn=nn.functional.softmax(scores,dim=-1)#(2,4,4),2表示两个样本,4*4是上面计算的结果形状
    if dropout is not None:# 有dropout层就添加,dropout随机把p_attn中的一些值置0
        p_attn=dropout(p_attn)
    # 最后完成p_attn和value的乘法,和p_attn一起返回,p_attn是概率
    return torch.matmul(p_attn,value),p_attn#(2,4,4)@(2,4,512)=(2,4,512),p_attn:(2,4,4)
# 实现多头注意力机制的类
class MultiHeadAttent(nn.Module):
    # 把单个词汇向量分成几组,词维度,dropout层,进行dropout时,置0的比例
    def __init__(self,head,cxl_dim,dropout=0.1):
        super(MultiHeadAttent,self).__init__()# 断言词维度能被head整除
        assert cxl_dim % head==0
        self.d_k=cxl_dim//head# 每个头获得的深度(词向量维度//4)# 64
        print(self.d_k)
        self.head=head# 8
        self.cxl_dim=cxl_dim# 512
        # 获得线性层,一共四个,Q,K,V,和输出线性层
        # 拷贝线性层,拷贝4个
        self.linears=nn.ModuleList(
            [copy.deepcopy(nn.Linear(cxl_dim,cxl_dim)) for _ in range(4)])
        self.attn=None# 初始化注意力张量
        self.dropout=nn.Dropout(dropout)# 初始化dropout
        # Q,K,v是注意力机制的三个输入张量,mask掩码张量
    def forward(self,query,key,value,mask=None):# (2,4,512)--样本数,序列长度,词维度
        # 过滤条件:mask不是None,会被设置掩码,mask(8,4,4)
        if mask is not None:#这样掩码是4维,(8,1,4,4)
            mask=mask.unsqueeze(0)# 将掩码在索引0的轴进行扩充,掩码做的是掩盖序列,与样本数无关
            # 所以取1就行
        print('mask:',mask.shape)
        batch_size=query.size(0)# 得到样本数
        # 把Q,K,V和他们各自要被输入的层,像拉链一样绑定在一起        
        zip_group=zip(self.linears,(query,key,value))
        # 首先变形成(batch_size,seq_len,head,d_k)这样的形状(2,4,8, 64)
        query,key,value=[model(x).view(batch_size,-1,self.head,self.d_k) \
                         .transpose(1,2)# 之后让序列和代表几个头的轴交换,
                         #因为在attention里做的是后两个轴交换
                         for model,x in zip_group]
        #(2, 8, 4, 64)
        print('query,key,value,mask:',query.size(),key.shape,value.size(),mask.size())
        # 把query,key,value传入注意力方法,p_attn和value的乘法,和p_attn一起返回,p_attn是概率
        # 传入时形状是 (2, 8, 4, 64),之后q与k转置相乘,(2,8,4,64)@(2,8,64,4)=(2,8,4,4)
        #输出时(2,8,4,4)@(2,8,4,64)=(2,8,4,64)
        # 要明白传入的key,query,value形状是(2, 8, 4, 64),后面两个轴是(序列长度,分成组的词向量维度)
        x,self.attn=attention(key,query,value,mask=mask,dropout=self.dropout)
        print('x attention之后得形状',x.shape,self.attn.shape)#2, 8, 4, 64
        # 得到每个头的结果是4维的张量,前面已经进行过1,2两个维度的转置,现在要转置回来
        # 经过transpose方法后,必须使用contiguous方法,不然无法使用view方法   
        # (2,4,8,64)--view(2,4,512),做了一个连接变形操作
        x=x.transpose(1,2).contiguous().view(batch_size,-1,self.head*self.d_k)
        print('x concanate后的形状:',x.shape,self.attn.shape)
        #最后将x输入线性层列表的最后一个线性层进行处理,得到最终的输出
        return self.linears[-1](x)# linear传入和传出都是512
# 前馈全连接层
class Qk_qlj_Layers(nn.Module):
    # cxl_dim词嵌入维度,qlj_dim全连接层之间传递的维度
    def __init__(self,cxl_dim,qlj_dim,dropout=0.1):
        super(Qk_qlj_Layers,self).__init__()
        self.cxl_dim=cxl_dim
        self.qlj_dim=qlj_dim
        self.w1=nn.Linear(cxl_dim,qlj_dim)
        self.w2=nn.Linear(qlj_dim,cxl_dim)
        self.dropout=nn.Dropout(dropout)
        print(cxl_dim,qlj_dim,dropout)
    def forward(self,x):
        # x代表上一层的输出,这里用的是经过多头机制处理后的输出,
        # 之后经过全连接1层,之后relu激活处理
        # 之后dropout随机置0处理,最后交由全连接二层处理输出
        # 输出形状(2,4,512),没有变化
        return self.w2(self.dropout(F.relu(self.w1(x))))
# 构造规范化层的类,做标准化处理的层
class Layer_Normer(nn.Module):
    # cxl_dim,词嵌入维度,eps:用在规范化计算的分母中,防止除0操作
    def __init__(self,cxl_dim,eps=1e-6):
        super(Layer_Normer,self).__init__()
        self.cxl_dim=cxl_dim
        self.eps=eps
        # 初始化两个张量,用来对结果做规范化操作
        self.a1=nn.Parameter(torch.ones(cxl_dim))
        self.a2=nn.Parameter(torch.zeros(cxl_dim))
    def forward(self,x):# (2,4,512)
        # x:代表上一层网络的输出,首先对x进行最后一个维度上的求均值
        # 操作,同时保持输入维度和输出维度一致
        mean=x.mean(-1,keepdim=True)
        # 接着对x进行最后一个维度上的求标准差的操作,保持输入维度和输出维度一致
        std=x.std(-1,keepdim=True)
        print('正要进行标准化处理........')
        # 按照规范化公式计算并返回
        return self.a1*(x-mean)/(std+self.eps)+self.a2
# 构建子层连接结构的类
class SubLayerConnection(nn.Module):
    def __init__(self,cxl_dim,dropout=0.1):
        super(SubLayerConnection,self).__init__()
        # 实例化一个规范化层的类
        self.norm=Layer_Normer(cxl_dim)
        self.dropout=nn.Dropout(dropout)
        self.cxl_dim=cxl_dim
    def forward(self,x,sublayer):
        # x:代表上一层传入的张量
        # sublayer,该子层连接中的子层函数
        # 首先将x标准化处理,之后送入子层函数处理,之后经过dropout处理
        # 最后进行残差连接
        return x+self.dropout(sublayer(self.norm(x)))
def copy_(layer,n):
    return [copy.deepcopy(layer) for _ in range(n)]
# 构建编码器层的类
class EncoderLayer(nn.Module):
    # 词嵌入维度,多头注意力对象,前馈全连接层对象,进行dropout时的置零比例
    def __init__(self,cxl_dim,multhead,qk_qlj,dropout=0.1):
        super(EncoderLayer,self).__init__()
        # 将这些参数赋值给对象,以便以后调用
        self.cxl_dim=cxl_dim
        self.multhead=multhead
        self.qk_qlj=qk_qlj
        #编码器层有两个子层连接结构,用copy_方法
        self.sublayer_con=copy_(SubLayerConnection(cxl_dim,dropout),2)
        print('进入EncoderLayer.....')
    def forward(self,x,mask):
        # x代表上一层的传人张量,mask代表掩码张量
        # 首先让x经过第一个子层连接结构,内部包含多头自注意力机制
        # 再让张量经过第二个子层连接结构,其中包括前馈全连接网络
        # 调用子连接层需要传入两个参数,x,和子层函数
        x=self.sublayer_con[0](x,lambda x:self.multhead(x,x,x,mask))
        return self.sublayer_con[1](x,self.qk_qlj)
# 构建编码器类,经过n个编码器层类和标准化后的输出
class Encoder(nn.Module):
    # layer表示编码器层类对象,N表示要几个编码器层
    def __init__(self,layer,N):
        super(Encoder,self).__init__()
        # 首先使用copy函数复制N个编码器层放在self.layers中
        self.layers=copy_(layer,N)
        print(layer.cxl_dim)
        # 初始化一个标准化层
        self.norm_layer=Layer_Normer(layer.cxl_dim)
    def forward(self,x,mask):
        # x:代表上一层的输出张量,mask代表掩码张量
        # 让x依次经过N个编码器层处理,之后经过标准化层处理输出
        for layer in self.layers:
            x=layer(x,mask)
        return self.norm_layer(x)#别写到循环里面
#构建解码器层类
class Decoderlayer(nn.Module):
    # 参数:词嵌入维度,多头自注意力机制实例对象,普通的注意力机制对象,前馈全连接层对象,
    # dropout:随机置0的比率,普通注意力对象和自注意力的区别是q和k,v不相同,自注意力的三者全相同
    def __init__(self,cxl_dim,self_attn,src_attn,qk_qlj,dropout):
        super(Decoderlayer,self).__init__()
        # 初始化类对象
        self.cxl_dim=cxl_dim
        self.self_attn=self_attn
        self.src_attn=src_attn
        self.qk_qlj=qk_qlj
        # 按照解码器层的结构,复制3个子层连接对象
        self.sublayer=copy_(SubLayerConnection(cxl_dim,dropout),3)
        print('进入Decoderlayer.....',len(self.sublayer))
        # x:代表上一层输入的张量,memory:代表编码器的语义存储张量
        # source_mask:原数据的掩码张量,target_mask:目标数据的掩码张量
        # 要明确的一点是,原数据用掩码和目标数据用掩码不一样,目标用掩码是防止
        # 当前词汇和之后得信息泄露,电脑看到的只有前面的词汇,而原数据掩码,是防止
    #电脑过度关注一些不太有用的信息
    def forward(self,x,memory,source_mask,target_mask):
        # 第一步让x经过第一个子层,多头自注意力的子层,采用target_mask,遮掩当前词和当前词后边的
        x=self.sublayer[0](x,lambda x : self.self_attn(x,x,x,target_mask))
        # 第二步,让x经历常规注意力的子层,Q!=K,K==V
        # 采用source_mask,为了遮掩掉对结果信息无用的数据,memory之前的编码输出
        x=self.sublayer[1](x,lambda x : self.src_attn(x,memory,memory,source_mask))
        # 第三步,让x经历第三个子层,前馈全连接层,并返回数据
        return self.sublayer[2](x,self.qk_qlj)
 构建解码器类
class Decoder(nn.Module):
    def __init__(self,decoder_layer,N):
        # layer:代表解码器层对象,N:指要拷贝多少个
        super(Decoder,self).__init__()
        self.layers=copy_(decoder_layer,N)
        print('layers:',len(self.layers))
        # 初始化一个标准化层
        self.norm_layer=Layer_Normer(decoder_layer.cxl_dim)
    def forward(self,x,memory,source_mask,target_mask):
        #x,代表目标数据的嵌入表示,memory,表示编码器的输出张量
        # source_mask:原数据的掩码张量,target_mask:目标数据的掩码张量
        #要让x经过所有的解码器层处理,最后标准化输出
        for layer in self.layers:
            x=layer(x,memory,source_mask,target_mask)
        return self.norm_layer(x)

#构建Generator类
class Generator_(nn.Module):
    # 词嵌入的维度,要词嵌入的词汇大小
    def __init__(self,d_dim,max_words):
        super(Generator_,self).__init__()
        # 定义一个线性层,完成网络输出维度的变换
        self.linear1=nn.Linear(d_dim,max_words)
    def forward(self,x):# NotImplementedError,写错方法名会报这个错
        #x,是上一层的输出张量,先将x送入线性层转换维度,之后经由
        # log_softmax求概率
        return F.log_softmax(self.linear1(x),dim=-1)
# 构建编码解码器类
class Encoder_Decoder(nn.Module):
    def __init__(self,encoder,decoder,source_embed,target_embed,generator):
        # encoder,指编码器对象,decoder:指解码器对象,source_embed:原数据的嵌入函数
        # target_embed:指目标数据的嵌入函数,generator:指输出部分类别生成器对象
        super(Encoder_Decoder,self).__init__()
        # 初始化类对象
        self.encoder=encoder
        self.decoder=decoder
        self.src_embed=source_embed
        self.tgt_embed=target_embed
        self.generator=generator
    def forward(self,source,target,source_mask,target_mask):
        # source:原数据,target:目标数据,source_mask:原数据掩码,target_mask:目标数据掩码
        # self.encode(source,source_mask)--编码后就是memory
        de_output=self.decode(self.encode(source,source_mask),\
                           source_mask,target,target_mask)
        return self.generator(de_output)
    def encode(self,source,source_mask):
        #调用真实的编码器对象的forward方法
        return self.encoder(self.src_embed(source),source_mask)
        #x,memory,source_mask,target_mask
    def decode(self,memory,source_mask,target,target_mask):
        # memory:经过编码器编码后的输出,保存着编码后的信息
        return self.decoder(self.tgt_embed(target),\
                            memory,source_mask,target_mask)
def make_model(source_vocab,target_vocab,N=6,d_dim=512,d_ff=2048,head=8,dropout=0.1):
    # source_vocab:原数据的词汇总数(这个取决于你选多少词汇),target_vocab:目标数据的词汇总数
    # N:代表编码器或解码器堆叠的层数,d_dim:代表词嵌入的维度,d_ff:前馈全连接层中变化矩阵的维度
    # head:多头注意力机制中的头数(把词向量分成几份),dropout:随机置0的比率
    c=copy.deepcopy
    attn=MultiHeadAttent(head,d_dim)# 实例化一个多头注意力类实例
    ff=Qk_qlj_Layers(d_dim,d_ff,dropout)# 实例化一个前馈全连接层的实例
    position=PositionEncoding(d_dim,dropout)# 实例化一个位置编码器
    #实例化模型,利用的是Encoder_Decoder类
    # 编码器层的结构里有两个子层连接层,attention层和前馈全连接层
    # 解码器层的结构里有三个子层连接,两个attention层和一个前馈全连接
    model=Encoder_Decoder(
        # c可以深拷贝,对象在内存占用不同的内存空间
        Encoder(EncoderLayer(d_dim,c(attn),c(ff),dropout),N),
        Decoder(Decoderlayer(d_dim,c(attn),c(attn),c(ff),dropout),N),
        nn.Sequential(Embedding(d_dim,source_vocab),c(position)),
        nn.Sequential(Embedding(d_dim,target_vocab),c(position)),
        Generator_(d_dim,target_vocab)
    )
    # 初始化模型中的参数,如果维度大于1,初始化成一个服从均匀分布的矩阵
    for p in model.parameters():
        if p.dim()>1:
            nn.init.xavier_uniform_(p)
    return model

source_vocab=11
target_vocab=11
N=6
res=make_model(source_vocab,target_vocab,N)
print(res)

np.set_printoptions(suppress=True)
w=torch.empty(3,5)
# 随机初始化为均匀分布
w=nn.init.xavier_uniform_(w,gain=nn.init.calculate_gain('relu'))

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

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

相关文章

记录一下在Pycharm中虚拟环境的创建

如果在Pycharm中要新建一个虚拟环境,那你可以在Terminal中选择Command Prompt,在这里面执行相关命令 一、安装了Anaconda,创建虚拟环境 当你使用解释器是Anaconda提供的时,你可以使用conda命令执行,见以下操作&#x…

前端Vue与uni-app中的九宫格、十二宫格和十五宫格菜单组件实现

在前端 Vue 开发中,我们经常会遇到需要开发九宫格、十二宫格和十五宫格菜单按钮的需求。这些菜单按钮通常用于展示不同的内容或功能,提供给用户快速访问和选择。 一、引言 在前端开发中,九宫格、十二宫格和十五宫格菜单按钮是一种常见的布局…

202206 CSP认证 | 角色授权

角色授权 fine,又是一道acwing上TLE但是平台通过了的,那就酱吧… 直接跟着题目来模拟的…先找到每个用户授予的所有角色,包括用户本身和它所属的用户组。 然后遍历这个角色集合,看是否有操作权限,种类权限以及资源名称…

Android 辅助功能 -抢红包

Android 辅助功能 -抢红包 本篇文章主要介绍下通过android辅助功能的方式来实现类似抢红包的功能. 1:权限声明 <uses-permissionandroid:name"android.permission.BIND_ACCESSIBILITY_SERVICE"tools:ignore"ProtectedPermissions" />2: 配置信息 …

SVN修改已提交版本的注释

目录 一、需求分析 二、问题分析 三、解决办法 一、需求分析 ​开发过程中&#xff0c;在SVN提交文件后&#xff0c;发现注释写的不完整或不够明确&#xff0c;想再修改之前的注释文字​。 使用环境&#xff1a; SVN服务器操作系统&#xff1a;Ubuntu 20.04.6 LTS SVN版本&…

Numpy数轴编号规则

当在NumPy数组中增加维度时&#xff0c;轴号的分配遵循一个明确的规则&#xff1a;每个新添加的维度都会作为一个新的轴被添加到数组形状的最前面&#xff0c;这意味着新轴成为轴0&#xff0c;原有的所有轴号随之增加。 精准描述&#xff1a; 对于一个已存在的N维数组&#x…

C语言实现二叉树

#include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构体 typedef struct TreeNode { int value; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 创建二叉树节点的函数 TreeNode* createNode(int value) { TreeNod…

JVM实战篇

内存调优 内存溢出和内存泄漏 内存泄漏&#xff1a;在java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收。 内存泄漏绝大多数情况都是由堆内存泄漏引起的&#xff0c;所以后续没有特别说明则讨论的都是堆…

Linux-centos如何搭建yum源仓库

1.本地搭建&#xff08;无需连接外网&#xff09; 1.1检查网络配置&#xff0c;及网络连接 打开虚拟机&#xff0c;点击【编辑——虚拟网络编辑器】 点击【仅主机模式】查看子网段是否和局内IP匹配 进入局内&#xff0c;查看网络IP是否在你上述设置的网段内&#xff0c;如果不…

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem 从这一章开始讲负反馈Control系统和小信号建模. 13.2 The Feedback Theorem 首先介绍 Middlebrook’s Feedback Theorem 考虑下面负反馈系统 传输函数 Guo/ui G ( s ) u o u i G ∞ T 1 T G…

1.实用Qt:解决绘制圆角边框时,圆角锯齿问题

目录 问题描述 解决方案 方案1&#xff1a; 方案2&#xff1a; 结果示意图 问题描述 做UI的时候&#xff0c;我们很多时候需要给绘制一个圆角边框&#xff0c;初识Qt绘制的童鞋&#xff0c;可能绘制出来的圆角边框很是锯齿&#xff0c;而且粗细不均匀&#xff0c;如下图&…

Vue | 使用 ECharts 绘制折线图

目录 一、安装和引入 ECharts 二、使用 ECharts 2.1 新增 div 盒子 2.2 编写画图函数 2.3 完整代码结构 三、各种小问题 3.1 函数调用问题 3.2 数据格式问题 3.3 坐标轴标签问题 3.4 间隔显示标签 参考博客&#xff1a;Vue —— ECharts实现折线图 本文是在上…

JVM学习-JVM简介以及其内部结构

目录 1.什么是JVM 2.JVM、JRE、JDK、JavaSE、JavaEE之间的联系 3.JVM的内部结构 4.各部分的作用 4.1 类加载器 4.2 方法区 4.3 堆 ​编辑 4.4 虚拟机栈 4.5 程序计数器 4.6 本地方法栈 4.7 解释器和JIT即时编译器 4.9 GC垃圾回收 5.拓展 5.1一些可能会遇到的问…

opencv安装(C++)并配置vs

准备工作&#xff1a; 1.opencv安装包(此教程使用4.9) 2.visual studio(此教程使用vs2019) opencv安装&#xff1a; 1、下载opencv&#xff1a; 1.1 官网下载&#xff1a;Releases - OpenCV 1.2 百度网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1NpEoFjbbyQJtFD…

CTF-希尔加解密

对于希尔加解密很多writeup都说用在线工具&#xff0c;所以研究了一下&#xff0c;写了一个方便的加解密python代码&#xff0c;根据给定的字母表及私钥字符串&#xff0c;尝试不同纬度不同重叠的加密矩阵输出加解密结果。运行效果如下&#xff1a; 代码文件Hill希尔加解密_fi…

8:00面试,8:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到9月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Portal

文章目录 定义用法事件冒泡 定义 Portals 提供了一个最好的在父组件包含的DOM结构层级外的DOM节点渲染组件的方法。 ReactDOM.createPortal(child,container);第一个参数child是可渲染的react子项&#xff0c;比如元素&#xff0c;字符串或者片段等。第二个参数container是一…

matlab simulink 工业现场漆包机烘炉模糊PID控制算法

1、内容简介 略 70-可以交流、咨询、答疑 2、内容说明 matlab simulink 工业现场漆包机烘炉模糊PID控制算法 第五章 控制算法仿真与分析 在第二章系统分析结合工业现场漆包机烘炉数学模型详细分析模糊PID控制算法以及解耦控制算法的优缺点、实现原理&#xff0c;为本章算法…

第8节课------列生成与分支定价法

列生成与分支定价法 1. 列生成 通过迭代的方式来构建和解决一个“受限”的主问题,并通过解决一系列相关的子问题来动态地生成新的变量(或称列),这些新变量有可能改进主问题的解。 原问题新添加的这一列可以通过对偶问题的行来计算。 2. 列生成的详细说明 对于原来的…

【TB作品】数字电压表设计,MSP430,电压表,Proteus仿真,分档位

文章目录 题目要求第1版方案第2版方案代码介绍获取代码和仿真 题目要求 33、数字电压表设计 基本要求: 了解电压表的工作原理。 对0~2.5V的模拟电压进行循环采集 采集的数据进行A/D转换后用LCD屏显示测量值,显示精度0.0001 用键盘选择测量范围(分档) 超过测量范围时指示灯持续…