【动手学深度学习】深入浅出深度学习之PyTorch基础

简介: 【动手学深度学习】深入浅出深度学习之PyTorch基础

image.gif

🌞一、实验目的

  1. 正确理解深度学习所需的数学知识;
  2. 学习一些关于数据的实用技能,包括存储、操作和预处理数据;
  3. 能够完成各种数据操作,存储和操作数据;
  4. PyTorch基础,完成《动⼿学深度学习》预备知识2.1-2.5节的课后练习。

🌞二、实验准备

  1. 根据GPU安装pytorch版本实现GPU运行实验代码;
  2. 配置环境用来运行 Python、Jupyter Notebook和相关库等相关库。

🌞三、实验内容

资源获取:关注公众号【科创视野】回复  深度学习

启动jupyter notebook,使用新增的pytorch环境新建ipynb文件,为了检查环境配置是否合理,输入import torch以及torch.cuda.is_available() ,若返回TRUE则说明实验环境配置正确,若返回False但可以正确导入torch则说明pytorch配置成功,但实验运行是在CPU进行的,结果如下:

import torch
torch.cuda.is_available() 

输出结果:


🌼1 数据操作

(1)使用jupyter notebook新增的pytorch环境新建ipynb文件,完成基本数据操作的实验代码与练习结果如下:


🌻1.1 入门
import torch
 
x = torch.arange(12)
x

输出结果:

x.shape

输出结果:

x.numel()

输出结果:

X = x.reshape(3, 4)
X

输出结果:

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

输出结果:

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

输出结果:

torch.randn(3, 4)

输出结果:

torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])

输出结果:


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

输出结果:

torch.exp(x)

输出结果:

X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)

输出结果:

X == Y

输出结果:

X.sum()

输出结果:


🌻1.3 广播机制
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b

输出结果:

a + b

输出结果:


🌻1.4 索引和切片
X[-1], X[1:3]

输出结果:

X[1, 2] = 9
X

输出结果:

X[0:2, :] = 12
X

输出结果:


🌻1.5 节省内存
before = id(Y)
Y = Y + X
id(Y) == before

输出结果:

Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))

输出结果:

before = id(X)
X += Y
id(X) == before

输出结果:


🌻1.6 转换为其他Python对象
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)

输出结果:

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

输出结果:


🌻1.7 小结

深度学习存储和操作数据的主要接口是张量((n)维数组)。它提供了各种功能,包括基本数学运算、广播、索引、切片、内存节省和转换其他Python对象。


🌻1.8 练习

1.运行本节中的代码。将本节中的条件语句X == Y更改为X < Y或X > Y,然后看看你可以得到什么样的张量。

X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
X<Y

输出结果:

X>Y

输出结果:

2.用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同?

a = torch.arange(3).reshape((3, 1))
b = torch.arange(3).reshape((1, 3))
a, b

输出结果:

a+b

输出结果:


🌼2. 数据预处理

(1)完成数据预处理的实验代码及练习内容如下:

🌻2.1 读取数据集
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')
 
# 如果没有安装pandas,只需取消对以下行的注释来安装pandas
# !pip install pandas
import pandas as pd
 
data = pd.read_csv(data_file)
print(data)

输出结果:


🌻2.2 处理缺失值
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
print(inputs)

输出结果:

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

输出结果:


🌻2.3 转换为张量格式
import torch
 
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
X, y

输出结果:


🌻2.4 小结

1.pandas软件包是Python中常用的数据分析工具中,pandas可以与张量兼容。

2.用pandas处理缺失的数据时,我们可根据情况选择用插值法和删除法。


🌻2.5 练习

1.创建包含更多行和列的原始数据集。

data1 = pd.read_csv(data_file)
data1

输出结果:

2.删除缺失值最多的列。

nan_numer = data1.isnull().sum(axis=0)
nan_max_id = nan_numer.idxmax()
data1 = data1.drop([nan_max_id], axis=1)
data1

输出结果:

3.将预处理后的数据集转换为张量格式。

data2 = torch.tensor(data1.values)
data2

输出结果:


🌼3 线性代数

🌻3.1 标量
import torch
 
x = torch.tensor(3.0)
y = torch.tensor(2.0)
 
x + y, x * y, x / y, x**y

输出结果:


🌻3.2 向量
x = torch.arange(4)
x

输出结果:

x[3]

输出结果:

len(x)

输出结果:

x.shape

输出结果:


🌻3.3 矩阵
A = torch.arange(20).reshape(5, 4)
A

输出结果:

A.T

输出结果:

B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B

输出结果:

B == B.T

输出结果:


🌻3.4 张量
X = torch.arange(24).reshape(2, 3, 4)
X

输出结果:


🌻3.5 张量算法的基本性质
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone()  # 通过分配新内存,将A的一个副本分配给B
A, A + B

输出结果:

A * B

输出结果:

a = 2
X = torch.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape

输出结果:


🌻3.6 降维
x = torch.arange(4, dtype=torch.float32)
x, x.sum()

输出结果:

A.shape, A.sum()

输出结果:

A_sum_axis0 = A.sum(axis=0)
A_sum_axis0, A_sum_axis0.shape

输出结果:

A_sum_axis1 = A.sum(axis=1)
A_sum_axis1, A_sum_axis1.shape

输出结果:

A.sum(axis=[0, 1])  # 结果和A.sum()相同

输出结果:

A.mean(), A.sum() / A.numel()

输出结果:

A.mean(axis=0), A.sum(axis=0) / A.shape[0]

输出结果:

# 2.3.6.1. 非降维求和
sum_A = A.sum(axis=1, keepdims=True)
sum_A

输出结果:

A / sum_A

输出结果:

A.cumsum(axis=0)

输出结果:


🌻3.7 点积
y = torch.ones(4, dtype = torch.float32)
x, y, torch.dot(x, y)

输出结果:

torch.sum(x * y)

输出结果:


🌻3.8 矩阵-向量积m
A.shape, x.shape, torch.mv(A, x)

输出结果:


🌻3.9 矩阵-矩阵乘法
B = torch.ones(4, 3)
torch.mm(A, B)

输出结果:


🌻3.10 范数
u = torch.tensor([3.0, -4.0])
torch.norm(u)

输出结果:

torch.abs(u).sum()

输出结果:

torch.norm(torch.ones((4, 9)))

输出结果:


🌻3.11 练习

1.证明一个矩阵 的转置的转置是 ,即

2.给出两个矩阵 ,证明“它们转置的和”等于“它们和的转置”,即

3.给定任意方阵 总是对称的吗?为什么?

4.本节中定义了形状((2,3,4))的张量X。len(X)的输出结果是什么?

X = torch.arange(24).reshape(2, 3, 4)
len(x)

输出结果:

5.对于任意形状的张量X,len(X)是否总是对应于X特定轴的长度?这个轴是什么?

对应axis=0这个轴

6.运行A/A.sum(axis=1),看看会发生什么。请分析一下原因?

# 运行运行A/A.sum(axis=1)是会报错的,是广播机制的原因,但是我们可以顺利运行A/A.sum(axis=1, keepdim=True),
# 我们可以来做个实验,实验中我们可以看到沿着不同的轴进行计算会有不同结果且写的方法不同,在axis≠0时一般需要加上keepdim=True
import torch
A = torch.ones((3, 4))
B = A/A.sum(axis=1, keepdim=True)
C = A/A.sum(axis=0)
B, C

输出结果:

7.考虑一个具有形状((2,3,4))的张量,在轴0、1、2上的求和输出是什么形状?

# 形状分别为[3, 4],[2, 4],[2, 3]
import torch
A = torch.ones((2, 3, 4))
B = A.sum(axis=0)
C = A.sum(axis=1)
D = A.sum(axis=2)
B.size(), C.size(), D.size()

输出结果:

8.为linalg.norm函数提供3个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算得到什么?

import torch
A = torch.ones((3,4))
torch.linalg.norm(A)

输出结果:


🌼4 微积分

🌻4.1 导数和微分
# matplotlib inline
import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2l
 
 
def f(x):
    return 3 * x ** 2 - 4 * x
 
def numerical_lim(f, x, h):
    return (f(x + h) - f(x)) / h
 
h = 0.1
for i in range(5):
    print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')
    h *= 0.1

输出结果:


🌻4.2 练习

1.绘制函数(y = f(x) = x^3 - \frac{1}{x})和其在(x = 1)处切线的图像。

import numpy as np
from matplotlib import pyplot as plt
 
def get_function(x):
    return x**3 - 1/x
 
def get_tangent(function, x, point):
    h = 1e-4
    grad = (function(point+h) - function(point)) / h
    return grad*(x-point) + function(point)
 
x = np.arange(0.1,3.0,0.01)
y = get_function(x)
y_tangent = get_tangent(get_function, x=x, point=1)
plt.plot(x,y)
plt.plot(x,y_tangent)
plt.show()

输出结果:

2.求函数 的梯度。

3.函数 的梯度是什么?

4.尝试写出函数 ,其中(x = x(a, b)),(y = y(a, b)),(z = z(a, b))的链式法则。


🌼5 自动微分

🌻5.1 一个简单的例子
import torch
 
x = torch.arange(4.0)
x

输出结果:

x.requires_grad_(True)  # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad  # 默认值是None
 
y = 2 * torch.dot(x, x)
y

输出结果:

y.backward()
x.grad

输出结果:

x.grad == 4 * x

输出结果:

# 在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
x.grad.zero_()
y = x.sum()
y.backward()
x.grad

输出结果:


🌻5.2 非标量变量的反向传播
# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 本例只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad

输出结果:


🌻5.3 分离计算
x.grad.zero_()
y = x * x
u = y.detach()
z = u * x
 
z.sum().backward()

输出结果:

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x

输出结果:


🌻5.4 Python控制流的梯度计算
def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
 
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
 
a.grad == d / a

输出结果:


🌻5.5 小结

深度学习框架可以自动计算导数:我们首先将梯度附加到想要对其计算偏导数的变量上,然后记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。


🌻5.6 练习

1.为什么计算二阶导数比一阶导数的开销要更大?

# 二阶导数是一阶导数的导数,计算二阶导数需要用到一阶导数,所以开销会比一阶导数更大

2.在运行反向传播函数之后,立即再次运行它,看看会发生什么。

# 会报错,因为进行一次backward之后,计算图中的中间变量在计算完后就会被释放,之后无法进行二次backward了,
# 如果想进行第二次backward,可以将retain_graph置为True,实验如下
①retain_graph默认为False
import torch
x = torch.randn((2, 3), requires_grad=True)
y = torch.square(x) - 1
loss = y.mean()
loss.backward()
loss.backward()

输出结果:

# retain_graph置为True
import torch
x = torch.randn((2, 3), requires_grad=True)
y = torch.square(x) - 1
loss = y.mean()
print(x)
loss.backward(retain_graph=True)
print(x.grad)
loss.backward()
print(x.grad)

输出结果:

3.在控制流的例子中,我们计算d关于a的导数,如果将变量a更改为随机向量或矩阵,会发生什么?

# 将变量a更改为随机向量或矩阵,会报错,原因可能是在执行 loss.backward() 时没带参数,
# 即可能默认是与 loss.backward(torch.Tensor(1.0)) 相同的,可以尝试如下的实验实验如下
import torch
def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
a = torch.randn((3), requires_grad=True)
d = f(a)
d.backward()

输出结果:

import torch
a = torch.randn((3), requires_grad=True)
d = a**2
print(a)
d.backward(torch.ones_like(d))
print(a.grad)
 
a = torch.randn((3), requires_grad=True)
d = f(a)
print(a)
d.backward(torch.ones_like(d))
print(a.grad)
 
torch.tensor([ 0.7534, -1.3026, -1.2577], requires_grad=True)
torch.tensor([51200., 51200., 51200.])
 
a = torch.randn((2, 3), requires_grad=True)
d = f(a)
print(a)
d.backward(torch.ones_like(d))
print(a.grad)
 
torch.tensor([[-2.0677, -1.0871,  0.1289],
        [ 0.4897, -0.4152,  0.2643]], requires_grad=True)
torch.tensor([[51200., 51200., 51200.],
        [51200., 51200., 51200.]])

输出结果:

4.重新设计一个求控制流梯度的例子,运行并分析结果。

import torch
def f(x, order):
    if order == 1:
        y = torch.sqrt(x)
    elif order == 2:
        y = torch.square(x)
    else:
        return x
    return y
 
x = torch.randn(size=(), requires_grad=True)
print(x)
y = f(x, order=1)
y.backward()
print(x.grad)
x.grad.zero_() # 清除梯度
y = f(x, order=2)
y.backward()
print(x.grad)

输出结果:

torch.tensor(-1.2684, requires_grad=True)
torch.tensor(-2.5369)

输出结果:

5.使 ,绘制 的图像,其中后者不使用

import numpy as np
from matplotlib import pyplot as plt
 
def get_function(x):
    return np.sin(x)
 
def get_derivative(function, x):
    h = 1e-4
    return (function(x+h) - function(x)) / h
 
x = np.arange(0.01,10.0,0.01)
y = get_function(x)
y_derivative = get_derivative(get_function, x)
plt.plot(x,y)
plt.plot(x,y_derivative)
plt.show()

输出结果:


🌞四、实验心得

通过这次实验,我对深度学习的数据处理知识有了更深入的了解。尽管在安装PyTorch的过程中遇到了一些问题(由于conda默认安装了CPU版本的PyTorch),但在删除numpy库后成功地安装了GPU版本的PyTorch。并且我对以下内容有了更深刻的理解:

1.张量(n维数组)是深度学习存储和操作数据的主要接口。它提供了广泛的功能,包括基本数学运算、广播、索引、切片,还可以实现内存节省和转换其他Python对象。

2.pandas是Python中常用的数据分析工具之一,它与张量兼容,为数据处理提供了便利。

3.在处理缺失数据时,pandas提供了多种方法,根据情况可以选择插值法或删除法进行处理。

4.标量、向量、矩阵和张量是线性代数中的基本数学对象。

5.向量是标量的推广,矩阵是向量的推广。

6.标量、向量、矩阵和张量分别具有零、一、二和任意数量的轴。

7.通过使用sum和mean等操作,可以沿指定的轴降低张量的维度。

8.两个矩阵的按元素乘法被称为Hadamard积,与矩阵乘法不同。

9.在深度学习中,常常使用范数,如L1范数、L2范数和Frobenius范数。

10.微分和积分是微积分的两个分支,其中微分在深度学习的优化问题中得到了广泛应用。

11.导数可以被理解为函数相对于其变量的瞬时变化率,同时是函数曲线的切线斜率。

12.梯度是一个向量,其分量是多变量函数相对于所有变量的偏导数。

13.链式法则可以用于求解复合函数的导数。

14.深度学习框架能够自动计算导数:首先将梯度附加到需要计算偏导数的变量上,然后记录目标值的计算过程,执行反向传播函数,并获得相应的梯度。


目录
相关文章
|
13天前
|
机器学习/深度学习 监控 PyTorch
深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
33 7
|
1月前
|
机器学习/深度学习 算法 PyTorch
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
这篇文章详细介绍了多种用于目标检测任务中的边界框回归损失函数,包括IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU和WIOU,并提供了它们的Pytorch实现代码。
161 1
深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
|
2月前
|
机器学习/深度学习 PyTorch 调度
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
在深度学习中,学习率作为关键超参数对模型收敛速度和性能至关重要。传统方法采用统一学习率,但研究表明为不同层设置差异化学习率能显著提升性能。本文探讨了这一策略的理论基础及PyTorch实现方法,包括模型定义、参数分组、优化器配置及训练流程。通过示例展示了如何为ResNet18设置不同层的学习率,并介绍了渐进式解冻和层适应学习率等高级技巧,帮助研究者更好地优化模型训练。
140 4
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
|
1月前
|
机器学习/深度学习 算法 数据可视化
如果你的PyTorch优化器效果欠佳,试试这4种深度学习中的高级优化技术吧
在深度学习领域,优化器的选择对模型性能至关重要。尽管PyTorch中的标准优化器如SGD、Adam和AdamW被广泛应用,但在某些复杂优化问题中,这些方法未必是最优选择。本文介绍了四种高级优化技术:序列最小二乘规划(SLSQP)、粒子群优化(PSO)、协方差矩阵自适应进化策略(CMA-ES)和模拟退火(SA)。这些方法具备无梯度优化、仅需前向传播及全局优化能力等优点,尤其适合非可微操作和参数数量较少的情况。通过实验对比发现,对于特定问题,非传统优化方法可能比标准梯度下降算法表现更好。文章详细描述了这些优化技术的实现过程及结果分析,并提出了未来的研究方向。
27 1
|
3月前
|
机器学习/深度学习 人工智能 PyTorch
【深度学习】使用PyTorch构建神经网络:深度学习实战指南
PyTorch是一个开源的Python机器学习库,特别专注于深度学习领域。它由Facebook的AI研究团队开发并维护,因其灵活的架构、动态计算图以及在科研和工业界的广泛支持而受到青睐。PyTorch提供了强大的GPU加速能力,使得在处理大规模数据集和复杂模型时效率极高。
192 59
|
2月前
|
机器学习/深度学习 数据挖掘 PyTorch
🎓PyTorch深度学习入门课:编程小白也能玩转的高级数据分析术
踏入深度学习领域,即使是编程新手也能借助PyTorch这一强大工具,轻松解锁高级数据分析。PyTorch以简洁的API、动态计算图及灵活性著称,成为众多学者与工程师的首选。本文将带你从零开始,通过环境搭建、构建基础神经网络到进阶数据分析应用,逐步掌握PyTorch的核心技能。从安装配置到编写简单张量运算,再到实现神经网络模型,最后应用于图像分类等复杂任务,每个环节都配有示例代码,助你快速上手。实践出真知,不断尝试和调试将使你更深入地理解这些概念,开启深度学习之旅。
36 1
|
1月前
|
机器学习/深度学习 数据采集 自然语言处理
【NLP自然语言处理】基于PyTorch深度学习框架构建RNN经典案例:构建人名分类器
【NLP自然语言处理】基于PyTorch深度学习框架构建RNN经典案例:构建人名分类器
|
2月前
|
机器学习/深度学习 人工智能 PyTorch
深度学习领域中pytorch、onnx和ncnn的关系
PyTorch、ONNX 和 NCNN 是深度学习领域中的三个重要工具或框架,它们在模型开发、转换和部署过程中扮演着不同但相互关联的角色。
126 11
|
3月前
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch 与边缘计算:将深度学习模型部署到嵌入式设备
【8月更文第29天】随着物联网技术的发展,越来越多的数据处理任务开始在边缘设备上执行,以减少网络延迟、降低带宽成本并提高隐私保护水平。PyTorch 是一个广泛使用的深度学习框架,它不仅支持高效的模型训练,还提供了多种工具帮助开发者将模型部署到边缘设备。本文将探讨如何将PyTorch模型高效地部署到嵌入式设备上,并通过一个具体的示例来展示整个流程。
528 1
|
3月前
|
机器学习/深度学习 算法 PyTorch
PyTorch Lightning:简化深度学习研究与开发
【8月更文第27天】PyTorch Lightning 是一个用于简化 PyTorch 开发流程的轻量级封装库。它的目标是让研究人员和开发者能够更加专注于算法和模型的设计,而不是被训练循环和各种低级细节所困扰。通过使用 PyTorch Lightning,开发者可以更容易地进行实验、调试和复现结果,从而加速研究与开发的过程。
138 1