IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 快速上手pytorch -> 正文阅读

[人工智能]快速上手pytorch

本文根据小土堆教程撰写。

蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA?密码: 5suq

这篇博客将以我自己的理解结合例子进行说明,示例中均有详细注释,建议自己尝试一下。

目录

0、环境说明

1、加载数据

2、tensorboard可视化工具

3、transform对图像操作

4、DataSet加载数据集

5、dataloader加载数据

6、卷积操作

7、卷积层

8、池化层

9、非线性激活层

10、线性层(全连接层)

11、简单的神经网络

12、损失函数

13、反向传播


0、环境说明

torch1.1+torchvision0.11.1+cudatoolkit10.0.130,其他的提示缺啥就下载啥

1、加载数据

? ? 首先是加载数据,这里是使用了一个类Dataset(数据集),在使用中会和下面的代码有一些出入,要视情况而定。

? ? 比如下面这个代码读取的数据集,其类名直接作为文件夹的名字,然后文件夹的内部就是一系列图片,所以root_dir指向数据集,label_dir说明类别,由root_dir+label_dir链接地址就能找到此类的图片,这就是MyData类所做的事情。

? ? main函数做的是将两个类图片分别读取然后合并得到总的数据集。

#加载数据#
import torch
from torch.utils.data import Dataset
from PIL import Image
import os

class MyData(Dataset):
    #初始化#
    def __init__(self,root_dir,label_dir):
        #加self表示类变量#
        self.root_dir=root_dir#基础路径(根目录)#
        self.label_dir=label_dir#指向基础路径下的目标文件地址#label_dir是图片文件夹名称即图片标签
        self.path=os.path.join(root_dir,label_dir)#将两个文件路径进行连接#
        self.img_path=os.listdir(self.path)#读取path指向的文件目录下每一个图片名称#

    #返回第idx张图片及其标签#
    def __getitem__(self, idx):
        img_name=self.img_path[idx]#获得第idx张图片名称#
        img_item_path=os.path.join(self.path,img_name)#此路径指向该图片#
        img=Image.open(img_item_path)#加载图片#
        #↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
        #label_dir是图片文件夹名称即图片标签
        label=self.label_dir
        return label,img#label是img的类别#

    #返回图片列表长度即训练集/测试集大小#
    def __len__(self):
        return len(self.img_path)#图片数量#
'''
#单张图片的读取
img_path = "pct/2959730355_416a18c63c.jpg"  # 图片路径并非图片文件夹“#
img = Image.open(img_path)
img.show()#显示图片#

'''

#利用Dataset读取
root_dir=""#基础路径(根目录)#
ants_dir="ant"
ants_dataset=MyData(root_dir,ants_dir)
label_0,img_0=ants_dataset[0]#第0号图片及其标签
#img_0.show()
print(label_0)
bees_dir="bee"
bees_dataset=MyData(root_dir,bees_dir)
label_0,img_0=bees_dataset[0]#第0号图片及其标签
#img_0.show()
print(label_0)
#将两个数据集进行合并#
all_dataset=ants_dataset+bees_dataset
print(len(all_dataset))

2、tensorboard可视化工具

? ? tensorboard是一个可视化的工具,重点要了解他怎么写和怎么读,这些都写在下面的代码里了,在使用的时候要记得在最后执行close

#tensorboard#
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np

writer=SummaryWriter("logs")#把数据写入logs文件夹内

image_path="./ant/308196310_1db5ffa01b.jpg"
img=Image.open(image_path)#此时img类型为JpegImageFile
img_array=np.array(img)#将img转化为numpy型
writer.add_image("test",img_array,1,dataformats="HWC")

'''
add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'):
tag:标题
img_tensor:图像(类型:torch.Tensor, numpy.array, or string/blobname)
global_step:步数
dataformats:图像类型HWC表示高度、宽度、通道(可以利用img_array.shape进行查看)
生成文件后放在前面在类中定义的logs文件夹中

阅读生成的文件:
控制台输入
tensorboard --logdir="logs" --port=6007
#logdir指定目录
#port指定接入端口
#点击TensorBoard 2.4.0 at http://localhost:6006/ (Press CTRL+C to quit)中的“http://localhost:6006/”

如果是在服务器下Tensorboard然后在本地查看:
可见https://zhuanlan.zhihu.com/p/231790992亲测有用
'''

for i in range(100):
    writer.add_scalar("y=x",i,i)
''' 
add_scalar(self, tag, scalar_value, global_step=None, walltime=None):
tag:图表标题
scalar_value:数值,与global_step对应,y轴
global_step:步数,训练多少步时对应数值是多少,x轴
生成文件后放在前面在类中定义的logs文件夹中

阅读生成的文件:
终端输入
tensorboard --logdir="logs" --port=6006
#logdir指定目录
#port指定接入端口
#点击TensorBoard 2.4.0 at http://localhost:6006/ (Press CTRL+C to quit)中的“http://localhost:6006/”
'''
writer.close()

3、transform对图像操作

? ? transform有一系列对图像的操作,比如类型转化、大小变化、裁剪等。

#transform对图像进行操作

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

#↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
img_path="pct/2959730355_416a18c63c.jpg"
img=Image.open(img_path)#打开图片为PIL数据类型
print(img)

"""
利用transform.ToTensor将PIL或numpy数据类型的img转化为Tensor数据类型的图片
tensor:包装了神经网络所需要的参数如梯度、反向传播等
"""
tensor_trans=transforms.ToTensor()
tensor_img=tensor_trans(img)#执行__call__将img转化为tensor类型
print(tensor_img)

#"""test2中所用到的SummaryWriter类"""
#writer=SummaryWriter("log")
#writer.add_image("Tensor_img",tensor_img)
#writer.close()

"""
Totensor的使用
Normalize归一化
resize调整大小
RandomCrop随机裁剪
"""

"""
Normalize(均值,方差)
output[channel] = (input[channel] - mean[channel]) / std[channel]
"""
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])#(output-0.5)/0.5
img_norm=trans_norm(tensor_img)

"""
resize调整大小
参数为大小(序列或整数):所需的输出大小。
如果大小是这样的序列(h,w),输出大小将与此匹配。如果大小是整数,图像的较小边缘将与此数字匹配。
"""
trans_resize=transforms.Resize((512,512))#调整到512X512的PIL类型img
img_resize=trans_resize(img)#这里输入为PIL,输出为PIL
print(img_resize)

trans_resize_2=transforms.Resize(1000)
#串联两个操作即先执行trans_resize_2再执行tensor_trans
trans_compose=transforms.Compose([trans_resize_2,tensor_trans])
img_resize_2=trans_compose(img)

"""
RandomCrop输入一个PIL类型的img
"""
trans_random=transforms.RandomCrop(20)#裁剪为512X512的,若指定(n,m)则裁剪大小为nXm
trans_compose_2=transforms.Compose([trans_random,tensor_trans])
for i in range(10):
    img_crop=trans_compose_2(img)


4、DataSet加载数据集

? ? 注意这一节与第一节是不同的,这里包含有MNIST、FakeData、COCO、LSUN、ImageFolder、DatasetFolder、ImageNet、CIFAR等一些常用的数据集,可以直接下载使用。

"""
使用官方提供的数据集
CIFAR10:6万32X32的图片,5万训练,1万测试
"""
import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transformsz.Compose([
    torchvision.transforms.ToTensor()
])

#下载CIFAR10到root路径下,train=True表示下载的是训练集,False表示下载的是测试集,download表示要下载
#transform=dataset_transform转化成Tensor数据类型
#↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意修改该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
train_set=torchvision.datasets.CIFAR10(root="./DataSet",train=True,transform=dataset_transform,download=True)
test_set=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)

# print(test_set.classes)
#
# print(test_set[0])#输出图片+标签信息
# img,target=test_set[0]#img存放图片信息,target存放标签信息
# print(img)
# print(target)
# print(test_set.classes[target])#输出标签类别
# img.show()#显示图片

writer=SummaryWriter("logs")
for i in range(10):
    img,target=test_set[i]
    writer.add_image("test_set",img,i)

writer.close()

5、dataloader加载数据

? ? 这里是读取第四步中下载的数据,dataloader本质是一个可迭代对象,将自定义的Dataset根据batch size大小、是否shuffle等封装成一个Batch Size大小的Tensor,用于后面的训练。

#DataLoader加载数据

import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)

"""
dataset:数据集
batch_size:一次取多少数据
shuffle:是否按顺序读取,默认为false
num_workers:多进程,默认为0,用主进程加载,>0时windows下可能出错
drop_last:对余数的处理(除不尽)
"""
test_loader=DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)

writer=SummaryWriter("dataloader")
for epoch in range(2):
    step=0
    for data in test_loader:
        img,targets=data
        writer.add_images("epoch_{}".format(epoch),img,step)
        step=step+1

writer.close()

6、卷积操作

? ? 这里是利用函数的卷积。

#conv2d卷积操作
import torch
from torch import nn
import torch.nn.functional as F

input=torch.tensor([[1,2,0,3,1],
                    [0,1,2,3,1],
                    [1,2,1,0,0],
                    [5,2,3,1,1],
                    [2,1,0,1,1]])

kernel=torch.tensor([[1,2,1],
                     [0,1,0],
                     [2,1,0]])
input=torch.reshape(input,(1,1,5,5))#尺寸变化,Conv2d有要求
kernel=torch.reshape(kernel,(1,1,3,3))
"""
二维卷积
conv2d(input,weight,bias=None,stride=1,padding=0,dilation=1,groups=1):
input:输入要求是(batch,通道,高,宽)
weight:权重(卷积核),输入要求是(输出通道,输入通道,高,宽)
bias:偏置
stride:步长,单个数(横纵皆是),俩数(横步长,纵步长)
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
"""
output=F.conv2d(input,kernel,stride=1)
print(output)
output2=F.conv2d(input,kernel,stride=2)
print(output2)
output3=F.conv2d(input,kernel,stride=1,padding=1)
print(output3)

7、卷积层

? ? 与第6节不同,这里引入了model的概念,自己定义卷积核的到校、步长等通过正向传播的得到结果。卷积层也是未来常用的一个层

#nn.Conv2d卷积层
import torch
import torchvision
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter

#加载数据集
dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
dataset=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset,batch_size=64)

"""
nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,
        padding=0,dilation=1,groups=1,bias=True,padding_mode='zeros'):
in_channels:输入通道数,RGB图像一般为3通道
out_channels:输出通道数,通道数1->2,两个卷积核
kernel_size:卷积核大小,数或者元组(行,列),卷积核中参数训练得到
stride:步长,单个数(横纵皆是),俩数(横步长,纵步长)
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
下面的不太常用一般设为默认值
dilation:卷积核对应位的距离
groups:分组卷积
bias:结果是否加减一个常数
padding_mode:按怎样模式填充
"""

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.conv1=Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

    def forward(self,x):
        x=self.conv1(x)
        return x

myModule=MyModule()
writer=SummaryWriter("nn.conv")
step=0

for data in dataloader:
    imgs,targets=data
    output=myModule(imgs)
    writer.add_images("input",imgs,step)
    #变化成六通道后不能显示(报错),需要reshape转化为三通道
    output=torch.reshape(output,(-1,3,30,30))#设-1会自动计算结果
    writer.add_images("output",output,step)
    step=step+1

writer.close()

8、池化层

? ? 池化操作,同7,也是module中的一个层次。

#pooling池化层
import  torch
from torch import nn
from torch.nn import MaxPool2d

input=torch.tensor([[1,2,0,3,1],
                    [0,1,2,3,1],
                    [1,2,1,0,0],
                    [5,2,3,1,1],
                    [2,1,0,1,1]],dtype=torch.float32)#将数字格式设置为浮点型
input=torch.reshape(input,(-1,1,5,5))#尺寸变化,MaxPool2d有要求


"""
nn.MaxPool2d(kernel_size, stride,padding, dilation, ceil_mode,return_indices)
kernel_size:窗口大小,数字或元组
stride:横向或纵向路径大小,默认值是窗口大小
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
dilation:窗口对应位的距离
ceil_mode:True则ceil模式(向下取整),False则floor模式(向上取整),设计到对边缘数的处理同理,默认为False
"""
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True)

    def forward(self, input):
        output=self.maxpool1(input)
        return output

MyModule=MyModule()
output=MyModule(input)
print(output)



9、非线性激活层

#非线性激活层
import torch
from torch import nn
from torch.nn import ReLU

input=torch.tensor([[1,-0.5],
                    [-1,3]])
output=torch.reshape(input,(-1,1,2,2))
"""
ReLU(inplace)
负数归0
inplace:是否覆盖input,true覆盖,False不覆盖,默认为False

Sigmoid()
归一化归至(-1,1)
"""

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.relu1=ReLU()

    def forward(self,input):
        output=self.relu1(input)
        return output

MyModule=MyModule()
output=MyModule(input)
print(output)

10、线性层(全连接层)

#线性层
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

#加载数据集
dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
dataset=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)

"""
torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None):
in_features:输入大小
out_features:输出大小
bias:True则设偏置学习,False不设
"""
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.linear1=Linear(196608,10)

    def forward(self,input):
        output=self.linear1(input)
        return output

MyModule=MyModule()
for data in dataloader:
    imgs,targets=data
    print(imgs.shape)
    """
    flatten将输入展成一行
    [[1,2],[3,4]]->[1,2,3,4]
    """
    input=torch.flatten(imgs)
    print(input.shape)
    output=MyModule(input)

11、简单的神经网络

? ? 这一节结合了7~10节,构成了一个简单的神经网络,当然,只有正向传播,这个代码的最后有一个tensorboard的黑科技,记得试一下。

#构建一个简单的神经网络
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.conv1=Conv2d(3,32,5,padding=2)
        self.maxpool1=MaxPool2d(2)
        self.conv2=Conv2d(32,32,5,padding=2)
        self.maxpool2=MaxPool2d(2)
        self.conv3=Conv2d(32,64,5,padding=2)
        self.maxpool3=MaxPool2d(2)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2=Linear(64,10)


        """
        Sequential():
        依次执行()中的操作
        """
        self.model1=Sequential(#这个与前面分开写的是一样的
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)
        return x

MyModule=MyModule()
input=torch.ones((64,3,32,32))#定义大小,其中元素全部复制为1
output=MyModule(input)

writer=SummaryWriter("../compute")
writer.add_graph(MyModule,input)#生成计算图,很神奇,记得点几下
writer.close()

12、损失函数

要进行训练,那么损失函数就必不可少了,这里展示了几种常见的loss函数例如MSELoss、CrossEntropyLoss。

#loss实际与预测值的损失,用于更新(反向传播)  注意输入输出
import torch
from torch.nn import L1Loss
from torch import nn

input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5],dtype=torch.float32)

input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))

"""
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean'):
reduction:mean:求均值;sum:求和
"""
loss=L1Loss()
result=loss(input,target)
print(result)

"""
nn.MSELoss()
先求平方差,再求均值
"""
loss_mse=nn.MSELoss()
result_mse=loss_mse(input,target)
print(result_mse)

"""
nn.CrossEntropyLoss():
交叉熵损失,常用于分类问题
input:(N,C)  N batch size,C类
output:实际标签
"""
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
loss_CE=nn.CrossEntropyLoss()
print(loss_CE(x,y))

13、反向传播

? ? 加上反向传播,可用pycharm的调试功能看到梯度的变化。

#Back propagation反向传播,在test14网络的基础上进行
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)


class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.conv1=Conv2d(3,32,5,padding=2)
        self.maxpool1=MaxPool2d(2)
        self.conv2=Conv2d(32,32,5,padding=2)
        self.maxpool2=MaxPool2d(2)
        self.conv3=Conv2d(32,64,5,padding=2)
        self.maxpool3=MaxPool2d(2)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2=Linear(64,10)


        """
        Sequential():
        依次执行()中的操作
        """
        self.model1=Sequential(#这个与前面分开写的是一样的
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)
        return x

MyModule=MyModule()
loss=nn.CrossEntropyLoss()
for data in dataloader:
    imgs,targets=data
    # 向前传播  该网络输出为一个10维向量,每一维表示是此类的概率
    outputs=MyModule(imgs)
    #利用交叉熵计算损失
    result_loss=loss(outputs,targets)
    #反向传播,计算梯度
    result_loss.backward()

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:15:13  更:2021-12-06 15:16:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 2:20:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码