环境配置

作为学习,还是用anaconda新建一个虚拟环境比较好.在terminal中conda create -n pytorch python=3.8 -y新建一个环境,使用python3.8版本。然后切换到pytorch环境,pip list看一下有什么包,发现没有pytorch,于是需要自己安装一下。来到pyorch官网,根据自己电脑型号选择对应版本,他会自动生成一条安装命令,在当前虚拟环境运行即可。

安装好了以后,再配置一下pycharm和Jupyter,以后两个应该都会用。
pycharm中新建一个项目,File->New Project->Pure Python->Python Interpreter->Previously Configured Interpreter->Add Interpreter->Add Local Interpreter->Conda Environment->Use existing environment选择自己刚刚创建的虚拟环境。这里我的pycharm是2022的,不同版本可能略有差异。
然后配置Jupyter,新建的虚拟环境也是没有Jupyter的,需要安装相关依赖。在相应的虚拟环境中运行conda install nb_conda安装nb_conda,这是一个用于在Jupyter Notebook中管理Conda环境的扩展,运行以后就可以在Jupyter中使用创建的环境。安装好以后在环境中运行Jupyter notebook就可以启动了,启动后notebook页面的new下面会出现自己创建的环境。

至此,相关环境就已经配置好了。

python几个帮助调试的函数

  • dir()
  • help()
  • print(type())//打印返回值类型

dir()函数可以查看目标中包含什么模块。


当展示的信息是__xx__的形式,表明这个模块已经是一个可以使用的函数了,里面没有其他东西。像下面这样:

然后就可以用help()来看它的使用方法:

Dataset

加载数据主要用到两个类:Dataset和Dataloader.
Dataset会提供一种方式来获取目标数据机器label,并且说明总共有多少个数据;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
28
29
30
31
32
33
34
35
from torch.utils.data import Dataset
from PIL import Image #处理图片
import os

class MyData(Dataset): #python中的继承语法

# self修饰的属性,相当于类的属性,类内其他方法也可以访问
def __init__(self,root_dir,label_dir): #初始化数据集
self.root_dir = root_dir #图片所在目录的上级目录的路径
self.lable_dir = label_dir #图片的标签,就是图片所在目录的名称
self.path = os.path.join(self.root_dir,self.lable_dir) #将这两个拼在一起组成图片所在目录的路径
self.img_path = os.listdir(self.path) #将路径下所有项转成列表

def __getitem__(self, idx): #从数据集中取图片
img_name = self.img_path[idx] #图片名,没有self修饰,只能在函数内访问
img_item_path = os.path.join(self.root_dir,self.lable_dir,img_name) #加上图片名就构成了图片的完整路径
img = Image.open(img_item_path) #拿图片
label = self.lable_dir #图片标签
return img,label; #返回图片和对应标签

def __len__(self): #数据集大小
return len(self.img_path)

root_dir = "dataset/train"
ant_label_dir = "ants"
bee_label_dir = "bees"
ants_dataset = MyData(root_dir,ant_label_dir)
bees_dataset = MyData(root_dir,bee_label_dir)

train_dataset = ants_dataset + bees_dataset #数据集可以这样加,组合成一个大的数据集
img1,label1 = train_dataset[120]
img2,label2 = train_dataset[150]
print(img1) #看图片信息
img1.show() #显示图片
img2.show()

Tendorboard

tensorboard可以将数据可视化。他之前属于tensorflow,后来可以单独安装使用了。但是我在单独使用它过程中,出现了无法显示图像的问题,报错failed to fetch run.尝试了很多方法都没用,想什么改绝对路径这些。后来索性把tensorflow也安装了,然后就好用了。

add_scalar()

1
2
3
4
5
6
7
8
9
10
11
12
13
from torch.utils.tensorboard import SummaryWriter
# 创建 SummaryWriter 对象
writer = SummaryWriter("logs") #参数"logs"为文件夹名,事件文件会保存在此
#创建好后可以用在teminal用tensorboard --logdir=logs --port=指定端口 命令显示train noise
#logs是创建对象时的参数,port可以自己指定,不加则默认为6006
# writer.add_image()
# y = x
for i in range(100):
writer.add_scalar("y=x",i,i) # 添加标量数据 参数依次为:图像名,y轴,x轴

# 用后关闭
writer.close()

1
2
# terminal run the command. use --port=n to appoint the port,default is 6006
tensorboard --logdir=logs

上述代码用tensorboard简单画了一个y=x的图像。

add_image()

前三个常用的参数
tag (str): Data identifier
img_tensor (torch.Tensor, numpy.ndarray, or string/blobname): Image data
global_step (int): Global step value to record
dataformats (str): Image data format specification of the form
CHW, HWC, HW, WH, etc.

其中numpy.ndarray有不同shape,对应了不用的dataformats.默认是3HW.
img_tensor的类型只能接收括号中的,而使用PIL的Image,获得的img不是这几个类型:

1
2
3
4
from PIL import Image
img = Image.open(image_path)
print(type(img))
<class 'PIL.JpegImagePlugin.JpegImageFile'>

可以使用numpy,这样将PIL的图片转换成的img是满足要求的类型:

1
2
3
4
5
6
7
8
import numpy as np
img_array = np.array(img)
print(type(img_array))
<class 'numpy.ndarray'>
print(img_array.shape)
(512, 768, 3) #与默认的格式不一样,需要指定dataformats,否则报错。C表示通道,图片一般都是3通道

writer.add_image("test",img_array,1,dataformats="HWC")

Transforms

简单的使用

transform可以将对象转换为tensor类型,该类型中记录了深度学习中需要的一系列属性。

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
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

# 如何使用常用的transforms
## 先加载数据
img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)

## ToTensor
tensor_trains = transforms.ToTensor() #返回ToTensor对象
tensor_img = tensor_trains(img) #将img转换成tensor

# print(tensor_img)

writer = SummaryWriter("logs")
writer.add_image("image",tensor_img)

## Normalize归一化
## (input[channel] - mean[channel]) / std[channel]
print(tensor_img[0][0][0]) #归一化前
trans_norm = transforms.Normalize([2,0.7,2],[0.4,0.8,2])
img_norm = trans_norm(tensor_img)
print(img_norm[0][0][0]) #归一化后
writer.add_image("normalize",img_norm,3)

## Resize
print(img.size)
trans_resize = transforms.Resize((512, 512))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
# img_resize PIL -> totensor -> img_resize tensor
img_resize = tensor_trans(img_resize)
writer.add_image("Resize", img_resize, 0)
print(img_resize)

## Compose - resize -2 参数需要transforms类型
trans_resize_2 = transforms.Resize(512) # 等比缩放
# PIL -> PIL -> tensor
trans_compose = transforms.Compose([trans_resize_2, tensor_trans]) # compose参数列表中,前一个的输出作为后一个的输入
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 1)

## RandomCrop
trans_random = transforms.RandomCrop((500, 600))
trans_compose_2 = transforms.Compose([trans_random, tensor_trans])
for i in range(10):
img_crop = trans_compose_2(img)
writer.add_image("RandomCropHW", img_crop, i)

writer.close()

_call_

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person:
def __call__(self, name):
print("__call__" + name)

def hello(self, name):
print("hello" + name)


person = Person()
person("zhangsan")
person.hello("lisi")

#output
__call__zhangsan
hellolisi

可以看出该方法使得一个类实例变得像函数一样可以被调用,并且能够接受参数。

Dataloader

dataset是对数据集进行预处理,Dataloader就是怎么将数据集应用到神经网络中。

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

test_set = torchvision.datasets.CIFAR10("./dataset1", train=False, transform=torchvision.transforms.ToTensor())

test_loader = DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)

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

writer.close()