AI学习笔记(02)--数据集下载
这次我打算写一个 AI 模型的 Hello World,手写数字识别MNIST
。大体学习一下 AI 模式的制作方法
一个 AI 模型的制作流程,大体分为分为五个步骤
- 数据准备: 下载加载数据集,并对这些数据集进行预处理。并且划分为训练集和测试集
- 编写模型: 根据具体的问题选择合适的模型(例如神经网络、决策树、支持向量机等)然后根据具体的问题编写训练的代码
- 训练模型:更具编写好的代码对模型进行训练。迭代训练数据集,将输入传递给模型,计算损失,然后反向传播和更新参数
- 评估模型: 使用测试集或验证集评估模型性能,计算准确率等指标。
- 保存和加载模型: 保存训练好的模型,已方便后续使用
数据准备
PyTorch 提供了数据集下载的模块,能够使用现成的数据集。而不用我们自己辛苦的对数据集进行收集与打标
比如我们这次开发训练的手写数字识别MNIST
,就用到PyTorch中torchvision.datasets模块,这个模块用于提供常见的计算机视觉数据集。它包含了许多经典的数据集,例如MNIST、CIFAR10、CIFAR100、ImageNet等
我们这次就使用其中的MNIST
数据集,模块的主要传参如下:
torchvision.datasets.MNIST(
root: str,
train: bool = True,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
download: bool = False,
)
- root:数据集存储的根目录,默认是当前工作目录。
- train:True 表示加载训练集,False 表示加载测试集。
- transform:可选参数,这个用与参数用于对数据进行转换,如常见的图像缩放、裁剪、旋转、归一化等操作
- target_transform:可选参数,用于对目标(标签)进行转换。在某些情况下,需要对标签进行特定的处理。通常使用定义一个函数来实现这种转换操作
- download:True表示如果数据集未下载,它将被下载并存储在 root 指定的目录中;False表示如果数据集未下载,将不会自动下载,而是会尝试使用已存在的数据集。如果不存在,将抛出一个 RuntimeError
有这个模块,我们就可以写一个数据集的下载的的方法
import torchvision
print("数据集下载")
torchvision.datasets.MNIST(
root="./dataset", train=True, download=True
)
运行代码。就能看到数据集自动就下载好了
其中t10k-images-idx3-ubyte
和 t10k-labels-idx1-ubyte
是训练集
train-images-idx3-ubyte
和 train-labels-idx1-ubyte
是验证集
这四个数据集都是以二进制格式存储的,其中包含了图像数据和对应的标签
如果你和我一样好奇数据集里的的内容,也可以使用下面的代码导出成图片
import os
import struct
import numpy as np
from PIL import Image
def read_idx3_data(filename):
with open(filename, 'rb') as f:
zero, data_type, dims = struct.unpack('>HBB', f.read(4))
shape = tuple(struct.unpack('>I', f.read(4))[0] for d in range(dims))
return np.frombuffer(f.read(), dtype=np.uint8).reshape(shape)
def save_images(data, output_dir):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i, image_data in enumerate(data):
image = Image.fromarray(image_data)
image.save(os.path.join(output_dir, f'image_{i}.png'))
# 读取训练图像数据
train_images_data = read_idx3_data('dataset/MNIST/raw/train-images-idx3-ubyte')
# 保存图像
save_images(train_images_data, 'mnist_images')
print("图像已成功导出为图片。")
但在实际使用中。我们需要将图片格式转换成张量,并且标准化
datasets.MNIST(root="./dataset", train=True, download=True, # 下载训练集
transform=transforms.Compose([
transforms.ToTensor(), # 转换为张量
transforms.Normalize((0.1307,), (0.3081,)) # 标准化
])),
什么是张量
张量(Tensor)是深度学习中的基本数据结构。它可以被看作是一个多维数组。以下是不同维度的张量的示例:
- 标量(0维张量):单个数字,例如 (5)。
- 向量(1维张量):一维数组,例如 ([1, 2, 3])。
- 矩阵(2维张量):二维数组,例如:([[1,2],[3,4]])。
- 高维张量(3维及以上):例如,一个图像可以表示为一个3维张量(颜色,宽度,高度)
以此类推如视频就是4 维张量(帧数,颜色,宽度,高度)
在深度学习中,张量是用于存储输入数据、权重、偏置和输出的主要数据结构。
转换为张量的原因:
- 深度学习框架(如PyTorch)需要处理的数据格式是张量。
- 张量允许高效的数学运算(如矩阵乘法),适合在GPU上进行加速计算。
什么是标准化
标准化(Normalization)是数据预处理中的一种常用技术,特别是在机器学习和深度学习中。它的主要目的是将数据转换为一个统一的尺度,以提高模型的训练效率和性能。标准化通常涉及将数据的特征缩放到特定的范围或使其具有零均值和单位方差。
说白就是让训练素材尺寸统一,更加方便 AI训练。
transforms.Normalize((0.1307,), (0.3081,) // 均值,标准差
那这个的均值和标准差怎么得到的呢?
可以通过下面的代码获取到均值和标准差
# 导入所需的库
import torch # PyTorch库,用于深度学习
from torchvision import datasets # torchvision库中的datasets模块,用于加载常见数据集
from torchvision.transforms import ToTensor # 用于将图像转换为Tensor的转换器
# 加载MNIST数据集
# root: 数据集存储的路径
# train: 如果为True,则加载训练数据集;如果为False,则加载测试数据集
# download: 如果数据集不存在,则下载数据集
# transform: 对图像应用的转换,这里将图像转换为Tensor格式
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=ToTensor())
# 创建数据加载器,用于按批次加载数据
# batch_size: 每个批次的样本数量
# shuffle: 如果为True,则在每个epoch开始时打乱数据
data_loader = torch.utils.data.DataLoader(dataset, batch_size=64, shuffle=True)
# 初始化均值、标准差和总图像计数
mean = 0.0 # 用于累加所有批次的均值
std = 0.0 # 用于累加所有批次的标准差
total_images_count = 0 # 记录总图像数量
# 遍历数据加载器中的每个批次
for images, _ in data_loader:
# 获取当前批次的大小(图像数量)
batch_count = images.size(0) # images的形状为 (batch_size, channels, height, width)
# 将每张图像从 (channels, height, width) 展平为 (channels, -1),
# 这样我们就可以按通道计算均值和标准差
images = images.view(batch_count, images.size(1), -1) # 将图像展平为 (batch_size, channels, height*width)
# print(images)
# 计算当前批次的均值
# images.mean(dim=2) 计算每个通道的均值,结果形状为 (batch_size, channels)
# sum(dim=0) 将所有批次的均值相加,得到每个通道的总均值
mean += images.mean(dim=2).sum(dim=0) # 累加均值
# 计算当前批次的标准差
# images.std(dim=2) 计算每个通道的标准差,结果形状为 (batch_size, channels)
# sum(dim=0) 将所有批次的标准差相加,得到每个通道的总标准差
std += images.std(dim=2).sum(dim=0) # 累加标准差
# 更新总图像数量
total_images_count += batch_count # 累加当前批次的图像数量
# 计算总体均值和标准差
mean /= total_images_count # 求总均值
std /= total_images_count # 求总标准差
# 打印结果
print('均值:', mean) # 输出每个通道的均值
print('标准差:', std) # 输出每个通道的标准差
我们通过torch.utils.data.DataLoader加载我们下载好的数据集,批量数设置为 64,且读取时打乱顺序
然后我们通过for循环遍历这个数据加载器,获取到那images 这个张量
images 这个张量是个四维张量 ,里面的维度分别为 [batch_size(当前图像的数量),channels(是通道数。看是灰度图像 1 还是彩色图像 3),图片长度,图片宽度]
通过images.view 将图片转为三维张量。分别为 [batch_size(当前图像的数量),channels(是通道数。看是灰度图像 1 还是彩色图像 3),图片面积]
images.mean(dim=2).sum(dim=0) 这个是计算这个批次的图片的灰度平均值
images.std(dim=2).sum(dim=0) 这个则是获取标准差[1]
通过这段代码获取到平均值为 0.1307
,标准差为 0.3015
修改train=True
得到测试数据集的平均值为 0.1325
,标准差为 0.3039
这样我们就能标准化数据集了
PS
在离散数学中,标准差是一个重要的统计量,用于衡量数据集的离散程度或变异性。标准差越大,表示数据点之间的差异越大;标准差越小,表示数据点更接近于均值。
标准差的定义
- 标准差 是衡量数据集离散程度的一个重要指标。
- 在离散数学和统计学中,标准差的计算和理解有助于分析和解释数据的变异性。