【YOLOv8改进- Backbone主干】2024最新轻量化网络MobileNetV4替换YoloV8的BackBone

本文涉及的产品
文件存储 NAS,50GB 3个月
简介: YOLO目标检测专栏聚焦于模型的改进和实战应用,介绍了MobileNetV4,它在移动设备上优化了架构。文章提到了UIB(通用反向瓶颈)模块,结合了多种结构,增强了特征提取;Mobile MQA是专为移动平台设计的注意力层,提升了速度;优化的NAS提升了搜索效率。通过这些创新,MNv4在不同硬件上实现了性能和效率的平衡,且通过蒸馏技术提高了准确性。模型在Pixel 8 EdgeTPU上达到87%的ImageNet-1K准确率,延迟仅为3.8ms。论文、PyTorch和TensorFlow实现代码链接也已提供。

YOLO目标检测创新改进与实战案例专栏

专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例

专栏链接: YOLO基础解析+创新改进+实战案例

介绍

image-20240711225315182

摘要

摘要:我们介绍了最新一代的MobileNets,称为MobileNetV4(MNv4),其架构设计在移动设备上具有通用的高效性。核心是我们引入了通用倒置瓶颈(UIB)搜索模块,这是一种统一且灵活的结构,融合了倒置瓶颈(IB)、ConvNext、前馈网络(FFN)以及一种新颖的额外深度可分离(ExtraDW)变体。除了UIB,我们还介绍了Mobile MQA,一种专为移动加速器设计的注意力模块,提供显著的39%速度提升。我们还引入了一种优化的神经架构搜索(NAS)配方,提高了MNv4的搜索效率。UIB、Mobile MQA和改进的NAS配方的整合,产生了一套新的MNv4模型,这些模型在移动CPU、DSP、GPU以及专用加速器(如Apple Neural Engine和Google Pixel EdgeTPU)上大多达到了帕累托最优,这是其他任何测试模型都不具备的特点。最后,为了进一步提高准确性,我们引入了一种新颖的蒸馏技术。在这种技术的增强下,我们的MNv4-Hybrid-Large模型在ImageNet-1K上达到了87%的准确率,在Pixel 8 EdgeTPU上的运行时间仅为3.8毫秒。

文章链接

论文地址:论文地址

代码地址:代码地址

代码地址:代码地址

基本原理

MobileNetV4是MobileNet系列的最新一代,旨在为移动设备提供高效的架构设计。MobileNetV4引入了Universal Inverted Bottleneck和Mobile MQA层,并结合改进的NAS(神经架构搜索)方法。通过这些创新设计和优化技术,MobileNetV4在Pixel 8 EdgeTPU上实现了87%的ImageNet-1K准确率,同时延迟仅为3.8ms,推动了移动计算机视觉的最新发展。

  1. Universal Inverted Bottleneck(通用反向瓶颈):

    • UIB结构融合了Inverted Bottleneck(IB)、ConvNext、Feed Forward Network(FFN)和Extra Depthwise(ExtraDW)变体,提供了统一且灵活的特征提取结构。
    • UIB通过引入两个可选的深度卷积层,改进了Inverted Bottleneck结构,实现了更高效的特征提取。
    • UIB统一了多种微体系结构,如Inverse Bottleneck(IB)、ConvNext和FFN,提供了更好的性能和灵活性。
    • image-20240711225649595
  2. Mobile MQA层:

    • Mobile MQA是一种专为移动加速器定制的注意力机制层,能够显著提升模型的速度。
    • 通过Mobile MQA层,MobileNetV4在移动设备上实现了39%的速度提升,为实时和交互式体验提供了支持。
  3. NAS方法:

    • MobileNetV4采用了优化的神经架构搜索(NAS)方法,自动化模型设计过程,提高了搜索效率。
    • 通过改进的NAS方法,MobileNetV4创建了一系列普遍优化的移动模型,适用于多种移动设备,包括移动CPU、DSP、GPU以及专用加速器。
  4. Distillation Approach(蒸馏方法):

    • MobileNetV4引入了一种新颖的蒸馏技术,通过模型蒸馏,提高了模型的准确性。
    • 借助这种蒸馏方法,MobileNetV4-Hybrid-Large模型在Pixel 8 EdgeTPU上实现了87%的ImageNet-1K准确率,同时仅需3.8ms的运行时间。

核心代码

@tf_keras.utils.register_keras_serializable(package='Vision')
class MobileNet(tf_keras.Model):
  """Creates a MobileNet family model."""

  def __init__(
      self,
      model_id: str = 'MobileNetV2',
      filter_size_scale: float = 1.0,
      input_specs: tf_keras.layers.InputSpec = layers.InputSpec(
          shape=[None, None, None, 3]
      ),
      # The followings are for hyper-parameter tuning.
      norm_momentum: float = 0.99,
      norm_epsilon: float = 0.001,
      kernel_initializer: str = 'VarianceScaling',
      kernel_regularizer: tf_keras.regularizers.Regularizer | None = None,
      bias_regularizer: tf_keras.regularizers.Regularizer | None = None,
      # The followings should be kept the same most of the times.
      output_stride: int | None = None,
      min_depth: int = 8,
      # divisible is not used in MobileNetV1.
      divisible_by: int = 8,
      stochastic_depth_drop_rate: float = 0.0,
      flat_stochastic_depth_drop_rate: bool = True,
      regularize_depthwise: bool = False,
      use_sync_bn: bool = False,
      # finegrain is not used in MobileNetV1.
      finegrain_classification_mode: bool = True,
      output_intermediate_endpoints: bool = False,
      **kwargs,
  ):
    """Initializes a MobileNet model.

    Args:
      model_id: A `str` of MobileNet version. The supported values are
        `MobileNetV1`, `MobileNetV2`, `MobileNetV3Large`, `MobileNetV3Small`,
        `MobileNetV3EdgeTPU`, `MobileNetMultiMAX` and `MobileNetMultiAVG`.
      filter_size_scale: A `float` of multiplier for the filters (number of
        channels) for all convolution ops. The value must be greater than zero.
        Typical usage will be to set this value in (0, 1) to reduce the number
        of parameters or computation cost of the model.
      input_specs: A `tf_keras.layers.InputSpec` of specs of the input tensor.
      norm_momentum: A `float` of normalization momentum for the moving average.
      norm_epsilon: A `float` added to variance to avoid dividing by zero.
      kernel_initializer: A `str` for kernel initializer of convolutional
        layers.
      kernel_regularizer: A `tf_keras.regularizers.Regularizer` object for
        Conv2D. Default to None.
      bias_regularizer: A `tf_keras.regularizers.Regularizer` object for Conv2D.
        Default to None.
      output_stride: An `int` that specifies the requested ratio of input to
        output spatial resolution. If not None, then we invoke atrous
        convolution if necessary to prevent the network from reducing the
        spatial resolution of activation maps. Allowed values are 8 (accurate
        fully convolutional mode), 16 (fast fully convolutional mode), 32
        (classification mode).
      min_depth: An `int` of minimum depth (number of channels) for all
        convolution ops. Enforced when filter_size_scale < 1, and not an active
        constraint when filter_size_scale >= 1.
      divisible_by: An `int` that ensures all inner dimensions are divisible by
        this number.
      stochastic_depth_drop_rate: A `float` of drop rate for drop connect layer.
      flat_stochastic_depth_drop_rate: A `bool`, indicating that the stochastic
        depth drop rate will be fixed and equal to all blocks.
      regularize_depthwise: If Ture, apply regularization on depthwise.
      use_sync_bn: If True, use synchronized batch normalization.
      finegrain_classification_mode: If True, the model will keep the last layer
        large even for small multipliers, following
        https://arxiv.org/abs/1801.04381.
      output_intermediate_endpoints: A `bool` of whether or not output the
        intermediate endpoints.
      **kwargs: Additional keyword arguments to be passed.
    """
    if model_id not in SUPPORTED_SPECS_MAP:
      raise ValueError('The MobileNet version {} '
                       'is not supported'.format(model_id))

    if filter_size_scale <= 0:
      raise ValueError('filter_size_scale is not greater than zero.')

    if output_stride is not None:
      if model_id == 'MobileNetV1':
        if output_stride not in [8, 16, 32]:
          raise ValueError('Only allowed output_stride values are 8, 16, 32.')
      else:
        if output_stride == 0 or (output_stride > 1 and output_stride % 2):
          raise ValueError('Output stride must be None, 1 or a multiple of 2.')

    self._model_id = model_id
    self._input_specs = input_specs
    self._filter_size_scale = filter_size_scale
    self._min_depth = min_depth
    self._output_stride = output_stride
    self._divisible_by = divisible_by
    self._stochastic_depth_drop_rate = stochastic_depth_drop_rate
    self._flat_stochastic_depth_drop_rate = flat_stochastic_depth_drop_rate
    self._regularize_depthwise = regularize_depthwise
    self._kernel_initializer = kernel_initializer
    self._kernel_regularizer = kernel_regularizer
    self._bias_regularizer = bias_regularizer
    self._use_sync_bn = use_sync_bn
    self._norm_momentum = norm_momentum
    self._norm_epsilon = norm_epsilon
    self._finegrain_classification_mode = finegrain_classification_mode
    self._output_intermediate_endpoints = output_intermediate_endpoints

    inputs = tf_keras.Input(shape=input_specs.shape[1:])

    block_specs = SUPPORTED_SPECS_MAP.get(model_id)
    self._decoded_specs = block_spec_decoder(
        specs=block_specs,
        filter_size_scale=self._filter_size_scale,
        divisible_by=self._get_divisible_by(),
        finegrain_classification_mode=self._finegrain_classification_mode,
    )

    x, endpoints, next_endpoint_level = self._mobilenet_base(inputs=inputs)

    self._output_specs = {
   
   l: endpoints[l].get_shape() for l in endpoints}
    # Don't include the final layer in `self._output_specs` to support decoders.
    endpoints[str(next_endpoint_level)] = x

    super(MobileNet, self).__init__(
        inputs=inputs, outputs=endpoints, **kwargs)

  def _get_divisible_by(self):
    if self._model_id == 'MobileNetV1':
      return 1
    else:
      return self._divisible_by

  def _mobilenet_base(
      self, inputs: tf.Tensor
  ) -> tuple[tf.Tensor, dict[str, tf.Tensor], int]:
    """Builds the base MobileNet architecture.

    Args:
      inputs: A `tf.Tensor` of shape `[batch_size, height, width, channels]`.

    Returns:
      A tuple of output Tensor and dictionary that collects endpoints.
    """

    input_shape = inputs.get_shape().as_list()
    if len(input_shape) != 4:
      raise ValueError('Expected rank 4 input, was: %d' % len(input_shape))

    # The current_stride variable keeps track of the output stride of the
    # activations, i.e., the running product of convolution strides up to the
    # current network layer. This allows us to invoke atrous convolution
    # whenever applying the next convolution would result in the activations
    # having output stride larger than the target output_stride.
    current_stride = 1

    # The atrous convolution rate parameter.
    rate = 1

    # Used to calulate stochastic depth drop rate. Some blocks do not use
    # stochastic depth since they do not have residuals. For simplicity, we
    # count here all the blocks in the model. If one or more of the last layers
    # do not use stochastic depth, it can be compensated with larger stochastic
    # depth drop rate.
    num_blocks = len(self._decoded_specs)

    net = inputs
    endpoints = {
   
   }
    endpoint_level = 2
    for block_idx, block_def in enumerate(self._decoded_specs):
      block_name = 'block_group_{}_{}'.format(block_def.block_fn, block_idx)
      # A small catch for gpooling block with None strides
      if not block_def.strides:
        block_def.strides = 1
      if (self._output_stride is not None and
          current_stride == self._output_stride):
        # If we have reached the target output_stride, then we need to employ
        # atrous convolution with stride=1 and multiply the atrous rate by the
        # current unit's stride for use in subsequent layers.
        layer_stride = 1
        layer_rate = rate
        rate *= block_def.strides
      else:
        layer_stride = block_def.strides
        layer_rate = 1
        current_stride *= block_def.strides

      if self._flat_stochastic_depth_drop_rate:
        stochastic_depth_drop_rate = self._stochastic_depth_drop_rate
      else:
        stochastic_depth_drop_rate = nn_layers.get_stochastic_depth_rate(
            self._stochastic_depth_drop_rate, block_idx + 1, num_blocks
        )
      if stochastic_depth_drop_rate is not None:
        logging.info(
            'stochastic_depth_drop_rate: %f for block = %d',
            stochastic_depth_drop_rate,
            block_idx,
        )

      intermediate_endpoints = {
   
   }
      if block_def.block_fn == 'convbn':

        net = Conv2DBNBlock(
            filters=block_def.filters,
            kernel_size=block_def.kernel_size,
            strides=block_def.strides,
            activation=block_def.activation,
            use_bias=block_def.use_bias,
            use_normalization=block_def.use_normalization,
            kernel_initializer=self._kernel_initializer,
            kernel_regularizer=self._kernel_regularizer,
            bias_regularizer=self._bias_regularizer,
            use_sync_bn=self._use_sync_bn,
            norm_momentum=self._norm_momentum,
            norm_epsilon=self._norm_epsilon
        )(net)

      elif block_def.block_fn == 'depsepconv':
        net = nn_blocks.DepthwiseSeparableConvBlock(
            filters=block_def.filters,
            kernel_size=block_def.kernel_size,
            strides=layer_stride,
            activation=block_def.activation,
            dilation_rate=layer_rate,
            regularize_depthwise=self._regularize_depthwise,
            kernel_initializer=self._kernel_initializer,
            kernel_regularizer=self._kernel_regularizer,
            use_sync_bn=self._use_sync_bn,
            norm_momentum=self._norm_momentum,
            norm_epsilon=self._norm_epsilon,
        )(net)

      elif block_def.block_fn == 'mhsa':
        block = nn_blocks.MultiHeadSelfAttentionBlock(
            input_dim=block_def.filters,
            num_heads=block_def.num_heads,
            key_dim=block_def.key_dim,
            value_dim=block_def.value_dim,
            use_multi_query=block_def.use_multi_query,
            query_h_strides=block_def.query_h_strides,
            query_w_strides=block_def.query_w_strides,
            kv_strides=block_def.kv_strides,
            downsampling_dw_kernel_size=block_def.downsampling_dw_kernel_size,
            cpe_dw_kernel_size=block_def.kernel_size,
            stochastic_depth_drop_rate=self._stochastic_depth_drop_rate,
            use_sync_bn=self._use_sync_bn,
            use_residual=block_def.use_residual,
            norm_momentum=self._norm_momentum,
            norm_epsilon=self._norm_epsilon,
            use_layer_scale=block_def.use_layer_scale,
            output_intermediate_endpoints=self._output_intermediate_endpoints,
        )
        if self._output_intermediate_endpoints:
          net, intermediate_endpoints = block(net)
        else:
          net = block(net)

      elif block_def.block_fn in (
          'invertedbottleneck',
          'fused_ib',
          'uib',
      ):
        use_rate = rate
        if layer_rate > 1 and block_def.kernel_size != 1:
          # We will apply atrous rate in the following cases:
          # 1) When kernel_size is not in params, the operation then uses
          #   default kernel size 3x3.
          # 2) When kernel_size is in params, and if the kernel_size is not
          #   equal to (1, 1) (there is no need to apply atrous convolution to
          #   any 1x1 convolution).
          use_rate = layer_rate
        in_filters = net.shape.as_list()[-1]
        args = {
   
   
            'in_filters': in_filters,
            'out_filters': block_def.filters,
            'strides': layer_stride,
            'expand_ratio': block_def.expand_ratio,
            'activation': block_def.activation,
            'use_residual': block_def.use_residual,
            'dilation_rate': use_rate,
            'regularize_depthwise': self._regularize_depthwise,
            'kernel_initializer': self._kernel_initializer,
            'kernel_regularizer': self._kernel_regularizer,
            'bias_regularizer': self._bias_regularizer,
            'use_sync_bn': self._use_sync_bn,
            'norm_momentum': self._norm_momentum,
            'norm_epsilon': self._norm_epsilon,
            'stochastic_depth_drop_rate': stochastic_depth_drop_rate,
            'divisible_by': self._get_divisible_by(),
            'output_intermediate_endpoints': (
                self._output_intermediate_endpoints
            ),
        }
        if block_def.block_fn in ('invertedbottleneck', 'fused_ib'):
          args.update({
   
   
              'kernel_size': block_def.kernel_size,
              'se_ratio': block_def.se_ratio,
              'expand_se_in_filters': True,
              'use_depthwise': (
                  block_def.use_depthwise
                  if block_def.block_fn == 'invertedbottleneck'
                  else False
              ),
              'se_gating_activation': 'hard_sigmoid',
          })
          block = nn_blocks.InvertedBottleneckBlock(**args)
        else:
          args.update({
   
   
              'middle_dw_downsample': block_def.middle_dw_downsample,
              'start_dw_kernel_size': block_def.start_dw_kernel_size,
              'middle_dw_kernel_size': block_def.middle_dw_kernel_size,
              'end_dw_kernel_size': block_def.end_dw_kernel_size,
              'use_layer_scale': block_def.use_layer_scale,
          })
          block = nn_blocks.UniversalInvertedBottleneckBlock(**args)

        if self._output_intermediate_endpoints:
          net, intermediate_endpoints = block(net)
        else:
          net = block(net)

      elif block_def.block_fn == 'gpooling':
        net = layers.GlobalAveragePooling2D(keepdims=True)(net)

      else:
        raise ValueError(
            'Unknown block type {} for layer {}'.format(
                block_def.block_fn, block_idx
            )
        )

      net = tf_keras.layers.Activation('linear', name=block_name)(net)

      if block_def.is_output:
        endpoints[str(endpoint_level)] = net
        for key, tensor in intermediate_endpoints.items():
          endpoints[str(endpoint_level) + '/' + key] = tensor
        if current_stride != self._output_stride:
          endpoint_level += 1

    if str(endpoint_level) in endpoints:
      endpoint_level += 1
    return net, endpoints, endpoint_level

  def get_config(self):
    config_dict = {
   
   
        'model_id': self._model_id,
        'filter_size_scale': self._filter_size_scale,
        'min_depth': self._min_depth,
        'output_stride': self._output_stride,
        'divisible_by': self._divisible_by,
        'stochastic_depth_drop_rate': self._stochastic_depth_drop_rate,
        'flat_stochastic_depth_drop_rate': (
            self._flat_stochastic_depth_drop_rate
        ),
        'regularize_depthwise': self._regularize_depthwise,
        'kernel_initializer': self._kernel_initializer,
        'kernel_regularizer': self._kernel_regularizer,
        'bias_regularizer': self._bias_regularizer,
        'use_sync_bn': self._use_sync_bn,
        'norm_momentum': self._norm_momentum,
        'norm_epsilon': self._norm_epsilon,
        'finegrain_classification_mode': self._finegrain_classification_mode,
    }
    return config_dict

  @classmethod
  def from_config(cls, config, custom_objects=None):
    return cls(**config)

  @property
  def output_specs(self):
    """A dict of {level: TensorShape} pairs for the model output."""
    return self._output_specs


@factory.register_backbone_builder('mobilenet')
def build_mobilenet(
    input_specs: tf_keras.layers.InputSpec,
    backbone_config: hyperparams.Config,
    norm_activation_config: hyperparams.Config,
    l2_regularizer: tf_keras.regularizers.Regularizer | None = None,
) -> tf_keras.Model:
  """Builds MobileNet backbone from a config."""
  backbone_type = backbone_config.type
  backbone_cfg = backbone_config.get()
  assert backbone_type == 'mobilenet', (f'Inconsistent backbone type '
                                        f'{backbone_type}')

  return MobileNet(
      model_id=backbone_cfg.model_id,
      filter_size_scale=backbone_cfg.filter_size_scale,
      input_specs=input_specs,
      stochastic_depth_drop_rate=backbone_cfg.stochastic_depth_drop_rate,
      flat_stochastic_depth_drop_rate=(
          backbone_cfg.flat_stochastic_depth_drop_rate
      ),
      output_stride=backbone_cfg.output_stride,
      output_intermediate_endpoints=backbone_cfg.output_intermediate_endpoints,
      use_sync_bn=norm_activation_config.use_sync_bn,
      norm_momentum=norm_activation_config.norm_momentum,
      norm_epsilon=norm_activation_config.norm_epsilon,
      kernel_regularizer=l2_regularizer,
  )

task与yaml配置

详见: https://blog.csdn.net/shangyanaf/article/details/140364353

相关实践学习
基于ECS和NAS搭建个人网盘
本场景主要介绍如何基于ECS和NAS快速搭建个人网盘。
阿里云文件存储 NAS 使用教程
阿里云文件存储(Network Attached Storage,简称NAS)是面向阿里云ECS实例、HPC和Docker的文件存储服务,提供标准的文件访问协议,用户无需对现有应用做任何修改,即可使用具备无限容量及性能扩展、单一命名空间、多共享、高可靠和高可用等特性的分布式文件系统。 产品详情:https://www.aliyun.com/product/nas
相关文章
|
2月前
|
机器学习/深度学习 自然语言处理 计算机视觉
【YOLOv8改进 - Backbone主干】VanillaNet:极简的神经网络,利用VanillaNet替换YOLOV8主干
【YOLOv8改进 - Backbone主干】VanillaNet:极简的神经网络,利用VanillaNet替换YOLOV8主干
|
2月前
|
编解码 Go 文件存储
【YOLOv8改进 - 特征融合NECK】 DAMO-YOLO之RepGFPN :实时目标检测的创新型特征金字塔网络
【YOLOv8改进 - 特征融合NECK】 DAMO-YOLO之RepGFPN :实时目标检测的创新型特征金字塔网络
|
2月前
|
机器学习/深度学习 自然语言处理 计算机视觉
【YOLOv8改进 - Backbone主干】VanillaNet:极简的神经网络,利用VanillaBlock降低YOLOV8参数
【YOLOv8改进 - Backbone主干】VanillaNet:极简的神经网络,利用VanillaBlock降低YOLOV8参数
|
2月前
|
机器学习/深度学习 计算机视觉
【YOLOv8改进 - 注意力机制】c2f结合CBAM:针对卷积神经网络(CNN)设计的新型注意力机制
【YOLOv8改进 - 注意力机制】c2f结合CBAM:针对卷积神经网络(CNN)设计的新型注意力机制
|
1天前
|
存储 安全 网络安全
云计算与网络安全:云服务、网络安全、信息安全等技术领域的探讨
【9月更文挑战第5天】云计算作为一种新兴的计算模式,已经在全球范围内得到了广泛的应用。然而,随着云计算的快速发展,网络安全问题也日益凸显。本文将从云服务、网络安全、信息安全等方面对云计算与网络安全进行探讨。
26 15
|
2天前
|
安全 算法 网络安全
网络安全与信息安全:漏洞、加密与安全意识的三重奏
【9月更文挑战第4天】在数字时代的交响乐中,网络安全与信息安全是不可或缺的乐章。本文将深入探讨网络安全的脆弱性,揭示那些隐藏在光鲜表面下的潜在风险。我们将一同穿梭于加密技术的迷宫,解锁保护数据的神秘钥匙。更重要的是,本文将点亮一盏灯,照亮培养个人和组织安全意识的道路。通过深入浅出的分析与生动的案例,我们将共同见证网络安全的复杂性、加密技术的力量以及安全意识的重要性。让我们携手,为这场数字交响乐谱写一曲无懈可击的安全篇章。
|
1天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第5天】在数字化时代,网络安全和信息安全已成为全球关注的焦点。本文将探讨网络安全漏洞、加密技术和安全意识等方面的内容,以帮助读者更好地了解网络安全的重要性,并提高自己的网络安全防护能力。我们将通过分析网络安全漏洞的原因和影响,介绍加密技术的基本原理和应用,以及强调安全意识在防范网络攻击中的关键作用。最后,我们将提供一些实用的建议,帮助读者保护自己的网络安全。
|
2天前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第4天】在数字化时代,网络安全和信息安全已成为全球关注的焦点。本文将探讨网络安全漏洞、加密技术以及提升安全意识的重要性。我们将通过深入浅出的方式,解析网络安全的基础知识,并提供实用的代码示例,帮助读者更好地理解并应对网络安全挑战。
|
3天前
|
监控 安全 网络安全
云计算与网络安全的融合之路:探索云服务中的信息安全实践
【9月更文挑战第3天】在数字化转型的浪潮中,云计算已成为现代企业不可或缺的技术基石。然而,随着数据和应用逐渐迁移至云端,网络安全和信息安全的挑战亦随之升级。本文将深入探讨云计算环境下的网络安全挑战,并分享如何通过策略和技术手段加强云服务的安全防护,确保企业资产与数据的完整性、可用性和保密性。
17 5
|
2天前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第4天】在数字化时代,网络安全和信息安全已经成为了我们生活中不可或缺的一部分。然而,随着网络技术的不断发展,网络安全漏洞也越来越多,给我们的生活带来了诸多不便。本文将介绍网络安全漏洞、加密技术和安全意识等方面的知识,帮助读者更好地了解网络安全的重要性,提高自己的安全防护能力。
下一篇
DDNS