像素级创意:深入浅出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)验证…...

扩散模型学习1
DDPM 总体训练原理 https://www.bilibili.com/video/BV1nB4y1h7CN/?spm_id_from333.337.search-card.all.click&vd_sourcef745c116402814185ab0e8636c993d8f 讲得很好:每次都是输入t和noise-x的图像,预测noise之后得到和加入的noise比较;…...

【HTML】制作一个跟随鼠标的流畅线条引导页界面(可直接复制源码)
目录 前言 HTML部分 CSS部分 JS部分 效果图 总结 前言 无需多言,本文将详细介绍一段HTML代码,图中线条可跟随鼠标移动,具体内容如下: 开始 首先新建一个HTML的文本,文本名改为[index.html],创建好后右…...

vue3父子组件、跨级组件之间的通信之provide, inject -- 通俗易懂
当组件之间的跨度比较大时,用父子孙之间的通信需要层层传递,不优雅,也不方便传值和更新。 此方法适用于父子组件之间、爷孙组件之间的通信且高效。 父组件: 孙组件: 此处本组件触发点击事件后,count的数据…...

input输入多行文本,保存为.dot文件和对应的.txt文件
需求 不管是上面的dot还是这个dot 变成 input输入文本按“# ꧂ ꧁”结束保存在dot文本文件夹下,用txt保存每个文件文件名: 编号. 第二行有字文字 时间戳 代码 首先,我会创建一个Python脚本,它将接受用户的输入,直到…...

如何让社区版IDEA变得好用
如何让社区版IDEA变得好用 背景 收费版的idea功能非常强大,但是费用高。社区版的免费,但是功能被阉割了。如何才能让社区版Idea变得好用,就需要各种插件支持了。经过全局配置编码,maven,jdk版本,在加上各…...

Hsql每日一题 | day02
前言 就一直向前走吧,沿途的花终将绽放~ 题目:主播同时在线人数问题 如下为某直播平台主播开播及关播时间,根据该数据计算出平台最高峰同时在线的主播人数。 id stt edt 1001,2021-06-14 12:12:12,2021-06-14 18:1…...

RepOptimizer原理与代码解析(ICLR 2023)
paper:Re-parameterizing Your Optimizers rather than Architectures offcial implementation:https://github.com/dingxiaoh/repoptimizers 背景 神经网络的结构设计是将先验知识融入模型中。例如将特征转换建模成残差相加的形式(\(yf(x…...

持续总结中!2024年面试必问 20 道 Redis面试题(六)
上一篇地址:持续总结中!2024年面试必问 20 道 Redis面试题(五)-CSDN博客 十一、Redis集群的原理是什么? 集群是一种分布式系统架构,它由多个节点组成,这些节点共同工作以提供高可用性、扩展性…...

【通义千问—Qwen-Agent系列2】案例分析(图像理解图文生成Agent||多模态助手|| 基于ReAct范式的数据分析Agent)
目录 前言一、快速开始1-1、介绍1-2、安装1-3、开发你自己的Agent 二、基于Qwen-Agent的案例分析2-0、环境安装2-1、图像理解&文本生成Agent2-2、 基于ReAct范式的数据分析Agent2-3、 多模态助手 附录1、agent源码2、router源码 总结 前言 Qwen-Agent是一个开发框架。开发…...

10G SFP双口万兆以太网控制器,高速光口网络接口卡
2-Port 10G SFP NIC 是一款高速网 络接口卡,采用了 PCI Express 3.0 x8 接口,支持双 端口万兆以太网,具有高性能、高可靠性、低功耗等 优点,是数据中心、云计算、虚拟化等领域的理想选 择。 支持多种网络协议,如 …...