pytorch | Tensor和Variable

pytorch | Tensor和Variable,第1张

Tensor是pytorch中最基本的构件,可以像numpy一样进行矩阵计算,最主要的是Tensor支持GPU加速运算。而且Tensor的运算与numpy的运算基本相似,但有部分高级的矩阵计算Tensor并不支持,比如计算特征值特征向量等。因此numpy还是有存在的必要的。

tensor是Pytorch中非常高效数据格式,但用tensor构建神经网络还远远不够,为了构建计算图,所以Variable是不可或缺的数据形式。Variable是对tensor的封装。

Variable有三个属性:

根据你自己的使用习惯吧,各有各的优势。如果想要跑一跑已经有的深度学习代码,其实选择已经有的样例比较方便的就可以了。如果真的要走在前沿,你会发现任何一个工具都不能为完全满足需求,如果是初学者你可以去北鲲云平台试试,他家这两个软件都有,上机就能用,看你更喜欢哪一个的系统模式吧

手工标记大量数据始终是开发机器学习的一大瓶颈。斯坦福AI Lab的研究人员探讨了一种通过编程方式生成训练数据的“弱监督”范式,并介绍了他们的开源Snorkel框架。

近年来,机器学习 (ML) 对现实世界的影响越来越大。这在很大程度上是由于深度学习模型的出现,使得从业者可以在基准数据集上获得 state-of-the-art 的分数,而无需任何手工特征设计。考虑到诸如 TensorFlow 和 PyTorch 等多种开源 ML 框架的可用性,以及大量可用的最先进的模型,可以说,高质量的 ML 模型现在几乎成为一种商品化资源了。然而,有一个隐藏的问题:这些模型依赖于大量手工标记的训练数据。

这些手工标记的训练集创建起来既昂贵又耗时 —— 通常需要几个月甚至几年的时间、花费大量人力来收集、清理和调试 —— 尤其是在需要领域专业知识的情况下。除此之外,任务经常会在现实世界中发生变化和演变。例如,标记指南、粒度或下游用例都经常发生变化,需要重新标记 (例如,不要只将评论分类为正面或负面,还要引入一个中性类别)。

由于这些原因,从业者越来越多地转向一种较弱的监管形式,例如利用外部知识库、模式 / 规则或其他分类器启发式地生成训练数据。从本质上来讲,这些都是以编程方式生成训练数据的方法,或者更简洁地说,编程训练数据 (programming training data)。

在本文中,我们首先回顾了 ML 中由标记训练数据驱动的一些领域,然后描述了我们对建模和整合各种监督源的研究。我们还讨论了为大规模多任务机制构建数据管理系统的设想,这种系统使用数十或数百个弱监督的动态任务,以复杂、多样的方式交互。

回顾:如何获得更多有标签的训练数据?

ML 中的许多传统研究方法也同样受到对标记训练数据的需求的推动。我们首先将这些方法与弱监督方法 (weak supervision) 区分开来:弱监督是利用来自主题领域专家(subject matter experts,简称 SME) 的更高级别和 / 或更嘈杂的输入。

目前主流方法的一个关键问题是,由领域专家直接给大量数据加标签是很昂贵的:例如,为医学成像研究构建大型数据集更加困难,因为跟研究生不同,放射科医生可不会接受一点小恩小惠就愿意为你标记数据。因此,在 ML 中,许多经过深入研究的工作线都是由于获取标记训练数据的瓶颈所致:

在主动学习 (active learning) 中,目标是让领域专家为估计对模型最有价值的数据点贴标签,从而更有效地利用领域专家。在标准的监督学习设置中,这意味着选择要标记的新数据点。例如,我们可以选择靠近当前模型决策边界的乳房 X 线照片,并要求放射科医生仅给这些照片进行标记。但是,我们也可以只要求对这些数据点进行较弱的监督,在这种情况下,主动学习与弱监督是完美互补的;这方面的例子可以参考 (Druck, settle, and McCallum 2009)。

在半监督学习 (semi-supervised learning ) 设置中,我们的目标是用一个小的标记训练集和一个更大的未标记数据集。然后使用关于平滑度、低维结构或距离度量的假设来利用未标记数据 (作为生成模型的一部分,或作为一个判别模型的正则项,或学习一个紧凑的数据表示);参考阅读见 (Chapelle, Scholkopf, and Zien 2009)。从广义上讲,半监督学习的理念不是从 SME 那里寻求更多输入,而是利用领域和任务不可知的假设来利用未经标记的数据,而这些数据通常可以以低成本大量获得。最近的方法使用生成对抗网络 (Salimans et al 2016)、启发式转换模型 (Laine and Aila 2016) 和其他生成方法来有效地帮助规范化决策边界。

在典型的迁移学习 (transfer learning )设置 中,目标是将一个或多个已经在不同数据集上训练过的模型应用于我们的数据集和任务;相关的综述见 (Pan 和 Yang 2010)。例如,我们可能已经有身体其他部位肿瘤的大型训练集,并在此基础上训练了分类器,然后希望将其应用到我们的乳房 X 光检查任务中。在当今的深度学习社区中,一种常见的迁移学习方法是在一个大数据集上对模型进行 “预训练”,然后在感兴趣的任务上对其进行 “微调”。另一个相关的领域是多任务学习 (multi-task learning),其中几个任务是共同学习的 (Caruna 1993; Augenstein, Vlachos, and Maynard 2015)。

上述范例可能让我们得以不用向领域专家合作者寻求额外的训练标签。然而,对某些数据进行标记是不可避免的。如果我们要求他们提供各种类型的更高级、或不那么精确的监督形式,这些形式可以更快、更简便地获取,会怎么样呢?例如,如果我们的放射科医生可以花一个下午的时间来标记一组启发式的资源或其他资源,如果处理得当,这些资源可以有效地替代成千上万的训练标签,那会怎么样呢

将领域知识注入 AI

从 历史 的角度来看,试图 “编程” 人工智能 (即注入领域知识) 并不是什么新鲜想法,但现在提出这个问题的主要新颖之处在于,AI 从未像现在这样强大,同时在可解释性和可控制性方面,它还是一个 “黑盒”。

在 20 世纪 70 年代和 80 年代,AI 的重点是专家系统,它将来自领域专家的手工策划的事实和规则的知识库结合起来,并使用推理引擎来应用它们。20 世纪 90 年代,ML 开始作为将知识集成到 AI 系统的工具获得成功,并承诺以强大而灵活的方式从标记的训练数据自动实现这一点。

经典的 (非表示学习)ML 方法通常有两个领域专家输入端口。首先,这些模型通常比现代模型的复杂度要低得多,这意味着可以使用更少的手工标记数据。其次,这些模型依赖于手工设计的特性,这些特性为编码、修改和与模型的数据基本表示形式交互提供了一种直接的方法。然而,特性工程不管在过去还是现在通常都被认为是 ML 专家的任务,他们通常会花费整个博士生涯来为特定的任务设计特性。

进入深度学习模型:由于它们具有跨许多领域和任务自动学习表示的强大能力,它们在很大程度上避免了特性工程的任务。然而,它们大部分是完整的黑盒子,除了标记大量的训练集和调整网络架构外,普通开发人员对它们几乎没有控制权。在许多意义上,它们代表了旧的专家系统脆弱但易于控制的规则的对立面 —— 它们灵活但难以控制。

这使我们从一个略微不同的角度回到了最初的问题:我们如何利用我们的领域知识或任务专业知识来编写现代深度学习模型?有没有办法将旧的基于规则的专家系统的直接性与这些现代 ML 方法的灵活性和强大功能结合起来?

代码作为监督:通过编程训练 ML

Snorkel 是我们为支持和 探索 这种与 ML 的新型交互而构建的一个系统。在 Snorkel中,我们不使用手工标记的训练数据,而是要求用户编写标记函数 (labeling functions, LF),即用于标记未标记数据子集的黑盒代码片段。

然后,我们可以使用一组这样的 LF 来为 ML 模型标记训练数据。因为标记函数只是任意的代码片段,所以它们可以对任意信号进行编码:模式、启发式、外部数据资源、来自群众工作者的嘈杂标签、弱分类器等等。而且,作为代码,我们可以获得所有其他相关的好处,比如模块化、可重用性和可调试性。例如,如果我们的建模目标发生了变化,我们可以调整标记函数来快速适应!

一个问题是,标记函数会产生有噪声的输出,这些输出可能会重叠和冲突,从而产生不太理想的训练标签。在 Snorkel 中,我们使用数据编程方法对这些标签进行去噪,该方法包括三个步骤:

1 我们将标记函数应用于未标记的数据。

2 我们使用一个生成模型来在没有任何标记数据的条件下学习标记函数的准确性,并相应地对它们的输出进行加权。我们甚至可以自动学习它们的关联结构。

3 生成模型输出一组概率训练标签,我们可以使用这些标签来训练一个强大、灵活的判别模型 (如深度神经网络),它将泛化到标记函数表示的信号之外。

可以认为,这整个 pipeline 为 “编程”ML 模型提供了一种简单、稳健且与模型无关的方法!

标记函数 (Labeling Functions)

从生物医学文献中提取结构化信息是最能激励我们的应用之一:大量有用的信息被有效地锁在数百万篇科学论文的密集非结构化文本中。我们希望用机器学习来提取这些信息,进而使用这些信息来诊断遗传性疾病。

考虑这样一个任务:从科学文献中提取某种化学 - 疾病的关系。我们可能没有足够大的标记训练数据集来完成这项任务。然而,在生物医学领域,存在着丰富的知识本体、词典等资源,其中包括各种化学与疾病名称数据、各种类型的已知化学 - 疾病关系数据库等,我们可以利用这些资源来为我们的任务提供弱监督。此外,我们还可以与生物学领域的合作者一起提出一系列特定于任务的启发式、正则表达式模式、经验法则和负标签生成策略。

作为一种表示载体的生成模型

在我们的方法中,我们认为标记函数隐含地描述了一个生成模型。让我们来快速复习一下:给定数据点 x,以及我们想要预测的未知标签 y,在判别方法中,我们直接对P(y|x) 建模,而在生成方法中,我们对 P(x,y) = P(x|y)P(y) 建模。在我们的例子中,我们建模一个训练集标记的过程 P(L,y),其中 L 是由对象 x 的标记函数生成的标签,y 是对应的 (未知的) 真实标签。通过学习生成模型,并直接估计 P(L|y),我们本质上是在根据它们如何重叠和冲突来学习标记函数的相对准确性 (注意,我们不需要知道 y!)

我们使用这个估计的生成模型在标签函数上训练一个噪声感知版本的最终判别模型。为了做到这一点,生成模型推断出训练数据的未知标签的概率,然后我们最小化关于这些概率的判别模型的预期损失。

估计这些生成模型的参数可能非常棘手,特别是当使用的标记函数之间存在统计依赖性时。在 Data Programming: Creating Large Training Sets, Quickly(>

注意:

oslistdir() 返回的文件名不是顺序的,如,本次实验返回['0png', '1png', '10png', '100png',],

filenamessort(key=lambda x:int(x[:-4])) # 倒数第四位''为分界线,按照‘'左边的数字从小到大排序

可根据自己文件名的特征去决定int(x[:])中?的值,从哪里去分割排序。

filename = filenamessort(key=lambda x:int(x[:-4])) 会出错,这时的filename是None,不知道原因。

已经有了路径的list, 种类编号的list。填到Dataset类里面就行了

实例化一个dataset, 然后用Dataloader包起来。

注意:

torchtensor类型转换为int类型:labelsitem()

torchIntTensor类型转换为torchLongTensor类型: torchLongTensor(labelsnumpy())

补充知识:

参考链接:

>

1 Scikit-learn(重点推荐)

>>

RNN是Recurrent Neural Networks的缩写,即循环神经网络,它常用于解决序列问题。RNN有记忆功能,除了当前输入,还把上下文环境作为预测的依据。它常用于语音识别、翻译等场景之中。

RNN是序列模型的基础,尽管能够直接调用现成的RNN算法,但后续的复杂网络很多构建在RNN网络的基础之上,如Attention方法需要使用RNN的隐藏层数据。RNN的原理并不复杂,但由于其中包括循环,很难用语言或者画图来描述,最好的方法是自己手动编写一个RNN网络。本篇将介绍RNN网络的原理及具体实现。

在学习循环神经网络之前,先看看什么是序列。序列sequence简称seq,是有先后顺序的一组数据。自然语言处理是最为典型的序列问题,比如将一句话翻译成另一句话时,其中某个词汇的含义不仅取决于它本身,还与它前后的多个单词相关。类似的,如果想预测**的情节发展,不仅与当前的画面有关,还与当前的一系列前情有关。在使用序列模型预测的过程中,输入是序列,而输出是一个或多个预测值。

在使用深度学习模型解决序列问题时, 最容易混淆的是,序列与序列中的元素 。在不同的场景中,定义序列的方式不同,当分析单词的感情色彩时,一个单词是一个序列seq;当分析句子感情色彩时,一个句子是一个seq,其中的每个单词是序列中的元素;当分析文章感情色彩时,一篇文章是一个seq。简单地说,seq是最终使用模型时的输入数据,由一系列元素组成。

当分析句子的感情色彩时,以句为seq,而句中包含的各个单词的含义,以及单词间的关系是具体分析的对象,此时,单词是序列中的元素,每一个单词又可有多维特征。从单词中提取特征的方法将在后面的自然语言处理中介绍。

RNN有很多种形式,单个输入单个输入;多个输入多个输出,单个输入多个输出等等。

举个最简单的例子:用模型预测一个四字短语的感情色彩,它的输入为四个元素X={x1,x2,x3,x4},它的输出为单个值Y={y1}。字的排列顺序至关重要,比如“从好变坏”和“从坏变好”,表达的意思完全相反。之所以输入输出的个数不需要一一对应,是因为中间的隐藏层,变向存储中间信息。

如果把模型设想成黑盒,如下图所示:

如果模型使用全连接网络,在每次迭代时,模型将计算各个元素x1,x2中各个特征f1,f2代入网络,求它们对结果y的贡献度。

RNN网络则要复杂一些,在模型内部,它不是将序列中所有元素的特征一次性输入模型,而是每一次将序列中单个元素的特征输入模型,下图描述了RNN的数据处理过程,左图为分步展示,右图将所有时序步骤抽象成单一模块。

第一步:将第一个元素x1的特征f1,f2输入模型,模型根据输入计算出隐藏层h。

第二步:将第二个元素x2的特征输入模型,模型根据输入和上一步产生的h再计算隐藏层h,其它元素以此类推。

第三步:将最后一个元素xn的特征输入模型,模型根据输入和上一步产生的h计算隐藏层h和预测值y。

隐藏层h可视为将序列中前面元素的特征和位置通过编码向前传递,从而对输出y发生作用,隐藏层的大小决定了模型携带信息量的多少。隐藏层也可以作为模型的输入从外部传入,以及作为模型的输出返回给外部调用。

本例仍使用上篇中的航空乘客序列数据,分别用两种方法实现RNN:自己编写程序实现RNN模型,以及调用Pytorch提供的RNN模型。前一种方法主要用于剖析原理,后一种用于展示常用的调用方法。

首先导入头文件,读取乘客数据,做归一化处理,并将数据切分为测试集和训练集,与之前不同的是加入了create_dataset函数,用于生成序列数据,序列的输入部分,每个元素中包括两个特征:前一个月的乘客量prev和月份值mon,这里的月份值并不是关键特征,主要用于在例程中展示如何使用多个特征。

第一步:实现模型类,此例中的RNN模型除了全连接层,还生成了一个隐藏层,并在下一次前向传播时将隐藏层输出的数据与输入数据组合后再代入模型运算。

第二步,训练模型,使用全部数据训练500次,在每次训练时,内部for循环将序列中的每个元素代入模型,并将模型输出的隐藏层和下一个元素一起送入下一次迭代。

第三步:预测和作图,预测的过程与训练一样,把全部数据拆分成元素代入模型,并将每一次预测结果存储在数组中,并作图显示。

需要注意的是,在训练和预测过程中,每一次开始输入新序列之前,都重置了隐藏层,这是由于隐藏层的内容只与当前序列相关,序列之间并无连续性。

程序输出结果如下图所示:

经过500次迭代,使用RNN的效果明显优于上一篇中使用全连接网络的拟合效果,还可以通过调整超参数以及选择不同特征,进一步优化。

使用Pytorch提供的RNN模型,torchnnRNN类可直接使用,是循环网络最常用的解决方案。RNN,LSTM,GRU等循环网络都实现在同一源码文件torch/nn/modules/rnnpy中。

第一步:创建模型,模型包含两部分,第一部分是Pytorch提供的RNN层,第二部分是一个全连接层,用于将RNN的输出转换成输出目标的维度。

Pytorch的RNN前向传播允许将隐藏层数据h作为参数传入模型,并将模型产生的h和y作为函数返回值。形如: pred, h_state = model(x, h_state)

什么情况下需要接收隐藏层的状态h_state,并转入下一次迭代呢?当处理单个seq时,h在内部前向传递;当序列与序列之间也存在前后依赖关系时,可以接收h_state并传入下一步迭代。另外,当模型比较复杂如LSTM模型包含众多参数,传递会增加模型的复杂度,使训练过程变慢。本例未将隐藏层转到模型外部,这是由于模型内部实现了对整个序列的处理,而非处理单个元素,而每次代入的序列之间又没有连续性。

第二步:训练模型,与上例中把序列中的元素逐个代入模型不同,本例一次性把整个序列代入了模型,因此,只有一个for循环。

Pythorch支持批量处理,前向传递时输入数据格式是[seq_len, batch_size, input_dim),本例中输入数据的维度是[100, 1, 2],input_dim是每个元素的特征数,batch_size是训练的序列个数,seq_len是序列的长度,这里使用70%作为训练数据,seq_len为100。如果数据维度的顺序与要求不一致,一般使用transpose转换。

第三步:预测和作图,将全部数据作为序列代入模型,并用预测值作图。

程序输出结果如下图所示:

可以看到,经过500次迭代,在前100个元素的训练集上拟合得很好,但在测试集效果较差,可能存在过拟合。

以上就是关于pytorch | Tensor和Variable全部的内容,包括:pytorch | Tensor和Variable、MXNet和pytorch哪个比较好用、放弃手工标记数据,斯坦福大学开发弱监督编程范式Snorkel等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/10110662.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存