- 实验目的
1.安装PyTorch
2.标量、向量、矩阵、Tensor
3.AutoGrad
二、实验环境
(使用的操作系统、编程软件等)
Windows,PyTorch
三、实验内容
(可以包括实验方法、实验数据、实验结果、实验结果分析等)
- 搭建基于PyTorch+OpenCV软件开发平台
(1)、问题描述
使用指令安装PyTorch过程发生报错:
问题解决:
原因是用指令安装PyTorch需要连接外网才可以安装,之后给conda加上镜像网址之后便能够成功安装了
conda config --add channels Index of /anaconda/pkgs/free/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
(2)、问题描述:
安装OpenCV过程中出现报错:
问题解决:
更新pip安装包之后再将指令放到命令行中就可以安装了。
- 主要功能源码以及分析
(1)、数据操作
代码:
y = x.view(15)
z = x.view(-1, 5) # -1所指的维度可以根据其他维度的值推出来
print(x.size(), y.size(), z.size())
分析:
这段代码使用view()函数来改变一个tensor的形状,原本x的形状是[5,3],是一个5行3列的二维张量。第一段代码将x的形状更改成一个1行15列的一维张量;第二段代码利用了一个特殊值-1,在PyTorch中特殊值-1表示该位置的维度大小将根据其他维度的值自动推断得出,第二段指定生成?行5列的形状,系统会自动推断出为3,因此生成一个3行5列的二维张量。
代码:
x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
分析:
这段代码中的“print(x+y)”,因为x和y的形状不同,因此PyTorch会首先检查这两个张量是否能进行广播:
对于维度1:x的第一个维度是1,y的第一个维度是3,虽然这两个维度不相同,但是满足
维度不同,其中一个为1这个条件,所以维度1满足;
对于维度2:x的第二个维度是2,y的第二个维度是1,虽然这两个维度不相同,但是满足维度不同,其中一个为1这个条件,所以维度2满足;
因此这两个张量能够进行广播,那么x中第一行的2个元素被广播(复制)到了第二行和第三行,而y中第一列的3个元素被广播(复制)到了第二列,生成一个形状为 3 行 2 列的结果张量,其中每个元素是对应位置 x 和 y 的元素相加的结果。
(2)、自动微分
代码:
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.grad_fn)
y = x + 2
print(y)
print(y.grad_fn)
z = y * y * 3
out = z.mean()
print(z, out)
out.backward()
print(x.grad)
分析:
这段代码体现了PyTorch中的自动求导功能,在这些代码中的一系列操作中,可以得出下面这一串表达式:
out=sum [(x+2)^2*3]/4
而代码out.backward()调用了out的backward()方法,由于out是z的均值因此求导后表达式为:
d(out)/dx=3/2(x+2)
将x=1带入式子,因此输出出来的x.grad为: {4.5,4.5
4.5,4.5}
(3)、线性代数
代码:
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
A_sum_axis0 = A.sum(axis=0)
A_sum_axis0, A_sum_axis0.shape
分析:
我们使用 .sum(axis=0) 方法对 A 张量的第 0 轴(即行轴)进行求和,得到一个新的张量 A_sum_axis0,该张量的形状为 (4,),其中每个元素是原始张量 A 中对应列的总和
代码:
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
- cumsum(axis=0)
分析:
在这段代码中利用到了cumsum()函数来计算沿着轴0的元素的累计总和,这段代码的输出为中:
A为: tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
输出的结果为:
tensor([[ 0., 1., 2., 3.],
[ 4., 6., 8., 10.],
[12., 15., 18., 21.],
[24., 28., 32., 36.],
[40., 45., 50., 55.]])
在这个结果中,每个元素都是从原始 tensor A 的相应位置开始,到当前位置(包括当前位置)的所有元素的累积总和。沿着 axis=0 方向,第一行保持不变,第二行是第一行和第二行的元素相加的结果,以此类推。
- 作业以及练习答案
(1)、数据操作
将广播机制中按元素操作的两个 NDArray 替换成其他形状,结果是否和预期一样?
#填写答案,可根据需要将当前Cell的CellType设置为Markdown或继续添加新的Cell
x = torch.arange(1, 4).view(1, 3)
print(x)
y = torch.arange(1, 5).view(4, 1)
print(y)
print(x + y)
输出:
tensor([[1, 2, 3]])
tensor([[1],
[2],
[3],
[4]])
tensor([[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
(2)、线性代数基础:
第一题:证明一个矩阵 𝐀的转置的转置是 𝐀,即 (𝐀⊤)⊤=𝐀 。
答案:
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
A_transpose = A.T
A_transpose_transpose = A_transpose.T
comparison = A_transpose_transpose == A
if comparison.all():
print("(A^T)^T = A 成立")
else:
print("(A^T)^T = A 不成立")
(A^T)^T = A 成立
第二题:给出两个矩阵𝐀和𝐁,证明“它们转置的和”等于“它们和的转置”,即𝐀⊤+𝐁⊤=(𝐀+𝐁)⊤。
答案:
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
left_side = A.T + B.T
right_side = (A + B).T
comparison = left_side == right_side
if comparison.all():
print("(A^T + B^T) = (A + B)^T 成立")
else:
print("(A^T + B^T) = (A + B)^T 不成立")
(A^T + B^T) = (A + B)^T 成立
第三题: (1). 对于任意形状的张量X,len(X)是否总是对应于X特定轴的长度?这个轴是什么?
(2). 运行A/A.sum(axis=1),看看会发生什么。你能分析原因吗?
(3). 考虑一个具有形状(2,3,4)
的张量,在轴0、1、2上的求和输出是什么形状?
(1)是,0轴(0-axis)
(2)会出错,原因在于A为5行4列的矩阵,维度为2,而A.sum(axis=1)则为长度为5的向量,二者无法相除,需要维度一致才会有广播机制
(3)轴0求和——>[3,4]
轴1求和——>[2,4]
轴2求和——>[2,3]
四、实验小结
本次实验是我第一次接触到深入学习中的编程,第一次搭建环境虽然就遇到了一些困难,但是最后也是成功的运行了实验中的案例;实验中的代码虽然不好理解,但是经过上网搜查最后也能加以理解,总之激发了我对这门课程的兴趣。