像素级创意:深入浅出PixelCNN图像合成技术
参考
https://arxiv.org/pdf/1601.06759
https://blog.csdn.net/zcyzcyjava/article/details/126559327
需要熟悉熵的一些理论、和极大释然估计等价于最小化交叉熵等知识
1. pixelcnn建模方法
pixelcnn做生成模型的想必都有耳闻。它是一种自回归模型,什么是自回归呢?简单的来说自回归模型意味着模型在生成数据时会条件依赖于之前已经生成的数据部分。我们知道无论是GAN还是VAE最初都在找一个思路,那就是想对 p θ ( x ) p_\theta(x) pθ(x)去建模型,事实上输入x的分布是难以确定的,因此,GAN和VAE都绕过了这条路,通过引入额外的网络,避开直接求解 p θ ( x ) p_\theta(x) pθ(x),比如GAN是引入对抗网络D,VAE是引入编码网络。而pixcelcnn不一样,它算是直接暴力求解 p θ ( x ) p_\theta(x) pθ(x),是像素级别的求解,认为第i个像素是由前i-1个像素决定的,因此释然函数可以写成如下,假设有n*n个像素:
p ( x ) = ∏ i = 1 n 2 p ( x i ∣ x 1 , x 2 , . . . , x i − 1 ) = ∏ i = 1 n 2 p ( x i ∣ X < i ) p(x) = \prod_{i=1}^{n^2}p(x_i|x_1,x_2,...,x_{i-1})= \prod_{i=1}^{n^2}p(x_i|X_{<i}) p(x)=i=1∏n2p(xi∣x1,x2,...,xi−1)=i=1∏n2p(xi∣X<i)
我们知道,最大化释然函数参数的求解写成对数如下:
θ = a r g m a x θ ∑ i n 2 l o g f i ( x i ∣ θ ) \theta=\underset{\theta}{argmax}\sum_i^{n^2} logf_i(x_i|\theta) θ=θargmaxi∑n2logfi(xi∣θ)
其中 f i ( x i ∣ θ ) f_i(x_i|\theta) fi(xi∣θ)为网络预测的结果,另外,作者假设每一个预测的像素值,为0~255中的一个分类,因此,预测分布等价于one-hot形式的多分类。损失函数进而转化为多分类的交叉熵问题,为: l o s s = E n t r y C r o s s ( y i , x i ) loss=EntryCross(y_i,x_i) loss=EntryCross(yi,xi) 其中 y i y_i yi为预测的像素值, x i x_i xi为输入的像素值。
2. 网络结构
以上是论文中提及到的网络结构,我们这里只看CNN结构,不看RNN结构。看这个网络结构其实很简单,也就是77卷积(maskA)+多个卷积残差结构(33 maskB)+2个1*1卷积(maskB)。但是,这里面有两个不是我们认识的那个CNN,一个是maskA一个是maskB。
maskA:
maskB:
简单来说,maskA是不包含中心元素的上半部分卷积,maskB是包含中心元素的上半部分卷积。这样做的目的是什么,具体详细原由可看原论文,意思是这样做生成的feature map每一个像素的感受野只会看到它上半部分的像素,不包含自身像素,这也满足之前pixcelcnn的建模:每一个像素都是由其前面i-1个像素决定的。因此pixelcnn网络结构是确定的,跟其建模是一致的。
3 MINIST测试pixelcnn
3.1 maskcnn构建
pixelcnn 关键是mask卷积的构造,我们看一下具体如何实现:
class MaskConv2d(nn.Module):""" 通过使用 mask 来构建 maskA和maskB Conv2d,方法是通过mask乘上卷积的权重"""def __init__(self, conv_type, *args, **kwargs):""":param conv_type: maskA还是maskB:param args::param kwargs:"""super(MaskConv2d, self).__init__()self.conv = nn.Conv2d(*args, **kwargs)k_h, k_w = self.conv.weight.shape[-2:]mask = torch.zeros((k_h, k_w), dtype=torch.float32)# maskAmask[0:k_h//2] = 1mask[k_h//2, 0:k_w//2] = 1# maskBif conv_type == 'B':mask[k_h//2, k_w//2] = 1mask = mask.reshape((1,1,k_h, k_w))self.register_buffer('mask', mask, False)def forward(self, x):self.conv.weight.data *= self.maskconv_res = self.conv(x)return conv_res
通过以上代码,我们可以看出,先构造一个nn.Conv2d,然后构建maskA和maskB的只有0和1值的大小为kernel size的矩阵,然后乘上nn.Conv2d的权重,来实现两种Mask CNN,非常简单。
3.2 整个网络结构
整个网络结构是按照论文里面构建的,不在多说,直接看代码:
import torch
import torch.nn as nnclass MaskConv2d(nn.Module):""" 通过使用 mask 来构建 maskA和maskB Conv2d,方法是通过mask乘上卷积的权重"""def __init__(self, conv_type, *args, **kwargs):""":param conv_type: maskA还是maskB:param args::param kwargs:"""super(MaskConv2d, self).__init__()self.conv = nn.Conv2d(*args, **kwargs)k_h, k_w = self.conv.weight.shape[-2:]mask = torch.zeros((k_h, k_w), dtype=torch.float32)# maskAmask[0:k_h//2] = 1mask[k_h//2, 0:k_w//2] = 1# maskBif conv_type == 'B':mask[k_h//2, k_w//2] = 1mask = mask.reshape((1,1,k_h, k_w))self.register_buffer('mask', mask, False)def forward(self, x):self.conv.weight.data *= self.maskconv_res = self.conv(x)return conv_resclass ResidualBlock(nn.Module):""" 残差块 """def __init__(self, h, bn=True):super(ResidualBlock, self).__init__()self.relu = nn.ReLU()self.conv1 = nn.Conv2d(2*h, h, 1)self.bn1 = nn.BatchNorm2d(h) if bn else nn.Identity()self.conv2 = MaskConv2d('B', h, h, 3, 1, 1)self.bn2 = nn.BatchNorm2d(h) if bn else nn.Identity()self.conv3 = nn.Conv2d(h, 2*h, 1)self.bn3 = nn.BatchNorm2d(2*h) if bn else nn.Identity()def forward(self, x):y = self.relu(x)y = self.conv1(y)y = self.bn1(y)y = self.relu(y)y = self.conv2(y)y = self.bn2(y)y = self.relu(y)y = self.conv3(y)y = self.bn3(y)return x + yclass PixelCNN(nn.Module):def __init__(self, n_block=15, h=128, bn=True, color_level=256):super(PixelCNN, self).__init__()# 7*7 convself.conv1 = MaskConv2d('A', 1, 2 * h, 7, 1, 3)self.bn1 = nn.BatchNorm2d(2 * h) if bn else nn.Identity()# residualself.residual_blocks = nn.ModuleList()for _ in range(n_block):self.residual_blocks.append(ResidualBlock(h, bn))self.relu = nn.ReLU()# 2个1*1 maskB,self.head = nn.Sequential(MaskConv2d('B', 2*h, h, 1),nn.ReLU(),MaskConv2d('B', h, h, 1),nn.ReLU(),nn.Conv2d(h, color_level, 1))def forward(self, x):x = self.conv1(x)x = self.bn1(x)for block in self.residual_blocks:x = block(x)x = self.relu(x)x = self.head(x)return xif __name__ == '__main__':from torchinfo import summarypixelcnn = PixelCNN()summary(pixelcnn, input_size=(1, 1, 28, 28), depth=2)
打印看一下网络结构,如果想看详细的层级结构,把summary中的depth改成3
PixelCNN [1, 256, 28, 28] –
├─MaskConv2d: 1-1 [1, 256, 28, 28] –
│ └─Conv2d: 2-1 [1, 256, 28, 28] 12,800
├─BatchNorm2d: 1-2 [1, 256, 28, 28] 512
├─ModuleList: 1-3 – –
│ └─ResidualBlock: 2-2 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-3 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-4 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-5 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-6 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-7 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-8 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-9 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-10 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-11 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-12 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-13 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-14 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-15 [1, 256, 28, 28] 214,528
│ └─ResidualBlock: 2-16 [1, 256, 28, 28] 214,528
├─ReLU: 1-4 [1, 256, 28, 28] –
├─Sequential: 1-5 [1, 256, 28, 28] –
│ └─MaskConv2d: 2-17 [1, 128, 28, 28] 32,896
│ └─ReLU: 2-18 [1, 128, 28, 28] –
│ └─MaskConv2d: 2-19 [1, 128, 28, 28] 16,512
│ └─ReLU: 2-20 [1, 128, 28, 28] –
│ └─Conv2d: 2-21 [1, 256, 28, 28] 33,024
3.2 训练
import torch
import torch.nn as nn
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import torch.nn.functional as Fclass MaskConv2d(nn.Module):""" 通过使用 mask 来构建 maskA和maskB Conv2d,方法是通过mask乘上卷积的权重"""def __init__(self, conv_type, *args, **kwargs):""":param conv_type: maskA还是maskB:param args::param kwargs:"""super(MaskConv2d, self).__init__()self.conv = nn.Conv2d(*args, **kwargs)k_h, k_w = self.conv.weight.shape[-2:]mask = torch.zeros((k_h, k_w), dtype=torch.float32)# maskAmask[0:k_h//2] = 1mask[k_h//2, 0:k_w//2] = 1# maskBif conv_type == 'B':mask[k_h//2, k_w//2] = 1mask = mask.reshape((1,1,k_h, k_w))self.register_buffer('mask', mask, False)def forward(self, x):self.conv.weight.data *= self.maskconv_res = self.conv(x)return conv_resclass ResidualBlock(nn.Module):""" 残差块 """def __init__(self, h, bn=True):super(ResidualBlock, self).__init__()self.relu = nn.ReLU()self.conv1 = nn.Conv2d(2*h, h, 1)self.bn1 = nn.BatchNorm2d(h) if bn else nn.Identity()self.conv2 = MaskConv2d('B', h, h, 3, 1, 1)self.bn2 = nn.BatchNorm2d(h) if bn else nn.Identity()self.conv3 = nn.Conv2d(h, 2*h, 1)self.bn3 = nn.BatchNorm2d(2*h) if bn else nn.Identity()def forward(self, x):y = self.relu(x)y = self.conv1(y)y = self.bn1(y)y = self.relu(y)y = self.conv2(y)y = self.bn2(y)y = self.relu(y)y = self.conv3(y)y = self.bn3(y)return x + yclass PixelCNN(nn.Module):def __init__(self, n_block=15, h=128, bn=True, color_level=256):super(PixelCNN, self).__init__()# 7*7 convself.conv1 = MaskConv2d('A', 1, 2 * h, 7, 1, 3)self.bn1 = nn.BatchNorm2d(2 * h) if bn else nn.Identity()# residualself.residual_blocks = nn.ModuleList()for _ in range(n_block):self.residual_blocks.append(ResidualBlock(h, bn))self.relu = nn.ReLU()# 2个1*1 maskB,self.head = nn.Sequential(MaskConv2d('B', 2*h, h, 1),nn.ReLU(),MaskConv2d('B', h, h, 1),nn.ReLU(),nn.Conv2d(h, color_level, 1))def forward(self, x):x = self.conv1(x)x = self.bn1(x)for block in self.residual_blocks:x = block(x)x = self.relu(x)x = self.head(x)return xdef train(num_epochs, batch, gpuid):device = torch.device(f"cuda:{gpuid}")trian_data = datasets.MNIST(root='data', train=True, download=True, transform=transforms.ToTensor())train_dataloader = DataLoader(trian_data, batch_size=batch, shuffle=True)model = PixelCNN()model = model.to(device)optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)loss_fn = nn.CrossEntropyLoss()for epoch in range(num_epochs):model.train()for x, _ in train_dataloader:x = x.to(device)label = torch.ceil(x*255).long()label = label.squeeze(1)loss = loss_fn(model(x), label)optimizer.zero_grad()loss.backward()optimizer.step()print(f"epoch:{epoch}, loss:{loss.item()}")sample(model, device, 64)def sample(model, device, n_sample=64):model.eval()C, H, W = (1, 28, 28)x = torch.zeros((n_sample, C, H, W)).to(device)with torch.no_grad():for i in range(H):for j in range(W):output = model(x)prob_dist = F.softmax(output[:,:,i,j], dim=1).datapixel = torch.multinomial(prob_dist, 1).float() / 255x[:,:,i,j] = pixel# Saving images row wisetorchvision.utils.save_image(x, 'imgs.png', nrow=8, padding=0)if __name__ == '__main__':train(100, 128, 0)
上面是整个完整代码,训练很简单,就是比较常规,看一眼都能明白。关键是采样算法,采样算法的过程是,先初始一个全0的图像,然后得到第一个像素,然后把第一个像素赋值给输入图像的第一个元素,以此类推得到最终的生成图像。关键步骤为下面三步:
- prob_dist = F.softmax(output[:,:,i,j], dim=1).data 得到当前像素的概率分布
- pixel = torch.multinomial(prob_dist, 1).float() / 255 从这个概率分布中随机采样一个值对应的索引,也就是一个0-255的像素值,因为softmax返回的是0-255(其实是/255归一化后)对应的概率,因此取索引值即为推理的像素值,然后/255归一化成minist输入
- x[:,:,i,j] = pixel,这个就是把推理的当前像素值赋值给输入x,去推理下一帧输入
结果:质量上还是比GAN差。以下是50个epoch的结果。
4 缺点
pixelCNN作为一类基于卷积神经网络的生成模型,在图像生成领域有着其独特之处,但也存在一些缺点,主要包括但不限于:
-
生成速度慢:PixelCNN的核心缺点之一是生成速度缓慢。因为它采用自回归的方式生成图像,即模型需要依次生成每一个像素,每个像素的生成都依赖于之前的所有像素。这种方式导致在生成高分辨率图像时,所需的计算时间和步骤显著增加。
-
训练时间长:据报道,即便是增强版的PixelCNN如PixelCNN++,也需要在强大的硬件配置(如8块Titan GPU)上训练多天才能收敛,而且这还仅是在处理相对较小的数据集(如CIFAR)时的情况。训练时间长不仅增加了资源消耗,也影响了研究与应用的效率。
-
采样效率低:由于逐像素生成的特性,PixelCNN在采样过程中无法并行化,这意味着即使在现代GPU上也无法有效利用硬件加速带来的并行计算优势,进一步降低了生成效率。
-
长程依赖建模能力有限:尽管PixelCNN使用了卷积层来捕捉局部特征,但自回归的生成顺序限制了模型对图像中远距离像素间依赖关系的建模能力,可能影响生成图像的全局一致性与细节丰富度。
-
内存使用:逐像素生成的过程中需要存储中间状态以供后续像素生成使用,这可能导致较高的内存使用,尤其是在处理大尺寸图像时。
-
样本质量:相比于同期的一些生成对抗网络(GANs)模型,PixelCNN生成的样本质量可能略逊一筹,尤其是在生成高保真度和视觉复杂度高的图像方面。
尽管有这些缺点,PixelCNN及其后续变体通过引入如门控机制、更高效的网络结构设计等方法,在一定程度上改善了这些问题,并在图像生成任务中保持着一定的竞争力。
相关文章:

像素级创意:深入浅出PixelCNN图像合成技术
参考 https://arxiv.org/pdf/1601.06759 https://blog.csdn.net/zcyzcyjava/article/details/126559327 需要熟悉熵的一些理论、和极大释然估计等价于最小化交叉熵等知识 1. pixelcnn建模方法 pixelcnn做生成模型的想必都有耳闻。它是一种自回归模型,什么是自回归…...

MyBatisPlus使用流程
引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version> </dependency> 版本号根据需要选取 在实体类上加注解声明,表信息 根据数…...

爬虫技术升级:如何结合DrissionPage和Auth代理插件实现数据采集
背景/引言 在大数据时代,网络爬虫技术已经成为数据收集的重要手段之一。爬虫技术可以自动化地从互联网上收集数据,节省大量人力和时间成本。然而,当使用需要身份验证的代理服务器时,许多现有的爬虫框架并不直接支持代理认证。这就…...

go 微服务框架kratos错误处理的使用方法及原理探究
通过go语言原生http中响应错误的实现方法,逐步了解和使用微服务框架 kratos 的错误处理方式,以及探究其实现原理。 一、go原生http响应错误信息的处理方法 处理方法: ①定义返回错误信息的结构体 ErrorResponse // 定义http返回错误信息的…...

AI播客下载:Dwarkesh Podcast(关于AI的深度访谈)
Dwarkesh Podcast 是由 Dwarkesh Patel 主持的播客,专注于深度访谈和探讨各种复杂且有趣的话题。该播客在业界获得了极高的评价,被认为是对话和思想交流的平台。 Dwarkesh Podcast 的内容涵盖了多个领域,包括经济学、哲学以及科技等。例如&am…...
C++11function包装器的使用
类模板std::function是一种通用、多态的函数包装。std::function的实例可以对任何可以调用的目标实体进行存储、 复制和调用操作。这些目标实体包括普通函数、Lambda表达式、函数指针、以及其他函数对象等。std::function对象是对 C中现有的可调用实体的一种类型安全的包裹&…...
Vue3判断变量和对象不为null和undefined
Vue3判断变量和对象不为null和undefined 一、判断变量二、判断对象 一、判断变量 在 Vue 3 中,你可以使用 JavaScript 提供的常规方式来检查变量是否不为 null 和不为 undefined。你可以分别使用严格不等运算符 ! 来比较变量是否不为 null 和不为 undefined。以下是…...

C++进阶:C++11(列表初始化、右值引用与移动构造移动赋值、可变参数模版...Args、lambda表达式、function包装器)
C进阶:C11(列表初始化、右值引用与移动构造移动赋值、可变参数模版…Args、lambda表达式、function包装器) 今天接着进行语法方面知识点的讲解 文章目录 1.统一的列表初始化1.1{}初始化1.2 initializer_listpair的补充 2.声明相关关键字2.1a…...
Vue.js Promise 与 async/await 的比较
在现代 Web 开发中,异步操作是不可避免的。在处理异步数据获取时,开发人员通常会使用 Promise 或 async/await。虽然两者都可以实现相同的功能,但它们在代码风格、可读性和错误处理等方面有所不同。本文将对这两种方法进行比较,并…...

Qt 报错总结 No suitable kits found
目录 “No suitable kits found” 解决 解决方法参考: chatGPT辅助解决QT构建报错error: multiple target patterns 我的解决方法:把语言设置为空 “No suitable kits found” 解决 没有找到合适的kits套件,在安装Qt Creator时没有安装Min…...

ThingsBoard如何拆分前后端分离启动
后端启动 前端启动 注意事项 ThingsBoard是一个开源的物联网平台,它原本的设计就考虑到了现代Web应用的前后端分离架构。尽管其核心是一个后端服务,负责设备连接、数据处理和存储等,但其用户界面是作为单独的前端应用程序实现的,…...
加载页面 跳转 新页面 vue
通常,我们点页面上的详情,或者编辑,需要加载一个新的页面出来。 vue中加载页面的方法: 在父页面中(通常是某个模块目录下的index.vue),先写这行代码: import AddEditForm from ./…...

中国主要城市房价指数数据集(2011-2024)
数据来源:东方财富网 时间跨度:2011年1月 - 2024年4月 数据范围:中国主要城市 包含指标: 日期、城市 新建商品住宅价格指数-同比 新建商品住宅价格指数-环比 新建商品住宅价格指数-定基 二手住宅价格指数-环比 二手住宅价格指…...

Creating Server TCP listening socket *:6379: listen: Unknown error
错误: 解决方法: 在redis安装路径中打开cmd命令行窗口,输入 E:\Redis-x64-3.2.100>redis-server ./redis.windows.conf结果:...

JUnit5标记测试用例
使用场景: 通过Tag对用例分组: 环境分组:测试环境、预发布环境阶段分组:冒烟用例版本分组:V1.1、V1.2 Tag标记用例: 设置标签根据标签执行 结合Maven执行结合测试套件执行 设置标签: 通过T…...

在Windows10中重命名文件和文件夹的6种方法,有你熟悉和不熟悉的
序言 你可以通过多种方式在Windows 10上重命名文件。如果每次你想更改文件名时仍右键单击并选择“重命名”,那么我们有一些技巧可以加快更改速度。 使用文件资源管理器重命名文件和文件夹 Windows 10的文件资源管理器是一个功能强大的工具。你知道吗,有四种不同的方法可以…...

Go源码--sync库(1)sync.Once和
简介 这篇主要介绍 sync.Once、sync.WaitGroup和sync.Mutex sync.Once once 顾名思义 只执行一次 废话不说 我们看源码 英文介绍直接略过了 感兴趣的建议读一读 获益匪浅 其结构体如下 Once 是一个严格只执行一次的object type Once struct {// 建议看下源码的注解…...
头歌OpenGauss数据库-I.复杂查询第3关:统计总成绩
本关任务:计算每个班的语文总成绩和数学总成绩,要求科目中低于60分的成绩不记录总成绩。 tb_score结构数据: namechinesemathsA8998B9989C5566D8866E5566F8899tb_class表结构数据: stunameclassnameAC1BC2CC3DC2EC1FC3--#请在此添加实现代码 --# # # # # # # # # # Begin #…...
LeetCode hot100-47-N
105. 从前序与中序遍历序列构造二叉树给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。这题放选择题里还能选出来,前序中序一起确定了一颗什…...

中北大学软件学院计算机网络实验一
目录 1.实验名称2.实验目的3.实验内容4.实验过程(1)安装Packer Tracer并熟悉软件操作(2)利用一台型号为2960的交换机将2台pc机互连组建一个小型局域网(3)分别设置pc机的ip地址(4)验证…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...