J4 - ResNet与DenseNet结合

news2024/9/21 19:08:10
  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

目录

  • 环境
  • 模型设计
  • 模型效果展示
  • 总结与心得体会


环境

  • 系统: Linux
  • 语言: Python3.8.10
  • 深度学习框架: Pytorch2.0.0+cu118
  • 显卡:GTX2080TI

模型设计

原始的DenseNet结构图如下:
DenseNet结构图
原始的ResNet结构图如下:
ResNet结构图
经过对比可以发现,ResNet的恒等块是经过了3个Conv层,而DenseNet只有两个,于是将DenseNet的结构修改为ResNet的风格,然后进行测试。

# BN ReLU Conv 顺序的残差块
class ResidualBlock(nn.Sequential):
    def __init__(self, kernel_size, input_size, hidden_size, drop_rate):
        super().__init__()
        
        self.add_module('norm1', nn.BatchNorm2d(input_size)),
        self.add_module('relu1', nn.ReLU(inplace=True)),
        self.add_module('conv1', nn.Conv2d(input_size, hidden_size, kernel_size=1, bias=False))
        
        self.add_module('norm2', nn.BatchNorm2d(hidden_size)),
        self.add_module('relu2', nn.ReLU(inplace=True)),
        self.add_module('conv2', nn.Conv2d(hidden_size, hidden_size, kernel_size=kernel_size, padding='same', bias=False))
        
        
        self.add_module('norm3', nn.BatchNorm2d(hidden_size)),
        self.add_module('relu3', nn.ReLU(inplace=True)),
        self.add_module('conv3', nn.Conv2d(hidden_size, input_size, kernel_size=1, bias=False))
        
        self.drop_rate = drop_rate
        
    def forward(self, x):
        features = super().forward(x)
        if self.drop_rate > 0:
            features = F.dropout(features, p = self.drop_rate, training=self.training)
        
        return torch.concat([x, features], 1)
class DenseBlock(nn.Sequential):
    def __init__(self, num_layers, input_size, drop_rate):
        super().__init__()
        for i in range(num_layers):
            layer = ResidualBlock(3, input_size, int(input_size / 4), drop_rate)
            input_size *= 2 # 每次都是上个的堆叠,每次都翻倍
            self.add_module('denselayer%d'%(i+1,), layer)
# 过渡层没有任务变化
class Transition(nn.Sequential):
    def __init__(self, input_size, output_size):
        super().__init__()
        self.add_module('norm', nn.BatchNorm2d(input_size))
        self.add_module('relu', nn.ReLU())
        self.add_module('conv', nn.Conv2d(input_size, output_size, kernel_size=1, stride=1, bias=False))
        self.add_module('pool', nn.AvgPool2d(2, stride=2))
# 构建自定义的DenseNet
class DenseNet(nn.Module):
	# 模型的规模小一点,方便测试
    def __init__(self, growth_rate=32, block_config=(2,4,3, 2), 
                 init_size=64, bn_size=4, compression_rate=0.5, drop_rate=0, num_classes=1000):
        super().__init__()
        
        self.features = nn.Sequential(OrderedDict([
            ("conv0", nn.Conv2d(3, init_size, kernel_size=7, stride=2, padding=3, bias=False)),
            ('norm0', nn.BatchNorm2d(init_size)),
            ('relu0', nn.ReLU()),
            ('pool0', nn.MaxPool2d(3, stride=2, padding=1))
        ]))
        
        num_features = init_size
        for i, num_layers in enumerate(block_config):
            block = DenseBlock(num_layers, num_features, drop_rate)
            self.features.add_module('denseblock%d' % (i + 1), block)
            num_features = num_features*(2**num_layers)
            if i != len(block_config) - 1:
                transition = Transition(num_features, int(num_features*compression_rate))
                self.features.add_module('transition%d' % (i + 1), transition)
                num_features = int(num_features * compression_rate)
                
        self.features.add_module('norm5', nn.BatchNorm2d(num_features))
        self.features.add_module('relu5', nn.ReLU())
        
        self.classifier = nn.Linear(num_features, num_classes)
        
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.bias, 0)
                nn.init.constant_(m.weight, 1)
            elif isinstance(m, nn.Linear):
                nn.init.constant_(m.bias, 0)
                
    def forward(self, x):
        features = self.features(x)
        out = F.avg_pool2d(features, 7, stride=1).view(features.size(0), -1)
        out = self.classifier(out)
        return out

打印一下模型的结构

DenseNet(
  (features): Sequential(
    (conv0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (norm0): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu0): ReLU()
    (pool0): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
    (denseblock1): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(64, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(16, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(32, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition1): Transition(
      (norm): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock2): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(32, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer3): ResidualBlock(
        (norm1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer4): ResidualBlock(
        (norm1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition2): Transition(
      (norm): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(2048, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock3): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer3): ResidualBlock(
        (norm1): BatchNorm2d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(4096, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(1024, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition3): Transition(
      (norm): BatchNorm2d(8192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(8192, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock4): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(4096, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(1024, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(8192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(8192, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(2048, 2048, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(2048, 8192, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (norm5): BatchNorm2d(16384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu5): ReLU()
  )
  (classifier): Linear(in_features=16384, out_features=2, bias=True)
)
# 使用torchinfo打印
summary(model, input_size=(32, 3, 224, 224))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
DenseNet                                 [32, 2]                   --
├─Sequential: 1-1                        [32, 16384, 7, 7]         --
│    └─Conv2d: 2-1                       [32, 64, 112, 112]        9,408
│    └─BatchNorm2d: 2-2                  [32, 64, 112, 112]        128
│    └─ReLU: 2-3                         [32, 64, 112, 112]        --
│    └─MaxPool2d: 2-4                    [32, 64, 56, 56]          --
│    └─DenseBlock: 2-5                   [32, 256, 56, 56]         --
│    │    └─ResidualBlock: 3-1           [32, 128, 56, 56]         4,544
│    │    └─ResidualBlock: 3-2           [32, 256, 56, 56]         17,792
│    └─Transition: 2-6                   [32, 128, 28, 28]         --
│    │    └─BatchNorm2d: 3-3             [32, 256, 56, 56]         512
│    │    └─ReLU: 3-4                    [32, 256, 56, 56]         --
│    │    └─Conv2d: 3-5                  [32, 128, 56, 56]         32,768
│    │    └─AvgPool2d: 3-6               [32, 128, 28, 28]         --
│    └─DenseBlock: 2-7                   [32, 2048, 28, 28]        --
│    │    └─ResidualBlock: 3-7           [32, 256, 28, 28]         17,792
│    │    └─ResidualBlock: 3-8           [32, 512, 28, 28]         70,400
│    │    └─ResidualBlock: 3-9           [32, 1024, 28, 28]        280,064
│    │    └─ResidualBlock: 3-10          [32, 2048, 28, 28]        1,117,184
│    └─Transition: 2-8                   [32, 1024, 14, 14]        --
│    │    └─BatchNorm2d: 3-11            [32, 2048, 28, 28]        4,096
│    │    └─ReLU: 3-12                   [32, 2048, 28, 28]        --
│    │    └─Conv2d: 3-13                 [32, 1024, 28, 28]        2,097,152
│    │    └─AvgPool2d: 3-14              [32, 1024, 14, 14]        --
│    └─DenseBlock: 2-9                   [32, 8192, 14, 14]        --
│    │    └─ResidualBlock: 3-15          [32, 2048, 14, 14]        1,117,184
│    │    └─ResidualBlock: 3-16          [32, 4096, 14, 14]        4,462,592
│    │    └─ResidualBlock: 3-17          [32, 8192, 14, 14]        17,838,080
│    └─Transition: 2-10                  [32, 4096, 7, 7]          --
│    │    └─BatchNorm2d: 3-18            [32, 8192, 14, 14]        16,384
│    │    └─ReLU: 3-19                   [32, 8192, 14, 14]        --
│    │    └─Conv2d: 3-20                 [32, 4096, 14, 14]        33,554,432
│    │    └─AvgPool2d: 3-21              [32, 4096, 7, 7]          --
│    └─DenseBlock: 2-11                  [32, 16384, 7, 7]         --
│    │    └─ResidualBlock: 3-22          [32, 8192, 7, 7]          17,838,080
│    │    └─ResidualBlock: 3-23          [32, 16384, 7, 7]         71,327,744
│    └─BatchNorm2d: 2-12                 [32, 16384, 7, 7]         32,768
│    └─ReLU: 2-13                        [32, 16384, 7, 7]         --
├─Linear: 1-2                            [32, 2]                   32,770
==========================================================================================
Total params: 149,871,874
Trainable params: 149,871,874
Non-trainable params: 0
Total mult-adds (G): 595.94
==========================================================================================
Input size (MB): 19.27
Forward/backward pass size (MB): 5317.85
Params size (MB): 599.49
Estimated Total Size (MB): 5936.61
==========================================================================================

模型效果展示

Epoch: 1, Train_acc:83.8, Train_loss: 0.392, Test_acc: 86.8, Test_loss: 0.324, Lr: 1.00E-04
Epoch: 2, Train_acc:86.8, Train_loss: 0.327, Test_acc: 88.5, Test_loss: 0.291, Lr: 1.00E-04
Epoch: 3, Train_acc:88.1, Train_loss: 0.290, Test_acc: 87.7, Test_loss: 0.415, Lr: 1.00E-04
Epoch: 4, Train_acc:88.1, Train_loss: 0.287, Test_acc: 89.8, Test_loss: 0.249, Lr: 1.00E-04
Epoch: 5, Train_acc:89.7, Train_loss: 0.251, Test_acc: 90.5, Test_loss: 0.235, Lr: 1.00E-04
Epoch: 6, Train_acc:90.2, Train_loss: 0.241, Test_acc: 90.7, Test_loss: 0.253, Lr: 1.00E-04
Epoch: 7, Train_acc:90.6, Train_loss: 0.227, Test_acc: 90.5, Test_loss: 0.236, Lr: 1.00E-04
Epoch: 8, Train_acc:91.5, Train_loss: 0.212, Test_acc: 90.5, Test_loss: 0.228, Lr: 1.00E-04
Epoch: 9, Train_acc:91.7, Train_loss: 0.207, Test_acc: 91.0, Test_loss: 0.247, Lr: 1.00E-04
Epoch:10, Train_acc:92.0, Train_loss: 0.206, Test_acc: 91.2, Test_loss: 0.290, Lr: 1.00E-04
Epoch:11, Train_acc:92.0, Train_loss: 0.203, Test_acc: 88.2, Test_loss: 0.283, Lr: 1.00E-04
Epoch:12, Train_acc:92.5, Train_loss: 0.185, Test_acc: 91.3, Test_loss: 0.232, Lr: 1.00E-04
Epoch:13, Train_acc:93.2, Train_loss: 0.172, Test_acc: 90.7, Test_loss: 0.247, Lr: 1.00E-04
Epoch:14, Train_acc:93.3, Train_loss: 0.177, Test_acc: 90.2, Test_loss: 0.238, Lr: 1.00E-04
Epoch:15, Train_acc:93.8, Train_loss: 0.166, Test_acc: 90.1, Test_loss: 0.357, Lr: 1.00E-04
Epoch:16, Train_acc:94.6, Train_loss: 0.146, Test_acc: 91.2, Test_loss: 0.255, Lr: 1.00E-04
Epoch:17, Train_acc:95.4, Train_loss: 0.119, Test_acc: 90.2, Test_loss: 0.270, Lr: 1.00E-04
Epoch:18, Train_acc:95.5, Train_loss: 0.116, Test_acc: 81.7, Test_loss: 0.752, Lr: 1.00E-04
Epoch:19, Train_acc:95.6, Train_loss: 0.117, Test_acc: 89.3, Test_loss: 0.339, Lr: 1.00E-04
Epoch:20, Train_acc:95.5, Train_loss: 0.120, Test_acc: 91.0, Test_loss: 0.285, Lr: 1.00E-04
Done

训练结果

打印评估结果

总结与心得体会

虽然大幅度的降低了模型的规模,实际的总参数还是数倍于DenseNet121。然而,模型似乎比DenseNet121的泛化性能好不少,训练和验证的Gap比DenseNet121小很多,甚至有的时候验证集上的表现比训练集还好。直接使用ResNet的ResidualBlock实现DenseNet会让参数量迅速的膨胀。接下来再改进,应该从如何压缩DenseNet的参数量的角度来考虑。

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

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

相关文章

【JavaScript】日程管理系统 页面案例开发

文章目录 一、登录页及校验二、注册页及校验 一、登录页及校验 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>日程管理登录</title><style>.ht {text-align: center;color: cadetblue;f…

商务与经济统计:中英文转换

数据分析基础中英文转换 Chap 1 数据与统计资料 Data and Statistics 1.2 数据 Data 数据集 Data Sets 个体 Element 变量 Variables 观测值 Observations 测量尺度 Scales of Measurement&#xff1a; 名义尺度 Nominal Scale 顺序尺度 Ordinal Scale 区间尺度 Interval…

数据结构之set类

set类 set 是集合类。这个类很特别&#xff0c;它是唯一坚决追求“特立独行”的数据类型。在这里&#xff0c;你没办法找到两个一样的值&#xff0c;即使强硬赋予&#xff0c;它也会强硬剔除&#xff0c;也就是去重&#xff0c;一个非常实用的技能&#xff0c;这也是 set 类存…

Web自动化之显式等待与隐式等待

等待就是当运行代码时&#xff0c;如果页面的渲染速度跟不上代码的运行速度&#xff0c;就需要人为的去限制代码执行的速度。 在做 Web 自动化时&#xff0c;一般要等待页面元素加载完成后&#xff0c;才能执行操作&#xff0c;否则会报找不到元素等各种错误&#xff0c;这样就…

软件测试基础知识整理(详细版)收藏这篇足矣

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

后面的输入框与前面的联动,输入框只能输入正数(不用正则)

概要 提示&#xff1a;这里可以描述概要 前面的输入框是发票金额&#xff0c;后面的输入框是累计发票金额&#xff08;含本次&#xff09;--含本次就代表后倾请求的接口的数据&#xff08;不是保存后返显的-因为保存后返显的是含本次&#xff09;是不含本次的所以在输入发票金…

ACM题解Day1|1.Accurate Movement ,2.Help the Support Lady, 3.Absolute Game

1.Accurate Movement 思路 : 本题为模拟题主要是模拟方块的移动,其中 以两木块的最右端做为记录点. 先挪动a, 每次a块只能挪到和b块相同的位置, b块每次最多挪动(b-a).为什么因为有限制挡板然后俩木块要不能同时移动只能移动一一个 #include<bits/stdc.h> using namespac…

网页设计(九)JavaScript基础应用

一、网页中文字的字号选择性改变 单击前初始状态页面 单击“中”链接后页面 文字素材&#xff1a;   JavaScript是一种能让你的网页更加生动活泼的程式语言&#xff0c;也是目前网页中设计中最容易学又最方便的语言。你可以利用JavaScript轻易的做出亲切的欢迎讯息、漂亮的…

Linux系统安装NFS服务器

NFS是一种网络文件系统&#xff0c;英文全称Network File System&#xff0c;通过NFS可以让不同的主机系统之间共享文件或目录。通过NFS&#xff0c;用户可以直接在本地NFS客户端读写NFS服务端上的文件&#xff0c;是非常好的共享存储工具。本篇文章将介绍如何在CentOS7上安装N…

使用Python在本地生成助记词

新建并打开一个空文件夹 逐行 执行命令 python3 -m pip install --upgrade pippip3 install eth_accountpip3 install web3touch acco.py然后看到文件夹下面会有个acco.py文件 将把下面的代码粘贴到acco.py中保存。 import os from eth_account import Accountif __name__ …

全网最详细!!Python 爬虫快速入门

1. 背景 最近在工作中有需要使用到爬虫的地方&#xff0c;需要根据 Gitlab Python 实现一套定时爬取数据的工具&#xff0c;所以借此机会&#xff0c;针对 Python 爬虫方面的知识进行了学习&#xff0c;也算 Python 爬虫入门了。 需要了解的知识点&#xff1a; Python 基础语…

Windows给docker设置阿里源

windows环境搭建专栏&#x1f517;点击跳转 Windows系统的docker设置阿里源 文章目录 Windows系统的docker设置阿里源1.获得镜像加速器2.配置docker 由于我们生活在中国大陆&#xff0c;所以外网的访问总是那么慢又困难&#xff0c;用docker拉取几兆的小镜象还能忍受&#xff…

idea中使用git提交代码报 Nothing To commit No changes detected

问题描述 在idea中右键&#xff0c;开始将变更的代码进行提交的时候&#xff0c;【Commit Directory】点击提交的时候 报 Nothing To commit No changes detected解决方案 在这里点击Test 看看是不是能下面显示git版本&#xff0c;不行的话 会显示一个 fix的字样&#xff0c;行…

【2023我的编程之旅】七次不同的计算机二级考试经历分享

目录 我报考过的科目 第一次报考MS Office 第二次报考Web语言&#xff0c;C语言&#xff0c;C语言 第三次报考C语言&#xff0c;C语言&#xff0c;Java语言 分享一些备考二级的方法 一些需要注意的细节 结语 2023年的CSDN征文活动已经进入了尾声&#xff0c;在这最后我…

YOLOv8改进 | 进阶实战篇 | 利用YOLOv8进行视频划定区域目标统计计数

一、本文介绍 Hello,各位读者,最近会给大家发一些进阶实战的讲解,如何利用YOLOv8现有的一些功能进行一些实战, 让我们不仅会改进YOLOv8,也能够利用YOLOv8去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是pyside2做一些小的界面给大家使用。 在开始之前给大家推…

二、VS2019编译的VTK9.0.0 + Qt 5.14.2 环境测试

1. 使用CMake VS2019 编译vtk 9.0.0 时,需要启用支持Qt开关、如下图 如果不会编译的可以参见我的这篇文章: 一、VTK 9.0.0 编译安装步骤 VS2019 CMake3.26.0-CSDN博客 打开Qt5.14.2 ,创建Qt Widget 项目: 构建设置选择 MSVC2017 64bit pro 项目文件加入两行配置: …

链表存数相加算法(leetcode第2题)

题目描述&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这…

zabbix监控php-fpm 服务的状态

目录 内容纯手敲&#xff0c;有错误请私信博主 一、zabbix-agent端配置 1.下载php-fpm 2.打开php-fpm的状态页面 3.启动php-fpm 4.安装nginx 5.设置nginx &#xff0c;设置代理php&#xff0c;和php-fpm的状态页面匹配 6重启nginx 7.查询php-fpm的状态页面 8. 根据用户…

Redis--HyperLogLog的指令语法与使用场景举例(UV统计)

文章目录 前言HyperLogLog介绍HyperLogLog指令使用使用场景&#xff1a;UV统计 前言 Redis除了常见的五种数据类型之外&#xff0c;其实还有一些少见的数据结构&#xff0c;如Geo&#xff0c;HyperLogLog等。虽然它们少见&#xff0c;但是作用却不容小觑。本文将介绍HyperLogL…

LeetCode 热题 100 | 双指针(下)

目录 42. 接雨水 1 方法一&#xff1a;我的方法 2 方法二&#xff1a;动态规划 3 方法三&#xff1a;双指针 菜鸟做题第一周&#xff0c;语言是 C 42. 接雨水 1 方法一&#xff1a;我的方法 Warning&#xff1a;这是我的智障做法&#xff0c;请勿模仿 我只能说它教会…