第一次作业:深度学习基础
一.数据操作及实现:
1.数组:
1).对于一个四维数组,可以简单理解为一个RGB图片的批量(批量大小*宽*高*通道)
2).对于一个五维数组,可以理解为一个视频批量(批量大小*时间*宽*高*通道)
3).访问元素方法:
[::3,::2]:表示从第零行到最后一行每3行一跳,从第0列到最后一列,每2列一跳
4).一些基础操作:
幂运算:x**y
连接:
torch.cat((X,Y),dim=0):将矩阵在第0维(行)进行合并,可以修改dim值,比如dim=1表示列
torch.zeros_like:复制一个全为0的数组
5).广播机制:
有时即使形状不同,也能执行按元素操作。当看到两个形状不同的张量(维度相同)时,低维度会复制成高维度。
6).元素访问:
X[0:2,:]:表示选中第0到第一行的全部值
7).numpy和tensor的转变:
对于一个numpy张量A,可以使用torch.tensor(A)来进行转变
二。数据预处理:
一个简单的例子:在当前目录的上一层常见一个data文件夹,并创建一个csv文件,并写入数据。
import os os.makedirs(os.path.join('..', 'data'), exist_ok=True) data_file = os.path.join('..', 'data', 'house_tiny.csv') with open(data_file, 'w') as f: f.write('NumRooms,Alley,Price\n') f.write('NA,Pave,127500\n') f.write('2,NA,106000\n') f.write('4,NA,178100\n') f.write('NA,NA,140000\n')
读取csv文件:使用pandas库
!pip install pandas import pandas as pd data = pd.read_csv(data_file) print(data)
对缺失数据的处理:插值和删除
插值:
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2] inputs = inputs.fillna(inputs.mean())#fillna表示对所有数值域为NaN的值填写为均值 print(inputs)
inputs = pd.get_dummies(inputs, dummy_na=True)#将非数值转化为一个数值特征
print(inputs)
#将csv文件变为一个tensor
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
插值时注意,对数值域可以采取整体求均值等方法;而对非数值域,可以将非数值先转化为数值特征,之后进行操作。
常见问题:
1.使用reshape函数不会改变地址
2.学习numpy的相关知识
线性代数:
范数:
三个基本属性:
𝑓(𝛼𝐱)=|𝛼|𝑓(𝐱).如果我们按常数因子𝛼缩放向量的所有元素,其范数也会按相同常数因子的绝对值缩放。
𝑓(𝐱+𝐲)≤𝑓(𝐱)+𝑓(𝐲). 即三角不等式
𝑓(𝐱)≥0.非负性
L1范数、L2范数(可以理解为欧几里得距离)和Lp范数:
矩阵𝐗∈ℝ𝑚×𝑛的弗罗贝尼乌斯范数是矩阵元素平方和的平方根(矩阵的L2范数)
torch.norm(torch.ones((4, 9)))
常用函数:
转置:N.T
分配新内存:B=A.clone()
哈达玛积(矩阵按元素相乘):A*B
降维求和:A.sum(axis=x) 其中x表示按照哪一个维度求和,可以设定keepdims=True,这样不改变维度
import torch A=torch.arange(20).reshape((5,2,2)) print(A) A.sum(axis=2,keepdims=True)
累加求和:A.cumsum(axis=0)
点积:torch.dot(x,y)
矩阵乘向量: torch.mv(A,x)
矩阵计算(求导):
亚导数:将倒数扩展到不可微的函数,例如:y=|x|(x=0时,无法求导),其导数计算如下:
梯度:指向值变化最大的方向
向量关于向量的求导是一个矩阵。
自动求导:
自动求导是值计算一个函数值在一个指定值的导数,采用计算图的原理,首先将代码分解成操作子,然后将计算表示成一个无环图(具体可参考下图)。
自动求导的两种方式:
正向和反向区别:
复杂度分析:
对于计算复杂度,二者相差不多,都是O(N)
对于内存复杂度,反向传播是O(N),因为要存储正向的所有结果
自动求导的实现:(对函数𝑦=2𝐱⊤𝐱关于列向量𝐱求导) 假设y是标量,x是向量。
1.梯度的存放:requires_grad_(True)
x.requires_grad_(True) x.grad # 默认值是None
2.梯度的反向传播函数:background()函数
y = 2 * torch.dot(x, x)
y.backward()
x.grad
注意,当重新进行求导时要调用grad.zero_()函数,因为pytorch默认的是保留梯度值。
假设y是向量,例如y=x*x
理论上说向量对向量求导得到的结果是一个矩阵,但在深度学习中,很少进行这种操作,通常进行一次求和运算
x.grad.zero_() y = x * x # 等价于y.backward(torch.ones(len(x))) y.sum().backward() x.grad
分离计算(将某些计算移到计算图之外):使用detach( )函数
x.grad.zero_() y = x * x u = y.detach() z = u * x z.sum().backward() x.grad == u #验证结果为True
问题及感受:
学习过程中发现对于导数还有线性代数的基础知识掌握不是十分熟练,已经找出了线性代数当年的笔记本,准备抓紧复习。除此之外也需复习了解python中numpy的相关知识。
本周任务中,涉及代码内容较少,很多知识也在本科毕设过程中有所涉及,但也学到了许多新的pytorch中常用的函数及部分原理,受益匪浅。