0


【自用】动手学深度学习——跟李沐学AI要点

自用,是学习实时笔记,未条条记录,没有进一步加工组织语言,按需查看

04数据操作+数据预处理

代码:d2l-zh/pytorch/chapter_preliminaries/index.ipynb

N维数组是机器学习和神经网络的主要数据结构

创造数组:形状,数据类型,值

访问元素的切片区间注意:[1:3,]开区间不包括3;[::3,::2]跳着访问,每三行

、每两列访问一个元素

ctrl回车单行运行

import torch

张量(n维数组)表示一个数值组成的数组 可多维度 torch.arange()

x.shape 形状 x.numel()张量元素总数 x.reshape(,)不改变数量和元素量

torch.zeros((2,3,4)),torch.ones((2,3,4))

python列表赋值torch.tensor(数组)

按元素运算符

  1. x = torch.tensor([1.0, 2, 4, 8])
  2. y = torch.tensor([2, 2, 2, 2])
  3. x + y, x - y, x * y, x / y, x ** y # **运算符是求幂运算

把多个张量连结,拼接

dim=0行,dim=1列

广播机制,维度不一样数组,赋值多余维度再运算

X[-1],最后一行X[1:3]1-2行

=赋值

节省内存

Y=X+Y产生新的内存

原地执行

可以使用切片表示法将操作的结果分配给先前分配的数组

  1. Y[:] = <expression>

**如果在后续计算中没有重复使用

  1. X

, 我们也可以使用

  1. X[:] = X + Y

  1. X += Y

来减少操作的内存开销。**

NumPy张量

A = X.numpy()
B = torch.tensor(A)
type(A), type(B)

  1. (numpy.ndarray, torch.Tensor)

要(将大小为1的张量转换为Python标量),我们可以调用

  1. item

函数或Python的内置函数。

a = torch.tensor([3.5])
a, a.item(), float(a), int(a)

  1. (tensor([3.5000]), 3.5, 3.5, 3)

数据预处理

  1. import os
  2. os.makedirs(os.path.join('..', 'data'), exist_ok=True)
  3. data_file = os.path.join('..', 'data', 'house_tiny.csv')
  4. with open(data_file, 'w') as f:
  5. f.write('NumRooms,Alley,Price\n') # 列名
  6. f.write('NA,Pave,127500\n') # 每行表示一个数据样本
  7. f.write('2,NA,106000\n')
  8. f.write('4,NA,178100\n')
  9. f.write('NA,NA,140000\n')

我们导入pandas包并调用read_csv函数。该数据集有四行三列。其中每行描述了房间数量(“NumRooms”)、巷子类型(“Alley”)和房屋价格(“Price”)。

  1. import pandas as pd
  2. data = pd.read_csv(data_file)
  3. print(data)

处理缺失数据

插值法用一个替代值弥补缺失值,而删除法则直接忽略缺失值。

inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean()) #插值法,均值
print(inputs)

对于**

  1. nputs

中的类别值或离散值,我们将“NaN”视为一个类别。非数值变成数值。**

  1. NumRooms Alley
  2. 0 3.0 Pave
  3. 1 2.0 NaN
  4. 2 4.0 NaN
  5. 3 3.0 NaN

inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)

  1. NumRooms Alley_Pave Alley_nan
  2. 0 3.0 1 0
  3. 1 2.0 0 1
  4. 2 4.0 0 1
  5. 3 3.0 0 1

**

  1. inputs

  1. outputs

中的所有条目都是数值类型,它们可以转换为张量格式。**

  1. import torch
  2. X = torch.tensor(inputs.to_numpy(dtype=float))
  3. y = torch.tensor(outputs.to_numpy(dtype=float))
  4. X, y

QA:

1.可以参考这个网页的第一个回答:https://stackoverflow.com/questions/49643225/whats-the-difference-between-reshape-and-view-in-pytorch

view只能作用在连续的张量上(张量中元素的内存地址是连续的)。而reshape连续or非连续都可以。调用x.reshape的时候,如果x在内存中是连续的,那么x.reshape会返回一个view(原地修改,此时内存地址不变),否则就会返回一个新的张量(这时候内存地址变了)。所以推荐的做法是,想要原地修改就直接view,否则就先clone()再改。

05 线性代数

p1线性代数的一些概念

p2p3

  1. x = torch.arange(4)
  2. 一维张量
  3. A = torch.arange(20).reshape(5, 4)
  4. 矩阵
  5. A.T
  6. 矩阵的转置
  7. B = A.clone() # 通过分配新内存,将A的一个副本分配给B
  8. 两个矩阵的按元素乘法称为Hadamard积(Hadamard product)(数学符号)
  9. A_sum_axis0 = A.sum(axis=0) 输入轴0的维数在输出形状中消失
  10. A.sum(axis=[0, 1]) 两个维度求和,sum维度是最后一个维度
  11. A.mean()均值
  12. A.mean(axis=0)按照维度求均值
  13. 不丢掉维度,而是把他变成1
  14. sum_A = A.sum(axis=1, keepdims=True)
  15. sum_A = A.sum(axis=1, keepdims=True)
  16. sum_A2 = A.sum(axis=1)
  17. sum_A,A,sum_A2
  18. (tensor([[ 6.],
  19. [22.],
  20. [38.],
  21. [54.],
  22. [70.]]),
  23. tensor([[ 0., 1., 2., 3.],
  24. [ 4., 5., 6., 7.],
  25. [ 8., 9., 10., 11.],
  26. [12., 13., 14., 15.],
  27. [16., 17., 18., 19.]]),
  28. tensor([ 6., 22., 38., 54., 70.]))
  29. 如果我们想沿[某个轴计算A元素的累积总和], 比如axis=0(按行计算),可以调用cumsum函数。如果我们想沿[某个轴计算A元素的累积总和], 比如axis=0(按行计算),可以调用cumsum函数。
  30. A.cumsum(axis=0)
  31. B=A.cumsum(axis=0)
  32. C=A.sum(axis=0)
  33. B,A,C
  34. 结果(tensor([[ 0., 1., 2., 3.],
  35. [ 4., 6., 8., 10.],
  36. [12., 15., 18., 21.],
  37. [24., 28., 32., 36.],
  38. [40., 45., 50., 55.]]),
  39. tensor([[ 0., 1., 2., 3.],
  40. [ 4., 5., 6., 7.],
  41. [ 8., 9., 10., 11.],
  42. [12., 13., 14., 15.],
  43. [16., 17., 18., 19.]]),
  44. tensor([40., 45., 50., 55.]))
  45. [点积是相同位置的按元素乘积的和]
  46. y = torch.ones(4, dtype = torch.float32)
  47. x, y, torch.dot(x, y)
  48. 等价为torch.sum(x * y)
  49. 点积
  50. 矩阵-向量积,mv函数
  51. A.shape, x.shape, torch.mv(A, x)
  52. 矩阵乘法mm
  53. torch.mm(A, B)
  54. 范数 向量的范数是表示一个向量有多大。 这里考虑的大小(size)概念不涉及维度,而是分量的大小。
  55. L2-
  56. u = torch.tensor([3.0, -4.0])
  57. torch.norm(u)
  58. L1-绝对值求和
  59. torch.abs(u).sum()
  60. 矩阵范数-Frobenius范数
  61. torch.norm(torch.ones((4, 9)))

06 矩阵计算

  1. 标量导数
  2. 亚导数--不可微点
  3. 梯度:
  4. y标量x列向量--变成一个行向量,第i个元素是y关于xi的导数
  5. <u,v>表示内积
  6. y列向量x标量--列向量,第i个元素是yi关于x的导数
  7. 分子布局符号,如果以上结果行列反过来,是分母布局
  8. y,x均为列向量--得到矩阵,ij列是yixj
  9. 扩展到矩阵求导
  10. 矩阵和标量:矩阵在下面--维度转置,矩阵在上面--维度不变
  11. 矩阵和向量:矩阵在下面--维度转置,前面加向量维度,矩阵在上面--维度不变,后面加
  12. 矩阵和矩阵:前面两项是上面,后面是转置下面

07 自动求导

  1. 向量链式法则
  2. 自动求导,计算一个函数在指定数的值,有别于符号求导和数值求导
  3. 计算图-等价于链式过程
  4. 代码分解成操作子,计算表示成无环的图,像树,显示构造,隐式构造
  5. 正向,从xy,计算复杂度n,内存复杂度1;反向,从yx,计算复杂度n,内存复杂度n
  6. 实现1
  7. import torch
  8. x = torch.arange(4.0)
  9. x.requires_grad_(True) # 等价于x=torch.arange(4.0,requires_grad=True)
  10. x.grad # 默认值是None,存梯度的地方
  11. y = 2 * torch.dot(x, x)
  12. y.backward() #求导
  13. x.grad
  14. x.grad == 4 * x
  15. 实现2
  16. # 在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
  17. x.grad.zero_()
  18. y = x.sum()
  19. y.backward()
  20. x.grad
  21. # 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
  22. # 本例只想求偏导数的和,所以传递一个1的梯度是合适的,大部分是标量对向量
  23. x.grad.zero_()
  24. y = x * x
  25. # 等价于y.backward(torch.ones(len(x)))
  26. y.sum().backward()
  27. x.grad
  28. 将某些计算移动到记录的计算图之外
  29. x.grad.zero_()
  30. y = x * x
  31. u = y.detach() #这里只赋值,u是常数,固定参数用
  32. z = u * x
  33. z.sum().backward()
  34. x.grad == u
  35. x.grad.zero_()
  36. y.sum().backward()
  37. x.grad == 2 * x
  38. Python控制流的梯度计算,即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度
  39. def f(a):
  40. b = a * 2
  41. while b.norm() < 1000:
  42. b = b * 2
  43. if b.sum() > 0:
  44. c = b
  45. else:
  46. c = 100 * b
  47. return c
  48. a = torch.randn(size=(), requires_grad=True)
  49. d = f(a)
  50. d.backward()
  51. a.grad == d / a
  52. 这就是隐式构造

08 线性回归 + 基础优化算法

p1线性回归,权重,偏差
线性模型可看作单层神经网络
衡量预估质量--平方损失

训练数据,收集数据决定权重和偏差,训练数据,越多越好,训练样本

参数学习,最小化训练损失

显式解

是相对于‌隐式解‌而言的,指的是在方程中,解可以明确地用自变量表示出来的形式。例如,如果方程的解可以写成 y=f(x)y=f(x) 的形式,那么这个解就是显式的。显式解的最大特点是能够直接用自变量 xx 表达出因变量 yy,而不需要通过其他方式求解。

显式解与隐式解的区别

  • 显式解‌:可以直接用自变量表示因变量,例如 y=x2+1y=x2+1。
  • 隐式解‌:无法直接用自变量表示因变量,例如 x2+y2=1x2+y2=1(这里无法直接从 x推导出 y 的表达式)。

p2

基础优化方法,不必知道显式解

剃度下降,沿负梯度方向,学习率是步长的超参数

小批量随机梯度下降

p3线性回归的从零开始实现

  1. %matplotlib inline
  2. import random
  3. import torch
  4. from d2l import torch as d2l
  5. #数据集
  6. def synthetic_data(w,b,num):
  7. X=torch.normal(0,1,(num,len(w)))#均值 方差 大小(行,列)
  8. y=torch.matmul(X,w)+b
  9. y+=torch.normal(0,0.01,y.shape)
  10. return X,y.reshape((-1,1))#列向量返回 -1表示自动计算,1表示固定
  11. ture_w=torch.tensor([2,-3.4])
  12. ture_b=4.2
  13. features,labels=synthetic_data(ture_w,ture_b,1000)
  14. def data_iter(batch_size,features,labels):
  15. num_examples=len(features)
  16. indices=list(range(num_examples))
  17. random.shuffle(indices)#打乱
  18. #起始 结束+1 步幅
  19. for i in range(0,num_examples,batch_size):
  20. batch_indices=torch.tensor(indices[i:min(i+batch_size,num_examples)])
  21. yield festures[batch_indices],labels[batch_indices]
  22. batch_size=10
  23. #for X,y in data_iter(batch_size,features,labels):
  24. # print(X,'\n',y)
  25. # break
  26. 定义初始化模型参数
  27. w=torch.normal(0,0.01,size=(2,1),requires_grad=True)
  28. b=torch.zeros(1,requested_grad=True)
  29. 定义模型
  30. def linreg(X,w,b):
  31. """线性回归模型"""
  32. return torch.matmul(X,w)+b
  33. 定义损失函数
  34. def squared_loss(y_hat,y):
  35. """均方误差"""
  36. return(y_hat-y.reshape(y_hat.shape))**2/2
  37. 定义优化算法
  38. def sgd(params,lr,batch_size):
  39. #参数 学习率 batch_size
  40. """小批量随机梯度下降"""
  41. with torch.no_grad():
  42. for param in params:
  43. param -=lr*param.grad/batch_size
  44. param.grad.zero_()
  45. 训练过程
  46. lr=0.03
  47. num_epochs=3#数据扫3遍
  48. net=linreg
  49. loss=squared_loss
  50. for epoch in range(num_epochs):
  51. for X,y in data_iter(batch_size,features,labels):
  52. l=loss(net(X,w,b),y)
  53. l.sum().backward()
  54. sgd([w,b],,lr,batch_size)
  55. with torch.no_grad():
  56. train_l=loss(net(features,w,b),labels)
  57. print(f'epoch{epoch+1},loss{float(train_l.mean()):f}')

p4简洁实现

  1. import numpy as np
  2. import torch
  3. from torch.utils import data
  4. from d2l import torch as d2l
  5. ture_w=torch.tensor([2,-3.4])
  6. ture_b=4.2
  7. features,labels=d2l.synthetic_data(ture_w,ture_b,1000)
  8. 调用框架现有API读取数据
  9. def load_array(data_arrays,batch_size,is_train=Ture):
  10. """构造一个PyTorch数据迭代器"""
  11. dataset =data.TensorDataset(*data_arrays)
  12. return data.DataLoader(dataset,batch_size,shuffle=is_train)#随机打乱
  13. batch_size=10
  14. data_iter=load_array((features,labels),batch_size)
  15. next(iter(data_iter))
  16. 模型定义
  17. from torch import nn
  18. net=nn.Sequential(nn.Linear(2,1))
  19. 初始化参数
  20. net[0].weight.data.normal_(0,0.01)
  21. net[0].bias.data.fill_(0)
  22. loss=nn.MSELoss()
  23. trainer=torch.optim.SGD(net.parameters(),lr=0.03)
  24. num_epochs=3
  25. for epoch in range(num_epochs):
  26. for X,y in data_iter:
  27. l=loss(net(X),y)
  28. trainer.zero_grad()
  29. l.backward()
  30. trainer.step()
  31. l=loss(net(festures),labels)
  32. print(f'epoch{epoch+1},loss[l:f]')

本文转载自: https://blog.csdn.net/qq_73462547/article/details/141867901
版权归原作者 Fibre1213 所有, 如有侵权,请联系我们删除。

“【自用】动手学深度学习——跟李沐学AI要点”的评论:

还没有评论