记录PyTorch 官方入门教程中的大部分代码和对代码的解释注释
暂时内容包括:张量;数据集和数据读取;转换
参考网站:Tensors — PyTorch Tutorials 1.12.0+cu102 documentation
Datasets & DataLoaders — PyTorch Tutorials 1.12.0+cu102 documentation
一、张量
下文为张量部分官方网站的代码和对代码的粗略解释
import cv2 as cv
import pickle
import pandas as pd
from sklearn.decomposition import dict_learning
import torch
import numpy as np
# 下面是对cifar10数据集的使用
def unpickle(file):
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict
# 一、张量
# 初始化方法
# 1.直接初始化
data = [[1,2],[3,4]]
x_data = torch.tensor(data)
# 2.使用numpy数组初始化
np_data = np.array(data)
x_np = torch.tensor(data)
# 3.使用其他的张量
x_ones = torch.ones_like(x_data)
# 这个like可能是保留了这个张量的各种特征的意思吗?
# ones_like会保留x_data这个张量的类型,其他元素一致初始化为1
# 但是rand_like会以随机数初始化(跑了一遍看来是随机初始化,不过数值都很小
print(f"Ones Tensor:\{x_ones}")
x_rand = torch.rand_like(x_data,dtype = torch.float)
print(f"Rand Tensor:{x_rand}")
# 4.以常量或者随机数和张量尺寸初始化一个张量
shape = (3,3,)
rand_tensor = torch.rand(shape)
print(rand_tensor)
ones_tensor = torch.ones(shape)
print(ones_tensor)
zeros_tensor = torch.zeros(shape)
print(zeros_tensor)
# 张量的特征(尺寸,类型,(加速)方法)
tensor = torch.rand(3,4)
print(tensor.shape)
# 尺寸
print(tensor.dtype)
# 数据类型
print(tensor.device)
# 这个是张量用CPU还是GPU加速
# 对张量的操作
# 转为GPU加速
tensor_operate = torch.rand(3,3)
if torch.cuda.is_available():
tensor_operate = tensor.to("cuda")
print(tensor_operate.device)
# 对张量的切片操作(切片索引)
print(tensor_operate[0])
# 对 行 的操作(可能完整地应该是tensor_operate[0,:],类似的,多维的话对那个维度不操作的话,那个维度就用 : 代替)
tensor_operate[:,0] = 0
print(tensor_operate[:,0])
# 对 列 的操作(比如tensor_operate[:,1]指第二列)
print(tensor_operate[...,-1])
# 对 最后一列 的操作
# torch.cat函数详解(对张量进行拼接)
tensor_cat = torch.cat([tensor_operate,tensor_operate],dim = 1)
# 前面的[A,A]是带连接的张量序列,dim指的是选择的扩维,值在0到len([A,A])之间
# dim设定后,沿着这个维度拼接(对于二维,0代表第一维,是纵着拼接,1是横着拼接)
print(tensor_cat)
# pytorch中的对应元素乘法和矩阵乘法
# 1.矩阵乘法
tensor_mul = torch.ones(1,3)
y1 = tensor_mul@tensor_mul.T
# tensor_mul.T指的是这个张量对象的转置
# @是将这两个对象进行矩阵乘法,与下面用*代表对应元素相乘区分
y2 = tensor_mul.matmul(tensor_mul.T)
print(f"{y1} \n {y2}")
# 2.对应元素乘法
z1 = tensor_mul*tensor_mul.T
z2 = tensor_mul.mul(tensor.T)
print(f"{z1} \n {z2}")
# 将张量中所有的元素的值相加
agg = tensor_mul.sum()
agg_item = agg.item()
# item用于拷贝吗?看起来应该是
print(agg_item,type(agg_item))
# 就地操作(不进行复制,直接将内存中的值改变
tensor_mul.add_(3)
print(f"{tensor_mul}")
# tips:就地操作可以节省一些内存,但在计算导数时可能会出现问题,因为会立即丢失历史记录。因此,不鼓励使用它们。
# 张量可以转变为np的数组
t = torch.ones(5)
n = t.numpy()
print(f"{t} \n {n} ")
# np的add
n = np.add(n,1)
print(n)
二、数据集合数据读取
1.加载数据集和可视化数据集
注意:没有魔法上网将无法自动从其网站下载数据集
import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
from torch.utils.data import dataloader
# 加载数据集
# root 为数据集的路径
# train 为设定其为训练集还是测试集
# dowload 是缺数据会从网上下载
# transform ?
train_data = datasets.FashionMNIST(
root = "D:\\Py workprojects\\6.27\\data_group",
train = True,
download = True,
transform = ToTensor()
)
test_data = datasets.FashionMNIST(
root="D:\\Py workprojects\\6.27\\data_group",
train=False,
download=True,
transform=ToTensor()
)
print((train_data))
# 迭代和可视化数据集
# 这里是对label的0,1,2,3......设定其标签名字
labels_map = {
0: "T-Shirt",
1: "Trouser",
2: "Pullover",
3: "Dress",
4: "Coat",
5: "Sandal",
6: "Shirt",
7: "Sneaker",
8: "Bag",
9: "Ankle Boot",
}
figure = plt.figure(figsize=(8, 8))
cols, rows = 3, 3
# 这一步可以视作横向划三条线,纵向分三条线
for i in range(1, cols * rows + 1):
sample_idx = torch.randint(len(train_data), size=(1,)).item()
# 这里是创建了一个索引(randint是在给定范围数据后随机生成,所以出来的图像是随机的)
# 详情参考randint函数的解释及其函数参数:https://blog.csdn.net/claroja/article/details/108316828?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165673852916781685313951%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165673852916781685313951&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-108316828-null-null.142^v30^control,185^v2^control&utm_term=torch.randint%28%29%E5%87%BD%E6%95%B0&spm=1018.2226.3001.4187
img, label = train_data[sample_idx]
# 分别对应着数据和索引
# print(img.shape)
figure.add_subplot(rows, cols, i)
# plt库的使用,应该就是把这个图像塞进对应分块
plt.title(labels_map[label])
plt.axis("off")
plt.imshow(img.squeeze(), cmap="gray")
# squeeze是降维,这里应该是把第一维降掉了,反正在这里只有一个
plt.show()
# 用数据加载器准备要被训练的数据集
train_dataloader = dataloader.DataLoader(train_data, batch_size = 64, shuffle = True)
test_dataloader = dataloader.DataLoader(test_data, batch_size = 64, shuffle = True)
# 通过数据加载器迭代
train_features, train_labels = next(iter(train_dataloader))
# 这一句重要捏
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
img = train_features[0].squeeze()
# squeeze就是降维地作用,使之能够被描绘出图
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {label}")
print("END")
2.自定义数据集
import os
from cv2 import transform
import pandas as pd
from sklearn import datasets
from torchvision.io import read_image
class MyDataset_test():
# 构造函数(初始化
def __init__(self,annotations_file,img_dir,transform = None,target_transform = None):
self.img_labels = pd.read_csv(annotations_file)
self.img_dir = img_dir
self.transform = transform
self.target_transform = target_transform
# 长度
def __len__(self):
return len(self.img_labels)
# 获取项目
# 函数从给定索引处的数据集中加载并返回一个样本。
# 基于索引,它识别图像在磁盘上的位置,使用将其转换为张量
# 从中的csv数据中检索相应的标签,调用其上的转换函数(如果适用)
# 并在元组中返回张量图像和相应的标签。
def __getitem__(self,idx):
img_path = os.path.join(self.img_dir,self.img_labels.iloc[idx,0])
image = read_image(img_path)
label = self.img_labels.iloc[idx,1]
# iloc[]函数详解:https://blog.csdn.net/Fwuyi/article/details/123127754
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
return image,label
三、转换
import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda
# 变换
# 数据并不总是以训练机器学习算法所需的最终形式所出现,所以要对其进行transform
ds = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
# 在这里transform用于对数据集的特征值的修改
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
# target_transform = Lambda(lambda y: torch.zeros(
# 10, dtype=torch.float).scatter_(dim=0, index=torch.tensor(y), value=1))
# 在这里target_transform用于对数据集标签的修改
# tips:lambda指的是匿名函数 参考:https://www.csdn.net/tags/OtDaYg1sMDk1ODctYmxvZwO0O0OO0O0O.html
)