ToB企服应用市场:ToB评测及商务社交产业平台

标题: PyTorch底子学习03_数学运算&自动微分 [打印本页]

作者: 何小豆儿在此    时间: 2024-11-25 01:03
标题: PyTorch底子学习03_数学运算&自动微分
目录
一、数学运算
1、基本操作
2、三角函数
3、统计学函数
二、生存和加载
三、并行化
四、自动微分
1、相关概念
2、盘算梯度
1.标量梯度盘算
2.向量梯度盘算
3.多标量梯度盘算
4.多向量梯度盘算
5.矩阵梯度盘算
3、梯度上下文控制
1、梯度控制
2、梯度更新
3、叶子节点

导入torch库:
  1. import torch
复制代码
一、数学运算

1、基本操作


  1. data = torch.tensor(
  2.     [
  3.         [1, 2, -3.5],  # 1
  4.         [4, 5, 6],  # 2
  5.         [10.5, 18.6, 19.6],  # 3
  6.         [11.05, 19.3, 20.6],  # 4
  7.     ]
  8. )
  9. print(data)
  10. # 向下取整(往小取 返回不大于每个元素的最大整数)
  11. x1 = torch.floor(data)
  12. print(x1)
  13. # 向上取整(往大取 返回不小于每个元素的最小整数)
  14. x2 = torch.ceil(data)
  15. print(x2)
  16. # 四舍五入 与python round()一致 四舍六入五看齐(看个位奇偶,奇进偶舍)
  17. x3 = torch.round(data)
  18. print(x3)
  19. # 截断,只保留整数部分
  20. x4 = torch.trunc(data)
  21. print(x4)
  22. # 截断,只保留小数部分
  23. x5 = torch.frac(data)
  24. print(x5)
  25. # 向零方向舍入(舍入到最接近零的整数)
  26. x6 = torch.fix(data)
  27. print(x6)
  28. # 取余
  29. x7 = torch.fmod(data, 2)
  30. print(x7)
  31. # 绝对值
  32. x8 = torch.abs(data)
  33. print(x8)
复制代码
2、三角函数


  1. # torch.set_printoptions(sci_mode=False)
  2. print(torch.pi) # 圆周率
  3. deg = torch.pi/180
  4. data = torch.tensor([0,90*deg,45*deg])
  5. x1 = torch.sin(data)
  6. print(x1)
  7. x2 = torch.cos(data)
  8. print(x2)
  9. x3 = torch.sinh(data)
  10. print(x3)
  11. x4 = torch.cosh(data)
  12. print(x4)
  13. x5 = torch.tan(data)
  14. print(x5)
  15. x6 = torch.tanh(data)
  16. print(x6)
复制代码
3、统计学函数

  1. torch.manual_seed(66)
  2. x = torch.tensor([1,2,2,3,3,3,4,4,5]).type(torch.float32)
  3. print(x)
  4. # 平均值
  5. x1 = x.mean()
  6. print(x1)
  7. # 求和
  8. x2 = x.sum()
  9. print(x2)
  10. # 标准差
  11. x3 = x.std()
  12. print(x3)
  13. # 方差
  14. x4 = x.var()
  15. print(x4)
  16. # 中位数
  17. x5 = x.median()
  18. print(x5)
  19. # 最大值
  20. x6 = x.max()
  21. print(x6)
  22. # 最小值
  23. x7 = x.min()
  24. print(x7)
  25. # 众数
  26. x8 = torch.mode(x)
  27. print(x8)
  28. # 排序 返回排序后的张量values和索引indices
  29. x9 = torch.sort(x)
  30. print(x9)
  31. x = torch.tensor([1,2,2,3,3,3,4,4,5,2,3,4,6]).type(torch.float32)
  32. print(torch.topk(x,3)) # 返回前3个最大值
  33. print(torch.histc(x,bins=10, min=2,max=4)) # 区间[min,max]分成bins份 表示各个区间的元素计数
  34. print(torch.unique(x)) # 返回分类的数据集中的数据类型
  35. x = torch.tensor([1,2,2,3,3,3,4,4,5,2,3,4,6])
  36. print(torch.bincount(x)) # 返回张量中每个元素的出现次数
复制代码
二、生存和加载

  1. # 保存
  2. x = torch.tensor([1,2,3])
  3. torch.save(x,'./data/tensor01.pth')
  4. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  5. # 加载
  6. y = torch.load('./data/tensor01.pth',map_location=device)
  7. print(y)
  8. print(y.device)
复制代码
三、并行化

在 PyTorch 中,可以查看和设置用于 CPU 运算的线程数。PyTorch 使用多线程来加速 CPU 运算,但偶尔大概需要调解线程数来优化性能。
  1. # torch.get_num_threads() 来查看当前 PyTorch 使用的线程数
  2. def test01():
  3.     count = torch.get_num_threads()
  4.     print(count)
  5. # torch.set_num_threads() 设置 PyTorch 使用的线程数
  6. def test02():
  7.     torch.set_num_threads(4)
  8.     count = torch.get_num_threads()
  9.     print(count)
  10. if __name__ == '__main__':
  11.     test01()
  12.     test02()
复制代码
 设置线程数时,确保思量到你的 CPU 核心数和其他历程的资源需求,以得到最佳性能。
注意事项

四、自动微分

自动微分模块torch.autograd负责自动盘算张量操作的梯度,具有自动求导功能。自动微分模块是构成神经网络训练的须要模块,可以实现网络权重参数的更新,使得反向传播算法的实现变得简单而高效。
1、相关概念

2、盘算梯度

使用tensor.backward()方法实行反向传播,以盘算张量的梯度。
1.标量梯度盘算

  1. # 创建张量:要计算梯度则必须为浮点类型
  2. x = torch.tensor(3, require_grad=True, dtype=torch.float64)
  3. # 定义函数
  4. y = x**2 + 2*x - 5
  5. # 计算梯度,也就是反向传播
  6. y.backward() # # 梯度计算 1.y函数对x求导函数 y'=2*x+2 2.代入x的当前值 x=3 3.求出导数值 y'=2*3+2
  7. # 读取梯度值
  8. print(x.grad) # tensor(8.)
复制代码
2.向量梯度盘算

  1. # 向量梯度计算
  2. x = torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
  3. y = x**2 + 2*x - 5
  4. print(y) # tensor([-2.,  3., 10.], dtype=torch.float64, grad_fn=<SubBackward0>)
  5. y = y.sum() # y必须是一个标量才能用这个标量对x求导 设置一个复合函数
  6. y.backward() # y'=2x+2
  7. print(x.grad) # tensor([4., 6., 8.], dtype=torch.float64)
复制代码
3.多标量梯度盘算

  1. # 多标量的梯度计算
  2. x1 = torch.tensor(1,requires_grad=True,dtype=torch.float64)
  3. x2 = torch.tensor(2,requires_grad=True,dtype=torch.float64)
  4. y = x1**2 + 3*x2 - 5
  5. y.backward() # 偏导数
  6. print(x1.grad)
  7. print(x2.grad)
复制代码
4.多向量梯度盘算

  1. # 多向量的梯度计算
  2. x1 = torch.tensor([1,2,3],requires_grad=True,dtype=torch.float64)
  3. x2 = torch.tensor([4,5,6],requires_grad=True,dtype=torch.float64)
  4. y = x1**2 + 3*x2 - 5
  5. y = y.sum()
  6. y.backward() # 偏导数
  7. print(x1.grad) # 2*x1 tensor(2., dtype=torch.float64)
  8. print(x2.grad) # 3 tensor(3., dtype=torch.float64)
复制代码
5.矩阵梯度盘算

  1. # 矩阵梯度计算
  2. x = torch.tensor([[1,2],[3,4]],requires_grad=True,dtype=torch.float64)
  3. y = x**2 + 2*x - 5
  4. y = y.sum()
  5. y.backward()
  6. print(x.grad)
复制代码
3、梯度上下文控制

梯度盘算的上下文控制和设置对于管理盘算图、内存消耗、以及盘算效率至关重要。
1、梯度控制

梯度盘算是有性能开销的,有些时候只是简单的运算,此时并不需要梯度。
  1. # 正常情况下
  2. def test01():
  3.     x = torch.tensor(10.5, requires_grad=True)
  4.     print(x.requires_grad)  # True
  5.     # 默认y的requires_grad=True
  6.     y = x**2 + 2 * x + 3
  7.     print(y.requires_grad)  # True
  8. def test02():
  9.     x = torch.tensor(5, requires_grad=True,dtype=torch.float64)
  10.     # 关闭y的梯度计算 使用with进行上下文管理
  11.     with torch.no_grad():
  12.         y = x**2 + 2*x - 5
  13.         print(y.requires_grad) # False
  14. # 使用装饰器
  15. @torch.no_grad()
  16. def test03():
  17.     x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)
  18.     y = x**2 + 2*x - 5
  19.     y = y.sum()
  20.     print(y.requires_grad) # False
  21.    
  22. # 自己创建装饰器
  23. def my_no_grad(func):
  24.     def wrapper():
  25.         with torch.no_grad():
  26.             re = func()
  27.             return re
  28.     return wrapper
  29. @my_no_grad
  30. def test04():
  31.     x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)
  32.     y = x**2 + 2*x - 5
  33.     y = y.sum()
  34.     print(y.requires_grad) # False
  35. # 全局设置关闭梯度计算
  36. def test05():
  37.     x = torch.tensor([1,2,3], requires_grad=True,dtype=torch.float64)
  38.     torch.set_grad_enabled(False)
  39.     y = x**2 + 2*x - 5
  40.     y = y.sum()
  41.     y.backward()
  42.     print(x.requires_grad)
  43.     print(y.requires_grad)
  44.     print(x.grad)
  45. # 累计梯度
  46. def test06():
  47.     x = torch.tensor(1, requires_grad=True,dtype=torch.float64)
  48.     y = x**2 + 2*x - 5
  49.     y.backward()
  50.     print(x.grad)
  51.     y = 2*x**2 + 7
  52.     y.backward()
  53.     print(x.grad)
  54. # 累计梯度02
  55. def test07():
  56.     x = torch.tensor(4, requires_grad=True,dtype=torch.float64)
  57.     for _ in range(4):
  58.             y = x**2 + 2*x - 5
  59.             y.backward()
  60.             print(x.grad)
  61. # 梯度清零
  62. def test08():
  63.     x = torch.tensor(4, requires_grad=True,dtype=torch.float64)
  64.     y = x**2 + 2*x - 5
  65.     y.backward() # 2*x + 2
  66.     print(x.grad)
  67.    
  68.     z = 3*x**2 + 7*x
  69.     # 清零
  70.     x.grad.zero_() # 不清零则为 10+31=41
  71.     z.backward() # 清零后为 6*4+7=31
  72.     print(x.grad)
  73.     # 综合梯度清零操作
  74.     for _ in range(3):
  75.         y = x**2 + 2 * x + 7
  76.         z = y.mean()
  77.         # 反向传播之前先对梯度进行清零
  78.         if x.grad is not None:
  79.             x.grad.zero_()
  80.             
  81.         z.backward()
  82.         print(x.grad)
  83. if __name__ == '__main__':
  84.     test01()
  85.     test02()
  86.     test03()
  87.     test04()
  88.     test05()
  89.     test06()
  90.     test07()
  91.     test08()
复制代码
2、梯度更新

大多数情况下是不需要梯度累加的,反向传播之前可以先用 .zero_() 对梯度进行清零。
更新梯度时,注意更新的数据应是data,直接改变原tensor会导致其变成新的数据。
  1. # 标量训练
  2. def test01():
  3.     # 生成初始化w
  4.     w = torch.tensor(25., requires_grad=True)
  5.     # 训练参数
  6.     lr = 0.01
  7.     epoch = 5
  8.     for i in range(epoch):
  9.         # 生成损失函数
  10.         loss = 3*w**2 + 2*w - 5
  11.         # 梯度清零
  12.         if w.grad is not None:
  13.             w.grad.zero_()
  14.         # 反向传播 求当前w的导数值:梯度值,斜率
  15.         loss.backward()
  16.         # 当前斜率
  17.         print(w.grad)
  18.         # 更新梯度
  19.         # w的tensor不能修改 避免w变成新的数据 应修改w.data
  20.         w.data = w.data - lr*w.grad.data
  21.         print(w)
  22.     # 访问训练后的w的值
  23.     print(w.data)
  24. # 向量训练
  25. def test02():
  26.     # 生成初始化w
  27.     w = torch.tensor([10,20,30], requires_grad=True,dtype=torch.float64)
  28.     # 训练参数
  29.     lr = 0.01
  30.     epoch = 5
  31.     for i in range(epoch):
  32.         # 生成损失函数
  33.         loss = 3*w**2 + 2*w - 5
  34.         loss = loss.sum() # 设置一个复合函数
  35.         # 梯度清零
  36.         if w.grad is not None:
  37.             w.grad.zero_()
  38.         # 反向传播 求当前w的导数值:梯度值,斜率
  39.         loss.backward()
  40.         # 当前斜率
  41.         print(w.grad)
  42.         # 更新梯度
  43.         # w的tensor不能修改 避免w变成新的数据 应修改w.data
  44.         w.data = w.data - lr*w.grad.data
  45.         print(w)
  46.     # 访问训练后的w的值
  47.     print(w.data)
  48.     # 保存训练好的权重数据
  49.     torch.save(w.data,'./data/weight.pth')
  50. # 加载训练好的权重数据
  51. def detect():
  52.     w = torch.load('./data/weight.pth',map_location='cuda')
  53.     # 使用w
  54.     print(w)
  55. if __name__ == '__main__':
  56.     # test01()
  57.     test02()
  58.     detect()
复制代码
3、叶子节点

当想使用不含求导功能的tensor时,可以使用detach()创建张量,该张量是作为叶子结点存在的,并且该张量和原张量共享数据,只是该张量不需要盘算梯度。
原因:可以求导的张量不能直接看成平凡的tensor使用,如转换为numpy数组操作: .numpy()
  1. # detach()产生的张量是作为叶子结点存在的,并且该张量和原张量共享数据,只是该张量不需要计算梯度。
  2. def test01():
  3.     x = torch.tensor([1, 2, 3], requires_grad=True,dtype=torch.float32)
  4.     # x1 = x.numpy() # 报错 如果x是一个可以求导的张量,那么它就不能直接当作普通的tensor使用
  5. def test02():
  6.     x = torch.tensor([1, 2, 3], requires_grad=True,dtype=torch.float32)
  7.     x2 = x.detach() # 创建一个叶子结点,并且和x共享数据,但是不需要计算梯度
  8.     print(x) # tensor([1., 2., 3.], requires_grad=True)
  9.     print(x2) # tensor([1., 2., 3.])
  10.    
  11.     print(id(x),id(x2)) # 两个对象
  12.     print(id(x.data),id(x2.data)) # 数据共享
  13.     x2[0] = 5
  14.     print(x,x2)
  15. if __name__ == '__main__':
  16.     test02()
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4