功能:将张量按维度dim进行拼接
·tensors:张量序列
·dim:要拼接的维度
功能:在新创建的维度dim上进行拼接
·tensors:张量序列
·dim:要拼接的维度
torch.cat(tensors, dim=0, out=None)
torch.stack(tensors, dim=0, out=None)
t = torch.ones((2, 3))
t_0 = torch.cat([t, t], dim=0)
t_1 = torch.cat([t, t], dim=1)
print("t_0:{} shape:{}\nt_1:{} shape:{}".format(t_0, t_0.shape, t_1, t_1.shape))
t_0 是在第0维度拼接,2+2=4
t_1 是在第1维度拼接,3+3=6
t = torch.ones((2, 3))
t_stack = torch.stack([t, t], dim=2)
print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape))
t原来是2×3的,没有第2维度,stack会创建第2维度,变成上面的样子。
如果在第0维度进行stack就会变成2×2×3的样子
功能:将张量按维度dim进行平均切分
返回值:张量列表
注意事项:若不能整除,最后一份张量小于其他张量
·input:要切分的张量
·chunks:要切分的份数
·dim:要切分的维度
a = torch.ones((2, 5)) # 7
list_of_tensors = torch.chunk(a, dim=1, chunks=2) # 3
for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
在第1维度上5分两份,第一份是3第二份是2
如果是7份三份就变成3/3/1,相当于对7/2向上取整。最后一个剩余多少就是多少。
功能:将张量按维度dim进行切分
返回值:张量列表
·tensor:要切分的张量
·split_size_or_sections:为int时,表示每一份的长度(这个时候和上面的1.3的差不多);为list时,按list元素切分,list里面的元素之和要和tensor的长度要一样,否则会报错。
·dim:要切分的维度
t = torch.ones((2, 5))
list_of_tensors = torch.split(t, [2, 1, 2], dim=1) # list里面的元素之和要和tensor的长度要一样,否则会报错。如果是[2, 1, 1]就报错
for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量
·input:要索引的张量
·dim:要索引的维度
·index:要索引数据的序号
t = torch.randint(0, 9, size=(3, 3))#创建3*3的张量
idx = torch.tensor([0, 2], dtype=torch.long) #这里的类型只能是long,不能是 float会报错
t_select = torch.index_select(t, dim=0, index=idx)#通过第0维度,就是行来select
print("t:\n{}\nt_select:\n{}".format(t, t_select))
功能:按mask中的True进行索引
返回值:一维张量
·input:要索引的张量
·mask:与input同形状的布尔类型张量
t = torch.randint(0, 9, size=(3, 3))
mask = t.ge(5) # ge is mean greater than or equal/ gt: greater than le lt还有le和lt
t_select = torch.masked_select(t, mask)
print("t:\n{}\nmask:\n{}\nt_select:\n{} ".format(t, mask, t_select))
功能:变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存
·input:要变换的张量
·shape:新张量的形状
t = torch.randperm(8)
t_reshape = torch.reshape(t, (2, 4)) # -1代表这个维度不关心,例如:(-1,2),-1那里就是8/2得到,如果是(-1,2,2),-1那里就是8/2/2得到。
print("t:{}\nt_reshape:\n{}".format(t, t_reshape))
老师补充说明:
关于reshape之后,tensor.data地址不一样的问题:
当张量是 contiguous的时候,才会共享内存,否则会开辟新的地址空间用于存储reshape之后的张量
你们再运行一下代码,并且加上这一行代码,观察如果id不同的时候,这个输出是否为False?
print("\na is contiguous? {}\n".format(a, a.is_contiguous()))
关于contiguous的概念,可以参考
https://zhuanlan.zhihu.com/p/64551412
变换形状还有一个函数就是view,这个函数要求矩阵必须是contiguous的。
功能:交换张量的两个维度(转置)
·input:要变换的张量
·dim0:要交换的维度
·dim1:要交换的维度
# torch.transpose
t = torch.rand((2, 3, 4))
t_transpose = torch.transpose(t, dim0=1, dim1=2) # c*h*w 变成 c*w*h,维度是从0开始算的
print("t shape:{}\nt_transpose shape: {}".format(t.shape, t_transpose.shape))
功能:2维张量转置,对矩阵而言,等价于torch.transpose(input,0,1)
功能:压缩长度为1的维度(轴)
·dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除;
t = torch.rand((1, 2, 3, 1))
t_sq = torch.squeeze(t)
t_0 = torch.squeeze(t, dim=0)
t_1 = torch.squeeze(t, dim=1)#这个方向的长度是2所以不会被移除
print(t.shape)
print(t_sq.shape)
print(t_0.shape)
print(t_1.shape)
功能:依据dim扩展维度
·dim:扩展的维度
1.2张量的数学运算
torch.add()
torch.addcdiv()
torch.addcmul()
torch.sub()
torch.div()
torch.mul()
torch.add()
功能:逐元素计算 input+alpha x other(就是先乘后加)
·input:第一个张量
·alpha:乘项因子
·other:第二个张量
还有两个函数很Pythonic:
torch. addcdiv()
torch. addcmul()
torch.log(input,out=None)
torch.log10(input,out=None)
torch.log2(input,out=None)
torch.exp(input,out=None)
torch.pow()
torch.abs(input,out=None)
torch.acos(input,out=None)
torch.cosh(input,out=None)
torch.cos(input,out=None)
torch.asin(input,out=None)
torch.atan(input,out=None)
torch.atan2(input,other,out=None)
线性回归是分析一个变量与另外一(多)个变量之间关系的方法
变量:y
自变量:x
关系:线性
y=wx+b
分析:求解w,b
求解步骤:
1.确定模型: y = w x + b y=wx+b y=wx+b
2.选择损失函数:
M S E : 1 m ∑ i = 1 m ( y i − y ^ i ) 2 MSE:\frac{1}{m}\sum_{i=1}^m(y_i-\widehat y_i)^2 MSE:m1i=1∑m(yi−y i)2
3.求解梯度并更新w,b
w = w − L R ∗ w . g r a d w=w-LR* w.grad w=w−LR∗w.grad
b = b − L R ∗ w . g r a d b=b-LR*w.grad b=b−LR∗w.grad
计算图是用来描述运算的有向无环图
计算图有两个主要元素:结点(Node)和边(Edge)
结点表示数据,如向量,矩阵,张量边表示运算,如加减乘除卷积等
例如:用计算图表示: y = ( x + w ) ∗ ( w + 1 ) y=(x+w)*(w+1) y=(x+w)∗(w+1)
a = x + w a=x+w a=x+w
b = w + 1 b=w+1 b=w+1
y = a ∗ b y=a*b y=a∗b
带入具体数字:
计算图与梯度求导
求y对w的导数就是上图中y到w两条路径的导数的和。
∂ y ∂ w = ∂ y ∂ a ∂ a ∂ w + ∂ y ∂ b ∂ b ∂ w = b ∗ 1 + a ∗ 1 = b + a = ( w + 1 ) + ( x + w ) = 2 ∗ w + x + 1 = 2 ∗ 1 + 2 + 1 = 5 \begin{aligned}\frac{\partial y}{\partial w}&=\frac{\partial y}{\partial a}\frac{\partial a}{\partial w}+\frac{\partial y}{\partial b}\frac{\partial b}{\partial w}\\ &=b*1+a*1\\ &=b+a\\ &=(w+1)+(x+w)\\ &=2*w+x+1\\ &=2*1+2+1\\&=5\end{aligned} ∂w∂y=∂a∂y∂w∂a+∂b∂y∂w∂b=b∗1+a∗1=b+a=(w+1)+(x+w)=2∗w+x+1=2∗1+2+1=5
import torch
w=torch. tensor([1.], requires grad=True)
x=torch. tensor([2.], requires_gradeTrue)
a=torch. add(w,x)# retain_grad()
b=torch. add(w,1)
y=torch. mul(a,b)
y. backward()
print(w. grad)
结果:
叶子结点:用户创建的结点称为叶子结点,如x与w。
is_leaf:指示张量是否为叶子结点
为了节省内存,非叶子节点在计算结束后就会释放,以节省开销,只有使用retain_grad()方法才能保存指定节点内存。
grad_fn:记录创建该张量时所用的方法(函数)
y.grad_fn=
a.grad_fn=
b.grad_fn=
根据计算图搭建方式,可将计算图分为动态图和静态图
动态图 | 静态图 |
---|---|
运算与搭建同时进行 | 先搭建图,后运算 |