Single-Image Crowd Counting via Multi-Column Convolutional Neural Network

================================================================

Single-Image Crowd Counting via Multi-Column Convolutional Neural Network

    • 论文背景
    • 人群密度方法过去的发展历史
      • 早期方法
      • 基于轨迹聚类的方法
      • 基于特征回归的方法
      • 基于图像的方法
    • Multi-column CNN用于人群计数
      • 基于密度图的人群计数
      • 通过几何自适应核生成密度图
      • 密度图估计的多列CNN

论文背景

在2015年的上海大规模踩踏事件中,35人丧生。自那以后,世界各地发生了许多类似的人潮踩踏事件,导致更多的伤亡。因此,精确估算图像或视频中的人群数量对于计算机视觉技术在人群控制和公共安全方面的应用变得愈发重要。在公共集会、体育赛事等场景中,参与人数或密度是未来活动规划和空间设计的基本信息。良好的人群计数方法也可以扩展到其他领域,如从显微图像中计数细胞或细菌、在野生动物保护区估算动物群体的数量,或者估算交通枢纽或交通拥堵中的车辆数量等。

人群密度方法过去的发展历史

早期方法

以前的方法主要采用检测风格的框架,通过在视频序列的两个连续帧上扫描检测器,基于增强外观和运动特征,估算行人的数量。一些方法使用类似的基于检测的框架进行行人计数。然而,这些方法的局限性在于,它们通常假定人群由可以通过某些给定检测器检测到的单独实体组成,这在拥挤的环境或非常密集的人群中显着影响检测器性能和最终的估算准确性。

具体步骤如下
当我们想要数一群人的时候,可以通过观察视频中相邻两帧的变化来实现。方法是这样的:

  • 看变化: 首先,我们会拿到视频中的两个连续画面,然后比较它们之间有哪些地方发生了变化,特别是有没有人在动。
  • 找动的人: 如果有地方发生了变化,我们会认为那些是移动的个体,也就是人。这就是通过观察画面变化来找到人群的方法。
  • 确认特征: 在找到的移动的地方,我们可能会再看一些其他特征,比如这些“移动的东西”是否看起来像人,或者它们的动作是不是像人的动作。
  • 数人: 最后,通过统计在两个画面之间发现的“移动的东西”,我们就能大致估算视频中整个人群的数量。

基于轨迹聚类的方法

这种方法的核心思想是通过对视觉特征的轨迹进行聚类来计数人群。简单来说,就是通过观察视频中物体在一段时间内的运动轨迹,将相似的轨迹归为一类,从而估算人群的数量。但需要注意的是,这种方法适用于视频,而不适用于单个静止图像。

具体步骤如下

  • 轨迹提取: 先从视频中提取物体的运动轨迹,可以使用一些跟踪器(比如KLT跟踪器)来追踪物体在不同帧之间的位置变化。
  • 轨迹聚类: 将这些轨迹按照它们的相似度进行聚类,相似的轨迹被归为同一类。这里的相似度可能包括轨迹的形状、长度、速度等方面的特征。
  • 估算人数: 每个聚类代表了一组相似运动的物体,我们可以认为这是同一群人。通过统计不同聚类中的轨迹数,就能估算出人群的数量。

基于特征回归的方法

这种方法通过对图像的前景进行分割,提取各种特征,然后使用回归函数来估算人群的数量

具体步骤如下

  • 分割前景: 在图像中,人群通常是前景,而其他部分是背景。首先,需要对图像进行前景分割,将人群从背景中分离出来。这可以使用图像分割算法来实现。
  • 提取特征: 从前景图中提取各种特征,这些特征可以包括人群区域的面积、边缘数量、纹理特征等。这些特征将用作回归模型的输入。
  • 回归函数: 使用回归函数来建模特征与人群数量之间的关系。回归函数的选择可以是简单的线性或分段线性函数,也可以采用更复杂的模型,如岭回归、高斯过程回归或神经网络。回归函数的目标是找到一个映射,使得输入特征可以准确地预测人群的数量。

具体的计算公式如下(以线性回归为例)

给定特征向量 x x x(包括面积、边缘数量、纹理等),人群数量的估计 y ^ \hat y y^为:
y ^ = w ⋅ x + b \hat y =w⋅x+b y^=wx+b

其中, w w w是回归系数向量, b b b是偏置。通过训练回归模型,得到最优的 w w w b b b参数,使得预测值 y ^ \hat y y^接近实际的人群数量。

这种方法的优势在于简单且易于理解,而更复杂的模型可以处理更高度非线性的关系,提高估算的准确性。

基于图像的方法

一些研究专注于从静态图像中估算人群数量。不同于前面介绍的视频帧间运动或轨迹聚类方法,这些方法主要依赖于单个静态图像。以下是其中一些方法的原理:

  • 多信息源计数: 一种方法是利用单个图像中的多个信息源来计算密集群中的个体数量。这些信息源可以包括SIFT(尺度不变特征变换)、傅立叶分析、小波分解、GLCM(灰度共生矩阵)特征以及对头部的低置信度检测。通过综合利用这些信息,可以更全面地估算人群数量。
  • 特征融合和支持向量机(SVM): 另一种方法是利用预训练的卷积神经网络(CNN)提取图像特征,并将这些特征用于训练支持向量机(SVM)。具体而言,研究者可以使用多个信息源,如SIFT、傅立叶分析、小波分解、GLCM特征以及低置信度头部检测,将它们融合为一个综合的特征向量。然后,这个特征向量可以用于训练SVM,从而建立图像特征与人群数量之间的关系。

具体而言,特征融合可以表示为:

特征向量=[SIFT特征,傅立叶分析特征,小波分解特征,GLCM特征,低置信度头部检测特征,…]

然后,将这个特征向量用于训练SVM模型,该模型可以根据输入的图像特征向量来预测人群的数量。

这些方法的优势在于能够从静态图像中获取人群数量的信息,而不需要考虑视频帧之间的运动或轨迹信息。然而,对于不同的场景和图像,需要综合利用多个信息源,以提高估算的准确性。

Multi-column CNN用于人群计数

基于密度图的人群计数

在通过卷积神经网络(CNNs)估算给定图像中人数的过程中,有两种自然的配置。

  • 一种是输入为图像,输出为估算的头部计数的网络。
  • 另一种是输出人群的密度图(每平方米多少人),然后通过积分得出头部计数。

本文支持第二种选择,因为密度图保留更多信息。相对于总人群数量,密度图给出了图像中人群的空间分布信息,这在许多应用中都很有用。例如,如果某个区域的密度远高于其他区域,可能表明该区域发生了异常情况。

提出了使用CNN学习密度图的方法,其学习的滤波器更适应于不同大小头部,从而更适用于透视效应变化显著的任意输入。

通过几何自适应核生成密度图

由于CNN需要从输入图像训练以估算密度图,训练数据中给定的密度质量在很大程度上决定了方法的性能。

具体步骤

首先,对于图像中的每个头,将用一个 δ δ δ函数来表示。这个 δ δ δ函数在图像上的位置由 x i x_i xi表示,其中 i i i是头部的编号。如果图像中有 N N N个头,那么将这些 δ δ δ函数的和表示为 H ( x ) H(x) H(x),其中 H ( x ) H(x) H(x)是一个包含 N N N δ δ δ函数的函数,即:

H ( x ) = ∑ i = 1 N δ ( x − x i ) H(x) = \sum_{i=1}^Nδ(x - x_i) H(x)=i=1Nδ(xxi)

为了将其转换为连续的密度函数,可以将该函数与高斯核 G σ G_σ Gσ卷积,使得密度为:
F ( x ) = H ( x ) ∗ G σ ( x ) F(x) = H(x) * G_σ(x) F(x)=H(x)Gσ(x)

然而,这样的密度函数假定 x i x_i xi是图像平面上的独立样本,而实际上,每个 x i x_i xi是3D场景中地面上的人群密度样本,由于透视失真,与不同 x i x_i xi对应的像素对应于场景中不同尺寸的区域。

为了准确估算人群密度 F F F,需要考虑由地平面和图像平面之间的单应性引起的扭曲。然而,在任务和数据集中,通常并不知道场景的几何形状。尽管如此,如果假设每个头周围的人群在图像上是均匀分布的,那么头与其最近的 k k k个邻居(在图像上)之间的平均距离给出了透视效应引起的几何扭曲的合理估计。

因此,应该基于图像中每个人的头尺寸自适应地确定传播参数 σ σ σ。对于给定图像中的每个头 x i x_i xi,将其到其 k k k个最近邻居的距离表示为 [ d 1 i , d 2 i , . . . , d m i ] [d^i_1, d^i_2, ..., d^i_m] [d1i,d2i,...,dmi]。平均距离是 d ˉ i = 1 m ∑ j = 1 m d j i \bar d^i = \frac{1}{m}\sum_{j=1}^m d^i_j dˉi=m1j=1mdji

因此,与 x i x_i xi关联的像素大致对应于场景中地面上半径与 d ˉ i \bar d_i dˉi成比例的区域。因此,为了估算 x i x_i xi周围的人群密度,需要将 δ ( x − x i ) δ(x - x_i) δ(xxi)与方差 σ i σ_i σi成比例的高斯核卷积。更具体地说,密度 F F F应为

F ( x ) = ∑ i = 1 N δ ( x − x i ) ∗ G σ ( x ) F(x) =\sum_{i=1}^Nδ(x-x_i) * G_σ(x) F(x)=i=1Nδ(xxi)Gσ(x)

其中 σ i = β ∗ d ˉ i σ_i = β * \bar d_i σi=βdˉi β β β是参数。换句话说,我们使用自适应于每个数据点周围局部几何的密度核,称为几何自适应核。在实验中,我们经验性地发现 β = 0.3 β = 0.3 β=0.3给出了最佳结果。

密度图估计的多列CNN

由于透视失真,图像通常包含不同大小的头,因此具有相同大小感受野的滤波器不太可能捕捉到不同尺度的人群密度特征。因此,更自然的方法是使用具有不同局部感受野大小的滤波器来学习原始像素到密度图的映射。受多列深度神经网络(MDNNs)成功的启发,提出使用多列卷积神经网络(MCNN)来学习目标密度图。在我们的MCNN中,对于每一列,我们使用不同大小的滤波器来建模与不同尺度头相对应的密度图。例如,具有较大感受野的滤波器对应于建模与较大头相对应的密度图。模型架构图如下:

在这里插入图片描述

MCNN包含三个平行的CNN,其滤波器具有不同大小的局部感受野。为简化起见,我们对所有列使用相同的网络结构(即,conv–pooling–conv–pooling),除了滤波器的大小和数量。对于每个2×2区域,应用最大池化,并且由于ReLU对于CNN的性能良好,采用修正线性单元(ReLU)作为激活函数。

为了减少计算复杂性(要优化的参数数量),对具有较大滤波器的CNN使用较少的滤波器。堆叠所有CNN的输出特征图,并将它们映射到密度图。为了将特征图映射到密度图,采用滤波器大小为1×1。然后,使用欧几里得距离来衡量估算的密度图与地面实况之间的差异。损失函数定义如下:

在这里插入图片描述
其中, Θ Θ Θ是MCNN中可学习参数的集合,N是训练图像的数量, X i X_i Xi是输入图像, F i F_i Fi是图像 X i X_i Xi的地面实况密度图。 F ( X i ; Θ ) F(X_i; \Theta) F(Xi;Θ)表示由带有参数 Θ Θ Θ的MCNN生成的估算密度图, L L L是估算密度图与地面实况密度图之间的损失。

注意事项:

  • 由于使用两层最大池化,每个图像的空间分辨率减少了1/4。因此,在训练阶段,我们在生成密度图之前将每个训练样本下采样1/4。
  • 传统的CNN通常将输入图像规范化为相同的大小。这里我们更喜欢输入图像保持其原始大小,因为将图像调整为相同的大小会引入难以估计的密度图中的额外失真。
  • 除了CNN中的滤波器具有不同的大小之外,MCNN与传统MDNN之间的另一个区别是使用具有可学习权重的所有CNN的输出(即,1×1滤波器)进行组合。相比之下,在提出的MDNNs中,输出简单地平均。

骨干结构在计算机视觉模型中无论是图像分类目标检测或者人群计数等任务中起到了提取图像特征的作用。因此它骨干模型的内部输出图像其实就是一个类似的密度图,MCNN再结合多尺度就会把整个图片里所有人头都检测

我这里有一个实现骨干模型内部可视化的脚本可以参考,模型就用的最常见的骨干模型VGG,VGG模型代码在后面。

import torch
import torch.nn as nn
from torch.autograd import Variable
from torchvision.transforms import transforms
import numpy as np
import cv2
from functools import partial
import matplotlib
import os
import json
matplotlib.use('agg')
import matplotlib.pyplot as plt
import requestsfrom models import Vgg16Conv
from models import Vgg16Deconvdef load_and_preprocess_image(img_path):"""加载和预处理图像"""# 从img_path读取图像img = cv2.imread(img_path)img = cv2.resize(img, (224, 224))# PyTorch必须通过以下均值和标准差对图片进行标准化transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])img = transform(img)img.unsqueeze_(0)return imgdef hook_function(module, input, output, key):"""用于存储特征图的钩子函数"""if isinstance(module, nn.MaxPool2d):model.feature_maps[key] = output[0]model.pool_locs[key] = output[1]else:model.feature_maps[key] = outputdef register_hooks(model):"""为骨干模型注册特征图存储钩子"""def hook(module, key):layer.register_forward_hook(partial(hook_function, key=key))for idx, layer in enumerate(model._modules.get('features')):    # _modules返回一个有序字典hook(layer, key=idx)def visualize_layer(layer, vgg16_conv, vgg16_deconv):"""可视化骨干模型的某一层的反卷积结果"""num_feat = vgg16_conv.feature_maps[layer].shape[1]# 将其他特征图激活设置为零new_feat_map = vgg16_conv.feature_maps[layer].clone()# 选择最大激活的特征图act_lst = []for i in range(0, num_feat):choose_map = new_feat_map[0, i, :, :]activation = torch.max(choose_map)act_lst.append(activation.item())act_lst = np.array(act_lst)mark = np.argmax(act_lst)choose_map = new_feat_map[0, mark, :, :]max_activation = torch.max(choose_map)# 对其他特征图进行零值处理if mark == 0:new_feat_map[:, 1:, :, :] = 0else:new_feat_map[:, :mark, :, :] = 0if mark != vgg16_conv.feature_maps[layer].shape[1] - 1:new_feat_map[:, mark + 1:, :, :] = 0choose_map = torch.where(choose_map==max_activation,choose_map,torch.zeros(choose_map.shape))# 对其他激活进行零值处理new_feat_map[0, mark, :, :] = choose_map# 输出反卷积结果deconv_output = vgg16_deconv(new_feat_map, layer, mark, vgg16_conv.pool_locs)new_img = deconv_output.data.numpy()[0].transpose(1, 2, 0)  # (H, W, C)# 归一化new_img = (new_img - new_img.min()) / (new_img.max() - new_img.min()) * 255new_img = new_img.astype(np.uint8)return new_img, int(max_activation)if __name__ == '__main__':img_path = './data/cat.jpg'# 前向处理img = load_and_preprocess_image(img_path)vgg16_conv = Vgg16Conv()vgg16_conv.eval()register_hooks(vgg16_conv)conv_output = vgg16_conv(img)pool_locs = vgg16_conv.pool_locs# 反向处理vgg16_deconv = Vgg16Deconv()vgg16_deconv.eval()plt.figure(num=None, figsize=(16, 12), dpi=80)plt.subplot(2, 4, 1)plt.title('Original Picture')img = cv2.imread(img_path)img = cv2.resize(img, (224, 224))plt.imshow(img)    for idx, layer in enumerate([14, 17, 19, 21, 24, 26, 28]):# for idx, layer in enumerate(vgg16_conv.conv_layer_indices):        plt.subplot(2, 4, idx+2)img, activation = visualize_layer(layer, vgg16_conv, vgg16_deconv)plt.title(f'{layer} Layer, Max Activation: {activation}')plt.imshow(img)plt.savefig('result.jpg')print('Result picture has been saved at ./result.jpg')

model.vgg16_conv.py

import torch
import torch.nn as nn
import torchvision.models as models
import torchvisionfrom collections import OrderedDictclass Vgg16Conv(nn.Module):"""vgg16 convolution network architecture"""def __init__(self, num_cls=1000):"""Inputnumber of class, default is 1k."""super(Vgg16Conv, self).__init__()self.features = nn.Sequential(# conv1nn.Conv2d(3, 64, 3, padding=1),nn.ReLU(),nn.Conv2d(64, 64, 3, padding=1),nn.ReLU(),nn.MaxPool2d(2, stride=2, return_indices=True),# conv2nn.Conv2d(64, 128, 3, padding=1),nn.ReLU(),nn.Conv2d(128, 128, 3, padding=1),nn.ReLU(),nn.MaxPool2d(2, stride=2, return_indices=True),# conv3nn.Conv2d(128, 256, 3, padding=1),nn.ReLU(),nn.Conv2d(256, 256, 3, padding=1),nn.ReLU(),nn.Conv2d(256, 256, 3, padding=1),nn.ReLU(),nn.MaxPool2d(2, stride=2, return_indices=True),# conv4nn.Conv2d(256, 512, 3, padding=1),nn.ReLU(),nn.Conv2d(512, 512, 3, padding=1),nn.ReLU(),nn.Conv2d(512, 512, 3, padding=1),nn.ReLU(),nn.MaxPool2d(2, stride=2, return_indices=True),# conv5nn.Conv2d(512, 512, 3, padding=1),nn.ReLU(),nn.Conv2d(512, 512, 3, padding=1),nn.ReLU(),nn.Conv2d(512, 512, 3, padding=1),nn.ReLU(),nn.MaxPool2d(2, stride=2, return_indices=True))self.classifier = nn.Sequential(nn.Linear(512 * 7 * 7, 4096),nn.ReLU(),nn.Dropout(),nn.Linear(4096, 4096),nn.ReLU(),nn.Dropout(),nn.Linear(4096, num_cls),nn.Softmax(dim=1))# index of convself.conv_layer_indices = [0, 2, 5, 7, 10, 12, 14, 17, 19, 21, 24, 26, 28]# feature mapsself.feature_maps = OrderedDict()# switchself.pool_locs = OrderedDict()# initial weightself.init_weights()def init_weights(self):"""initial weights from preptrained model by vgg16"""vgg16_pretrained = models.vgg16(pretrained=True)# fine-tune Conv2dfor idx, layer in enumerate(vgg16_pretrained.features):if isinstance(layer, nn.Conv2d):self.features[idx].weight.data = layer.weight.dataself.features[idx].bias.data = layer.bias.data# fine-tune Linearfor idx, layer in enumerate(vgg16_pretrained.classifier):if isinstance(layer, nn.Linear):self.classifier[idx].weight.data = layer.weight.dataself.classifier[idx].bias.data = layer.bias.datadef check(self):model = models.vgg16(pretrained=True)return modeldef forward(self, x):for idx, layer in enumerate(self.features):if isinstance(layer, nn.MaxPool2d):x, location = layer(x)# self.pool_locs[idx] = locationelse:x = layer(x)# reshape to (1, 512 * 7 * 7)x = x.view(x.size()[0], -1)output = self.classifier(x)return outputif __name__ == '__main__':model = models.vgg16(pretrained=True)print(model)

model.vgg16_deconv.py

import torch
import torch.nn as nn
import torchvision.models as modelsimport sysclass Vgg16Deconv(nn.Module):"""vgg16 transpose convolution network architecture"""def __init__(self):super(Vgg16Deconv, self).__init__()self.features = nn.Sequential(# deconv1nn.MaxUnpool2d(2, stride=2),nn.ReLU(),nn.ConvTranspose2d(512, 512, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(512, 512, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(512, 512, 3, padding=1),# deconv2nn.MaxUnpool2d(2, stride=2),nn.ReLU(),nn.ConvTranspose2d(512, 512, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(512, 512, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(512, 256, 3, padding=1),# deconv3nn.MaxUnpool2d(2, stride=2),nn.ReLU(),nn.ConvTranspose2d(256, 256, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(256, 256, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(256, 128, 3, padding=1),# deconv4nn.MaxUnpool2d(2, stride=2),nn.ReLU(),nn.ConvTranspose2d(128, 128, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(128, 64, 3, padding=1),# deconv5nn.MaxUnpool2d(2, stride=2),nn.ReLU(),nn.ConvTranspose2d(64, 64, 3, padding=1),nn.ReLU(),nn.ConvTranspose2d(64, 3, 3, padding=1)    )self.conv2deconv_indices = {0:30, 2:28, 5:25, 7:23,10:20, 12:18, 14:16, 17:13,19:11, 21:9, 24:6, 26:4, 28:2}self.unpool2pool_indices = {26:4, 21:9, 14:16, 7:23, 0:30}self.init_weight()def init_weight(self):vgg16_pretrained = models.vgg16(pretrained=True)for idx, layer in enumerate(vgg16_pretrained.features):if isinstance(layer, nn.Conv2d):self.features[self.conv2deconv_indices[idx]].weight.data = layer.weight.data#self.features[self.conv2deconv_indices[idx]].bias.data\# = layer.bias.datadef forward(self, x, layer, activation_idx, pool_locs):if layer in self.conv2deconv_indices:start_idx = self.conv2deconv_indices[layer]else:raise ValueError('layer is not a conv feature map')for idx in range(start_idx, len(self.features)):if isinstance(self.features[idx], nn.MaxUnpool2d):x = self.features[idx]\(x, pool_locs[self.unpool2pool_indices[idx]])else:x = self.features[idx](x)return x

在这里插入图片描述
在这里插入图片描述
从上面图片来看,每层都有一些特征保留出来,而这种特征看起来像是一些opencv特征算法提取的感觉。这种特征结合高斯密度函数,就可以转为密度图啦

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

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

相关文章

【论文+在线运行】AnyText:能准确写汉字的AI绘图工具

源码:https://github.com/tyxsspa/AnyText 阿里在线运行: https://modelscope.cn/studios/damo/studio_anytext/summary 论文:2311.AnyText: Multilingual Visual Text Generation And Editing 一、AnyTexT是什么? 是一个基于扩散模型的&am…

ATE自动测试设备是什么?如何帮助测试电源反复短路?

什么是电源反复短路测试? 反复短路测试是电源极限测试项目之一,是在各种输入和输出状态下将电源输出短路,反复多次短路测试,检测电源是否可以实现保护或回缩,测试结束后之后,电源是否可以自动恢复正常运行。反复短路测…

Java原生启动Tomcat

文章目录 引入依赖启动Tomcat代码示例将嵌入式 Tomcat 服务器用于已有的 WAR 文件为现有的 Java Web 应用程序嵌入 Tomcat 服务器 相关APITomcat APIContonxt API 启动错误springboot底层Tomcat的实现学习博客 引入依赖 maven: <dependency><groupId>org.apache.…

python 深度学习 记录遇到的报错问题10

本篇继python 深度学习 解决遇到的报错问题9_module d2l.torch has no attribute train_ch3-CSDN博客 一、CUDA error: no kernel image is available for execution on the device CUDA kernel errors might be asynchronously reported at some other API call,so the stackt…

数据结构【图篇】

数据结构【图篇】 文章目录 数据结构【图篇】前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f; 目录一、图(一)、图的存储(二)、图的基本操作(三)、最短路径问题 二、拓扑排序三、结语 前言 为什么突然想学算法了&#xff1f; > 用较为“官方…

金融追梦者,向着春天出发——社科院与美国杜兰大学金融管理硕士

随着时代的进步和社会的变迁&#xff0c;教育已经不再是单纯的学生时代的事情&#xff0c;而是贯穿人的一生。特别是在金融行业&#xff0c;由于其变幻莫测的特性&#xff0c;在职继续攻读硕士学位的人越来越多。他们希望通过进一步的学习和研究&#xff0c;提升自己的专业素养…

transformers Trainer自定义optimizer和scheduler

1.需求 我自定义了一个evaluate方法&#xff0c;想在每一轮训练过后都执行一次。如果只是在TrainingArguments里设置warmup_steps100&#xff0c;那么每轮都会重置学习率&#xff0c;也就是每一轮开始的时候都会按照warmup刚开始的学习率进行训练&#xff0c;这就很头疼。 2.…

【双指针算法】-- 左右指针

左右指针 前言一、双指针算法二、左右指针1.用于在已排序数组中找到两个数使其和为特定值2.在字符串中判断是否为回文 总结 前言 今天在刷Leetcode的时候觉得自己双指针掌握的还是不错的记录一下,写个学习笔记,也方便以后翻阅,如果也帮助到你了,那真是太好啦! 本篇介绍的是左右…

医院配电能效监管方案

摘要:本文以医院能源监管系统为研究对象,采用智能化技术组建数据库、构建智能化的能耗信息管理系统,实现对医院的能源利用状况进行实时、准确的动态监管。具体而言,该系统建设的主要功能是对医院的能源消耗进行采集、上报、汇总与分析,并生成动态的数据和报表曲线,以及利用分析…

SAP ABAP ZPL打印

前言 本文用于简单介绍在SAP中使用ZPL语言进行打印的开发步骤&#xff0c;由于对ZPL语言并不是很熟悉&#xff0c;所以ZPL相关的部分并不会很深入&#xff0c;主要介绍在SAP端如何动态填充ZPL内容及预览、打印。 什么是ZPL ZPL是斑马条码打印机工业型号用的编程语言。利用这些…

M3u8视频地址如何转为mp4视频

在当今数字化的时代&#xff0c;视频格式的转换已成为日常需求。M3u8格式的视频由于其分段的特性&#xff0c;常常给播放和编辑带来不便。而MP4格式则因其通用性和高质量而广受欢迎。那么&#xff0c;如何将M3u8视频地址转换为MP4格式呢&#xff1f;接下来&#xff0c;我们将为…

JRT代码结构调整和示例

之前一直没建表专门使用ORM的api&#xff0c;做模板设计器需要建表&#xff0c;就一边开发设计器一般测试和调整ORM的api&#xff0c;只有做业务才能知道哪些api使用别扭&#xff0c;写了设计器之后改进了ORM的api以方便业务操作数据库。新写法差不多是ORM操作数据库的稳定api了…

向日葵远程控制软件MySQL5.7的安装与配置

目录 一. 向日葵远程控制软件 1.1 简介 1.2 选择原因 1.3 安装及使用 1.4 使用场景 二. MySQL5.7 安装与配置 2.1 什么是MySQL 2.2 安装 MySQL5.7 2.2.1 安装步骤 2.2.2 内部连接 2.2.3 外部连接 三. 思维导图 一. 向日葵远程控制软件 1.1 简介 向日葵电脑版是一款拥有多年…

Java基础-----集合类(四)

文章目录 1. Iterator和ListIterator1.1 简介1.2 常用方法 2. remove方法2.1 比较foreach方式和迭代器方式删除元素2.2 找原因 -- 迭代器删除操作源码 1. Iterator和ListIterator 1.1 简介 1.Iterator 可以遍历List集合&#xff0c;也可以遍历Set集合&#xff1b; ListIterat…

05-SpringCloud-RabbitMQ-概述

RabbitMQ 1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&am…

Linux安装rabbitMq RPM安装 以及带延迟插件

rabbitmq安装 文档中rabbitmq下载链接 以及延迟插件 网盘下载 目前下载文件中版本已经过多个服务器安装测试 完全成功 1.安装执行 rpm -ivh openssl-libs-1.0.2k-19.el7.x86_64.rpm --force --nodeps rpm -ivh libnsl-2.34-28.el9_0.x86_64.rpm --force --nodeps rpm -ivh e…

京东商品详情API:数据分析和挖掘以优化销售策略

京东商品详情API提供的数据分析和挖掘功能可以帮助商家优化销售策略&#xff0c;提高销售额和用户转化率。以下是一些可能的应用场景&#xff1a; 商品关联分析&#xff1a;通过分析商品之间的关联规则&#xff0c;商家可以发现哪些商品经常一起被购买&#xff0c;从而制定捆绑…

c++ / day04

1. 整理思维导图 2. 全局变量&#xff0c;int monster 10000;定义英雄类hero&#xff0c;受保护的属性string name&#xff0c;int hp,int attck&#xff1b;公有的无参构造&#xff0c;有参构造&#xff0c;虚成员函数 void Atk(){blood-0;}&#xff0c;法师类继承自英雄类&a…

跟cherno手搓游戏引擎【1】:配置与入口点

环境配置&#xff1a; 编译环境&#xff1a;VS2019 创建两个项目&#xff1a; 设置Sandbox为启动项&#xff1a; 设置sandbox的配置属性-常规-输出目录\中间目录为如下&#xff1a; 预处理定义&#xff1a;为了配置一些只有windows才能用的函数。 设置YOTOEngin&#xff08;我…

【大数据HA】keepalived结合haproxy实现高可用的HMS

背景 上一篇实现了haproxy代理后端HMS服务实现高可用。但是对于haproxy还是单点故障&#xff0c;所以需要对haproxy进一步做HA&#xff0c;实现真正的后端服务的HA。 要实现haproxy的HA&#xff0c;需要使用到keepalived&#xff0c;使用keepalived是VIP虚拟IP服务&#xff0…