pytorch基础知识(个人学习记录分享)

一.基础知识

1.1两大法宝函数

pytorch就相当于是package,也就是一个工具箱的作用

下面这两个函数是学习时的一个很好的辅助函数

1.dir()函数:

作用:提供打开操作

2.help()函数;

作用:函数说明书

import torch
# print(torch.cuda.is_available())
print(dir(torch))
print(dir(torch.cuda))
print(dir(torch.cuda.is_available()))
#1.下面的图
#2.['Any', 'BFloat16Storage', 'BFloat16Tensor', 'BoolStorage', 'BoolTensor', 'ByteStorage', 'ByteTensor', 'CUDAGraph', 'CUDAPluggableAllocator', 'CharStorage', 'CharTensor', 'ComplexDoubleStorage', 'ComplexFloatStorage', 'CudaError', 'DeferredCudaCallError', 'Device', 'DoubleStorage', 'DoubleTensor', 'Event', 'ExternalStream', 'FloatStorage', 'FloatTensor', 'HalfStorage', 'HalfTensor', 'IntStorage', 'IntTensor', 'List', 'LongStorage', 'LongTensor', 'Optional', 'OutOfMemoryError', 'ShortStorage', 'ShortTensor', 'Stream', 'StreamContext', 'Tuple', 'Union', '_CudaBase', '_CudaDeviceProperties', '_DeviceGuard', '_HAS_PYNVML', '_LazySeedTracker', '_PYNVML_ERR', '_WrappedTritonKernel', '__all__', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_check_capability', '_check_cubins', '_cudart', '_device', '_device_count_nvml', '_device_t', '_dummy_type', '_exchange_device', '_get_device', '_get_device_index', '_get_generator', '_get_nvml_device_index', '_get_pynvml_handler', '_get_rng_state_offset', '_initialization_lock', '_initialized', '_is_compiled', '_is_in_bad_fork', '_lazy_call', '_lazy_init', '_lazy_new', '_lazy_seed_tracker', '_maybe_exchange_device', '_memory_viz', '_nvml_based_avail', '_parse_visible_devices', '_queued_calls', '_raw_device_count_nvml', '_raw_device_uuid_nvml', '_register_triton_kernels', '_set_rng_state_offset', '_set_stream_by_id', '_sleep', '_tls', '_transform_uuid_to_ordinals', '_utils', '_warn_typed_storage_removal', 'amp', 'caching_allocator_alloc', 'caching_allocator_delete', 'can_device_access_peer', 'cast', 'change_current_allocator', 'check_error', 'classproperty', 'clock_rate', 'contextlib', 'cudaStatus', 'cudart', 'current_blas_handle', 'current_device', 'current_stream', 'default_generators', 'default_stream', 'device', 'device_count', 'device_of', 'empty_cache', 'get_allocator_backend', 'get_arch_list', 'get_device_capability', 'get_device_name', 'get_device_properties', 'get_gencode_flags', 'get_rng_state', 'get_rng_state_all', 'get_sync_debug_mode', 'graph', 'graph_pool_handle', 'graphs', 'has_half', 'has_magma', 'importlib', 'init', 'initial_seed', 'ipc_collect', 'is_available', 'is_bf16_supported', 'is_current_stream_capturing', 'is_initialized', 'jiterator', 'list_gpu_processes', 'lru_cache', 'make_graphed_callables', 'manual_seed', 'manual_seed_all', 'max_memory_allocated', 'max_memory_cached', 'max_memory_reserved', 'mem_get_info', 'memory', 'memory_allocated', 'memory_cached', 'memory_reserved', 'memory_snapshot', 'memory_stats', 'memory_stats_as_nested_dict', 'memory_summary', 'memory_usage', 'nccl', 'nvtx', 'os', 'power_draw', 'profiler', 'random', 'reset_accumulated_memory_stats', 'reset_max_memory_allocated', 'reset_max_memory_cached', 'reset_peak_memory_stats', 'seed', 'seed_all', 'set_device', 'set_per_process_memory_fraction', 'set_rng_state', 'set_rng_state_all', 'set_stream', 'set_sync_debug_mode', 'sparse', 'stream', 'streams', 'synchronize', 'sys', 'temperature', 'threading', 'torch', 'traceback', 'utilization', 'warnings']
#3.['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

当出现__def__这个情况的时候说明不在是分割区了,已经是确确实实的最下层函数了

help(torch.cuda.is_available)

#Help on function is_available in module torch.cuda:
#is_available() -> bool
#    Return a bool indicating if CUDA is currently available.

1.2不同的操作系统的不同运行方式

1.3.其他工具

二.基础数据类型(tensor)和相关知识

2.1介绍:

张量(tensor)表示一个数值组成的数组,这个数组可能有多个维度,它是pytorch中最基本的数据结构。

2.2有关张量的操作:

2.2.1导入torch库

① 虽然库为PyTorch库,但应该导入torch,而不是pytorch

import torch
x = torch.arange(12) # 初始化一个0-11的张量
 

#tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])

2.2.2访问张量的形状

① 可以通过张量的shape属性来访问张量的形状和张量中元素的总数。

import torch
x = torch.arange(12) # 初始化一个0-11的张量
x.shape # 张量的形状
print(a.size())

#torch.Size([12])

注意:这里的shape和size的结果虽然一样,都是打印出矩阵的形状,但是他的用法是不同的,一个是方法,一个是属性

import torch
x = torch.arange(12) # 初始化一个0-11的张量
x.numel() # 张量中元素的总数

#12

2.2.3 改变张量形状

① 要改变一个张量的形状而不改变元素数量和元素值,可以调用reshape函数。

import torch
x = torch.arange(12) # 初始化一个0-11的张量
x = x.reshape(3,4) # 一维张量改为3行四列的张量
x
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])

2.2.4 创建全0、全1张量

① 使用全0、全1、其他常量或者从特定分布中随即采样的数字。

import torch
y = torch.zeros((2,3,4))
print(y)
tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]],

        [[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]])

import torch
y = torch.ones((2,3,4))
print(y)
tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]],

        [[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]]])

2.2.5 创建特定值张量

① 通过提供包含数值的Python列表(或嵌套列表)来为所需张量中的每个元素赋予确定值。

import torch
y = torch.tensor([[2,1,4,3],[1,2,3,4],[4,3,2,1]]) # 二维tensor
z = torch.tensor([[[2,1,4,3],[1,2,3,4],[4,3,2,1]]]) # 三维tensor
print(y)
print(z)
tensor([[2, 1, 4, 3],
        [1, 2, 3, 4],
        [4, 3, 2, 1]])
tensor([[[2, 1, 4, 3],
         [1, 2, 3, 4],
         [4, 3, 2, 1]]])

import torch
y = torch.tensor([[2,1,4,3],[1,2,3,4],[4,3,2,1]]) # 二维tensor
z = torch.tensor([[[2,1,4,3],[1,2,3,4],[4,3,2,1]]]) # 三维tensor
print(y.shape)
print(z.shape)
torch.Size([3, 4])
torch.Size([1, 3, 4])

除此之外,我们还可以指定numpy的方法来创建矩阵

2.2.6 张量运算操作

① 常见的标准算术运算符(+、-、*、/、和 **)都可以被升级为按元素运算。

import torch
x = torch.tensor([1.0,2,4,8]) 
y = torch.tensor([2,2,2,2]) 
print(x+y)
print(x-y)
print(x*y)
print(x/y)
print(x**y) # **运算符是求幂运算
tensor([ 3.,  4.,  6., 10.])
tensor([-1.,  0.,  2.,  6.])
tensor([ 2.,  4.,  8., 16.])
tensor([0.5000, 1.0000, 2.0000, 4.0000])
tensor([ 1.,  4., 16., 64.])

② 对每个元素应用更多的计算。

import torch
x = torch.tensor([1.0,2,4,8]) 
x = torch.exp(x) # e的x次方
print(x)
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])

2.2.7 张量合并操作

⑧ 可以把多个张量结合在一起。

使用cat方法进行拼接,dim为0就是上下拼接,dim为1就是左右拼接

import torch
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]])
m = torch.cat((x,y),dim=0) # 按行合并起来
n = torch.cat((x,y),dim=1) # 按列合并起来
print(m) 
print(n)
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [ 2.,  1.,  4.,  3.],
        [ 1.,  2.,  3.,  4.],
        [ 4.,  3.,  2.,  1.]])
tensor([[ 0.,  1.,  2.,  3.,  2.,  1.,  4.,  3.],
        [ 4.,  5.,  6.,  7.,  1.,  2.,  3.,  4.],
        [ 8.,  9., 10., 11.,  4.,  3.,  2.,  1.]])

2.2.8 张量逻辑运算

① 通过逻辑运算符构建二元张量。

import torch
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]])
print(x) 
print(y)
print(x == y) # 对应元素相等为 True,否则为 False
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]])
tensor([[2., 1., 4., 3.],
        [1., 2., 3., 4.],
        [4., 3., 2., 1.]])
tensor([[False,  True, False,  True],
        [False, False, False, False],
        [False, False, False, False]])

2.2.9 张量累加运算

① 对张量中所有元素进行求和会产生一个只有一个元素的张量。

sum方法进行求和

import torch
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
print(x.sum())
tensor(66.)

2.2.10 张量广播运算

① 即使形状不同,仍然可以通过调用广播机制(broadcasting mechanism) 来执行按元素操作。

就是说当矩阵的形式不符合相加的要求时会自动补齐,并进行相加。

import torch
a = torch.arange(3).reshape((3,1))
b = torch.arange(2).reshape((1,2))
print(a)
print(b)
print(a+b) # a会复制出一个3*2的矩阵,b复制出一个3*2的矩阵,然后再相加,会得到一个3*2矩阵
tensor([[0],
        [1],
        [2]])
tensor([[0, 1]])
tensor([[0, 1],
        [1, 2],
        [2, 3]])

2.2.11 张量访问运算

① 可以用[-1]选择最后一个元素,可以用[1:3]选择第二个和第三个元素。

也就是切片操作了

import torch
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
print(x[-1])    
print(x[1:3])
tensor([ 8.,  9., 10., 11.])
tensor([[ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]])

2.2.12 张量元素改写

import torch
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
x[1,2] = 9    
print(x)
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  9.,  7.],
        [ 8.,  9., 10., 11.]])

② 为多个元素赋值相同的值,只需要索引所有元素,然后为它们赋值。

import torch
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
x[0:2,:] = 12    
print(x)
tensor([[12., 12., 12., 12.],
        [12., 12., 12., 12.],
        [ 8.,  9., 10., 11.]])

2.2.13 *张量内存变化

① 运行一些操作可能会导致为新结果分配内容。

import torch
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]])
before = id(y) 
y = x + y
print(id(y) == before) # 运行操作后,赋值后的y的id和原来的id不一样
False

import torch
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]])
z = torch.zeros_like(y) # z 的数据类型、尺寸和y一样,里面的元素全为0
print("id(z):",id(z))    
z[:] = x + y
print("id(z):",id(z))
id(z): 2712056119192
id(z): 2712056119192

② 如果在后续计算中没有重复使用X,即内存不会过多复制,也可以使用X[:] = X + Y 或 X += Y 来减少操作的内存开销。

import torch
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]])
before = id(x) 
x += y
print(id(x) == before)
True

2.2.14 张量转Numpy

① 张量转 NumPy。

import torch
x = torch.arange(12,dtype=torch.float32).reshape((3,4))
A = x.numpy()
B = torch.tensor(A)
print(type(A),type(B))
<class 'numpy.ndarray'> <class 'torch.Tensor'>

② 将大小为1的张量转为 Python 标量。

import torch
a = torch.tensor([3.5])
print(a)
print(a.item())
print(float(a))
print(int(a))
tensor([3.5000])
3.5
3.5
3

2.3.数据

Pytorch主要通过Dataset和DataLoader进行构建数据管道

Dataset提供一种方式去获取每个数据及其对应的label,告诉我们总共有多少个数据。

Dataloader为后面的网络提供不同的数据形式,它将一批一批数据进行一个打包

什么是label?

在PyTorch中,label通常指的是用于监督学习的目标或真实值。在训练一个模型时,我们通常提供输入数据(如图像、文本等)和对应的目标值(即label),模型会尝试学习从输入数据中预测出正确的目标值。

例如,在图像分类任务中,label可能是每个图像的类别编号。如果我们有一个包含猫和狗的图像数据集,label可能是一个整数,其中0代表猫,1代表狗。在训练过程中,模型会接收一张图像作为输入,并尝试预测其对应的label(即类别)。然后,我们使用一个损失函数(如交叉熵损失)来计算模型预测的label与真实label之间的差异,并通过反向传播算法来更新模型的参数,以减小这种差异。

简而言之,label在PyTorch中就是用于监督学习的真实目标值,帮助模型在训练过程中学习和改进。

2.3.1Dataset and DataLoader

Dataset

一个数据集抽象类,所有自定义的Dataset都需要继承它,并且重写__getitem__()或__get_sample__()这个类方法

DataLoader

一个可迭代的数据装载器。在训练的时候,每一个for循环迭代,就从DataLoader中获取一个batch_sieze大小的数据。

也就是所谓的数据集和数据处理器

2.3.2数据的读取和预处理

2.3.2.1Dataloader的基本介绍
DataLoader(
 dataset,
 batch_size=1,
 shuffle=False,
 sampler=None,
 batch_sampler=None,
 num_workers=0,
 collate_fn=None,
 pin_memory=False,
 drop_last=False,
 timeout=0,
 worker_init_fn=None,
 multiprocessing_context=None,
)

在实践中,主要修改的参数以下标为橙色

num_workers是用来指定多进程读取数据时的进程数目的参数。在使用多进程读取数据时,系统会启动多个进程来并行读取数据,加快数据读取的速度。通过设置num_workers参数,我们可以控制启动的进程数目,从而对系统资源的利用进行优化,避免资源的浪费或者过载。通常情况下,根据实际硬件配置和任务需求来合理设置num_workers参数。

2.3.2.2数据读取的主要流程

1. 从DataLoader开始

2. 进入DataLoaderIter,判断单线程还是多线程

3. 进入Sampler进行采样,获得一批一批的索引,这些索引告诉我们需要读取哪些数据、

4. 进入DatasetFetcher,依据索引读取数据

5. Dataset告诉我们数据的地址

6. 自定义的Dataset中会重写__getietm__方法,针对不同的数据来进行定制化的数据读取

7. 到这里就获取的数据的Text和Label

8. 进入collate_fn将之前获取的个体数据进行组合成batch

9. 一个一个batch组成Batch Data

接下来举一个具体的例子:

from torch.utils.data import DataLoader
from torch.utils.data.dataset import TensorDataset
 
# 自构建数据集
dataset = TensorDataset(torch.arange(1, 40))
dl = DataLoader(dataset,
                batch_size=10,  		#批次的大小
                shuffle=True,			#每个epoch是否乱序
                num_workers=1,			#使用多进程读取数据,设置进程数
                drop_last=True)			#是否丢弃最后以恶搞样品数不足batch——size批次数据
# 数据输出
for batch in dl:
    print(batch)

2.3.3数据的预处理

而数据预处理主要是重写Dataset和DataLoader中的方法,具体的代码实现在后面介绍

2.4神经网络工具箱torch.nn

2.4.1介绍:

torch.autograd库虽然实现了自动求导与梯度反向传播,但如果我们要完成一个模型的训练,仍需要手写参数的自动更新、训练过程的控制等,还是不够便利。为此,PyTorch进一步提供了集成度更高的模块化接口torch.nn,该接口构建于Autograd之上,提供了网络模组、优化器和初始化策略等一系列功能。

概念:torch.nn是神经网路工具箱,该工具箱建立于Autograd(主要有自动求导和梯度反向传播功能),提供了网络搭建的模组,优化器等一系列功能。

三:神经网络具体的学习内容在里面,先大致了解

2.4.2相关知识点:

2.4.2.1nn.Module类

nn.Module是PyTorch提供的神经网络类,并在类中实现了网络各层的定义及前向计算与反向传播机制。在实际使用时,如果想要实现某个神经网络,只需继承nn.Module,在初始化中定义模型结构与参数,在函数forward()中编写网络前向过程即可。

1.nn.Parameter函数

2.forward()函数与反向传播

3.多个Module的嵌套

4.nn.Module与nn.functional库

5.nn.Sequential()模块

2.4.3如何让搭建神经网络模型

搭建网络流程

1 数据读取

2 定义模型

3 定义损失函数和优化器

4 模型训练

5 获取训练结果

1.数据集

diabetes.csv


import numpy as np
import torch
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader


# Prepare the dataset
class DiabetesDateset(Dataset):
    # 加载数据集
    def __init__(self, filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32, encoding='utf-8')
        self.len = xy.shape[0]  # shape[0]是矩阵的行数,shape[1]是矩阵的列数
        self.x_data = torch.from_numpy(xy[:, :-1])
        self.y_data = torch.from_numpy(xy[:, [-1]])

    # 获取数据索引
    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    # 获得数据总量
    def __len__(self):
        return self.len


dataset = DiabetesDateset('diabetes.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)  # num_workers为多线程


# Define the model
class FNNModel(torch.nn.Module):
    def __init__(self):
        super(FNNModel, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)  # 输入数据的特征有8个,也就是有8个维度,随后将其降维到6维
        self.linear2 = torch.nn.Linear(6, 4)  # 6维降到4维
        self.linear3 = torch.nn.Linear(4, 2)  # 4维降到2维
        self.linear4 = torch.nn.Linear(2, 1)  # 2w维降到1维
        self.sigmoid = torch.nn.Sigmoid()  # 可以视其为网络的一层,而不是简单的函数使用

    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        x = self.sigmoid(self.linear4(x))
        return x


model = FNNModel()

# Define the criterion and optimizer
criterion = torch.nn.BCELoss(reduction='mean')  # 返回损失的平均值
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

epoch_list = []
loss_list = []

# Training
if __name__ == '__main__':
    for epoch in range(100):
        # i是一个epoch中第几次迭代,一共756条数据,每个mini_batch为32,所以一个epoch需要迭代23次
        # data获取的数据为(x,y)
        loss_one_epoch = 0
        for i, data in enumerate(train_loader, 0):
            inputs, labels = data
            y_pred = model(inputs)
            loss = criterion(y_pred, labels)
            loss_one_epoch += loss.item()

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        loss_list.append(loss_one_epoch / 23)
        epoch_list.append(epoch)
        print('Epoch[{}/{}],loss:{:.6f}'.format(epoch + 1, 100, loss_one_epoch / 23))

    # Drawing
    plt.plot(epoch_list, loss_list)
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.show()

2.5Tensorboard

2.5.1.概念介绍和主要使用

2.5.1.1概念 :

TensorBoard 是一组用于数据可视化的工具。它包含在流行的开源机器学习库 Tensorflow 中。

TensorBoard 的主要功能包括:

1.可视化模型的网络架构

2.跟踪模型指标,如损失和准确性等

3.检查机器学习工作流程中权重、偏差和其他组件的直方图

4.显示非表格数据,包括图像、文本和音频

5.将高维嵌入投影到低维空间

2.5.1.2主要API

Pytorch使用Tensorboard主要用到了三个API:

SummaryWriter:这个用来创建一个log文件,TensorBoard面板查看时,也是需要选择查看那个log文件。

add_something: 向log文件里面增添数据。例如可以通过add_scalar增添折线图数据,add_image可以增添图片。

close:当训练结束后,我们可以通过close方法结束log写入。

2.5.2.tensorboard的启动

在这里我们可能看不懂里面的内容,具体的例子讲解在5.Transforms的讲解中,有对具体的步骤进行讲解,建议结合一起看

2.5.2.1创建和写入和读取
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs") # 创建一个logs文件夹,writer写的文件都在该文件夹下
#writer.add_image()
for i in range(100):
    writer.add_scalar("y=2x",2*i,i)
writer.close()

首先呢1.我们先把这个代码运行一次,他会创建一个日志,并且写入数据,如下图

开始读取

2.之后呢,复制logs文件的绝对路径

再去我们创建的虚拟环境输入 tensorboard --logdir=路径

然后我们复制这个网址在浏览器里打开即可,会出现下图所示界面

2.5.2.2读图片
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np

img_path1 = "Data/FirstTypeData/train/ants/0013035.jpg" 
img_PIL1 = Image.open(img_path1)
img_array1 = np.array(img_PIL1)

img_path2 = "Data/SecondTypeData/train/bees_image/17209602_fe5a5a746f.jpg" 
img_PIL2 = Image.open(img_path2)
img_array2 = np.array(img_PIL2)

writer = SummaryWriter("logs") 
writer.add_image("test",img_array1,1,dataformats="HWC") # 1 表示该图片在第1步
writer.add_image("test",img_array2,2,dataformats="HWC") # 2 表示该图片在第2步                   
writer.close()

小土堆的照片

📎hymenoptera_data.zip

操作原理是一样的,很简单,需要注意的就是路径问题,需要我们在前面加个r,这样可以避免绝对路径的问题

2.6Transforms

2.6.1概念和用途

概念:transform是torchvision下的一个.py文件,这个python文件中定义了很多的类和方法,主要实现对图片进行一些变换操作

用途:

Transforms当成工具箱的话,里面的class就是不同的工具。例如像totensor、resize这些工具。

Transforms拿一些特定格式的图片,经过Transforms里面的工具,获得我们想要的结果。

2.6.2.ToTensor类

    """Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor. This transform does not support torchscript.
#可以看到其实就将PIL Image、numpy.ndarray类型的图片转换为tensor类型
#PIL针对的是Python自带的Image进行open操作;numpy.ndarray针对的是OpenCV的imread操作

    Converts a PIL Image or numpy.ndarray (H x W x C) in the range
    [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0]
    if the PIL Image belongs to one of the modes (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)
    or if the numpy.ndarray has dtype = np.uint8

    In the other cases, tensors are returned without scaling.

    .. note::
        Because the input image is scaled to [0.0, 1.0], this transformation should not be used when
        transforming target image masks. See the `references`_ for implementing the transforms for image masks.

    .. _references: https://github.com/pytorch/vision/tree/main/references/segmentation
    """

transforms.ToTensor()函数的作用:是将原始的PILImage格式或者numpy.array格式的数据格式化为可被pytorch快速处理的张量类型。

输入模式为(L、LA、P、I、F、RGB、YCbCr、RGBA、CMYK、1)的PIL Image 或 numpy.ndarray (形状为H x W x C)数据范围是[0, 255] 到一个 Torch.FloatTensor,其形状 (C x H x W) 在 [0.0, 1.0] 范围内。

2.6.3.如何使用

2.6.3.1使用
from torchvision import transforms
from PIL import Image

img_path = "Data/FirstTypeData/val/bees/10870992_eebeeb3a12.jpg"
img = Image.open(img_path)  

tensor_trans = transforms.ToTensor()  # 创建 transforms.ToTensor类 的实例化对象
tensor_img = tensor_trans(img)  # 调用 transforms.ToTensor类 的__call__的魔术方法   
print(tensor_img)
tensor([[[0.5725, 0.5725, 0.5725,  ..., 0.5686, 0.5725, 0.5765],
         [0.5725, 0.5725, 0.5725,  ..., 0.5686, 0.5725, 0.5765],
         [0.5686, 0.5686, 0.5725,  ..., 0.5686, 0.5725, 0.5765],
         ...,
         [0.5490, 0.5647, 0.5725,  ..., 0.6314, 0.6235, 0.6118],
         [0.5608, 0.5765, 0.5843,  ..., 0.5961, 0.5843, 0.5765],
         [0.5725, 0.5843, 0.5922,  ..., 0.5647, 0.5529, 0.5490]],

        [[0.4471, 0.4471, 0.4471,  ..., 0.4235, 0.4275, 0.4314],
         [0.4471, 0.4471, 0.4471,  ..., 0.4235, 0.4275, 0.4314],
         [0.4431, 0.4431, 0.4471,  ..., 0.4235, 0.4275, 0.4314],
         ...,
         [0.4000, 0.4157, 0.4235,  ..., 0.4706, 0.4627, 0.4510],
         [0.4118, 0.4275, 0.4353,  ..., 0.4431, 0.4314, 0.4235],
         [0.4235, 0.4353, 0.4431,  ..., 0.4118, 0.4000, 0.3961]],

        [[0.2471, 0.2471, 0.2471,  ..., 0.2588, 0.2627, 0.2667],
         [0.2471, 0.2471, 0.2471,  ..., 0.2588, 0.2627, 0.2667],
         [0.2431, 0.2431, 0.2471,  ..., 0.2588, 0.2627, 0.2667],
         ...,
         [0.2157, 0.2314, 0.2392,  ..., 0.2510, 0.2431, 0.2314],
         [0.2275, 0.2431, 0.2510,  ..., 0.2196, 0.2078, 0.2000],
         [0.2392, 0.2510, 0.2588,  ..., 0.1961, 0.1843, 0.1804]]])

2.6.3.2为什么需要tensor数据类型

1.Tensor有一些属性,比如反向传播、梯度等属性,它包装了神经网络需要的一些属性。

2. 在 Anaconda 终端里面,激活py3.6.3环境,再输入 tensorboard --logdir=C:\Users\wangy\Desktop\03CV\logs 命令,将网址赋值浏览器的网址栏,回车,即可查看tensorboard显示日志情况。

3.输入网址可得Tensorboard界面。

2.6.3.2.1opencv

这个地方用到了opencv,在c++上也是有的,这里的使用就是为了告诉我们如何读numpy,从而使用add和ToTensor,opencv的下载: pip install opencv-python

from torchvision import transforms
from PIL import Image

# python的用法 tensor数据类型
# 通过transforms.ToTensor去看这两个问题(作用就是转化为tensor的基本类型)
# transform 该如何使用
# tensor为什么需要

img_path = r"D:\pycharm\textbackage\hymenoptera_data\hymenoptera_data\train\ants\0013035.jpg"
img = Image.open(img_path)
print(img)
tensor_trans = transforms.ToTensor()#
tensor_img = tensor_trans(img)
print(tensor_img)

import cv2
cv_img=cv2.imread(img_path)
print(cv_img)
C:\Anaconda\envs\pytorch\python.exe D:\pycharm\textbackage\tensoroard.py 
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=768x512 at 0x2561E11AF10>
    
tensor([[[0.3137, 0.3137, 0.3137,  ..., 0.3176, 0.3098, 0.2980],
         [0.3176, 0.3176, 0.3176,  ..., 0.3176, 0.3098, 0.2980],
         [0.3216, 0.3216, 0.3216,  ..., 0.3137, 0.3098, 0.3020],
         ...,
         [0.3412, 0.3412, 0.3373,  ..., 0.1725, 0.3725, 0.3529],
         [0.3412, 0.3412, 0.3373,  ..., 0.3294, 0.3529, 0.3294],
         [0.3412, 0.3412, 0.3373,  ..., 0.3098, 0.3059, 0.3294]],

        [[0.5922, 0.5922, 0.5922,  ..., 0.5961, 0.5882, 0.5765],
         [0.5961, 0.5961, 0.5961,  ..., 0.5961, 0.5882, 0.5765],
         [0.6000, 0.6000, 0.6000,  ..., 0.5922, 0.5882, 0.5804],
         ...,
         [0.6275, 0.6275, 0.6235,  ..., 0.3608, 0.6196, 0.6157],
         [0.6275, 0.6275, 0.6235,  ..., 0.5765, 0.6275, 0.5961],
         [0.6275, 0.6275, 0.6235,  ..., 0.6275, 0.6235, 0.6314]],

        [[0.9137, 0.9137, 0.9137,  ..., 0.9176, 0.9098, 0.8980],
         [0.9176, 0.9176, 0.9176,  ..., 0.9176, 0.9098, 0.8980],
         [0.9216, 0.9216, 0.9216,  ..., 0.9137, 0.9098, 0.9020],
         ...,
         [0.9294, 0.9294, 0.9255,  ..., 0.5529, 0.9216, 0.8941],
         [0.9294, 0.9294, 0.9255,  ..., 0.8863, 1.0000, 0.9137],
         [0.9294, 0.9294, 0.9255,  ..., 0.9490, 0.9804, 0.9137]]])
    
[[[233 151  80]
  [233 151  80]
  [233 151  80]
  ...
  [234 152  81]
  [232 150  79]
  [229 147  76]]

 [[234 152  81]
  [234 152  81]
  [234 152  81]
  ...
  [234 152  81]
  [232 150  79]
  [229 147  76]]

 [[235 153  82]
  [235 153  82]
  [235 153  82]
  ...
  [233 151  80]
  [232 150  79]
  [230 148  77]]

 ...

 [[237 160  87]
  [237 160  87]
  [236 159  86]
  ...
  [141  92  44]
  [235 158  95]
  [228 157  90]]

 [[237 160  87]
  [237 160  87]
  [236 159  86]
  ...
  [226 147  84]
  [255 160  90]
  [233 152  84]]

 [[237 160  87]
  [237 160  87]
  [236 159  86]
  ...
  [242 160  79]
  [250 159  78]
  [233 161  84]]]

2.6.3.3使用的讲解:
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image


# python的用法 tensor数据类型
# 通过transforms.ToTensor去看这两个问题(作用就是转化为tensor的基本类型)
# transform 该如何使用
# tensor为什么需要

img_path = r"D:\pycharm\textbackage\hymenoptera_data\hymenoptera_data\train\ants\0013035.jpg"
img = Image.open(img_path)
print(img)

writer = SummaryWriter("logs")

tensor_trans = transforms.ToTensor()#
tensor_img = tensor_trans(img)
print(tensor_img)

writer.add_image("Tensor_img",tensor_img)

writer.close()

接下来就做一下个人的理解:

首先:img_path就是获取照片路径

img = Image.open(img_path)

就是为了打开照片,具体的内容可以查看3.5PIL(中的2)

writer = SummaryWriter("logs")

这一步的作用是创建一个用于记录和可视化训练过程中损失和其他指标的SummaryWriter对象。这个对象将会把记录写入到指定的日志路径下,方便用户后续分析和可视化训练过程中的数据。

tensor_trans = transforms.ToTensor()#

tensor_img = tensor_trans(img)

这两步的作用是将原始的图像数据转换为张量数据。transforms.ToTensor()将图像转换为张量,而tensor_trans(img)对应于实际的转换操作,将原始的图像img转换为张量tensor_img。张量是PyTorch中用于表示数据和进行计算的基本数据类型

writer.add_image("Tensor_img",tensor_img)

writer.close()

这两步的作用是将名为"Tensor_img"的图像添加到writer中,并在完成添加操作后关闭writer。这样可以将图像与其他数据一起保存在writer中,以便进行后续处理和分析。

接下的步骤就和tensoroard的操作一样,就是在终端打开,如然后查看网址就可以看见这图片了

复制logs文件的绝对路径

再去我们创建的虚拟环境输入 tensorboard --logdir=路径

2.6.4.常见的transforms

2.6.4.1概述

from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image

img_path = r"D:\pycharm\textbackage\photo\13C81A0B43F894A38CDD21B766708E92.jpg"
img = Image.open(img_path)
print(img)

writer = SummaryWriter("logs")

trans_totensor = transforms.ToTensor()  #就是相当于化简操作img_tensor = transforms.ToTensor(img)
img_tensor = trans_totensor(img)  # 这边属于是一个类型转化

writer.add_image("ToTenser",img_tensor)
writer.close()

2.6.4.2Normalize

作用讲解:(以下面的代码为例)

这个方法的作用是对输入的图像进行标准化处理。具体来说,它将每个通道的像素值减去0.5,然后再除以0.5,以确保图像的像素值位于[-1, 1]的范围内。这种标准化方法有助于训练深度学习模型,因为它可以加速收敛并提高模型的准确性。

也就是需要输入一个均值和标准差

from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image

img_path = r"D:\pycharm\textbackage\photo\13C81A0B43F894A38CDD21B766708E92.jpg"
img = Image.open(img_path)
print(img)

writer = SummaryWriter("logs")

trans_totensor = transforms.ToTensor()  # 就是相当于化简操作img_tensor = transforms.ToTensor(img)
img_tensor = trans_totensor(img)  # 这边属于是一个类型转化
writer.add_image("ToTenser", img_tensor)

# Normalize

print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])

writer.close()

tensor(0.6353)
tensor(0.2706)

做到了对照片像素的一个修改

2.6.4.3Resize

作用:进行一个等比例的缩放

from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image

img_path = r"D:\pycharm\textbackage\photo\13C81A0B43F894A38CDD21B766708E92.jpg"
img = Image.open(img_path)
print(img)

writer = SummaryWriter("logs")

trans_totensor = transforms.ToTensor()  # 就是相当于化简操作img_tensor = transforms.ToTensor(img)
img_tensor = trans_totensor(img)  # 这边属于是一个类型转化
writer.add_image("ToTenser", img_tensor)

# Normalize
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([1, 2, 3], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm,2)

#Resize
print(img.size)#原本照片的尺度和规格,也就是长宽
trans_resize = transforms.Resize((512,512))#一个已经限制好的class
img_size = trans_resize(img)
#img PIL  ---> Resize  ----->img_size PIL

img_resize = trans_totensor(img_size)
#img_size PIL --> totensor ---> img_resize tensor
print(img_size)
writer.add_image("Resize", img_resize,0)



writer.close()

这里的照片和上述的照片比起来他的框架发生了改变

2.6.4.4Compose

这里需要注意的是

PIL-->PIL-->tensor

不可以调换顺序,否则会报错,

接下来介绍作用:

torchvision.transforms是pytorch中的图像预处理包。一般用Compose把多个步骤整合到一起

例如上述的操作,将两个操作结合,先弄比例再做张量转化

2.6.4.5Random

作用:随机裁剪一个大小的照片位置

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值