Datawhale AI 夏令营-Task2笔记

从baseline入门深度学习

实践代码的运行和分析

import torch
import numpy as np

代码作用:
导入相关库
torch 库
torch 是一个由 Facebook 开发的开源深度学习框架,称为 PyTorch。它提供了强大的张量计算功能和深度学习模型的构建与训练工具。PyTorch 被广泛应用于学术研究和工业界的机器学习任务。

主要功能:
张量计算:与 NumPy 类似的多维数组操作,但可以在 GPU 上加速。
自动微分:支持动态计算图,可自动计算导数,方便构建和训练神经网络。
神经网络模块:提供了丰富的神经网络层、损失函数和优化器等模块,便于快速搭建深度学习模型。
模型训练与评估:提供了训练循环、模型评估和持久化的工具。
numpy 库
numpy 是 Python 语言的一个库,支持大规模的多维数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。它是科学计算中最基本的包之一,也是许多其他科学计算库的基础。

主要功能:
多维数组对象:高效的数组操作和切片功能。
广播:无需显式复制数据即可执行算术运算。
线性代数:提供丰富的线性代数函数,如矩阵乘法、特征值计算等。
随机数生成:提供了丰富的随机数生成函数。

# 直接从数据创建
data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)
x_data.shape

代码作用:
这里定义了一个二维的 Python 列表 data,包含两个子列表,每个子列表有两个元素。使用 torch.tensor(data) 将 Python 列表 data 转换为一个 PyTorch 张量 x_data。PyTorch 张量是一个多维数组,可以在 CPU 或 GPU 上进行高效计算。通过x_data.shape 返回张量 x_data 的形状。这将输出一个 torch.Size 对象,显示张量的维度。
解释说明:

  1. 数据类型:torch.tensor 可以接受多种类型的数据,如 Python 列表、NumPy 数组等。默认情况下,创建的张量数据类型为
    torch.float32。
  2. 自动推断类型:当输入数据为整数时,PyTorch 会自动将其转换为 torch.int64 类型。
  3. 设备设置:默认情况下,张量会被创建在 CPU 上。如果需要在 GPU 上创建,可以使用 device 参数。
# 从Numpy创建
np_array = np.array(data)
x_data = torch.from_numpy(np_array)
x_data.shape

代码作用:
这里定义了一个二维的 Python 列表 data,然后使用 np.array(data) 将其转换为一个 NumPy 数组 np_array。使用 torch.from_numpy(np_array) 将 NumPy 数组 np_array 转换为一个 PyTorch 张量 x_data。这种方法将共享 NumPy 数组的内存,因此对一个数组的修改将反映在另一个数组中。x_data.shape 返回张量 x_data 的形状。这将输出一个 torch.Size 对象,显示张量的维度。
解释说明:

  1. 数据类型:torch.from_numpy 会保持 NumPy 数组的原始数据类型。在这个例子中,NumPy 数组的类型是
    int32,因此创建的 PyTorch 张量也是 int32 类型。
  2. 共享内存:通过 torch.from_numpy 创建的张量与原始 NumPy 数组共享内存。这意味着对 NumPy 数组的修改会反映在
    PyTorch 张量中,反之亦然。
x_ones = torch.ones_like(x_data)  # retains the properties of x_data
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float)  # overrides the datatype of x_data
print(f"Random Tensor: \n {x_rand} \n")

代码作用:
torch.ones_like(x_data) 创建了一个与 x_data 形状和数据类型相同的全 1 张量 x_ones。这个函数保留了 x_data 的所有属性(例如形状和数据类型)。torch.rand_like(x_data, dtype=torch.float) 创建了一个与 x_data 形状相同的随机数张量 x_rand,但数据类型被覆盖为 torch.float。torch.rand_like 函数生成的随机数在 [0, 1) 之间均匀分布。
解释说明:
torch.ones_like:
功能:创建一个与给定张量 x_data 具有相同形状和数据类型的全 1 张量。
使用场景:需要生成与现有张量相同形状但内容为全 1 的张量时。
torch.rand_like:
功能:创建一个与给定张量 x_data 具有相同形状的随机数张量,数据类型可以通过 dtype 参数指定。
使用场景:需要生成与现有张量相同形状但内容为随机数的张量时,可以指定所需的数据类型。

tensor = torch.rand(3, 4)

print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
# We move our tensor to the GPU if available
if torch.cuda.is_available():
    tensor = tensor.to('cuda')

代码作用:
使用 torch.rand(3, 4) 创建一个形状为 (3, 4) 的随机数张量 tensor。生成的随机数在 [0, 1) 之间均匀分布。检查是否有可用的 CUDA 设备(即 GPU)。如果有,将张量 tensor 移动到 GPU。
解释说明:
torch.rand:
功能:生成形状为 (3, 4) 的张量,张量中的值为 [0, 1) 之间的随机数。
使用场景:需要初始化张量为随机数时。
tensor.shape:
功能:返回张量的形状。
使用场景:需要了解张量的维度时。
tensor.dtype:
功能:返回张量的数据类型。
使用场景:需要确认张量的数据类型时。
tensor.device:
功能:返回张量存储的设备(CPU 或 GPU)。
使用场景:需要确认张量存储位置时。
torch.cuda.is_available:
功能:检查是否有可用的 CUDA 设备(即 GPU)。
使用场景:需要判断是否可以使用 GPU 进行加速计算时。
tensor.to(‘cuda’):
功能:将张量从 CPU 移动到 GPU。
使用场景:需要利用 GPU 加速张量计算时。

# x = torch.ones(2, 2, requires_grad=True)
x = torch.tensor([[1, 2], [3, 4]], dtype=float, requires_grad=True)
print(x)

y = x + 2
print(y)
print(y.grad_fn)  # y就多了一个AddBackward

z = y * y * 3
out = z.mean()

print(z)  # z多了MulBackward
print(out)  # out多了MeanBackward

# out = 0.25 ((x+2) * (x+2) * 3)
out.backward()
# 0.25 * 3 * 2 * (x+2)
print(x.grad)  # out=0.25*Σ3(x+2)^2

代码作用:
创建张量并设置 requires_grad=True,这行代码创建了一个 2×2 的张量 x,并设置 requires_grad=True,表示需要对该张量进行梯度计算。
y = x + 2:对 x 进行加法操作,生成新张量 y。由于 x 需要梯度计算,y 也将记录计算图中的操作。
y.grad_fn:返回 y 的梯度函数,这里是 AddBackward,表示 y 是通过加法操作得到的。
z = y * y * 3:对 y 进行元素级乘法并乘以 3,生成新张量 z。由于 y 需要梯度计算,z 也将记录计算图中的操作。
out = z.mean():计算 z 的均值,生成标量张量 out。由于 z 需要梯度计算,out 也将记录计算图中的操作。
z.grad_fn:返回 z 的梯度函数,这里是 MulBackward,表示 z 是通过乘法操作得到的。
out.grad_fn:返回 out 的梯度函数,这里是 MeanBackward,表示 out 是通过均值操作得到的。
计算 out 相对于 x 的梯度。由于 out 是一个标量,这里的 backward() 方法会自动计算 out 对 x 的梯度。
解释说明:

  1. requires_grad=True:表示这个张量需要计算梯度,在反向传播时会保留梯度信息。
  2. 计算图:每个张量操作都会记录在计算图中,以便于反向传播计算梯度。 grad_fn:记录了创建该张量的函数,用于反向传播时追踪计算。
  3. 反向传播:out.backward() 会计算 out 相对于所有叶子节点(如 x)的梯度,并保存在这些张量的 grad 属性中。
import matplotlib.pyplot as plt

from IPython.display import set_matplotlib_formats
set_matplotlib_formats('svg')

# 画图就展示到notebook
%matplotlib inline
# numpy 数值计算、矩阵运算,CPU计算
# tensor 数值计算、矩阵运算 CPU 或 GPU计算

# 准备数据
x = np.linspace(0, 10, 100)
y = -3 * x + 4 + np.random.randint(-2, 2, size=100)
# y = -3x + 4
# y = wx + b

plt.scatter(x, y)
# 需要计算得到的参数
w = torch.ones(1, requires_grad=True)
b = torch.ones(1, requires_grad=True)

# 数据
x_tensor = torch.from_numpy(x)
y_tensor = torch.from_numpy(y)

# y = wx + b
def mse(label, pred):
    diff = label - pred
    return torch.sqrt((diff ** 2).mean())


pred = x_tensor * w + b
loss = mse(y_tensor, pred)
loss  # 误差
# 执行20次参数更新

for _ in range(20):
    # 重新定义一下,梯度清空
    w = w.clone().detach().requires_grad_(True)
    b = b.clone().detach().requires_grad_(True)

    # 正向传播
    pred = x_tensor * w + b
    loss = mse(y_tensor, pred)
    print(loss)

    loss.backward()
    w = w - w.grad * 0.05  # 学习率
    b = b - b.grad * 0.05

    # 正向传播、计算损失、计算梯度、参数更新
    # 多步的训练,随机梯度下降
    
pred = x_tensor * w + b
plt.scatter(x, y)
plt.plot(x, pred.data.numpy())
plt.legend(['y=-3x+4', 'Network'])

代码解释:
导入必要的库并设置Matplotlib的显示格式。
x = np.linspace(0, 10, 100):生成 0 到 10 之间的 100 个等间距点。
y = -3 * x + 4 + np.random.randint(-2, 2, size=100):生成目标值 y,并加入随机噪声。
绘制 x 和 y 的散点图。
初始化参数 w 和 b,并设置 requires_grad=True 以便计算梯度。
将 NumPy 数组 x 和 y 转换为 PyTorch 张量 x_tensor 和 y_tensor。
定义均方误差(MSE)损失函数,用于计算预测值和实际值之间的差异。
pred = x_tensor * w + b:计算预测值。
loss = mse(y_tensor, pred):计算初始损失。
循环 20 次进行参数更新。
w 和 b 的梯度在每次迭代开始时被清空,并重新定义,以防止累积之前的梯度。
计算预测值和损失,进行反向传播计算梯度。
使用梯度下降法更新参数 w 和 b,学习率设为 0.05。
再次绘制 x 和 y 的散点图。
绘制最终训练得到的线性模型预测值 pred。
解释说明:
通过 20 次迭代的梯度下降,参数 w 和 b 被优化,使得预测值 pred 尽量拟合原始数据点。最终绘制的图形显示了拟合的直线与原始数据点的对比。

!wget https://mirror.coggle.club/image/tyler-swift.jpg
!wget https://mirror.coggle.club/imagenet_classes.txt
from PIL import Image
image = Image.open('tyler-swift.jpg')
image
import timm
from PIL import Image

model = timm.create_model('resnet18', pretrained=True)

transform = timm.data.create_transform(
    **timm.data.resolve_data_config(model.pretrained_cfg)
)

image_tensor = transform(image)
output = model(image_tensor.unsqueeze(0))
probabilities = torch.nn.functional.softmax(output[0], dim=0)
values, indices = torch.topk(probabilities, 5)

IMAGENET_1k_LABELS = open('imagenet_classes.txt').readlines()
[{'label': IMAGENET_1k_LABELS[idx], 'value': val.item()} for val, idx in zip(values, indices)]
torch.topk(probabilities, 50)

代码解释:
使用 wget 命令下载图像文件和 ImageNet 标签文件。
使用 PIL 库加载图像文件。
使用 timm 库加载预训练的 ResNet18 模型。timm 是一个用于加载各种预训练模型的库。
使用 timm 提供的 create_transform 函数,根据模型的预训练配置对图像进行预处理。
transform(image):对图像进行预处理,将其转换为模型所需的张量格式。
image_tensor.unsqueeze(0):增加一个批次维度,使其符合模型输入格式。
output = model(image_tensor.unsqueeze(0)):将图像输入模型,得到输出。
torch.nn.functional.softmax(output[0], dim=0):对模型输出应用 softmax 函数,得到每个类别的概率。
torch.topk(probabilities, 5):获取概率最高的前五个类别的索引和值。
open(‘imagenet_classes.txt’).readlines():读取 ImageNet 标签文件。
列表推导式:根据索引从标签文件中获取对应的标签,并与概率值一起输出。
解释说明:
wget:下载图像和标签文件。
PIL:用于加载和处理图像。
timm:加载预训练模型和创建图像预处理管道。
torch.nn.functional.softmax:计算类别概率。
torch.topk:获取概率最高的前五个类别。

本文旨在通过对于Task2的运行代码进行逐行分析进行理解学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值