Model_ComFuc
扩维 降维 squeeze和unsuqeeze
squeeze(input, dim=None, out=None) 降维函数功能:去除size为1的维度,包括行和列。当维度大于等于2时,squeeze()无作用。
input (Tensor) – 输入张量 dim (int, optional) – 如果给定,则input只会在给定维度挤压,维度的索引(从0开始) out (Tensor, optional) – 输出张量
当给定dim时,那么挤压操作只在给定维度上。注意这里dim指定的维度,其size必须为1,
其中squeeze(0)代表若第一维度值为1则去除第一维度,squeeze(1)代表若第二维度值为1则去除第二维度;-1,去除最后维度值为1的维度 当不给定dim时,将输入张量形状中的1 去除并返回。
例如:如果输入是形如(A×1×B×1×C×1×D)(A×1×B×1×C×1×D),squeeze()那么输出形状就为: (A×B×C×D)(A×B×C×D) 例如:输入形状为: (A×1×B)(A×1×B), squeeze(input, 0) 将会保持张量不变(因为A≠1),只有用 squeeze(input, 1),形状会变成 (A×B)(A×B)。
注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。
unsqueeze(input, dim, out=None) 增维功能:增加大小为1的维度,也就是返回一个新的张量,对输入的指定位置插入维度 1且必须指明维度
x = torch.unsqueeze(x, 3) # 在第3个维度上扩展 注意: 返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。
如果dim为负,则将会被转化dim+input.dim()+1
原文链接:https://blog.csdn.net/lj2048/article/details/114263912
举例:
# 如我们有一组数据3,7,2,5,6,8。我们想用一个变量来表示它,那么可以把它们放在一个数组里,相当于把这六个元素(小球)投到了一个箱子里
a= torch.tensor([3,7,2,5,6,8])
print(a.size()) # torch.Size([6])
# 我们希望这组小球里,把3,7单独放在一个箱子里,2,5放在一个箱子,6,8放在一个箱子:
a = torch.tensor([[3,7],[2,5],[6,8]])
print(a.size()) # torch.Size([3, 2])
# 图省略,比如最外层的箱子起名为a,里面一层的3个箱子起名a\[0\],a\[1\]和a\[2\],这三个箱子里分别有2的小球.分别对其命名
# unsqueeze(i)表示用一个箱子把第i层的箱子都包起来;
a= a.unsqueeze(0)
print(a.size()) # torch.Size([1, 3, 2])
# 而squeeze(i)表示把第i层的箱子去掉(第i层只有一个箱子时才能用这个函数)
a = a.squeeze(0)
print(a.size()) # torch.Size([3, 2])本文转自 https://blog.csdn.net/kuan__/article/details/109209709,如有侵权,请联系删除。
TORCH.spilt()
torch.split(tensor, split_size_or_sections, dim=0)
torch.split()作用将tensor分成块结构。
参数:
tesnor:input,待分输入
split_size_or_sections:需要切分的大小(int or list )
dim:切分维度
output:切分后块结构 <class 'tuple'>
当split_size_or_sections为int时,tenor结构和split_size_or_sections,正好匹配,那么ouput就是大小相同的块结构。如果按照split_size_or_sections结构,tensor不够了,那么就把剩下的那部分做一个块处理。
当split_size_or_sections 为list时,那么tensor结构会一共切分成len(list)这么多的小块,每个小块中的大小按照list中的大小决定,其中list中的数字总和应等于该维度的大小,否则会报错(注意这里与split_size_or_sections为int时的情况不同)。
split_size_or_sections为int型时
split_size_or_sections为list型时。
本文转自 https://blog.csdn.net/qq_42518956/article/details/103882579,如有侵权,请联系删除。
glob.glob()之返回路径的正反斜杆问题
拼接1 torch.cat()
1. 字面理解:torch.cat是将两个张量(tensor)拼接在一起,cat是concatenate的意思,即拼接,联系在一起。
2. 例子理解
上面给出了两个张量A和B,分别是2行3列,4行3列。即他们都是2维张量。因为只有两维,这样在用torch.cat拼接的时候就有两种拼接方式:按行拼接和按列拼接。即所谓的维数0和维数1.
C=torch.cat((A,B),0)就表示按维数0(行)拼接A和B,也就是竖着拼接,A上B下。此时需要注意:列数必须一致,即维数1数值要相同,这里都是3列,方能列对齐。拼接后的C的第0维是两个维数0数值和,即2+4=6.
C=torch.cat((A,B),1)就表示按维数1(列)拼接A和B,也就是横着拼接,A左B右。此时需要注意:行数必须一致,即维数0数值要相同,这里都是2行,方能行对齐。拼接后的C的第1维是两个维数1数值和,即3+4=7.
从2维例子可以看出,使用torch.cat((A,B),dim)时,除拼接维数dim数值可不同外其余维数数值需相同,方能对齐。
3.实例
在深度学习处理图像时,常用的有3通道的RGB彩色图像及单通道的灰度图。张量size为cxhxw,即通道数x图像高度x图像宽度。在用torch.cat拼接两张图像时一般要求图像大小一致而通道数可不一致,即h和w同,c可不同。当然实际有3种拼接方式,另两种好像不常见。比如经典网络结构:U-Net
里面用到4次torch.cat,其中copy and crop操作就是通过torch.cat来实现的。可以看到通过上采样(up-conv 2x2)将原始图像h和w变为原来2倍,再和左边直接copy过来的同样h,w的图像拼接。这样做,可以有效利用原始结构信息。
4.总结
使用torch.cat((A,B),dim)时,除拼接维数dim数值可不同外其余维数数值需相同,方能对齐。
本文转自 https://blog.csdn.net/qq_39709535/article/details/80803003,如有侵权,请联系删除。
拼接2 torch.stack
先用图示讲讲 torch.cat() 是在原先维度上进行拼接
我们用图+代码来举例



注意:对于cat拼接张量,==维度数量 (不是维度上的量)必须相同==;==进行拼接的维度的尺寸可以不同,但是其它维度的尺寸必须相同==。【简而言之,堆积木,对上了就可以拼】
torch.stack() 新增一个维度
我们继续用图+代码来举例




补充: 拼接多个向量,例如:torch.stack((x1, x2, x3, x4), 2),再上述的方法中接入需要拼接的向量就可以了
本文转自 https://blog.csdn.net/weixin_42516475/article/details/119084904,如有侵权,请联系删除。
tf.expand_dims
TensorFlow中,想要维度增加一维,可以使用tf.expand_dims(input, dim, name=None)函数。当然,我们常用tf.reshape(input, shape=[])也可以达到相同效果,但是有些时候在构建图的过程中,placeholder没有被feed具体的值,这时就会包下面的错误:TypeError: Expected binary or unicode string, got 1
在这种情况下,我们就可以考虑使用expand_dims来将维度加1。比如我自己代码中遇到的情况,在对图像维度降到二维做特定操作后,要还原成四维[batch, height, width, channels],前后各增加一维。如果用reshape,则因为上述原因报错
用下面的方法可以实现:
在最后,给出官方的例子和说明
举例:
结果:
本文转自 https://blog.csdn.net/duanlianvip/article/details/96448393,如有侵权,请联系删除。
torch.flatten()
(14条消息) torch.flatten()函数_torch.flatten(x,1)_行者无疆哇的博客-CSDN博客
1)flatten(x,1)是按照x的第1个维度拼接(按照列来拼接,横向拼接); 2)flatten(x,0)是按照x的第0个维度拼接(按照行来拼接,纵向拼接); 3)有时候会遇到flatten里面有两个维度参数,flatten(x, start_dim, end_dimension),此时flatten函数执行的功能是将从start_dim到end_dim之间的所有维度值乘起来,其他的维度保持不变。例如x是一个size为[4,5,6]的tensor, flatten(x, 0, 1)的结果是一个size为[20,6]的tensor。
flatten的中文含义为“扁平化”,具体怎么理解呢?我们可以尝试这么理解,假设你的数据为1维数据,那么这个数据天然就已经扁平化了,如果是2维数据,那么扁平化就是将2维数据变为1维数据,如果是3维数据,那么就要根据你自己所选择的“扁平化程度”来进行操作,假设需要全部扁平化,那么就直接将3维数据变为1维数据,如果只需要部分扁平化,那么有一维的数据不会进行扁平操作,具体看下面的案例分析。


torch.view()
view()的原理很简单,其实就是把原先tensor中的数据进行排列,排成一行,然后根据所给的view()中的参数从一行中按顺序选择组成最终的tensor。
view()可以有多个参数,这取决于你想要得到的是几维的tensor,一般设置两个参数,也是神经网络中常用的(一般在全连接之前),代表二维。
view(h,w),h代表行(想要变为几行),w代表的是列(想要变为几列)#这里所说并不严谨,只是为了更好理解,
h
取值代表行数,当不知道要变为几行,但知道要变为几列时可取-1
w
取值代表列数,当不知道要变为几列,但知道要变为几行时可取-1
注意:元素个数要能整除行和列
下面看几个例子就理解了。 1、把原先tensor中的数据进行排列,排成一行,然后根据所给的view()中的参数从一行中按顺序选择组成最终的tensor
2、当知道要变成的tensor的行时:
2、当知道要变成的tensor的列时:
图像处理
张量存储为图片
三维张量转图片
四维张量转图片(卷积神经网络的输出,多了一个batch_size维度)
本文转自 https://blog.csdn.net/everyxing1007/article/details/126881242,如有侵权,请联系删除。
随机数Rand
torch.rand
torch.rand(*sizes, out=None) → Tensor
返回一个张量,包含了从区间[0,1)的均匀分布中抽取的一组随机数,形状由可变参数sizes 定义。
输出为:
torch.randn
torch.randn(*sizes, out=None) → Tensor
返回一个张量,包含了服从标准正态分布(均值为0,方差为 1,即高斯白噪声)中抽取一组随机数,形状由可变参数sizes定义。
参数:sizes (int…) – 整数序列,定义了输出形状;out (Tensor, optinal) - 结果张量
torch.randperm
torch.randperm(n, out=None) → LongTensor
给定参数n,返回一个从[0, n -1) 的随机整数排列。
参数:n (int) – 上边界(不包含)
可以回想一下range或者arrange。他们俩是返回有序的数列并且可以设定步长,官方建议是使用函数 torch.arange()。
介绍完上边的rand*函数再介绍一个torch.normal()
torch.normal()
torch.normal(means, std, out=None)
返回一个张量,包含从给定参数means,std的离散正态分布中抽取随机数。
均值means是一个张量,包含每个输出元素相关的正态分布的均值。
std是一个张量,包含每个输出元素相关的正态分布的标准差。均值和标准差的形状不须匹配,但每个张量的元素个数须相同。
参数:
means (Tensor) – 均值
std (Tensor) – 标准差
out (Tensor) – 可选的输出张量
randn和normal的区别
虽然randn和normal都可以生成服从正态分布的随机数,但是normal可以自己设定均值和标准差。就这点区别。
torch.Tensor.uniform_()
A.uniform_(-10,20)将会把A里面的每个值都从[-10, 20]里面重新随机取一次,即在[-10, 20]的随机均匀分布里面取值并重新赋值是
uniform_(),不是uniform()!以下划线结尾的是inplace方法。 什么是inplace方法:将会**==改变调用者本身值的方法==**。如a, b = torch.rand(2,2), torch.rand(2,2),如果a.add(b),那么a值不变;如果a.add_(b),a值就会变为a+b
比如:
三种都是,生成一个2×3的张量,将其中的值改为5-6之间的浮点数。
torch.rand和torch.Tensor.uniform_
这样看到话,两个都能取0-1之间的均匀分布,但是问题在于rand取不到1,uniform_可以取到1。
torch 检查
判断tensor中是否存在NAN, inf
在用torch搭建深度学习模型时,很容易在数据中存在inf与nan的情况,对应的数据类型分别时torch.inf与torch.nan。 大多数情况下,产生nan数据的原因基本上是出现了分母为0的情况,所以需要检查张量计算过程中是否有除法运算,比如softmax就有除法。
Numpy函数
numpy.tile()
numpy.tile()是个什么函数呢,说白了,就是把数组沿各个方向复制
比如 a = np.array([0,1,2]), np.tile(a,(2,1))就是把a先沿x轴(就这样称呼吧)复制1倍,即没有复制,仍然是 [0,1,2]。 再把结果沿y方向复制2倍,即最终得到
array([[0,1,2], [0,1,2]])
原文链接:https://blog.csdn.net/qq_18433441/article/details/54897250
torch的model.train()和eval()
两种模式
pytorch可以给我们提供两种方式来切换训练和评估(推断)的模式,分别是:model.train() 和 model.eval()。
一般用法是:在训练开始之前写上 model.trian() ,在测试时写上 model.eval() 。
功能
==model.train()==
在使用 pytorch 构建神经网络,添加一句model.train()作用是 启用 batch normalization 和 dropout 。
如果模型中有BN层(Batch Normalization)和 Dropout ,需要在 训练时 添加 model.train()。
model.train() 是保证 BN 层能够用到 每一批数据 的均值和方差。
对于 Dropout,model.train() 是 随机取一部分 网络连接来训练更新参数。
==model.eval()==
model.eval()的作用是 不启用 Batch Normalization 和 Dropout。
如果模型中有 BN 层(Batch Normalization)和 Dropout,在 测试时 添加 model.eval()。
model.eval() 是保证 BN 层能够用 全部训练数据 的均值和方差,即测试过程中要保证 BN 层的均值和方差不变。
对于 Dropout,model.eval() 是利用到了 所有 网络连接,即不进行随机舍弃神经元。
为什么测试时要用 model.eval() ?
训练完 train 样本后,生成的模型 model 要用来测试样本了。在 model(test) 之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是 model 中含有 BN 层和 Dropout 所带来的的性质。
eval() 时,pytorch 会自动把 BN 和 DropOut 固定住,不会取平均,而是用训练好的值。 不然的话,一旦 test 的 batch_size 过小,很容易就会被 BN 层导致生成图片颜色失真极大。 eval() 在非训练的时候是需要加的,没有这句代码,一些网络层的值会发生变动,不会固定,你神经网络每一次生成的结果也是不固定的,生成质量可能好也可能不好。
也就是说,测试过程中使用model.eval(),这时神经网络会 沿用 batch normalization 的值,而并 不使用 dropout。
总结与对比
如果模型中有 BN 层(Batch Normalization)和 Dropout,需要在训练时添加 model.train(),在测试时添加 model.eval()。
其中 model.train() 是保证 BN 层用每一批数据的均值和方差,而 model.eval() 是保证 BN 用全部训练数据的均值和方差;
而对于 Dropout,model.train() 是随机取一部分网络连接来训练更新参数,而 model.eval() 是利用到了所有网络连接。
参考链接
本文转自 https://blog.csdn.net/weixin_44211968/article/details/123774649,如有侵权,请联系删除。
with torch.no_grad()
1.关于with
withwith是python中上下文管理器,简单理解,当要进行固定的进入,返回操作时,可以将对应需要的操作,放在with所需要的语句中。比如文件的写入(需要打开关闭文件)等。
以下为一个文件写入使用with的例子。
with后部分,可以将with后的语句运行,将其返回结果给到as后的变量(sh),之后的代码块对close进行操作。
2.关于with torch.no_grad():
with torch.no_grad():在使用pytorch时,并不是所有的操作都需要进行计算图的生成(计算过程的构建,以便梯度反向传播等操作)。而对于tensor的计算操作,默认是要进行计算图的构建的,在这种情况下,可以使用 with torch.no_grad():,强制之后的内容不进行计算图构建。
以下分别为使用和不使用的情况:
(1)使用with torch.no_grad():
运行结果:
此时的outputs没有 属性。
(2)不使用with torch.no_grad():
而对应的不使用的情况
结果如下:
可以看到,此时有grad_fn=<AddmmBackward>属性,表示,计算的结果在一计算图当中,可以进行梯度反传等操作。但是,两者计算的结果实际上是没有区别的。
简单的说:
本文转自 https://blog.csdn.net/weixin_44134757/article/details/105775027,如有侵权,请联系删除。
tf.placeholder
函数形式:
为什么要用placeholder?
Tensorflow的设计理念称之为计算流图,在编写程序时,首先构筑整个系统的graph,代码并不会直接生效,这一点和python的其他数值计算库(如Numpy等)不同,graph为静态的,类似于docker中的镜像。然后,在实际的运行时,启动一个session,程序才会真正的运行。这样做的好处就是:避免反复地切换底层程序实际运行的上下文,tensorflow帮你优化整个系统的代码。我们知道,很多python程序的底层为C语言或者其他语言,执行一行脚本,就要切换一次,是有成本的,tensorflow通过计算流图的方式,帮你优化整个session需要执行的代码,还是很有优势的。
所以placeholder()函数是在神经网络构建graph的时候在模型中的占位,此时并没有把要输入的数据传入模型,它只会分配必要的内存。等建立session,在会话中,运行模型的时候通过feed_dict()函数向占位符喂入数据。
代码示例:
本文转自 https://blog.csdn.net/kdongyi/article/details/82343712,如有侵权,请联系删除。
关于SELF理解
在使用tensorFlow2搭建神经网络模型的时候,除了Sequential的方法,还有就是自己写模型class,然后初始化。自己写模型类的优势就是可以自定义层与层之间的连接关系,自定义数据流x的流向。
这是为鸢尾花数据做的一个简单基础的神经网络模型代码:
我在第一次学习用类来写这个代码的时候,有几个地方觉得很奇怪,不习惯。
1、为什么要定义 def __init__()
2、为什么要有 super(MyModel ,self).__init__()
3、为什么到处都有一个self? 又不能省略,又感觉很累赘,它到底意义何在?
原文:博文:self参数 - __ init__ ()方法 super(Net, self).__init__()是什么
原文:博主Chou_pijiang,原文链接:https://blog.csdn.net/zyh19980527/article/details/107206483
总结下来,有这样几点:
1、self参数
self指的是实例Instance本身,在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self,也就是说,类中的方法的第一个参数一定要是self,而且不能省略。 我觉得关于self有三点是很重要的: self指的是实例本身,而不是类 self可以用this替代,但是不要这么去写 类的方法中的self不可以省略
2、__ init__ ()方法
在python中创建类后,通常会创建一个 __ init__ ()方法,这个方法会在创建类的实例的时候自动执行。 __ init__ ()方法必须包含一个self参数,而且要是第一个参数
__ init__ ()方法在实例化的时候就已经自动执行了,但是如果不是 __ init__ ()方法,那肯定就只有调用才执行。如果 __ init__ ()方法中还需要传入另一个参数name,但是我们在创建Bob的实例的时候没有传入name,那么程序就会报错, 说我们少了一个__ init__ ()方法的参数,因为__ init__ ()方法是会在创建实例的过程中自动执行的,这个时候发现没有name参数,肯定就报错了。
那么什么需要在__ init__ ()方法中定义?就是当我们认为一些属性、操作是在创建实例的时候就有的时候,就应该把这个量定义在__ init__ ()方法中。我们写神经网络的代码的时候,一些网络结构的设置,也最好放在__ init__ ()方法中。
3、super(MyModel, self).__init__()
简单理解就是子类把父类的__init__()放到自己的__init__()当中,这样子类就有了父类的__init__()的那些东西。
Net类继承nn.Module,super(Net, self).__init__()就是对继承自父类nn.Module的属性进行初始化。而且是用nn.Module的初始化方法来初始化继承的属性。
子类继承了父类的所有属性和方法,父类属性自然会用父类方法来进行初始化。 当然,如果初始化的逻辑与父类的不同,不使用父类的方法,自己重新初始化也是可以的。
写神经网络模型的时候,父类Modle中还有一些属性我们不用再自己手写了,直接将其初始化就好,另外Model也是有继承的父类network.Network,这里也有一些我们不知道、不知如何自己写的属性和方法。所以最好都加上 super(MyModel,self).__init__()这样的父类初始化命令行。
参考TensorFLow官方API中Model的代码,我们来看看Model初始化__init__()中都定义了什么:https://github.com/tensorflow/tensorflow/blob/v2.5.0/tensorflow/python/module/module.py#L286-L317
本文转自 https://blog.csdn.net/eylier/article/details/118931908,如有侵权,请联系删除。
Last updated