【pytorch】现代卷积神经网络
文章目录
- 1 AlexNet
- 2 VGG
- 3 NiN
- 4 GoogLeNet
- 5 批量规范化batch normalization
- 6 ResNet
- 6.1 残差块
- 6.2 resnet
- 7 DenseNet
- 7.1 稠密块体
- 7.2 过渡层
- 7.3 DenseNet模型
1 AlexNet
AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个全连接输出层。
AlexNet使用ReLU而不是sigmoid作为其激活函数。
AlexNet通过暂退法(Dropout)控制全连接层的模型复杂度
import torch
from torch import nn
from d2l import torch as d2lnet = nn.Sequential(# 这里使用一个11*11的更大窗口来捕捉对象。# 同时,步幅为4,以减少输出的高度和宽度。# 另外,输出通道的数目远大于LeNetnn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),# 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),# 使用三个连续的卷积层和较小的卷积窗口。# 除了最后的卷积层,输出通道的数量进一步增加。# 在前两个卷积层之后,汇聚层不用于减少输入的高度和宽度nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Flatten(),# 这里,全连接层的输出数量是LeNet中的好几倍。使用dropout层来减轻过拟合nn.Linear(6400, 4096), nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5),# 最后是输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000nn.Linear(4096, 10))
2 VGG
VGG网络可以分为两部分:第一部分主要由卷积层和汇聚层组成,第二部分由全连接层组成。
我们定义了一个名为vgg_block的函数来实现一个VGG块。
import torch
from torch import nn
from d2l import torch as d2ldef vgg_block(num_convs, in_channels, out_channels):layers = []for _ in range(num_convs):layers.append(nn.Conv2d(in_channels, out_channels,kernel_size=3, padding=1))layers.append(nn.ReLU())in_channels = out_channelslayers.append(nn.MaxPool2d(kernel_size=2,stride=2))return nn.Sequential(*layers)
原始VGG网络有5个卷积块,其中前两个块各有一个卷积层,后三个块各包含两个卷积层。 第一个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。由于该网络使用8个卷积层和3个全连接层,因此它通常被称为VGG-11。
下面的代码实现了VGG-11。可以通过在conv_arch上执行for循环来简单实现。
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
def vgg(conv_arch):conv_blks = []in_channels = 1# 卷积层部分for (num_convs, out_channels) in conv_arch:conv_blks.append(vgg_block(num_convs, in_channels, out_channels))in_channels = out_channelsreturn nn.Sequential(*conv_blks, nn.Flatten(),# 全连接层部分nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),nn.Linear(4096, 10))net = vgg(conv_arch)
3 NiN
NiN的想法是在每个像素位置(针对每个高度和宽度)应用一个全连接层。如果我们将权重连接到每个空间位置,我们可以将其视为1 × 1卷积层,或作为在每个像素位置上独立作用的全连接层。从另一个角度看,即将空间维度中的每个像素视为单个样本,将通道维度视为不同特征(feature)。
NiN块定义:
import torch
from torch import nn
from d2l import torch as d2ldef nin_block(in_channels, out_channels, kernel_size, strides, padding):return nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),nn.ReLU(),nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())
NiN和AlexNet之间的一个显著区别是NiN完全取消了全连接层。相反,NiN使用一个NiN块,其输出通道数等于标签类别的数量。最后放一个全局平均汇聚层(global average pooling layer),生成一个对数几率(logits)。
net = nn.Sequential(nin_block(1, 96, kernel_size=11, strides=4, padding=0),nn.MaxPool2d(3, stride=2),nin_block(96, 256, kernel_size=5, strides=1, padding=2),nn.MaxPool2d(3, stride=2),nin_block(256, 384, kernel_size=3, strides=1, padding=1),nn.MaxPool2d(3, stride=2),nn.Dropout(0.5),# 标签类别数是10nin_block(384, 10, kernel_size=3, strides=1, padding=1),nn.AdaptiveAvgPool2d((1, 1)),# 将四维的输出转成二维的输出,其形状为(批量大小,10)nn.Flatten())
4 GoogLeNet
在GoogLeNet中,基本的卷积块被称为Inception块
前三条路径使用窗口大小为1 × 1、3 × 3和5 × 5的卷积层,从不同空间大小中提取信息。中间的两条路径在输入上执行1 × 1卷积,以减少通道数,从而降低模型的复杂性。第四条路径使用3 × 3最大汇聚层,然后使用1 × 1卷积层来改变通道数。这四条路径都使用合适的填充来使输入与输出的高和宽一致,最后我们将每条线路的输出在通道维度上连结,并构成Inception块的输出。在Inception块中,通常调整的超参数是每层输出通道数。
import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2lclass Inception(nn.Module):# c1--c4是每条路径的输出通道数def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):super(Inception, self).__init__(**kwargs)# 线路1,单1x1卷积层self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)# 线路2,1x1卷积层后接3x3卷积层self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)# 线路3,1x1卷积层后接5x5卷积层self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)# 线路4,3x3最大汇聚层后接1x1卷积层self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)def forward(self, x):p1 = F.relu(self.p1_1(x))p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))p4 = F.relu(self.p4_2(self.p4_1(x)))# 在通道维度上连结输出return torch.cat((p1, p2, p3, p4), dim=1)
GoogLeNet一共使用9个Inception块和全局平均汇聚层的堆叠来生成其估计值。Inception块之间的最大汇聚层可降低维度。第一个模块类似于AlexNet和LeNet,Inception块的组合从VGG继承,全局平均汇聚层避免了在最后使用全连接层。
逐一实现GoogLeNet的每个模块。
第一个模块使用64个通道、7 × 7卷积层。
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
第二个模块使用两个卷积层:第一个卷积层是64个通道、1×1卷积层;第二个卷积层使用将通道数量增加三倍的3×3卷积层。
b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),nn.ReLU(),nn.Conv2d(64, 192, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
第三个模块串联两个完整的Inception块。 第一个Inception块的输出通道数为64+128+32+32=256,四个路径之间的输出通道数量比为64:128:32:32=2:4:1:1。 第二个和第三个路径首先将输入通道的数量分别减少到96/192=1/2和16/192=1/12,然后连接第二个卷积层。第二个Inception块的输出通道数增加到128+192+96+64=480,四个路径之间的输出通道数量比为128:192:96:64=4:6:3:2。 第二条和第三条路径首先将输入通道的数量分别减少到128/256=1/2和32/256=1/8。
b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),Inception(256, 128, (128, 192), (32, 96), 64),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
第四模块更加复杂, 它串联了5个Inception块,其输出通道数分别是192+208+48+64=512、160+224+64+64=512、128+256+64+64=512、112+288+64+64=528和256+320+128+128=832。 这些路径的通道数分配和第三模块中的类似,首先是含3×3卷积层的第二条路径输出最多通道,其次是仅含1×1卷积层的第一条路径,之后是含5×5卷积层的第三条路径和含3×3最大汇聚层的第四条路径。 其中第二、第三条路径都会先按比例减小通道数。
b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),Inception(512, 160, (112, 224), (24, 64), 64),Inception(512, 128, (128, 256), (24, 64), 64),Inception(512, 112, (144, 288), (32, 64), 64),Inception(528, 256, (160, 320), (32, 128), 128),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
第五模块包含输出通道数为256+320+128+128=832和384+384+128+128=1024的两个Inception块。 其中每条路径通道数的分配思路和第三、第四模块中的一致,只是在具体数值上有所不同。 需要注意的是,第五模块的后面紧跟输出层,该模块同NiN一样使用全局平均汇聚层,将每个通道的高和宽变成1。 最后我们将输出变成二维数组,再接上一个输出个数为标签类别数的全连接层。
b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),Inception(832, 384, (192, 384), (48, 128), 128),nn.AdaptiveAvgPool2d((1,1)),nn.Flatten())net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10))
5 批量规范化batch normalization
在每次训练迭代中,我们首先规范化输入,即通过减去其均值并除以其标准差,其中两者均基于当前小批量处理。接下来,我们应用比例系数和比例偏移。
只有使用足够大的小批量,批量规范化这种方法才是有效且稳定的。请注意,在应用批量规范化时,批量大小的选择可能比没有批量规范化时更重要。
批量规范化BN根据以下表达式转换x:
µˆB是小批量B的样本均值,σˆ B是小批量B的样本标准差。应用标准化后,生成的小批量的平均值为0和单位方差为1。由于单位方差(与其他一些魔法数)是一个主观的选择,因此我们通常包含拉伸参数(scale)γ和偏移参数(shift)β,它们的形状与x相同。
在方差估计值中添加一个小的常量ϵ > 0,以确保我们永远不会尝试除以零,即使在经验方差估计值可能消失的情况下也是如此。
**批量规范化层在”训练模式“(通过小批量统计数据规范化)和“预测模式”(通过数据集统计规范化)中的功能不同。**在训练过程中,我们无法得知使用整个数据集来估计平均值和方差,所以只能根据每个小批次的平均值和方差不断训练模型。而在预测模式下,可以根据整个数据集精确计算批量规范化所需的平均值和方差。
**全连接层和卷积层,他们的批量规范化实现略有不同。**将批量规范化层置于全连接层中的仿射变换和激活函数之间。在卷积层之后和非线性激活函数之前应用批量规范化。当卷积有多个输出通道时,我们需要对这些通道的“每个”输出执行批量规范化,每个通道都有自己的拉伸(scale)和偏移(shift)参数,这两个参数都是标量。假设我们的小批量包含m个样本,并且对于每个通道,卷积的输出具有高度p和宽度q。那么对于卷积层,我们在每个输出通道的m · p · q个元素上同时执行每个批量规范化。因此,在计算平均值和方差时,我们会收集所有空间位置的值,然后在给定通道内应用相同的均值和方差,以便在每个空间位置对值进行规范化。
我们从头开始实现一个具有张量的批量规范化层:
import torch
from torch import nn
from d2l import torch as d2ldef batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):# 通过is_grad_enabled来判断当前模式是训练模式还是预测模式if not torch.is_grad_enabled():# 如果是在预测模式下,直接使用传入的移动平均所得的均值和方差X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)else:assert len(X.shape) in (2, 4)if len(X.shape) == 2:# 使用全连接层的情况,计算特征维上的均值和方差mean = X.mean(dim=0)var = ((X - mean) ** 2).mean(dim=0)else:# 使用二维卷积层的情况,计算通道维上(axis=1)的均值和方差。# 这里我们需要保持X的形状以便后面可以做广播运算mean = X.mean(dim=(0, 2, 3), keepdim=True)var = ((X - mean) ** 2).mean(dim=(0, 2, 3), keepdim=True)# 训练模式下,用当前的均值和方差做标准化X_hat = (X - mean) / torch.sqrt(var + eps)# 更新移动平均的均值和方差moving_mean = momentum * moving_mean + (1.0 - momentum) * meanmoving_var = momentum * moving_var + (1.0 - momentum) * varY = gamma * X_hat + beta # 缩放和移位return Y, moving_mean.data, moving_var.data
现在可以创建一个正确的BatchNorm层。这个层将保持适当的参数:拉伸gamma和偏移beta,这两个参数将在训练过程中更新。此外,我们的层将保存均值和方差的移动平均值,以便在模型预测期间随后使用。
class BatchNorm(nn.Module):# num_features:完全连接层的输出数量或卷积层的输出通道数。# num_dims:2表示完全连接层,4表示卷积层def __init__(self, num_features, num_dims):super().__init__()if num_dims == 2:shape = (1, num_features)else:shape = (1, num_features, 1, 1)# 参与求梯度和迭代的拉伸和偏移参数,分别初始化成1和0self.gamma = nn.Parameter(torch.ones(shape))self.beta = nn.Parameter(torch.zeros(shape))# 非模型参数的变量初始化为0和1self.moving_mean = torch.zeros(shape)self.moving_var = torch.ones(shape)def forward(self, X):# 如果X不在内存上,将moving_mean和moving_var# 复制到X所在显存上if self.moving_mean.device != X.device:self.moving_mean = self.moving_mean.to(X.device)self.moving_var = self.moving_var.to(X.device)# 保存更新过的moving_mean和moving_varY, self.moving_mean, self.moving_var = batch_norm(X, self.gamma, self.beta, self.moving_mean,self.moving_var, eps=1e-5, momentum=0.9)return Y
也可以直接使用深度学习框架中定义的BatchNorm:
net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5), **nn.BatchNorm2d(6)**, nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(6, 16, kernel_size=5), **nn.BatchNorm2d(16)**, nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),nn.Linear(256, 120), **nn.BatchNorm1d(120)**, nn.Sigmoid(),nn.Linear(120, 84), **nn.BatchNorm1d(84)**, nn.Sigmoid(),nn.Linear(84, 10))
6 ResNet
6.1 残差块
ResNet沿用了VGG完整的3 × 3卷积层设计。残差块里首先有2个有相同输出通道数的3 × 3卷积层。每个卷积层后接一个批量规范化层和ReLU激活函数。然后我们通过跨层数据通路,跳过这2个卷积运算,将输入直接加在最后的ReLU激活函数前。
import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2lclass Residual(nn.Module): #@savedef __init__(self, input_channels, num_channels,use_1x1conv=False, strides=1):super().__init__()self.conv1 = nn.Conv2d(input_channels, num_channels,kernel_size=3, padding=1, stride=strides)self.conv2 = nn.Conv2d(num_channels, num_channels,kernel_size=3, padding=1)if use_1x1conv:self.conv3 = nn.Conv2d(input_channels, num_channels,kernel_size=1, stride=strides)else:self.conv3 = Noneself.bn1 = nn.BatchNorm2d(num_channels)self.bn2 = nn.BatchNorm2d(num_channels)def forward(self, X):Y = F.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.conv3:X = self.conv3(X)Y += Xreturn F.relu(Y)
此代码生成两种类型的网络:一种是当use_1x1conv=False时,应用ReLU非线性函数之前,将输入添加到输出。另一种是当use_1x1conv=True时,添加通过1 × 1卷积调整通道和分辨率。
6.2 resnet
ResNet的前两层跟之前介绍的GoogLeNet中的一样: 在输出通道数为64、步幅为2的7×7卷积层后,接步幅为2的3×3的最大汇聚层。 不同之处在于ResNet每个卷积层后增加了批量规范化层。
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
GoogLeNet在后面接了4个由Inception块组成的模块。 ResNet则使用4个由残差块组成的模块,每个模块使用若干个同样输出通道数的残差块。 第一个模块的通道数同输入通道数一致。 由于之前已经使用了步幅为2的最大汇聚层,所以无须减小高和宽。 之后的每个模块在第一个残差块里将上一个模块的通道数翻倍,并将高和宽减半。
def resnet_block(input_channels, num_channels, num_residuals,first_block=False):blk = []for i in range(num_residuals):if i == 0 and not first_block:blk.append(Residual(input_channels, num_channels,use_1x1conv=True, strides=2))else:blk.append(Residual(num_channels, num_channels))return blk
在ResNet加入所有残差块,这里每个模块使用2个残差块。
b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))
与GoogLeNet一样,在ResNet中加入全局平均汇聚层,以及全连接层输出。
net = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1,1)),nn.Flatten(), nn.Linear(512, 10))
每个模块有4个卷积层(不包括恒等映射的1×1卷积层)。 加上第一个7×7卷积层和最后一个全连接层,共有18层。 因此,这种模型通常被称为ResNet-18。
7 DenseNet
稠密连接网络(DenseNet)在某种程度上是ResNet的逻辑扩展。
ResNet(左)与 DenseNet(右)在跨层连接上的主要区别:使用相加和使用连结。ResNet和DenseNet的关键区别在于,DenseNet输出是连接(用图中的[, ]表示)而不是如ResNet的简单相加。
最后一层与之前的所有层紧密相连。
稠密网络主要由2部分构成:稠密块(dense block)和过渡层(transition layer)。前者定义如何连接输入和输出,而后者则控制通道数量。
7.1 稠密块体
DenseNet使用了ResNet改良版的“批量规范化、激活和卷积”架构
import torch
from torch import nn
from d2l import torch as d2ldef conv_block(input_channels, num_channels):return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1))
一个稠密块由多个卷积块组成,每个卷积块使用相同数量的输出通道。 然而,在前向传播中,我们将每个卷积块的输入和输出在通道维上连结。
class DenseBlock(nn.Module):def __init__(self, num_convs, input_channels, num_channels):super(DenseBlock, self).__init__()layer = []for i in range(num_convs):layer.append(conv_block(num_channels * i + input_channels, num_channels))self.net = nn.Sequential(*layer)def forward(self, X):for blk in self.net:Y = blk(X)# 连接通道维度上每个块的输入和输出X = torch.cat((X, Y), dim=1)return X
7.2 过渡层
由于每个稠密块都会带来通道数的增加,使用过多则会过于复杂化模型。 而过渡层可以用来控制模型复杂度。 它通过1×1卷积层来减小通道数,并使用步幅为2的平均汇聚层减半高和宽,从而进一步降低模型复杂度。
def transition_block(input_channels, num_channels):return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=1),nn.AvgPool2d(kernel_size=2, stride=2))
7.3 DenseNet模型
构造DenseNet模型。DenseNet首先使用同ResNet一样的单卷积层和最大汇聚层。
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
类似于ResNet使用的4个残差块,DenseNet使用的是4个稠密块。与ResNet类似,我们可以设置每个稠密块使用多少个卷积层。这里我们设成4,从而与 7.6节的ResNet‐18保持一致。稠密块里的卷积层通道数(即增长率)设为32,所以每个稠密块将增加128个通道。
在每个模块之间,ResNet通过步幅为2的残差块减小高和宽,DenseNet则使用过渡层来减半高和宽,并减半通道数。
# num_channels为当前的通道数
num_channels, growth_rate = 64, 32
num_convs_in_dense_blocks = [4, 4, 4, 4]
blks = []
for i, num_convs in enumerate(num_convs_in_dense_blocks):blks.append(DenseBlock(num_convs, num_channels, growth_rate))# 上一个稠密块的输出通道数num_channels += num_convs * growth_rate# 在稠密块之间添加一个转换层,使通道数量减半if i != len(num_convs_in_dense_blocks) - 1:blks.append(transition_block(num_channels, num_channels // 2))num_channels = num_channels // 2
与ResNet类似,最后接上全局汇聚层和全连接层来输出结果。
net = nn.Sequential(b1, *blks,nn.BatchNorm2d(num_channels), nn.ReLU(),nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(num_channels, 10))
相关文章:
【pytorch】现代卷积神经网络
文章目录 1 AlexNet2 VGG3 NiN4 GoogLeNet5 批量规范化batch normalization6 ResNet6.1 残差块6.2 resnet 7 DenseNet7.1 稠密块体7.2 过渡层7.3 DenseNet模型 1 AlexNet AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个全连接输出层。 AlexNet使用ReLU而不…...
Excel 身份证号计算年龄
1. 设置身份证号列格式 复制身份证列值到记事本或其他地方重新设置身份证号列单元格格式为“文本”将复制出去的身份证号重新复制粘贴回来 2. 年龄列单元格中添加公式 DATEDIF(DATE(LEFT(MID(A2, 7, 8), 4), MID(MID(A2, 7, 8), 5, 2), RIGHT(MID(A2, 7, 8), 2)), TODAY(), …...
【ArcGIS Pro】完整的nc文件整理表格模型构建流程及工具练习数据分享
学术科研啥的要用到很多数据,nc文件融合了时间空间数据是科研重要文件。之前分享过怎样将nc文件处理成栅格后整理成表格。小编的读者还是有跑不通整个流程的,再来做一篇总结篇,也分享下练习数据跟工具,如果还是弄不了的࿰…...
WebRTC的线程模型
WebRTC中的线程类: Thread类: (1)Thread类中的数据: class Thread {// 消息队列:MessageList messages_; // 消息队列,所有需要线程处理的消息,都要先入队PriorityQueue delayed_m…...
活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化
课程介绍 参加“Microsoft Power Platform 在线技术公开课:实现业务流程自动化”活动,了解如何更高效地开展业务。参加我们举办的本次免费培训活动,了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…...
Docker安装(Docker Engine安装)
一、Docker Engine和Desktop区别 Docker Engine 核心组件:Docker Engine是Docker的核心运行时引擎,负责构建、运行和管理容器。它包括守护进程(dockerd)、API和命令行工具客户端(docker)。适用环境&#…...
Spring自动化创建脚本-解放繁琐的初始化配置!!!(自动化SSM整合)
一、实现功能(原创,转载请告知) 1.自动配置pom配置文件 2.自动识别数据库及数据表,创建Entity、Dao、Service、Controller等 3.自动创建database.properties、mybatis-config.xml等数据库文件 4.自动创建spring-dao.xml spring-mvc.xml …...
Llama系列关键知识总结
系列文章目录 第一章:LoRA微调系列笔记 第二章:Llama系列关键知识总结 第三章:LLaVA模型讲解与总结 文章目录 系列文章目录Llama: Open and Efficient Foundation Language Models关键要点LLaMa模型架构:Llama2分组查询注意力 (G…...
分布式系统架构6:链路追踪
这是小卷对分布式系统架构学习的第6篇文章,关于链路追踪,之前写过traceId的相关内容:https://juejin.cn/post/7135611432808218661,不过之前写的太浅了,且不成系统,只是简单的理解,今天来捋一下…...
flink cdc使用flink sql方式运行一直报Make sure a planner module is on the classpath
flink cdc使用flink sql方式运行一直报Make sure a planner module is on the classpath 引入jar包信息: flink-connector-oracle-cdc:3.2.1 flink:1.20.0 flink-table-runtime:1.20.0 flink-streaming-java:1.20.0 flink-clients:1.20.0 Exception in thread &q…...
Vue.js组件开发-怎样将style私有化
Vue.js组件开发中,将style私有可以通过使用<style scoped>来实现的。scoped属性会告诉Vue为这个组件的CSS样式添加一个数据属性,从而确保这些样式只应用于该组件的元素,而不会影响到其他组件或全局样式。 示例: 展示如何使…...
第十届“挑战杯”大学生课外学术科技作品竞赛解析及资料
“挑战杯”被誉为大学生科技创新创业的“奥林匹克”盛会,它汇聚了来自各个学科、各个年级的精英人才。在这里,同学们带着对未知的好奇和对知识的渴望,组成一个个团队,向难题发起挑战。现在,第十届“挑战杯”大学生课外…...
从0入门自主空中机器人-2-1【无人机硬件框架】
关于本课程: 本次课程是一套面向对自主空中机器人感兴趣的学生、爱好者、相关从业人员的免费课程,包含了从硬件组装、机载电脑环境设置、代码部署、实机实验等全套详细流程,带你从0开始,组装属于自己的自主无人机,并让…...
跟着逻辑先生学习FPGA-实战篇第一课 6-1 LED灯闪烁实验
硬件平台:征战Pro开发板 软件平台:Vivado2018.3 仿真软件:Modelsim10.6d 文本编译器:Notepad 征战Pro开发板资料 链接:https://pan.baidu.com/s/1AIcnaGBpNLgFT8GG1yC-cA?pwdx3u8 提取码:x3u8 1 知识背景 LED,又名…...
【文献精读笔记】Explainability for Large Language Models: A Survey (大语言模型的可解释性综述)(四)
****非斜体正文为原文献内容(也包含笔者的补充),灰色块中是对文章细节的进一步详细解释! 四、提示范式(Explanation for Prompting Paradigm) 随着语言模型规模的扩大,基于提示(prom…...
分布式算法(五):初识ZAB协议
文章目录 一、什么是Zookeeper二、ZAB与Zookeeper的关系为什么Zookeeper不直接使用Paxos 三、ZAB简介1.名词解释提案(Proposal)事务(Transaction)原子广播(Atomic Broadcast) 2.集群角色领导者(…...
用Python操作字节流中的Excel工作簿
Python能够轻松地从字节流中加载文件,在不依赖于外部存储的情况下直接对其进行读取、修改等复杂操作,并最终将更改后的文档保存回字节串中。这种能力不仅极大地提高了数据处理的灵活性,还确保了数据的安全性和完整性,尤其是在网络…...
PHP-Casbin v4.0.0 发布,支持 ACL、RBAC、ABAC 等模型的访问控制框架
PHP-Casbin 是一个用 PHP 语言打造的轻量级开源访问控制框架,支持 ACL、RBAC、ABAC 多种模型。它采用了元模型的设计思想,支持多种经典的访问控制方案,如基于角色的访问控制 RBAC、基于属性的访问控制 ABAC 等。 更新内容: http…...
MIT S081 Lab 2 System Calls
Lab链接 一 实现trace功能 1 题目要求 In this assignment you will add a system call tracing feature that may help you when debugging later labs. You’ll create a new trace system call that will control tracing. It should take one argument, an integer “ma…...
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(2):配置主数据库
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(2):配置主数据库 目录 Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(2):配置主数据库一、配置…...
(leetcode算法题)10. 正则表达式匹配
10. 正则表达式匹配 - 力扣(LeetCode) 此题的要求一个字符串 s 和一个字符规律 p之间支持 . 和 * 的正则表达式匹配 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串…...
Hive性能调优考量
Hive作为大数据领域常见的数据仓库组件,在设计和开发阶段需要注意效率。影响Hive效率的不仅仅是数据量过大,数据倾斜、job(小文件过多)或者磁盘I/O过多、MapReduce分配不合理等因素都会对Hive的效率有影响。对Hive的调优可以从架构…...
2024-12-29-sklearn学习(26)模型选择与评估-交叉验证:评估估算器的表现 今夜偏知春气暖,虫声新透绿窗纱。
文章目录 sklearn学习(26) 模型选择与评估-交叉验证:评估估算器的表现26.1 计算交叉验证的指标26.1.1 cross_validate 函数和多度量评估26.1.2 通过交叉验证获取预测 26.2 交叉验证迭代器26.2.1 交叉验证迭代器–循环遍历数据26.2.1.1 K 折26.2.1.2 重复 K-折交叉验…...
Spring Boot + MinIO 实现分段、断点续传,让文件传输更高效
一、引言 在当今的互联网应用中,文件上传是一个常见的功能需求。然而,传统的文件上传方式在面对大文件或不稳定的网络环境时,可能会出现性能瓶颈和上传失败的问题。 传统文件上传,就像是用一辆小推车搬运大型家具,一…...
获取用户详细信息-ThreadLocal优化
Thread全局接口可用,不用再重复编写。所以为了代码的复用,使用Thread。把之前的内容(函数的参数和map与username)注释掉,换为Thread传过来的内容(map与username)。 因为Thread需要在拦截器里面…...
R语言6种将字符转成数字的方法,写在新年来临之际
咱们临床研究中,拿到数据后首先要对数据进行清洗,把数据变成咱们想要的格式,才能进行下一步分析,其中数据中的字符转成数字是个重要的内容,因为字符中常含有特殊符号,不利于分析,转成数字后才能…...
Go语言方法和接收器类型详解
Go语言方法和接收器类型详解 1. 方法接收器类型 1.1 值接收器 值接收器方法不会改变接收器的状态,因为Go语言会在调用时复制接收器的值。因此,任何对接收器成员变量的修改都只会影响副本,而不会影响原始结构体实例。 type Person struct …...
Linux常用命令总结
目录 查询java服务的pid查询pid上的进程占用的端口方法 1:使用 lsof 查询端口方法 2:使用 netstat 查询端口方法 3:使用 ss 命令查询端口 system相关命令 查询java服务的pid JPS查询pid上的进程占用的端口 要根据进程 ID(PID&am…...
Linux总结之CentOS Stream 9安装mysql8.0实操安装成功记录
Linux总结之CentOS Stream 9安装mysql8.0实操安装成功记录 由于网上很多的mysql8.0安装教程都是老版本或者安装过程记录有问题,导致经常安装到一半需要删除重新安装。所以将成功的实操安装过程记录一下,方面后面查阅,大家还有问题的可以在此讨…...
ROS2软件架构全面解析-学习如何设计通信中间件框架
前言 ROS(Robot Operating System) 2 是一个用于开发机器人应用的软件平台,也称为机器人软件开发工具包 (SDK)。 ROS2是ROS1的迭代升级版本 ,最主要的升级点是引入DDS(Data Distribution Service)为基础的…...
基于微信小程序的校园自助打印系统
博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实…...
Linux命令——3.网络与用户
文章目录 一、网络1.网络测试与诊断2.网络接口配置3.无线网络配置4.防火墙与网络管理6.防火墙管理1)firewalld命令2)iptables命令 二、用户和群组1.管理员模式2.用户账户管理1)useradd创建2)usermod修改3)userdel 删除…...
2、redis的持久化
redis的持久化 在redist当中,高可用的技术包括持久化,主从复制,哨兵模式,集群。 持久化是最简单的高可用的方法,作用就是备份数据。即将数据保存到硬盘,防止进程退出导致数据丢失。 redis持久化方式&…...
建造者模式 Builder Pattern
在创建一个对象的时候,构造器参数有点多,而且有些参数还是可选的,再者还有不少同类型的,那就更应该使用 builder 模式了。 使用 Builder 模式的初衷是 把易变性(mutability)移动到Builder类,而…...
制作一个类似ChatGPT的AI对话网站,模型能力使用ChatGPT
要快速搭建一个类似ChatGPT的AI对话网站,并且使用类似ChatGPT的模型能力,可以考虑以下技术和工具: ### 1. **使用现有的AI模型平台** - **OpenAI API**: 如果你希望使用类似于ChatGPT的能力,OpenAI提供了强大的API服务(…...
LinuxC高级day2
1.在家目录下创建目录文件,dir a.dir下创建dir1和dir2 b.把当前目录下的所有文件拷贝到dir1中, c.把当前目录下的所有脚本文件拷贝到dir2中 d.把dir2打包并压缩为dir2.tar.xz e.再把dir2.tar.xz移动到dir1中 f.解压dir1中的压缩包 g.使用tree工具&#x…...
Word格式修改
经常修改格式,留下这篇汇总 Word的累加符号上下标变右标指定目录:word如何取消封面或者目录下方的页码,页码从正文开始加参考文献:【Word】怎样给论文添加引用参考文献删空白页: word中无法删除空白页怎么办ÿ…...
深度学习-稀疏卷积
步骤: 1、构建输入输出哈希表; 输入哈希表的键为激活点的索引,值为激活点的坐标;输出哈希表的键为激活点对应的输出点的索引,值为输出点的坐标。 2、构建规则书; 规则书的每一行包含4个值,分别是…...
Microsoft Visual Studio中的/MT, /MTd,/MD,/MDd分别是什么意思?
1. /MT,/MTd,/MD,/MDd的含义 /MT,/MTd,/MD,/MDd是 Microsoft Visual C 编译器的运行时库链接选项。它们决定了程序如何链接 C 运行时库(CRT)。具体含义如下: /MT&#x…...
交换机关于环路、接口绑定、链路聚合的相关知识
文章目录 1、对交换机SW-1进行配置,仅允许Host-1通过Ethernet0/0/1接口与Host-3和Host-4通信,Host-2无法与其他主机通信。2、关闭生成树协议,验证环路造成的影响3、关闭生成树协议通过链路聚合实现两条链路正常通信并提高链路可靠性。 内容包…...
5.微服务灰度发布落地实践(rocketmq增强)
文章目录 前言发送端灰度增强订阅端灰度增强 前言 上一篇分析了,在灰度发布实现中为什么要对消息队列灰度发布进行增强。本篇主要介绍如何实现rocketmq 灰度发布的增强. 发送端灰度增强 订阅端灰度增强...
32单片机从入门到精通之开发环境——库文件(六)
每个人都有自己的追求和梦想,但要实现这些梦想并不容易。在追逐梦想的路上,我们会遇到各种困难和挫折,甚至会感到无助和失望。然而,正是这些困难和挫折让我们更加坚韧和坚定地追求自己的目标。不要害怕失败,失败只是暂…...
大电流和大电压采样电路
大电压采样电路: 需要串联多个电阻进行分压,从而一级一级降低电压,防止电阻损坏或者短路直接打穿MCU。 为什么需要加电压跟随器:进行阻抗的隔离,防止MCU的IO阻抗对分压产生影响: 大电流检测电路ÿ…...
用户态和内核态?
目录 一、定义与特点 二、功能与权限差异 三、安全性与稳定性 四、系统调用与交互 五、参考 用户态和内核态是操作系统中的两种基本运行状态,它们各自具有不同的特点和权限,共同构成了操作系统的运行基础。以下是对用户态和内核态的详细解释&#x…...
Qt天气预报系统设计界面布局第四部分左边
Qt天气预报系统设计 1、第四部分左边的第一部分1.1添加控件1.2修改控件名字 2、第四部分左边的第二部分2.1添加控件2.2修改控件名字 3、第四部分左边的第三部分3.1添加控件3.2修改控件名字 4、对整个widget04l调整 1、第四部分左边的第一部分 1.1添加控件 拖入一个widget&…...
【Spring MVC 常用注解】注解驱动开发的魔法
在 Spring MVC 中,注解可以说是开发者的“魔法棒”,通过简单的注解配置,开发者能够实现请求处理、参数绑定、响应返回等复杂功能,真正做到“少写代码多干活”。 我们接下来就来一起看看 Spring MVC 中常用的注解,它们的…...
FFmpeg 4.3 音视频-多路H265监控录放C++开发二十一.4,SDP协议分析
SDP在4566 中有详细描述。 SDP 全称是 Session Description Protocol, 翻译过来就是描述会话的协议。 主要用于两个会话实体之间的媒体协商。 什么叫会话呢,比如一次网络电话、一次电话会议、一次视频聊天,这些都可以称之为一次会话。 那为什…...
STM32 高级 WIFi案例1:测试AT指令
需求描述 测试AT指令是否能够正常控制ESP32的wifi,比如重启、读取设备信息等。 思路: stm32通过串口usart2向ESP32发布命令。ESP32通过串口1返回信息。 配置: 第一步:对ESP32芯片烧录可以读取stm32命令的固件(fac…...
Mono里运行C#脚本18—mono_image_load_names
前面已经分析完成加载CLR的流表,接着下来就是使用前面分析的数据,更进一步来处理了。下面就是通过函数mono_image_load_names获得程序集的名称和模块名称。 在CLI定义的文档里,表Assembly : 0x20: Assembly表结构信息,以下是该表各列的简要说明: HashAlgId: 这是一个4字…...
Java和Python区别: 应用领域与性能抉择的深度解析
文章目录 1. 引言2. 语言特性对比:灵活性与严谨性的碰撞3. 应用场景分析:专注任务的工具选择3.1 数据库交互:Java 的优势所在3.2 图像识别与计算:Python 的专长3.3 Web 开发 4. 高并发请求处理:架构设计与硬件选择4.1 …...