一、数据操作
二、数据预处理
1.函数
(1)递归创建目录:os.makedirs()
如果路径中的父级目录不存在,os.makedirs() 将递归创建这些目录。参数 exist_ok=True 表示如果目录已经存在,不会抛出异常。
(2)读取CSV文件:pandas.read_csv()
(3)合并路径:os.path.join()
path1 = '/path/to/directory'
path2 = 'file.txt'
full_path = os.path.join(path1, path2)
(4)按索引访问:iloc()
# 使用 iloc 选择第一行
row_0 = df.iloc[0]
# 使用 iloc 选择特定的行范围
rows_1_2 = df.iloc[1:3]
# 使用 iloc 选择特定的行和列范围
subset = df.iloc[0:2, 1:3]
(5)填充缺失值:fillna()
# 使用 fillna 填充缺失值为指定的值0
df_filled = df.fillna(0)
(6)转化离散信息:get_dummies()
可参考这篇博客
pd.get_dummies相当于onehot编码,常用与把离散的类别信息转化为onehot编码形式。
(感觉和数学建模中的虚拟变量有点像)
(7)转换为张量格式:torch.tensor()
2.练习
(1)删除缺失值最多的列。
(2)将预处理后的数据集转换为张量格式
import os
import pandas as pd
import torch
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格式读取文件
data = pd.read_csv(data_file)
print(data)
# 删除缺失值最多的列
max_col_name=data.isna().sum().idxmax()
data = data.drop(max_col_name,axis=1)
print(data)
# 将预处理后的数据集转换为张量格式
data_tensor = torch.tensor(data.values)
print(data_tensor)
三、线性代数
以后有时间再写吧
四、微积分
五、自动微分
1.函数
(1)x.requires_grad_(True)
通过调用 requires_grad_(True) 方法,可以将张量 x 标记为需要计算梯度。
当一个张量被标记为需要计算梯度时,PyTorch 会在对其进行操作时自动构建计算图,并在反向传播过程中计算相对于这个张量的梯度。这对于训练神经网络和执行自动微分非常有用,因为可以轻松地获取每个张量相对于损失函数的梯度,从而更新模型参数。
(2)x.grad.zero_()
清除之前的梯度(梯度会累积)
(3).detach()
u = y.detach() 的作用是将张量 y 从计算图中分离出来,并将其赋值给变量 u。通过这样的操作,变量 u 包含了与 y 相同的数值数据,但不再保留与计算图相关的梯度信息。
(4).backward()
看到了一篇知乎里写得很好的文章:
Pytorch autograd,backward详解
更新于2024.4.15
最近又不理解backward是如何计算的了
在这里留下足迹:
探索loss.backward() 和optimizer.step()的关系并灵活运用
这篇文章中有个图,我觉得很好:
2.练习
(1)为什么计算二阶导数比一阶导数的开销要更大?
额外的计算量:计算二阶导数需要对一阶导数进行进一步的求导,这意味着需要进行更多的数学运算。在计算图中,每个节点都需要考虑其二阶导数,因此会涉及到更复杂的运算过程。
高阶链式法则:计算二阶导数需要应用高阶链式法则,这会增加计算的复杂性。高阶链式法则涉及更多的乘法、加法和函数调用,从而增加了计算的开销。
内存消耗:在计算二阶导数时,需要存储更多的中间结果和计算图信息,以便进行二阶梯度的计算。这可能导致更多的内存消耗,尤其是对于较大的张量和计算图。
数值稳定性:在计算二阶导数时,由于涉及更多的数值计算和微小的数值变化,可能会增加数值稳定性方面的挑战,导致数值误差的累积。
(2)在运行反向传播函数之后,立即再次运行它,看看会发生什么。
会报错:
RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.
解决方法:
加上“retain_graph=True”
d.backward(retain_graph=True)
(3)在控制流的例子中,我们计算d关于a的导数,如果将变量a更改为随机向量或矩阵,会发生什么?
会报错
解决方法:
用sum()
下面这篇文章里有解释
Pytorch autograd,backward详解
(4)重新设计一个求控制流梯度的例子,运行并分析结果。
当a=1,即b=a*3<30时,b会再次乘以20,所以最后的梯度为60
而当a=11,即b=a*3>30时,b不会乘以20,所以最后的梯度为3
(5) 题目如下图:
%matplotlib inline
from d2l import torch as d2l
x = torch.linspace(0, 10, 1000)
x.requires_grad_(True)
y = torch.sin(x)
y.backward(torch.ones_like(x))
y = y.detach()
d2l.plot(x.detach(), [y, x.grad], 'f(x)', "f'(x)", legend=['f(x)', 'Tangent line'])
d2l.plt.show()
六、概率
1.函数
(1)Multinomial()
个人理解:
Multinomial(抽样几次,权重)
import torch
from torch.distributions import Multinomial
# 定义试验次数和每个结果的概率
probs = torch.tensor([0.2, 0.3, 0.5])
total_count = 4
# 创建多项式分布对象
m = Multinomial(total_count=total_count, probs=probs)
# 进行抽样
samples = m.sample()
print(samples)
抽样是随机的。每一与运行的结果可能不一样:
(2)cumsum()
作用: 计算数组元素的累积和
import torch
# 创建一个张量
x = torch.tensor([1, 2, 3, 4, 5])
# 对张量进行累积求和操作
cumulative_sum = torch.cumsum(x, dim=0)
print("原始张量:", x)
print("累积求和结果:", cumulative_sum)
运行结果:
对于矩阵来说,可以在两个方向上求和。
在0轴方向上求和:
在1轴方向上求和:
(3)ply.plot()
2.练习
(1)