d2lzh_pytorch 模块
import random
import torch
import matplotlib_inline
from matplotlib import pyplot as plt
import torchvision
import torchvision.transforms as transforms
import torchvision.datasets
import sys
from collections import OrderedDict
# ---------------------------------------------------------------------------------------------
# 图表展示
def use_svg_display():
# 用矢量图表示
matplotlib_inline.backend_inline.set_matplotlib_formats('svg')
def set_figsize(figsize=(3.5, 2.5)):
use_svg_display()
# 设置图的尺寸
plt.rcParams['figure.figsize'] = figsize
# ---------------------------------------------------------------------------------------------
# 读取数据
# 获取总的样本数量,然后打乱顺序,用batch-size获取每一部分索引去索引对应样本中的数据,使用yield返回
'''
函数详解:
torch.linspace(start, end, steps, dtype) → Tensor 从start开始到end结束,生成steps个数据点,数据类型为dtype
torch.index_select(input, dim, index) 索引张量中的子集
**
input:需要进行索引操作的输入张量
dim:张量维度 0,1
index:索引号,是张量类型
**
yield: 使用yield的函数返回迭代器对象,每次使用时会保存变量信息,使用next()或者使用for可以循环访问迭代器中的内容
'''
def data_iter(batch_size, features, labels):
num_examples = len(features) # features nxm
indices = list(range(num_examples)) # 借助range生成索引序列
random.shuffle(indices) # 把list列表中的值打乱顺序
for i in range(0, num_examples, batch_size):
j = torch.LongTensor(indices[i:min(i + batch_size, num_examples)]) # 这里的i是对标乱序表中的下标索引号
yield features.index_select(0, j), labels.index_select(0, j) # 0维度,有1000个样本,j就是他们的下标
# ---------------------------------------------------------------------------------------------
# 定义模型
def linreg(X, w, b):
return torch.mm(X, w) + b # 传进来的参数和样本特征都符合矩阵形式 w,b都是列矩阵 X:1000x2 w:2x1 b:1x1
# 这里使用了广播
# ---------------------------------------------------------------------------------------------
# 定义损失函数
def square_loss(y_hat, y):
# 保证y_hat和y同型,pytorch中的MSELoss没有除以2的操作
return (y_hat - y.view(y_hat.size())) ** 2 / 2 # 这里是多个样本的预测值和实际值之间的差值,返回nxm大小的张量
# 这里的得到的也是一个小批量的样本的损失张量
# ---------------------------------------------------------------------------------------------
# 定义优化算法
# 这里使用的是sgd算法,使用小批量梯度和(参数求导后的和:梯度会自动累加,不用自己加和梯度)除以小批量样本个数来求小批量平均值
def sgd(params, lr, batch_size):
for param in params:
param.data -= lr * param.grad / batch_size # 这里更改param时使用的是param.data,这样就不会影响反向梯度
# 这里的param指的是w1,w2,b
# 这里应该是小批量中的每个loss运行完,得到小批量每个样本的梯度然后pytorch自动进行了梯度累加,之后一个小批量得到一个累加和后的
# 梯度w1,w2,b
# ---------------------------------------------------------------------------------------------
'''
FashionMNIST 数据集
'''
# ----------------------------------------------------------将数值标签转换成文本标签
def get_fashion_mnist_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat', 'sandal',
'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
# -----------------------------------------------------在一行里画出多张图像和对应标签的函数
def show_fashion_mnist(images, labels):
use_svg_display()
# 这里的_表示忽略(不使用)的变量
_, figs = plt.subplots(1, len(images), figsize=(12, 12)) # 设置一行 len(images)个数量,每个figsize大小的画布
# figs 返回的是一个画布对象,这个对象有imshow,set_tittle,axes_get_xasis().set_visible,
# axes.get_yaxis().set_visible()这几种函数调用方式,用来给figs里面添加图像
for f, img, lbl, in zip(figs, images, labels): # 这个画布对象循环往里面添加图像信息
f.imshow(img.view((28, 28)).numpy()) # img承接图像信息,将tensor转化为numpy 这里参数为数组元素
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.savefig("路径")
# ----------------------------------------------------------------获取并读取FashionMNIST数据集函数,返回小批量train,test
def load_data_fashion_mnist(batch_size):
mnist_train = torchvision.datasets.FashionMNIST(root='路径',
train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='路径',
train=False, download=True, transform=transforms.ToTensor())
'''
上面的mnist_train,mnist_test都是torch.utils.data.Dataset的子类,所以可以使用len()获取数据集的大小
训练集和测试集中的每个类别的图像数分别是6000,1000,两个数据集分别有10个类别
'''
# mnist是torch.utils.data.dataset的子类,因此可以将其传入torch.utils.data.DataLoader来创建一个DataLoader实例来读取数据
# 在实践中,数据读取一般是训练的性能瓶颈,特别是模型较简单或者计算硬件性能比较高的时候
# DataLoader一个很有用的功能就是允许多进程来加速读取 使用num_works来设置4个进程读取数据
if sys.platform.startswith('win'):
num_workers = 0
else:
num_workers = 4
train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True,
num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False,
num_workers=num_workers)
return train_iter, test_iter
# -------------------------------------------------------------查看mnist前10个图像和标签
def check_mnist():
mnist_train = torchvision.datasets.FashionMNIST(root='路径',
train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='路径',
train=False, download=True, transform=transforms.ToTensor())
X, y = [], []
for i in range(10):
X.append(mnist_train[i][0]) # 循环获取图像张量矩阵
y.append(mnist_train[i][1]) # 循环获取图像对应数值标签
show_fashion_mnist(X, get_fashion_mnist_labels(y))
# feature, label = mnist_train[0]
# print(feature.shape, label) CxHxW
# feature对应高和宽均为28像素的图像,因为使用了transforms.ToTensor(),所以每个像素的数值对应于【0.0,1.0】的32位浮点数
# C 是通道数,RGB,灰色图像,通道数为1,H,W分别为高,宽
# mnist_train[0] 是一个元祖,它包含两部分,图像数据结构和图像标签值,图像的数据结构是1x28x28结构,是一个浮点数矩阵,代表一个图像
# -------------------------------------------------------------------------评价模型net在数据集data_iter上的准确率
def evaluate_accuracy(test_iter, net):
acc_sum, n, x = 0.0, 0, 0.0
for X, y in test_iter: # 返回一个批量的数据元组迭代对象
if isinstance(net, torch.nn.Module):
net.eval() # 评估模式,这会关闭dropout
acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() # 将net模型的预测y与标签y进行了准确率比较
net.train() # 改回训练模式
else: # 自定义模型
if ('is_training' in net.__code__.co_varnames): # 就是说如果net函数的参数中如果有is_training这个参数
# 将is_training 设置为False
acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item()
else:
acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
n += y.shape[0] # 累加获得样本个数
x = acc_sum / n
return x
# -------------------------------------------------------------------------训练模型函数
def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None, optimizer=None):
for epochs in range(num_epochs): # 循环周期
train_l_sum, train_acc_sum, n = 0.0, 0.0, 0 # 预先定义 训练损失,训练精度,批量个数
for X, y in train_iter: # 批量更新
y_hat = net(X)
l = loss(y_hat, y).sum() # 损失计算
# 梯度清零
if optimizer is not None:
optimizer.zero_grad()
elif params is not None and params[0].grad is not None: # 权重存在并且权重的梯度存在
for param in params:
param.grad.data.zero_()
l.backward() # 反向传播
# 梯度更新操作
if optimizer is None:
sgd(params, lr, batch_size) # 调用sgd进行梯度下降操作
else:
optimizer.step() # softmax回归的简洁实现将要用到
train_l_sum += l.item() # 损失累加
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item() # (y_hat.argmax(dim=1) == y)
# 取出y_hat每一行中最大的概率索引和y比较,结果为tensor,元素值为0/1
n += y.shape[0] # 计算一个批量中标签的个数
test_acc = evaluate_accuracy(test_iter, net) # 一个循环之后进行测试集的准确度计算
print(f'epoch %d,loss %.4f,train_acc %.3f,test_acc %.3f'
% (epochs + 1, train_l_sum / n, train_acc_sum / n, test_acc))
# x = torch.tensor([[0.1, 0.4, 0.2], [1, 0.06, 0.5]])
# print((x.argmax(dim=1)==torch.tensor([[1,1]])).float())
# -------------------------------------------------------------------------x的形状转换功能函数
class FlattenLayer(torch.nn.Module):
def __init__(self):
super(FlattenLayer, self).__init__() # 初始化函数,自动调用forward函数
def forward(self, x): # x shape: (batch,*,*,....)
return x.view(x.shape[0], -1) # 转换成(batch_size,特征数)形状
# 这样就方便定义模型
net = torch.nn.Sequential(
# FlattenLayer()
# torch.nn.Linear(num_inputs,num_outputs)
OrderedDict([
('flatten', FlattenLayer()),
('linear', torch.nn.Linear(2, 3))
])
)
'''
-------------------------------------------------------------------作图函数
'''
def semilogy(x_vals, y_vals, xlabel, ylabel, label, x2_vals=None, y2_vals=None, legend=None):
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.semilogy(x_vals, y_vals) # y轴使用对数尺度
if x2_vals and y2_vals:
plt.semilogy(x2_vals, y2_vals, linestyle=':')
plt.legend(legend)
plt.savefig("路径" + label + "模拟.png")
文章来源地址https://www.toymoban.com/news/detail-810750.html
文章来源:https://www.toymoban.com/news/detail-810750.html
到了这里,关于李沐深度学习-d2lzh_pytorch模块实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!