🖼 人工智能学习总目录

🖼 小结可以看这里

🖼 视频资料都在这里—教程看这里B站小土堆【PyTorch快速入门教程】

第1章

1、实验环境Anaconda

1.1 为什么用Anaconda?

  • 1、自带了一大批常用的数据科学包(150+),不需要自己一个一个配置
  • 2、conda便于管理Python包
  • 3、可以创建自己的虚拟环境,在环境里面选择自己想要的版本的包

1.2 CUDA

英伟达(NVIDIA)显卡,也叫GPU,安装PyTorch需要指定GPU版本(没有就是None)

Windows可能有,Mac没有,Windows在命令行输入下命令,查看自己的CUDA版本,及时更新

1
nvidia-smi

1.3 配置环境pytorch

可以看这个起步(安装Python、PyCharm、Anaconda)

虚拟环境名叫pytorch,进入虚拟环境

2、PyTorch加载数据

2.1 拿到指定目录图片列表

直接解释代码,总的来说就是学会怎么拿数据,注:

HTLrpkmBegaI5Xw

GtYzORAX274N1wf

dqD2z5RMTYlWKQ4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# 1、Dataset需要对输入的图片进行处理,变成我们需要的数据格式(取数据)
# DataLoader是对格式化的tensor数据进行分组
from torch.utils.data import Dataset, DataLoader
# 2、统计URL,也就是图片在系统中的位置,组成的list,进行批量操作
import os
# 3、PIL可以吧图片转化成ndarray类型的数据(数组)
from PIL import Image
# 4、把ndarray类型的数组转化成我们需要的数据格式
from torchvision import transforms


# 这里重写Dataset方法,便于我们批量处理数据
class MyData(Dataset):

# 如果传入数据是下面的参数,那么就会创建实例。ants_dataset = MyData(root_dir, image_ants, label_ants)
def __init__(self, root_dir, image_dir, label_dir, transform=None):
# ① 拿到总路径 /data/train
self.root_dir = root_dir
# ② 总路径下的图片路径 /ants_image
self.image_dir = image_dir
# ③ 总路径下的标签路径 /ants_label
self.label_dir = label_dir

# ④ 把路径合到一起,比如/data/train/ants_image,图片文件夹
self.image_path = os.path.join(self.root_dir, self.image_dir)
self.label_path = os.path.join(self.root_dir, self.label_dir)

# ⑤ 把文件夹下的所有文件名做成一个list列表
self.image_list = os.listdir(self.image_path)
self.label_list = os.listdir(self.label_path)

# ⑥ 自调用,传入图片处理方式,自动调用对所有文件进行处理
self.transform = transform

# ⑦ 排序一下列表,可以保证取出的数据和label是一一对应的
self.image_list.sort()
self.label_list.sort()


# 如果在实例中传入index,会传出img和label。img0,label0 = ants_dataset[0]
def __getitem__(self, idx):
img_name = self.image_list[idx]
label_name = self.label_list[idx]
img_item_path = os.path.join(self.root_dir, self.image_dir, img_name)
label_item_path = os.path.join(self.root_dir, self.label_dir, label_name)
# 传出的img参数 对应 img_item_path的图片
img = Image.open(img_item_path)
# 传出的label参数 对应 label_item_path的文件内容。比如ants
with open(label_item_path, 'r') as f:
label = f.readline()
# 如果transform传入参数不为空,我们对图片进行transform变形。
if self.transform:
img = transform(img)
return img, label


def __len__(self):
assert len(self.image_list) == len(self.label_list)
return len(self.image_list)

# 这个transform后面会讲到,这里的Compose可以组合几种变换,里面先调整大小,再转换成ToTensor类型数据
transform = transforms.Compose([transforms.Resize(400), transforms.ToTensor()])
root_dir = "/Users/ruiqingyan/Code/PyCharm/3、~PyTroch快速入门/数据集/练手数据集/train"
image_ants = "ants_image"
label_ants = "ants_label"
# 创建实例,自调用__init__()
ants_dataset = MyData(root_dir, image_ants, label_ants)
# 拿到元素,调用__getitem__()
img0, label0 = ants_dataset[0]
img0.show()
print(label0)

2.2 Tensorboard视图

(在编译环境)先在写代码,生成文件 , 新版本从tensorboardX里面导包

(在终端)之后在终端中打开文件 , 需要下载charset_normalizer包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# torch.utils.tensorboard新的torch弃用换成tensorflowX了,这里需要下载包
from tensorboardX import SummaryWriter
import numpy as np
from PIL import Image

# 指定写入logs文件夹,没有会在当前目录生成
writer = SummaryWriter("logs")
# 指定我的图片在本地的路径,拿到图片
image_path = "/Users/ruiqingyan/Code/PyCharm/3、~PyTroch快速入门/数据集/练手数据集/train/ants_image/5650366_e22b7e1065.jpg"
img_PIL = Image.open(image_path)
# 把PIL图片转换成ndarray数组,ndarray的意思是n维数组
img_array = np.array(img_PIL)
# 在Tensorboard滑板上添加图片,名字是"train",传入img_array,进行第1步处理(可以理解成分组),是HWC类别的(不用理解)
writer.add_image("train", img_array, 1, dataformats='HWC')

# 写入一个函数,名字叫y=2x,y值是2i,x值是i
for i in range(100):
writer.add_scalar("y=2x", 2*i, i)

writer.close()

这里打开tensorboard的终端地址可能不是程序的地址,注意路径问题,不会用相对路径里面logs可以拷贝绝对路径用

之后在当前目录终端,输入(第一个命令下载必要包,第二个命令打开los目录下的tensorboard视图):

1
2
3
pip install tensorboard
pip install --upgrade charset-normalizer
tensorboard --logdir=logs

xmkOM9tlJuNzBjn

4981cBzHFZpv2mK

2.3 transform调图

  • 1、输入PIL图片(Image.open())
  • 2、用tensorform创建自己调图工具处理PIL图片(讲工具)
  • 3、输出tensor类型的数据(ToTensor方法)

    其实上面第一段代码里面也有相关内容,如下图(调用是实例__getitem__哪里会处理):

1
2
3
4
5
# 4、把ndarray类型的数组转化成我们需要的数据格式
from torchvision import transforms

# 这个transform后面会讲到,这里的Compose可以组合几种变换,里面先调整大小,再转换成ToTensor类型数据
transform = transforms.Compose([transforms.Resize(400), transforms.ToTensor()])

下面介绍下tensorform工具及自己创建工具,主要img_PIL要传入自己的图片URL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from PIL import Image
from torchvision import transforms
from tensorboardX import SummaryWriter

writer = SummaryWriter("logs")
img_PIL = Image.open("/Users/ruiqingyan/Code/PyCharm/3、~PyTroch快速入门/数据集/练手数据集/train/ants_image/6743948_2b8c096dda.jpg")

# 1、Totensor (把输入PIL,输出tensor)
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img_PIL)
writer.add_image("ToTensor",img_tensor,1) # 这个1代表TonTensor名下,step=1的图

# 2、Normalize (传入两个列表参数,分别是mean中值和标准差std)
trans_norm = transforms.Normalize([0,3,1],[9,3,3])
img_norm = trans_norm(img_tensor)
writer.add_image("Normalize",img_norm,2) # 这个2代表Normalize名下,step=2的图

# 3、Resize (先把PIL进行resize,再把resize之后的PIL转化成tensor)
# 最新的Resize可以直接传入tensor,不需要先传入PIL在转化成tensor
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img_PIL)
img_resize = trans_totensor(img_resize)
writer.add_image("Resize",img_resize,3) #这个3代表Resize名下,step=3的图

# 4、Compose 组合操作 (先进行resize2的操作,在进行totensor操作)
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([ trans_resize_2 , trans_totensor ])
img_resize_2 = trans_compose(img_PIL)
writer.add_image("Resize",img_resize,4) #这个4代表Resize名下,step=4的图

# 5、RandomCrop (随机剪裁)
trans_random = transforms.RandomCrop(512)
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):
img_corp = trans_compose_2(img_PIL)
writer.add_image("RandomCrop", img_corp, i) #这个i代表RandomCrop名下,step=i的图,总共10张

writer.close()

写好之后在终端打开视图,使用如下命令:

1
tensorboard --logdir=logs

wz94YKmrMZaNcTg

hSqUgJc4dE5m8QZ

hbxmRVKUQ9WqkPF

nFsWZjr9JLQglxP

wDQI8RF6WL9khCt

xgE3d9eHPDUJAWz

总结,关注transforms.xxx的输入输出,多看官方文档,不同步数可以对应不同的结果。

3、torchvision中数据集的使用

进入pytorch给的数据集API文档https://pytorch.org/vision/0.9/

1HWKYwLjr8nhkbR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
# 这里root代表跟路劲,tranin表示是否进行transform训练,为true的话进行PIL转tensor,Download为是否从网上下载数据集(不存在就下载,默认视为True就好)
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)

# 图片写入的文件夹是当前文件夹下的p10文件夹
writer = SummaryWriter("p10")
# 依次写入十张图片
for i in range(10):
img, target = test_set[i]
# 图片集名是test_set,对应的step是i,传入的图片是img(一个tensor张量-多维数组)
writer.add_image("test_set", img, i)

writer.close()

在终端,输入下面命令查看图片

1
tensorboard --logdir=p10

4、DataLoader使用

进入pytorch给的dataloader文档https://pytorch.org/docs/1.8.1/data.html?highlight=dataloader#torch.utils.data.DataLoader

mEMcvNwiKdjW4oY

1
2
3
4
5
6
# 看着参数很多,只有dataset(数据集的地址)是必要的,其他都有默认值
# 1、batch_size,每次取几个数据(拿抓牌举例就是每次抓几张牌)
# 2、shuffle,打乱(每次打牌前是否洗牌,洗牌的话下次拿到的牌就不一样,不洗的话就一样)
# 3、num_workers,采用单进程还是多进程加载,多进程块,0表示主进程(BrokenError可以考虑设为0)
# 4、drop_last,如果最后只剩一个数据的话,是否舍弃
torch.utils.data.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, generator=None, *, prefetch_factor=2, persistent_workers=False)

下面是一个简单的例子,我们在第三步的时候下载了CIFAR10数据集,进行Dataloader打包输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import torchvision

# 准备的测试数据集
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor())
# 1、这里我们传入的数据集是test_data,每次取64个数据打包,打乱顺序,使用主进程,最后存在多余数据的话就舍弃
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

# 2、测试数据集中第一张图片及target
img, target = test_data[0]
print(img.shape)
print(target)

writer = SummaryWriter("dataloader")
# 3、表示进行两次操作,因为有shuffle操作,所以两次图片顺序不同(第二次遍历test_loader时会重新shuffle打乱)
for epoch in range(2):
step = 0
# 4、遍历test_loader(一组64张图),依次写入画布,这里发现156因为不足64张图舍弃了
for data in test_loader:
imgs, targets = data
#"Epoch: {}".format(epoch)就是一种简单的格式化输出,类似f"Epoch: {epoch}"
writer.add_images("Epoch: {}".format(epoch), imgs, step)
step = step + 1

writer.close()

Fgr7UwGmbnCcvDx