操作
注意所有的操作都在这个anaconda prompt下面进行:
复制新的conda环境
首先我们再anaconda中集成的conda包就可以创造出两个屋子来存放不同的pytorch版本,例如一个项目此时需要用到pytorch0.4,一个需要用到pytorch1.0,假设我们此时我们都在一个conda包创建的屋子里面使用不同版本的pytorch的话,就相当于我们要卸载了又安装就非常的麻烦,此时就需要我们创建两个不同的屋子,一个屋子使用pytorch0.4,一个屋子使用pytorch1.0
指令如下:
conda create -n pytorch python=3.6
其中pytorch 就是屋子的名字,python=3.6就是这个屋子的python版本,注意python后面的等号不能有空格.
注意:在安装另一个小屋子pytorch之前,我们要确保我们已经安装了清华镜像,具体教程在这里(前提是已经装了anaconda,要在anaconda的prompt环境下运行):具体博客地址在这里:点我进入博客
创建完成后先点击y,会让我们去激活这个新的小屋子:
激活完成后此时我们可以看到左边括号就是我们的环境名称了
base是我默认的环境名称,也就是我之前那个小屋子,这个小屋子已经将我们的pytorch环境和jupyter环境安装到位了,但是在新的pytorch这个环境中是没有这两个环境的,都需要我们自己手动配置.
此时使用pip list指令来看下发现我们pytorch这个小屋子里面并没有这个pytorch的环境,所以此时就需要我们安装pytorch这个环境,如下图所示:(红色报错不影响)
在新的环境中安装pytorch
此时可以安装pytorch了,关于在安装pytorch的时候选择什么:如果是英伟达显卡的话:选择如下配置:windows推荐conda安装,如果是集显的话选择cpu那个配置
复制command到我们的命令行:
此时如果出现如下错误:把我们的vpn关掉即可
然后再使用pip list指令即可查看我们安装成功:
注意:可以使用activate命令进行环境的迁移
上面我们就从base环境迁移到了pytorch环境,如果要回到我们的根目录也就是base环境的话可以使用conda.bat deactivate命令
安装完成后,检验是否安装成功:(三步走)
在新的环境中安装jupyter
jupyter默认只安装在base环境中,在base环境中使用conda list
查看到时有这个包:所以此时我们需要在pytorch这个新环境中安装.
使用命令 conda install nb_conda
如下图所示:
安装完成后在命令框输入:jupyter notebook
跳转到页面后(如果没有跳转请手动粘贴地址到浏览器)
点击new---->点击python进去,到如下页面输入两行代码
import torch torch.cuda.is_available()
如果最终输入结果为true,就说明我们的jupyter是在我们的pytorch环境下运行啦
python中的两大法宝函数(也可用在pytorch)
1:dir()函数:打开看见 2:help()函数:说明书
建立新项目
1:首先建立新项目:
2:选择我们的python解释器,选择Existing interpreter:
注意这里的选择问题,因为我们是再pytorch这个小房子内部进行开发的,所以我们就要选择pytorch环境下的python.exe文件:
此时点击settings:可以看到我们的pytorch版本为1.10.2,python版本为3.6.13,说明我们使用了我们pytorch环境下的pytorch版本.
针对这个项目打开我们的jupyter notebook
首先因为我们的项目存储于d盘,所以我就需要在命令行输入的时候加上导航到d盘的指令:使用jupyter notebook d:假设是在桌面的话就直接jupyter notebook
注意:此时我们在创建笔记的时候需要注意的是:我们需要用管理员命令打开我们的anaconda环境,不然创建笔记的时候会出错,还有一个问题就是假如我们打开jupyter notebook无法跳转浏览器的话,也可能是没有使用管理员命令打开的原因:
此时打开jupyter notebook后运行这两段代码:
import pytorch torch.cuda.is_available()
发现为true,说明此时的jupyter notebook就是在pytorch环境中:此时就可以在里面编写代码了:
在这里区分一下python文件,jupyter notebook以及python控制台的区别
pytorch记载数据初认识
首先需要认识两个概念,一个是dataset,一个是dataloader,我把区别放在了下面:
垃圾数据中的蓝色的就是我们的可回收垃圾,也就是我们的数据
DataSet可以为这些数据进行一个编号,
dataset代码示例
此时我们先来看看Dataset这个类在官网中是如何使用的:
打开jupyter notebook,输入以下代码:
from torch.utils.data import Dataset
或者使用Dataset??也可以,以下就是官网对于Dataset类的解释:
Init signature: Dataset() Source: class Dataset(Generic[T_co]): r"""An abstract class representing a :class:`Dataset`. All datasets that represent a map from keys to data samples should subclass it. All subclasses should overwrite :meth:`__getitem__`, supporting fetching a data sample for a given key. Subclasses could also optionally overwrite :meth:`__len__`, which is expected to return the size of the dataset by many :class:`~torch.utils.data.Sampler` implementations and the default options of :class:`~torch.utils.data.DataLoader`. .. note:: :class:`~torch.utils.data.DataLoader` by default constructs a index sampler that yields integral indices. To make it work with a map-style dataset with non-integral indices/keys, a custom sampler must be provided. """ def __getitem__(self, index) -> T_co: raise NotImplementedError def __add__(self, other: 'Dataset[T_co]') -> 'ConcatDataset[T_co]': return ConcatDataset([self, other]) # No `def __len__(self)` default? # See NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ] # in pytorch/torch/utils/data/sampler.py File: d:\anaconda3\lib\site-packages\torch\utils\data\dataset.py Type: type Subclasses: IterableDataset, TensorDataset, ConcatDataset, Subset, IterableDataset[str], IterableDataset[typing.Tuple[str, io.IOBase]], IterableDataset[typing.Tuple[str, io.BufferedIOBase]], IterableDataset[typing.Tuple[str, typing.Any]], IterableDataset[+T_co], IterableDataset[typing.Tuple[+T_co]], ...
意思就是DataSet是一个抽象类,然后我们所有子类都需要重写__getitem__方法,这个方法主要是获取每个数据及其对应的lable,同时还可以重写我们的__len__方法,定义我们的数据有多长
__getitem__就是获取样本对,模型直接通过这一函数获得一对样本对{x:y}。__len__是指数据集长度。
from torch.utils.data import Dataset # 使用此方法来读取我们的图片 from PIL import Image # os用来获取所有图片的地址 import os # 创建一个MyData类继承于我们的Dataset类 class MyData(Dataset): """ root_dir一般情况下设置为dataset下的地址,这里的路径是dataset/train lable_dir就是ants """ def __init__(self, root_dir, label_dir): self.roots_dir = root_dir self.label_dir = label_dir # 使用join方法可以很好的进行拼接,因为破折号/再不同系统中的含义不同,使用此方法可以忽略路径拼接中因为不同系统引发的问题 # lable_path就等价于dataset/train\\ants self.label_path = os.path.join(self.root_dir, self.label_dir) # img_path为获取所有图片的地址的集合,lable_path就等价于dataset/train\\ants self.img_path = os.listdir(self.label_path) # 此处重写我们DataSet类中的__getitem__方法 # 我们通过index来获取图片的地址 def __getitem__(self, idx): # img_name为获取每一个图片的名称 img_name = self.img_path[idx] # 获取每个图片的相对路径,举例:dataset/train\\ants\\'0013035.jpg' image_item_path = os.path.join(self.root_dir, self.label_dir, img_name) # img为获取到某个图片 img = Image.open(image_item_path) # 获取到标签 label = self.label_dir # 返回数据和标签 return img, label # 定义数据集的长度 def __len__(self): # 返回的长度也只是ants这个数据集下的图片的长度 return len(self.img_path) root_dir = "dataset/train" ants_label_dir = "ants" bees_label_dir = "bees" ants_dataset = MyData(root_dir, ants_label_dir) bees_dataset = MyData(root_dir,bees_label_dir) img,label = bees_dataset[1] img.show()
安装tensorboard
我们这里说的是在每个conda环境下安装tensorboard
命令为pip
1:在命令行安装:
这里我们的conda环境为base
2: 也可以在项目的终端中安装:
这里的conda环境为pytorch
tensorboard中的add_scalar()方法
def add_scalar( self, tag, scalar_value, global_step=None, walltime=None, new_style=False, double_precision=False, ): """Add scalar data to summary. Args: tag (string): Data identifier scalar_value (float or string/blobname): Value to save global_step (int): Global step value to record walltime (float): Optional override default walltime (time.time()) with seconds after epoch of event new_style (boolean): Whether to use new style (tensor field) or old style (simple_value field). New style could lead to faster data loading. Examples:: from torch.utils.tensorboard import SummaryWriter writer = SummaryWriter() x = range(100) for i in x: writer.add_scalar('y=2x', i * 2, i) writer.close() Expected result: .. image:: _static/img/tensorboard/add_scalar.png :scale: 50 % """ torch._C._log_api_usage_once("tensorboard.logging.add_scalar") if self._check_caffe2_blob(scalar_value): from caffe2.python import workspace scalar_value = workspace.FetchBlob(scalar_value) summary = scalar( tag, scalar_value, new_style=new_style, double_precision=double_precision ) self._get_file_writer().add_summary(summary, global_step, walltime)
这个方法有很多的内置参数,例如
tag:图表的标题
scalar_value:需要保存的数值,即为训练到多少步的时候的数值的大小即为此值
gloabal_step:步长
对应图像的话就是scalar_value表示y轴,然后global_step表示x轴
那么我们如何看到类似的图像呢?拿一段代码来举例把:
from torch.utils.tensorboard import SummaryWriter writer = SummaryWriter("logs") # tag:y = x # scalar_value:i # gloabal_step:i for i in range(100): writer.add_scalar("y=x", i, i) writer.close()
那么如何看到这段图像呢?
首先打开我们的terminal终端,然后输入这段指令:tensorboard --logdir=logs
此时会默认出来一个网址:复制粘贴到浏览器就可以找到对应的模块了:
当然此时要注意一个问题,假设此时我们不同人在一个服务器下跑模型的时候,大家都会默认打开上面的6006端口,这样就会带来很多不便,所以此时我们需要去指定端口号,避免冲突:
使用如下指令指定6007端口号:
tensorboard --logdir=logs --port=6007
但是需要注意的是假设我们不断向writer写入新的事件的时候,每一次的事件的图像都会进行一次拟合,就不能得到我们想要的某一次事件的图像,那么该如何解决这个问题呢?
其实就可以直接将logs文件夹下的文件全部删掉,然后重新运行程序后在终端再次输入tensorboard --logdir=logs --port=6007后,便可以直接得到某次想要的结果了,并不是像之前那样拟合好几次的结果
tensorboard中的add_image()方法
先来看此方法内部的实现:
def add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'): """Add image data to summary. Note that this requires the ``pillow`` package. Args: tag (string): Data identifier img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data global_step (int): Global step value to record walltime (float): Optional override default walltime (time.time()) seconds after epoch of event Shape: img_tensor: Default is :math:`(3, H, W)`. You can use ``torchvision.utils.make_grid()`` to convert a batch of tensor into 3xHxW format or call ``add_images`` and let us do the job. Tensor with :math:`(1, H, W)`, :math:`(H, W)`, :math:`(H, W, 3)` is also suitable as long as corresponding ``dataformats`` argument is passed, e.g. ``CHW``, ``HWC``, ``HW``. Examples:: from torch.utils.tensorboard import SummaryWriter import numpy as np img = np.zeros((3, 100, 100)) img[0] = np.arange(0, 10000).reshape(100, 100) / 10000 img[1] = 1 - np.arange(0, 10000).reshape(100, 100) / 10000 img_HWC = np.zeros((100, 100, 3)) img_HWC[:, :, 0] = np.arange(0, 10000).reshape(100, 100) / 10000 img_HWC[:, :, 1] = 1 - np.arange(0, 10000).reshape(100, 100) / 10000 writer = SummaryWriter() writer.add_image('my_image', img, 0) # If you have non-default dimension setting, set the dataformats argument. writer.add_image('my_image_HWC', img_HWC, 0, dataformats='HWC') writer.close() Expected result: .. image:: _static/img/tensorboard/add_image.png :scale: 50 % """ torch._C._log_api_usage_once("tensorboard.logging.add_image") if self._check_caffe2_blob(img_tensor): from caffe2.python import workspace img_tensor = workspace.FetchBlob(img_tensor) self._get_file_writer().add_summary( image(tag, img_tensor, dataformats=dataformats), global_step, walltime)
tag为图片标题
img_tensor为图像的数据类型:可以看到有很多个数据类型可以指定: 例如torch.Tensor, numpy.array, or string/blobname这几个类型都可.后面的代码要用到numpy类型作为举例,大家注意仔细观看。
global_step为步长
安装Opencv
还是两种方式:
1:在anconda中使用命令安装,这里是我们的base环境:
2:在对应项目的terminal中使用命令安装,注意如果一个项目已经在某个conda环境下,在这个项目的终端(terminal)中安装了cv后,就不需要再命令行安装了
利用opencv读取图片,获取numpy型数据图片
import cv2 img_path = "data/train/ants_image/0013035.jpg" cv_img = cv2.imread(img_path)
利用numpy.array(),对PIL图片进行转换
首先我们可以看到此时这个图片是PIL类型,我们需要将其转为numpy类型,代码如下所示:
在命令行调试完毕后,我们来编写代码把:
from torch.utils.tensorboard import SummaryWriter import numpy as np from PIL import Image # 日志文件logs writer = SummaryWriter("logs") # 某个图片的相对地址 image_path = "data/train/ants_image/6240329_72c01e663e.jpg" # 打开这个图片 img_PIL = Image.open(image_path) # 讲这个图片从PIL类型转换为numpy类型 img_array = np.array(img_PIL) # 这里打印我们img_array的类型结果为<class 'numpy.ndarray'> # 说明此时图片由PIL类型转为了numpy类型 print(type(img_array)) """ 这里打印shape是因为我们这个numpy类型图片打印出来是(369, 500, 3) 这里的3是通道,369是高度,500是宽度 因为此时3这个通道在最后面,所以我们应该在add_image方法中指定dataformats 他会让你选三个``CHW``, ``HWC``, ``HW`` C代表通道,H代表高度,W代表宽度 """ print(img_array.shape) """ test等价于tag img_array等价于img_tensor 1等价于global_step """ writer.add_image("train", img_array, 1, dataformats='HWC') # y = 2x for i in range(100): writer.add_scalar("y=2x", 3*i, i) writer.close()
注意事项:
为什么我们要在add_image中指定dataformats?
答:
由print(img_array.shape)语句可知:其结果为
(369, 500, 3)
来看add_image方法内部是怎么说的:
Shape:
img_tensor: Default is :math:(3, H, W). You can use torchvision.utils.make_grid() to
convert a batch of tensor into 3xHxW format or call add_images and let us do the job.
Tensor with :math:(1, H, W), :math:(H, W), :math:(H, W, 3) is also suitable as long as
corresponding dataformats argument is passed, e.g. CHW, HWC, HW.
意思为 img_tensor中默认为(3, H, W),其中代表通道的3在最前面,
这里的3是通道,H是高度,W是宽度
但是假如我们打印shape的结果中通道3没有或者在最后面的话,就需要指定我们的dataformats
他会让你选三个CHW, HWC, HW
C代表通道,H代表高度,W代表宽度
其中(3, H, W)对应CHW
(H, W, 3)对应HWC































