变长输入神经网络设计

我对使用 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 Gaussianxvalues.append(np.random.normal(loc=0, scale=truesigmas[row], size=thisNumPoints))# convert to float32 to avoid problems with incompatible data types during trainingxvalues.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 = 1self.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_inputSidefor 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 variancenum_outputs = 1else:num_outputs = width_inputSideself.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 minibatchoutputs = []# loop over minibatch entriesfor this_points in points:# outputs of each point of this minibatch entrythis_outputs = []# stack all input points into a 2D tensorh = torch.stack(this_points)# variance (Var.from_numpy(h))h = Variable(torch.from_numpy(h))# forward all input points through the input side networkfor 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 networkout = 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 layerif layer_index == len(self.outputSideLayers) - 1:h = F.relu(h)outputs.append(h)# end of loop over minibatch entriesreturn 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 = 40optimizer = 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 modemodel.train()train_loss = 0train_steps = 0for indices in np.array_split(all_indices, minibatchSize):optimizer.zero_grad()# forward through the networkoutput = model.forward(input_train[indices] for index in indices)# build a PyTorch variable with the target valuetarget = Variable(thisTarget, requires_grad=False)# so that we can propagate backwards afterwordstrain_loss += lossFunc.forward(output, thisTarget)# accumulatetrain_loss += loss.data[0]# backpropagateloss.backward()# update learning rateoptimizer.step()# update learning rateoptimizer.step()train_steps += 1train_loss /= train_stepstrain_losses.append(train_loss)# evaluate model on test setmodel.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 - trueValuesreturn np.mean(absDiff**2)import pandas as pddf = 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.rhkb.cn/news/373184.html

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

相关文章

7.9实验室总结 SceneBuilder的使用方法+使用javafx等

由于下错了东西,所以一直运行不出来,今天一直在配置环境,配置好了才学,所以没学多少,看了网课学习了SceneBuilder的使用方法还有了解了javafx是怎么写项目的,, 学习了怎么跳转页面:…

html H5 dialog弹窗学习,实现弹窗显示内容 替代confirm、alert

html H5 dialog弹窗学习,实现弹窗内容 替代confirm 框架使用的mui,使用mui.confirm() 弹窗内容过多时,弹窗被撑的到屏幕外去了,使用H5 dialog 标签自定义一个固定大小的弹窗,内容过多时可下拉显示 效果展示 隐私政策内容很多,可以下拉显示 代码 myDialog.css dialog{p…

【光伏仿真系统】光伏设计的基本步骤

随着全球对可再生能源需求的不断增长,光伏发电作为一种清洁、可再生的能源形式,正日益受到重视。光伏设计是确保光伏系统高效、安全、经济运行的关键环节,它涉及从选址评估到系统安装与维护的全过程。本文将详细介绍光伏设计的基本步骤&#…

【RHCE】转发服务器实验

1.在本地主机上操作 2.在客户端操作设置主机的IP地址为dns 3.测试,客户机是否能ping通

LLM应用构建前的非结构化数据处理(三)文档表格的提取

1.学习内容 本节次学习内容来自于吴恩达老师的Preprocessing Unstructured Data for LLM Applications课程,因涉及到非结构化数据的相关处理,遂做学习整理。 本节主要学习pdf中的表格数据处理 2.环境准备 和之前一样,可以参考LLM应用构建前…

Raylib 实现超大地图放大缩小与两种模式瓦片地图刷新

原理: 一种刷新模式: 在宫格内整体刷新,类似九宫格移动到边缘,则九宫格整体平移一个宫格,不过这里是移动一个瓦片像素,实际上就是全屏刷新,这个上限是 笔记本 3060 70帧 100*100个瓦片每帧都…

压缩感知3——重构算法正交匹配追踪算法

算法流程 问题的实质是&#xff1a;AX Y 求解&#xff08;A是M维&#xff0c;Y是N维且N>>M并且稀疏度K<M&#xff09;明显X有无穷多解&#xff0c;重构过程是M次采样得到的采样值升维的过程。OMP算法的具体步骤&#xff1a;(1)用X表示信号&#xff0c;初始化残差e0 …

802.11漫游流程简单解析与笔记_Part2_05_wpa_supplicant如何通过nl80211控制内核开始关联

最近在进行和802.11漫游有关的工作&#xff0c;需要对wpa_supplicant认证流程和漫游过程有更多的了解&#xff0c;所以通过阅读论文等方式&#xff0c;记录整理漫游相关知识。Part1将记录802.11漫游的基本流程、802.11R的基本流程、与认证和漫游都有关的三层秘钥基础。Part1将包…

C#用反射机制调用dll文件的字段、属性和方法

1、创建dll文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace CLStudent {public class Student{//字段public string Name "Tom";//属性public double ChineseScore { get; s…

connect to github中personal access token生成token方法

一、问题 执行git push时弹出以下提示框 二、解决方法 去github官网生成Token&#xff0c;步骤如下 选择要授予此 令牌token 的 范围 或 权限 要使用 token 从命令行访问仓库&#xff0c;请选择 repo 。 要使用 token 从命令行删除仓库&#xff0c;请选择 delete_repo 其他根…

下载Windows版本的pycharm

Python环境搭建 第一步下载安装python 等待安装完成 验证python是否安装成功 Python开发工具安装部署 JetBrains: Essential tools for software developers and teams PyCharm: the Python IDE for data science and web development 下载社区版本的PyCharm 双击打开下载好的…

C++20中的基于范围的for循环(range-based for loop)

C11中引入了对基于范围的for循环(range-based for loop)的支持&#xff1a;该循环对一系列值(例如容器中的所有元素)进行操作。代码段如下&#xff1a; const std::vector<int> vec{ 1,2,3,4,5 }; for (const auto& i : vec)std::cout << i << ", …

Github Actions 构建Vue3 + Vite项目

本篇文章以自己创建的项目为例&#xff0c;用Github Actions构建。 Github地址&#xff1a;https://github.com/ling08140814/myCarousel 访问地址&#xff1a;https://ling08140814.github.io/myCarousel/ 具体步骤&#xff1a; 1、创建一个Vue3的项目&#xff0c;并完成代…

书生大模型实战营(暑假场)-入门岛-第一关

书生大模型实战营暑假场重磅开启&#xff01;&#xff0c;这场学习路线看起来很好玩呀&#xff0c;闯关学习既能学到知识又有免费算力可得&#xff0c;太良心啦。感兴趣的小伙伴赶快一起报名学习吧&#xff01;&#xff01;&#xff01; 关卡任务 好的&#xff0c;我们废话不多…

CentOS6用文件配置IP模板

CentOS6用文件配置IP模板 到 CentOS6.9 , 默认还不能用 systemctl , 能用 service chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 ### chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 sudo chkconfig sshd onservice sshd start …

Profibus转ModbusTCP网关模块实现Profibus_DP向ModbusTCP转换

Profibus和ModbusTCP是工业控制自动化常用的二种通信协议。Profibus是一种串口通信协议&#xff0c;它提供了迅速靠谱的数据传输和各种拓扑结构&#xff0c;如总线和星型构造。Profibus可以和感应器、执行器、PLC等各类设备进行通信。 ModbusTCP是一种基于TCP/IP协议的通信协议…

FPGA开发笔试1

1. 流程简介 我是两天前有FPGA公司的HR来问我实习的事情&#xff0c;她当时问我距离能不能接受&#xff0c;不过确实距离有点远&#xff08;地铁通勤要将近一个半小时&#xff09;&#xff0c;然后她说给我约个时间&#xff0c;抽空做1个小时的题目&#xff08;线上做&#xf…

800 元打造家庭版 SOC 安全运营中心

今天,我们开始一系列新的文章,将从独特而全面的角度探索网络安全世界,结合安全双方:红队和蓝队。 这种方法通常称为“紫队”,集成了进攻和防御技术,以提供对威胁和安全解决方案的全面了解。 在本系列的第一篇文章中,我们将指导您完成以 100 欧元约800元左右的预算创建…

Flutter【组件】标签

简介 flutter 标签组件。标签组件是一种常见的 UI 元素&#xff0c;用于显示和管理多个标签&#xff08;或标签集合&#xff09;。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit pub地址&#xff1a;https://pub.dev/packages/jac_uikit 使用方式&…

liunx清理服务器内存和日志

1、查看服务器磁盘占用情况 # 查看磁盘占用大小 df -h 2、删除data文件夹下面的日志 3、查看每个服务下面的日志输出文件&#xff0c;过大就先停掉服务再删除out文件再重启服务 4、先进入想删除输入日志的服务文件夹下&#xff0c;查看服务进程&#xff0c;杀掉进程&#xff…