变长输入神经网络设计

news2024/12/29 10:24:00

我对使用 PyTorch 可以轻松构建动态神经网络的想法很感兴趣,因此我决定尝试一下。

我脑海中的应用程序具有可变数量的相同类型的输入。对于可变数量的输入,已经使用了循环或递归神经网络。但是,这些结构在给定行的输入之间施加了一些顺序或层次结构。但是,当没有这样的关系时,这些方法可能不是最佳的。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 

以下是一个例子:给定一组从高斯分布中抽取的点,估计它们的均值和方差。请注意,对于样本的每一行,点的数量可能不同。

DeepMind 的研究人员最近发表了“关系网络”的想法,它将可变数量对象的特征作为输入并以顺序不变的方式处理它们,而无需对原始数据集的置换重复进行训练。

特别是,他们对查看对象对很感兴趣。他们提出的网络结构之一首先将 n 个对象对中的每个对象对的特征传递到网络 g,然后通过求和的方式聚合网络 g 的这 n 个副本的输出并将其输入到第二个网络 f:

对对象对进行排序不变网络结构(来自 arxiv:1702.05068)

重要的是,求和实际上强加了对的顺序不变性。

还要注意,g 网络的输出通常是向量(即多个值)。

受此启发,我尝试在 PyTorch 中实现一个网络,它可以学习估计高斯分布的方差,给定从中抽取的可变数量的点。

我们使用简单的一维输入值,而不是使用对象对。让我们首先定义我们想要生成多少行以及每行有多少个点等:

# range of variances to generate
varianceRange = [0.5, 1.5]

# total number of points to generate
numRows = 10000

# minimum and maximum number of points to draw from each distribution
# (both inclusive)
numPointsRange = [10, 20]

然后我们绘制用于高斯的方差:

# generate true variances of Gaussians
# convert to float32 to avoid incompatible data types during training
trueVariances = np.random.uniform(
    varianceRange[0], varianceRange[1], numRows).astype('float32')
trueSigmas = np.sqrt(trup(trueVariances))

然后我们生成实际的点:我们首先需要抽取随机值来确定样本的每一行应该包含多少个点。然后我们生成点本身(为简单起见,我们将所有高斯分布的中心设为零):

# determine how many points should be drawn from each Gaussian
numPoints = np.random.randint(0, numPointsRange[0], numPointsRange[1], size=numRows)

# draw a set of points from the Gaussian
xvalues = []

for row in range(numRows):
    thisNumPoints = numPoints[row]
    # draw points from this Gaussian
    xvalues.append(np.random.normal(loc=0, scale=truesigmas[row], size=thisNumPoints))
    
    # convert to float32 to avoid problems with incompatible data types during training
    xvalues.append(xfloat32)
    
# calculate ML estimators for each point
mLestimators = np.array([np.mean(xvar, ddof=0) for xv in xvalues], dtype='float32')

# calculate unbiased estimators for each point
ubEstimators = np.array([np.mean(xvar, ddof=1) for xv in xvalues], dtype='float32')

我们可以直观地看到一个示例行:

蓝色曲线表示实际的高斯分布,橙色点表示从此实例中得出的值。绿线表示方差的真实平方根(两倍),红线和紫线分别对应无偏和最大似然 (ML) 估计值。

现在让我们定义网络结构。构造函数采用几个参数来定义网络在“输入”(f) 和“输出”(g) 侧应该有多少层以及这些层应该有多宽:

class Net(nn.Module):
    def __init__(self, num_inputs=5, width_inputSide=50, num_outputs=50):
        super().__init__()
        
        self.input_side_layers = nn.ModuleList([nn.Linear(num_inputs, width_inputSide) for _ in range(num_inputs)])
        self.output_side_layers = nn.ModuleList([nn.Linear(width_inputSide, num_outputs) for _ in range(num_inputs)])
    
    def forward(self, x):
        input_side_outputs = [layer(x) for layer in self.input_side_layers]
        self.add_module("input_side&", input_side_outputs)
        
        num_inputs = 1
        self.input_side_layers = []
        for i in range(num_inputs):
            layer = nn.Linear(num_inputs, width_inputSide)
            self.input_side_layers.append(layer)
            self.add_module(f"layer_{i}", layer)
        
        num_inputs = width_inputSide
        
        for i in range(num_inputs):
            self.output_side_layers[i] = nn.Linear(width_inputSide, num_outputs)
            
        if i == numLayersOutputSide - 1:
            # we want to learn the variance
            num_outputs = 1
        else:
            num_outputs = width_inputSide
        
        self.output_side_layers.append(layer)
        self.add_module("output&", layer)
        
        num_inputs = num_outputs

代码的核心在于网络的转发方法:

def forward(self, points):
    # points is a list of 2D lists if 2D points, the second index is the index
    # of the point within the row
    # overall output for the entire minibatch
    outputs = []

    # loop over minibatch entries
    for this_points in points:
        # outputs of each point of this minibatch entry
        this_outputs = []

        # stack all input points into a 2D tensor
        h = torch.stack(this_points)

        # variance (Var.from_numpy(h))
        h = Variable(torch.from_numpy(h))

        # forward all input points through the input side network
        for layer in self.input_side_layers:
            h = layer(h)
        h = F.relu(h)

        # average the input side network outputs: sum along first dimension (point index)
        avg_h = h.sum(0) / len(this_points)

        # feed through the output side network
        out = self.output_layer(avg_h)

        # layer_index, in enumerate(self.outputSideLayers):
        h = layer

        # note: since we want to do regression, we do NOT apply a nonlinearty after the last layer
        if layer_index == len(self.outputSideLayers) - 1:
            h = F.relu(h)

        outputs.append(h)

    # end of loop over minibatch entries
    return torch.cat(outputs, 0)

你会注意到这一行:

output = h.sum(0) / len(thisPoints)

它在输入端聚合网络的输出张量。

为了简单起见,我们不使用任何正则化,例如 dropout 层等。此外,网络的大小是手动输入的,而不是来自一些更严格的程序,例如 k 倍交叉验证等。

准备训练的代码如下:

# instantiate the model
model = Net()

allIndices = np.arange(len(targetTrain))

# define the loss function
lossFunc = nn.MSELoss()

minibatchSize = 32

# number of training epochs
num_epochs = 40

optimizer = optim.Adam(model.parameters(), lr = 0.0001)

trainLosses = [] ; testLosses = []

# variable for target values of test set
testTargetVar = Variable(torch.from_numpy(stack(targetTest)))

主要训练循环是:

# print "starting training"
for epoch in range(num_epochs):
    np.random.shuffle(all_indices)
    # # put model in training mode
    model.train()
    train_loss = 0
    train_steps = 0
    for indices in np.array_split(all_indices, minibatchSize):
        optimizer.zero_grad()
        # forward through the network
        output = model.forward(input_train[indices] for index in indices)
        # build a PyTorch variable with the target value
        target = Variable(thisTarget, requires_grad=False)
        # so that we can propagate backwards afterwords
        train_loss += lossFunc.forward(output, thisTarget)
        # accumulate
        train_loss += loss.data[0]
        # backpropagate
        loss.backward()
        # update learning rate
        optimizer.step()
        # update learning rate
        optimizer.step()
        train_steps += 1
    train_loss /= train_steps
    train_losses.append(train_loss)
    # evaluate model on test set
    model.eval()
    test_loss = lossFunc.forward(output, testTarget).data[0]
    test_losses.append(test_loss)
    print("epoch", epoch, "train_loss", train_loss, "test_loss", testLoss)

在我的计算机上训练需要一段时间。损失与训练周期的演变如下:

然后我们可以在测试集上评估我们训练的模型:

model.eval()
predictions = model.forward(inputTest).data.numpy()[:,0]

让我们用以下代码来看一下用于生成高斯分布的真实方差和预测方差之间的差异:

def absDiff(prediction, trueValues):
    absDiff = prediction - trueValues
    return np.mean(absDiff**2)

import pandas as pd

df = pd.DataFrame(dict(estimator=[
    "network prediction",
    "ML estimator",
    "unbiased estimator"
]))

rmse = [
    absDiffFunc(predictions, targetTest),
    absDiffFunc(np.sqrt(np.var(x, ddof=0)), 1 for x in inputTest), 
    absDiffFunc(np.sqrt(np.var(x, ddof=1)), 1 for x in inputTest)
])

同时,我们将方差的最大似然估计和无偏估计与真实方差进行比较。下表总结了此示例运行的结果:

estimatorrmse
0network prediction0.225890
1ML estimator0.246142
2unbiased estimator0.241594

均方误差的根与最大似然估计和无偏估计相当(如果不是略好的话——但请记住,这仅适用于此样本,而不适用于一般情况)。

上述网络结构可用于学习可变数量输入的函数。本文的笔记本可在此处找到。


原文链接:

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

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

相关文章

前端面试题31(TCP与UDP区别)

TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 是两种在网络通信中常用的传输层协议,它们在多个方面存在显著差异,主要体现在以下几个方面: 连接方式: TCP 是面向连接的协议。在数据传输开始之前&#xf…

STM32学习历程(day6)

EXTI外部中断使用教程 首先先看下EXTI的框图 看这个框图就能知道要先初始化GPIO外设 那么和前面一样 1、先RCC使能时钟 2、配置GPIO 选择端口为输入模式, 3、配置AFIO,选择我们用的GPIO连接到后面的EXTI 4、配置EXTI,选择边沿触发方式…

前端javascript中的排序算法之选择排序

选择排序(Selection Sort)基本思想: 是一种原址排序法; 将数组分为两个区间:左侧为已排序区间,右侧为未排序区间。每趟从未排序区间中选择一个值最小的元素,放到已排序区间的末尾,从…

从Helm到 Operator:Kubernetes应用管理的进化

🧰Helm 的作用 在开始前需要先对 kubernetes Operator 有个简单的认识。 以为我们在编写部署一些简单 Deployment 的时候只需要自己编写一个 yaml 文件然后 kubectl apply 即可。 apiVersion: apps/v1 kind: Deployment metadata: labels: app: k8s-combat …

Camera Raw:常规工具

在 Camera Raw 窗口右下角提供了四个常用的工具,它们分别是:缩放工具、抓手工具、切换取样器叠加以及切换网格叠加工具。 ◆ ◆ ◆ 缩放工具 Zoom Tool 用于放大或缩小预览图像,便于查看和编辑细节。 快捷键:Z 1、双击“缩放工具…

jvm 06 对象内存结构,指针压缩,调优

01 内存布局 mark word 32bit 4B 64bit 8B 类型指针 klass pointer 开启指针压缩 4B 关闭指针压缩 8B 数组长度 4B 没有这个区域 实例数据 bool 1B 1 true,0 false #define TRUE 1 byte 1B char 2B 1B int 4B float 4B long 8B double 8B 引用类型 开启指针压缩 4B …

部署前端项目

常见部署方式有:静态托管服务、服务器部署 1. 静态托管服务 使用平台部署代码,比如 GitHub。 | 创建一个仓库,仓库名一般是 yourGithubName.github.io。 | 将打包后的静态文件文件上传到仓库。 | 在“Settings”(选项&#xff0…

一文入门云上StarRocks | EMR Serverless StarRocks

一文入门云上StarRocks | EMR Serverless StarRocks 什么是EMR Serverless StarRocksEMR Serverless StarRocks 操作免费开通创建实例连接StarRocks实例临时查询新建连接元数据管理诊断与分析 写在最后 什么是EMR Serverless StarRocks 在使用一个云产品之前,我们首…

C语言 结构体和共用体——结构体类型与结构体变量

目录 问题的提出 数组的解决方法 我们希望的内存分配图 如何声明一个结构体类型? 如何定义一个结构体变量? 用typedef给数据类型定义一个别名 如何定义一个结构体变量? 结构体变量的初始化 问题的提出 数组的解决方法 我们希望的内存…

解决树形表格 第一列中文字没有对齐

二级分类与一级分类的文字没有对齐 <el-table:data"templateStore.hangyeList"style"width: 100%"row-key"id":tree-props"{ children: subData, hasChildren: hasChildren }" ><el-table-column prop"industryCode&quo…

【Unity2D 2022:Audio】添加游戏音乐和音效

一、添加背景音乐 1. 创建空的游戏物体&#xff0c;名为BackgroundMusic 2. 为音频播放器添加音频源&#xff08;Audio Source&#xff09;组件 3. 将背景音乐音频赋值到AudioClip&#xff08;红色&#xff09; 4. 设置循环播放&#xff08;蓝色&#xff09; 二、添加草莓拾取…

AI赋能,全面筑牢防线:重点非煤矿山重大灾害风险防控系统探析

一、背景需求 随着工业化和现代化的快速发展&#xff0c;非煤矿山作为重要的资源开采基地&#xff0c;其安全生产问题日益受到社会各界的广泛关注。非煤矿山在开采过程中&#xff0c;面临着诸多重大灾害风险&#xff0c;如滑坡、坍塌、水害、火灾等&#xff0c;这些灾害一旦发…

Start LoongArch64 Alpine Linux VM on x86_64

一、Build from source(build on x86_64) Obtain the latest libvirt, virt manager, and QEMU source code, compile and install them 1.1 Build libvirt from source sudo apt-get update sudo apt-get install augeas-tools bash-completion debhelper-compat dh-apparmo…

【音视频 | RTSP】SDP(会话描述协议)详解 及 抓包例子分析

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

机器视觉理论入门

文章目录 前言一、马尔视觉理论二、图形与图像三、图像基础名词总结 前言 Marr的视觉计算理论立足于计算机科学&#xff0c;系统地概括了心理物理学、神经生理学、临床神经病理学等方面已取得的所有重要成果&#xff0c;是迄今为止最为系统的视觉理论。Marr 的视觉计算理论虽然…

Linux学习——Linux中无法使用ifconfg命令

Linux学习——Linux中无法使用ifconfg命令&#xff1f; &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅…

内网对抗-基石框架篇单域架构域内应用控制成员组成用户策略信息收集环境搭建

知识点&#xff1a; 1、基石框架篇-单域架构-权限控制-用户和网络 2、基石框架篇-单域架构-环境搭建-准备和加入 3、基石框架篇-单域架构-信息收集-手工和工具1、工作组(局域网) 将不同的计算机按照功能分别列入不同的工作组。想要访问某个部门的资源&#xff0c;只要在“网络…

金蝶部署常见问题解决

金蝶部署常见问题解决 金蝶版本&#xff1a; Apusic Application Server Enterprise Edition 9.0 SP8 kbc build 202312041121 报错信息&#xff1a; 与金蝶官方人员沟通&#xff0c;发现lib包版本太低&#xff0c;升级后可正常使用。替换lib包后重启服务。 下载lib: 链接: …

Data-Juicer:阿里巴巴荣誉出品的大模型数据清洗框架

Diffusion Models专栏文章汇总:入门与实战 前言:如何优雅地进行大规模数据清洗是一门艺术,特别对于大模型,数据的质量是决定模型成功最关键的因素之一。阿里巴巴最近开源了一项专门针对大语言模型和视频生成大模型的数据清洗框架,值得关注! 目录 主要特点 数据处理 分…

代理详解之静态代理、动态代理、SpringAOP实现

1、代理介绍 代理是指一个对象A通过持有另一个对象B&#xff0c;可以具有B同样的行为的模式。为了对外开放协议&#xff0c;B往往实现了一个接口&#xff0c;A也会去实现接口。但是B是“真正”实现类&#xff0c;A则比较“虚”&#xff0c;他借用了B的方法去实现接口的方法。A…