GPNN_HICO.py
1.class GPNN_HICO(torch.nn.Module): 类
torch.nn.Module这个类内部有多达48个函数,是pytorch中所有神经网络模型的基类;GPNN_HICO继承了torch.nn.Module这个类,成为了torch.nn.Module的子类,
2.def __init__(self, model_args): 方法
self是定义每个类的方法 的必要参数(指类的实例),代表自身,默认情况下每个方法的第一个参数是self。
__init__()是初始化函数,
3.def forward(self):
forward是GPNN_HICO这个子类的函数,在Module父类中是没有forward里的详细代码的,需要在子类中进行实现。
4.super(GPNN_HICO, self).__init__()
对继承自父类Module的属性进行初始化【super()是调用父类的一个方法,这里在Python3中表示为super().__init__()】
config.py
5.当遇到一个函数,我们想要看这个函数的内置函数时,在pycharm中,我们可以把光标定位到这个函数前,用快捷键Ctrl+B去查看。
6.self.tmp_root = os.path.join(self.project_root, 'tmp') [在这里发现了和github上相同的tmp相对路径]
os.path.join用于路径拼接,这里表示将project_root的路径后边 加上/tmp ,成为了tmp_root的路径。(个人觉得不用拼接,直接放上全部路径也是可以的)os.path的相关教程(主要用于获取相关文件的属性),常用的有os.path.dirname;os.path.exists;os.makedirs
import os 这里的os是对文件,文件夹进行操作
7.try: ...except ...raise
检测try后的语句,若发生错误,用except进行异常捕捉并处理。还是有错误则用raise触发异常,后面语句不再执行。
8.关于日志设置的一些代码,目前为止不知道有什么作用,关于logging,logging模块的简单用法,
logger = logging.getLogger(name) #对 日志对象logger 进行初始化
file_handler = logging.FileHandler(name, mode='w') #FileHandler以读的方式打开learner.log这个日志文件,赋给file_handler
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s',
"%Y-%m-%d %H:%M:%S")) #%字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
#%文本形式的日志级别 %用户输出的消息
#setFormatter()为该处理器选择一个格式化器。
logger.addHandler(file_handler) #添加许多 设置好的 规则
logger.setLevel(logging.DEBUG) #设置日志级别,DEBUG以上的级别都会显示在控制台上
return logger #最后返回这个日志
还有一点,logger可以看做是一个记录日志的人,对于记录的每个日志,他需要有一套规则,比如记录的格式(formatter),等级(level)等等,这个规则就是handler。使用logger.addHandler(handler)添加多个规则,就可以让一个logger记录多个日志。
GPNN_HICO.py
9.调用自己项目中的自定义模块。若主程序和模块程序在相同目录下,可以将要调用的模块右键,Mark Directory As->Sources Roor,这样可以直接调用;若不在相同目录下,我选择了将模块包直接复制了一份到site-packsges里,(可以用sys.path查看相关路径,可以在下方Python console中进行查看)这里查了一下午,真的要疯了,这是一点觉得有用的链接!!!
10.GPNN_HICO类的__init__初始化,以下是一些初始化的内容
self.edge_feature_resize = torch.nn.Linear(model_args['edge_feature_size'], model_args['message_size']) #Linear,ctrl+B,看到初始化函数__init__(self, in_features, out_features, bias=True):
self.node_feature_resize = torch.nn.Linear(model_args['node_feature_size'], model_args['message_size']) #对传入数据应用线性变换:y = A x+ b ,bias默认为true
torch.nn.init.xavier_normal(self.edge_feature_resize.weight) #self.weight = Parameter(torch.Tensor(out_features, in_features))
torch.nn.init.xavier_normal(self.node_feature_resize.weight) #xavier的正态分布权重初始化 https://blog.csdn.net/dss_dssssd/article/details/83959474
其中,weight是torch.nn.linear的参数。
11.PyTorch中permute: edge_features = edge_features.permute(0, 3, 1, 2)
permute(dims):将tensor的维度换位。
例如。a=rand(2,3,4); #这是一个三维数组,各维的长度分别为:2,3,4
现在交换第一维和第二维:permute(A,[2,1,3]) #变成3*2*4的矩阵
12.node_features[batch_i, ...].unsqueeze(0).clone()
对数据维度进行扩充,这里是0维的位置加上维数为一的维度
clone()函数是新开辟一个内存给数据,但是仍然在计算图上
[batch_i, ...]省略所有的冒号来用省略号代替,但这个地方我自己用列表写的小语句无法运行,不知道为什么!!!
13. hidden_node_states = [[node_features[batch_i, ...].unsqueeze(0).clone() for _ in range(self.propagate_layers+1)] for batch_i in range(node_features.size()[0])]
size()函数主要是用来统计矩阵元素个数,或矩阵某一维上的元素个数的函数。
for _ in range中的“_”表示的意思和i相同,都是循环此数的作用,只不过下边的语句块中不涉及到这个数。
[1 for i in range(n)] 表示【1...1】n个1的列表。目前只看出这是一个有关点的循环拷贝后的列表,没太看懂!!第二天看的理解是:hidden_states:0维度是 向前传播的更新次数;1维度是 点的数量(*向前传播的更新次数)——每个点都要进行 propagate_layers 次的 前向传播!
14. 看了这么多代码,感觉还是有点懵,于是想知道每个变量的类型什么的,就查了查,有关debug的,但是还暂时用不上
15. Variable变量的相关理解,Autograd is a PyTorch package for the differentiation for all operations on Tensors. It performs the backpropagation starting from a variable,以及关于cuda的一点想法,如下代码注释。
pred_adj_mat = torch.autograd.Variable(torch.zeros(adj_mat.size())) #Variable是torch.autograd的核心类,把用置零的邻接矩阵放在Variable里;autograd=true表示可以从Variable开始反向传播
pred_node_labels = torch.autograd.Variable(torch.zeros(node_labels.size())) #类比装鸡蛋的篮子,Variable代表鸡蛋个数,会不断变化;tensor代表鸡蛋,不变
if args.cuda:
pred_node_labels = pred_node_labels.cuda()
pred_adj_mat = pred_adj_mat.cuda() #若有GPU可以用,cuda可以将变量pred_node_labels,pred_adj_mat传到GPU上
autograd包为张量上的所有操作提供了自动求导.它是一个运行时定义的框架,这意味着反向传播是根据你的代码如何运行来定义,并且每次迭代可以不同。
volatile属性为True的节点不会求导,volatile的优先级比requires_grad高。
2020.4.24 稍微理解了一点模块间的调用,但是具体列表中的细节 还是不懂
16. expand_as(m_v)是改变tensor的形状和m_v一样
17. h_v[None].contiguous()
contiguous 本身是形容词,表示连续的,关于 contiguous,PyTorch 提供了is_contiguous
、contiguous
(形容词动用)两个方法 ,分别用于判定Tensor是否是 contiguous 的,以及保证Tensor是contiguous(会开辟一段新的连续内存)。
None类型NoneType,经常代表缺失的变量,就像 默认参数没有传递给函数一样
LinkFunction.py
18. 首先大体看了整个代码,LinkFunction这个类 是Module的子类,这个类中定义了9个方法。
19. self.learn_args = torch.nn.ParameterList([])
torch.nn.ParameterList,这个函数理解为类型转换函数,将一个 不可训练的类型Tensor 转换成可以训练的类型parameter并将这个parameter绑定到这个module里面,所以经过类型转换这个self.learn_args变成了模型的一部分,成为了模型中根据训练可以改动的参数了。使用这个函数的目的也是想让某些变量在学习的过程中不断的修改其值以达到最优化。
其实parameterList()就是一种和列表、元组之类一样的一种新的数据格式,用于保存神经网络权重及参数。
20. self.learn_modules = torch.nn.ModuleList([])
ModuleList([]) 这些类我们称之为容器 (containers),因为我们可以添加模块 (module) 到它们之中。它是一个储存不同 module,并自动将每个 module 的 parameters 添加到网络之中的容器。但是,我们需要注意到,nn.ModuleList 并没有定义一个网络,它只是将不同的模块储存在一起,这些模块之间并没有什么先后顺序可言。
继承Module,内部没有封装forward函数,只是使用append或者extend操作对list进行扩充,本质上是一个list;它和纯python中的list(list.append)不同,用nn.ModuleList或者ParameterList包裹模型各个层之后,我们不光可以像python里的list一样对模型的各个层进行索引,同时这些层的参数将会被自动注册,这些层的参数只有被正确注册之后,优化器才能发现和训练这些参数!
例如:self.learn_modules.append(torch.nn.Conv2d(input_size, hidden_size, 1))
Conv2d->def __init__(self, in_channels, out_channels, kernel_size, ...):
21. 其中link_def是linkfunction函数的输入,它是一个字符串
self.l_definition = '' #空字符串
self.l_definition = link_def.lower() #转换字符串中所有的大写字母为小写, 因为后边要查找该键对应的字典中的值,而字典中的键都是小写
22. dict.get(key,default) 字典的相关用法
init_parameters = {
'graphconv': self.init_graph_conv,
'graphconvlstm': self.init_graph_conv_lstm,
}.get(self.l_definition, lambda x: (torch.nn.ParameterList([]), torch.nn.ModuleList([]), {})) #返回值是个匿名函数,lambda自定义一个元组,
init_parameters() #调用的是返回的“值”所对应的函数
若没找到self.l_definition对应的键, 返回x。匿名函数lambda自定义一个包含三个元素的元组。
self.l_function = {
'graphconv': self.l_graph_conv,
'graphconvlstm': self.l_graph_conv_lstm,
}.get(self.l_definition, None) #dict.get(key,default)函数返回指定键key的值,如果值不在字典中返回默认值None。
# self.l_function不需要调用,因为这是函数自己的属性
23. for layer in self.learn_modules: 循环遍历self.learn_modules中的第layer个 元素
for _ in range(self.args['link_hidden_layers']-1): 循环的是range()后的 数值
都是循环的意思
2020.4.25 好久没看卷积相关知识点和公式,有点遗忘了
ConvLSTM.py
24. self.padding = (self.kernel_size - 1) / 2 #要填充的padding值
self.Gates = nn.Conv2d(input_size + hidden_size, 4 * hidden_size, self.kernel_size, padding=self.padding)
步长s为1,使输入和输出保持一致的空间维度【o = (i+2*p-f)/s + 1】;
2020.4.28
25. batch_size = input_.data.size()[0] #提取输入的数据的尺寸 第0维 是批处理次数; 第2维以后 是空间尺寸
spatial_size = input_.data.size()[2:]
26. state_size = [batch_size, self.hidden_size] + list(spatial_size)
这里的‘+’表示列表连接(与extend,append略有不同), LSTM状态初始化以及输入输出,
27. 对于LSTM,每一个A是一个核(lstmcell);
每个核内,代码和图对应如下(输入;Gates);
关于pytorch中的chunk
stacked_inputs = torch.cat((input_, prev_hidden), 1) #元组中元素值不能修改,但可进行连接组合;dims=1表示横着拼(按列)
gates = self.Gates(stacked_inputs) #Conv2d
# chunk across channel dimension
in_gate, remember_gate, out_gate, cell_gate = gates.chunk(4, 1) #切分成4块,(dims=1)竖着切,即列
# apply sigmoid non linearity
in_gate = torch.sigmoid(in_gate)
remember_gate = torch.sigmoid(remember_gate)
out_gate = torch.sigmoid(out_gate)
# apply tanh non linearity
cell_gate = torch.tanh(cell_gate)
# compute current cell and hidden state
cell = (remember_gate * prev_cell) + (in_gate * cell_gate) #prev_cell对应state_size,即图中的s(t-1)
hidden = out_gate * torch.tanh(cell)
return hidden, cell #即图中h(t)短时间记忆或工作记忆,s(t)长时间记忆
28. if hidden_layer_num < 1:
sys.exit("Hidden layer number less than 1.")
sys.exit(n) 退出程序引发SystemExit异常, 可以捕获异常执行些清理工作.n默认值为0, 表示正常退出. 其他都是非正常退出。
29. self.prev_states = [None for _ in range(self.hidden_layer_num)]
有n个隐藏层,就有n个prev_state
终端试验运行 >>> x=[None for i in range(5)];print(x) ->[None, None, None, None, None]
30. prev_state[0].detach_() #将 Variable 从创建它的 graph 中分离,把它作为叶子节点
prev_state[1].detach_() #列表中第0项h,第1项s ->.detach_()
detach_()相关链接 但这里具体是起了什么作用还是不太懂!!!
其实就相当于变量之间的关系本来是x -> m -> y,这里的叶子variable是x,但是这个时候对m进行了.detach_()操作,其实就是进行了两个操作:
# detach_ 的源码
def detach_(self):
"""Detaches the Variable from the graph that created it, making it a
leaf.
"""
self._grad_fn = None
self.requires_grad = False
torch.Tensor
是包的核心类。如果将其属性设置 .requires_grad
为True
,则会开始跟踪其上的所有操作。完成计算后,您可以调用.backward()
并自动计算所有梯度。该张量的梯度将累积到.grad
属性中。
要阻止张量跟踪历史记录,您可以调用.detach()
将其与计算历史记录分离,并防止将来的计算被跟踪。
31. python中的for循环总结(enumerate())
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
zip()返回一个以元组为元素的列表,其中第 i 个元组包含每个参数序列的第 i 个元素。
LSTM这里只是粗浅的了解了一下代码,具体原理还不是很清楚
MessageFunction.py,
UpdateFunction.py,ReadoutFunction.py(output_classes在哪返回?) (相似,不做过多重复笔记)
units文件夹中这四个.py文件之间输入输出的联系,每一部分所起作用,还需要再看
32. if hasattr(args, 'cuda') and args.cuda:
hasattr(args, 'cuda')和args.cuda都满足时,才会执行下边的语句
hasattr用于判断对象是否包含对应的属性
33. self.learn_modules.append(torch.nn.GRU(message_size, node_feature_size, num_layers=num_layers, bias=bias, dropout=dropout))
output, h = self.learn_modules[0](m_v, h_v)
关于GRU(RNNBase是父类)【rnn.py】
(RNNBase中)def __init__(self, mode->GRU, input_size(m_v), hidden_size(h_v),
num_layers=1, bias=True, batch_first=False, dropout=0., bidirectional=False):
2020.4.29 开始看datasets->HICO文件夹的内容,整体看了看,解决了两个问题,再看代码
34. target = target.cuda(async = True)
python3.7以后没有async关键字,(解决方法)直接用cuda();或用 async_ 代替;或用non_blocking代替
一旦固定了张量或存储,就可以使用异步的GPU副本。只需传递一个额外的async=True
参数到cuda()
的调用。这可以用于将数据传输与计算重叠 查到这里时找到了一份:PyTorch中文文档
35. import cv2 #(opencv-python)
”cv”和”cv2”表示的是底层C API和C++API的区别(不是版本号)
pip3 install opencv-python(在网速较好的情况下才可以安装成功)
终端验证:python >>>import cv2;print(cv2.__version__) 结果输出4.2.0,回到pycharm项目中cv2的红色波浪线消失。
roi_feature_model.py
36. import random random.random() 方法返回随机生成的一个实数,它在[0,1)范围内
针对scipy.misc.imread,新版scipy中没有.imead这个模块,所以需要对版本号进行降级。pip install scipy==1.2.1(在网络良好条件下可以安装)(scipy是基于numpy的)
conda的使用(包括虚拟环境创建改名删除)
2020.4.30
37. 针对shape
>>> import numpy as np
>>> x=np.array([1,2,3])
>>> print(x)
[1 2 3]
>>> print(x.shape[0])
3
>>> print(x.shape)
(3,)
38. return np.hstack((np.minimum(box1[:2], box2[:2]), np.maximum(box1[2:], box2[2:])))
np.hstack将参数元组的元素数组按水平方向进行叠加(np.vstack表示按垂直方向堆叠数组)
np.maximum()取对应位置上的大值,np.minimum 取对应位置上的较小值
这里的[:2]不包括索引2
39. new_box = box.copy()
copy()后的new_box不会再随着box改变;[:]是list的复制,会随之改变
40. anno_file = os.path.join(root, '{}_annotations.mat'.format(imageset))
将format内的内容(imageset)放到{}里,再拼接路径
41. ld = sio.loadmat(anno_file) #读
数据集都是mat格式的标注信息,使用模块scipy.io的函数loadmat和savemat可以实现Python对mat数据的读写。
42. 针对iou和NMS
43. np.save("anno_tune.npy", data)
.npy文件的打开 在终端找到了相应的位置,下载不了,allow_pickle=False
44.
with open(os.path.join(config.Paths().project_root, '{}_all.txt'.format(imageset))) as f:
for line in f.readlines():
image_list.append(line.strip())
这里with用于打开文件;使用 with as 语句操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源。
readlines()方法读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素,但读取大文件会比较占内存。
str.strip()用于去除头尾的空格
45. coco_to_hico = [hico_classes.index(c) for c in coco_classes]
例如coco_classes中的‘person’(在第一个位置),在hico_classes中的位置是50,则coco_to_hico[1]=50;
coco_to_hico是个包含很多数字的列表,它对应上了相同字符串的位置映射。
coco_to_hico是要从coco转换到hico的一个list;coco_classes是一个list,里边是包括人和物的字符串
c=coco_classes[i] i从0递增 是个字符串
.index(str)直接查找到字符串里面某个字符的位置
46. assert os.path.exists(image_path)
断言:确定这个路径存在,若不存在会引发assertionError
47. roi_image = original_img[roi[1]:roi[3]+1, roi[0]:roi[2]+1, :]
这是一个RGB图像的感兴趣区域(roi)的范围比如 第0维的范围是从(roi[1])到(roi[3]+1)
48. roi_image = cv2.resize(roi_image, self.imsize, interpolation=cv2.INTER_LINEAR)
原图像roi_image;输入的input_imsize决定了裁剪的大小;线性插值Linear Interpolation(已知两个点的坐标可以得到一条线,又已知线上一点的一个坐标可以求得这个点的另一个坐标值。这就是线性插值的原理)
cv2.INTER_LINEAR 双线性插值,用于放大,核心思想是在两个方向分别进行一次线性插值。
49. roi_image = np.fliplr(roi_image).copy()
roi_image图像矩阵左右翻转(.shape形状不变)
50. roi_image = self.transform(roi_image)
transform?对数据进行某种统一处理
51. torch.utils.data.Dataset
是代表自定义数据集方法的抽象类,可以定义自己的数据类继承这个抽象类,非常简单,只需要定义__len__
和__getitem__
这两个方法就可以。(数据读取Dataset,DataLoader)
class HICO(torch.utils.data.Dataset):
def __init__(self, root, input_imsize, transform, imageset):
def __getitem__(self, index):
return roi_image, label
def __len__(self):
return len(self.img_files)
52. self.features = torchvision.models.vgg16(pretrained=True).features
导入参数和网络结构 特征 pytorch中的torchvision包有三个子包,分别是.datasets;.models;.transforms
53. self.classifier = torch.nn.Sequential()
nn.Sequential() 有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行.
54.
def _initialize_weights(self):
for m in self.modules(): #a module in the network
if isinstance(m, torch.nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_() #m.weight.data是卷积核参数, m.bias.data是偏置项参数
elif isinstance(m, torch.nn.Linear):
m.weight.data.normal_(0, 0.01) #均值 方差(正态分布)
m.bias.data.zero_()
isinstance(m, torch.nn.BatchNorm2d) isinstance(a,b)判断a是否是b类型,是就返回true
55. x = x.view(x.size(0), -1)
torch里面,view函数相当于numpy的reshape 。 -1表示不确定的数 。
将前面多维度的tensor展平成一维[x.size(0)指batchsize?]
56. PyTorch框架中有一个包:torchvision,该包主要由3个子包组成,分别是:torchvision.datasets、torchvision.models、torchvision.transforms。
normalize = torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
#.Normalize用来做数据归一化 ‘ input[channel] = (input[channel] - mean[channel]) / std[channel]’
torchvision.transforms.Compose([torchvision.transforms.ToTensor(), normalize])
#.Compose([]) 这个类是用来管理各个transform的
#.ToTensor() Convert a PIL Image
or numpy.ndarray
to tensor
2020.5.1
roi_pooling.py(torch中已经实现了自适应池化层(troch.nn.functional.adaptive_max_pool2d))
57. indices = input.new().long()
new()创建一个新的Tensor,该Tensor的type和device都和原有Tensor一致,且无内容。
long() 函数将数字或字符串转换为一个长整型。
58. type(input) 是查询input的数据类型。
59. rois = rois.data.float() #.float()转换为十进制浮点数
什么时候需要用 .data来读取数据???
60. x = torch.Tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
x.shape >>> torch.Size([3, 3])
注意不是print(x.shape())
61. 对于变量,有时候需要去变量的某一维度的某几个值,可以使用narrow函数
data = x.narrow(dimension, start, length) → Tensor
表示取变量x的第dimension维,从索引start开始到,start+length-1范围的值,赋值给data。
parse_features.py
62. bbox = np.array(bbox, dtype=np.float32)
array会copy出一个副本,占用新的内存,但asarray不会。
Ctrl+B -> def array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
63. import pickle 用于python特有的类型和python的数据类型间进行转换
pickle.dump(instance, open(os.path.join(save_data_path, '{}.p'.format(filename)), 'wb'))
instance是要封装的对象;open()是要写入的文件对象;以二进制可写模式打开 ['r'表示只读]
2020.5.2
64. os.path.splitext()将文件名和扩展名分开
'/home/xuan/pycharmpro/gpnn/bbox.py' -> /home/xuan/pycharmpro/gpnn/bbox + .py
65. break和continue的区别 最开始的知识点还是记错了。。。
break表示结束整个循环;continue表示结束这次循环,进入到下一次循环
2020.5.3
extract_vgg_features.py
66. self.conv_block=torch.nn.Sequential()
self.conv_block.add_module("conv1",torch.nn.Conv2d(3, 32, 3, 1, 1))
对应着:Sequential(
(conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
)
for x in range(len(pretrained_vgg.features)): #Parameter features of torchvision.models.vgg.VGG.__init__
self.features.add_module(str(x), pretrained_vgg.features[x])
67. pickle.load(f) #数据的加载,默认解码为ASCII码进行输出; 读取pkl文件需要import pickle包
68. det_boxes_all = np.vstack((det_boxes_all, np.array(detection[:4])[np.newaxis, ...]))
np.newaxis表示在该位置增加一维,这里是变为二维;np.vstack按垂直方向(行顺序)堆叠数组构成一个新的数组。
69. det_classes_all.extend(edge_classes)
extend只能添加可迭代对象,会将添加对象进行迭代,迭代的元素挨个添加到被添加的数组中
70. np.ndarray的[h, w, c]转为Tensor的[c, h, w]
2020.5.6
extract_roi_features.py
71. .startswith()用于检查字符串是否以指定子字符串开头。如果是则返回 True,否则返回 False。如果参数 beg 和 end 指定值,则在指定范围内检查。
torch.nn.DataParallel() 多GPUs训练
if feature_type.startswith('alexnet') or feature_type.startswith('vgg'):
feature_network.features = torch.nn.DataParallel(feature_network.features) #默认所有存在的显卡都会被使用 features
feature_network.cuda()
else:
feature_network = torch.nn.DataParallel(feature_network).cuda()
但这里搞不懂,为什么要分成特征和网络两种情况???
72. np.empty((0, 4)) >>>array([], shape=(0, 4), dtype=float64)
find_rare_hoi.py (代码细节不懂), hico.py
73. import argparse
argparse 是 Python 内置的一个用于命令项选项与参数解析的模块,通过在程序中定义好我们需要的参数,argparse 将会从 sys.argv 中解析出这些参数,并自动生成帮助和使用信息。
def parse_arguments():
paths = hico_config.Paths()
parser = argparse.ArgumentParser(description='HICO dataset') #创建 ArgumentParser() 对象
parser.add_argument('--data-root', default=paths.data_root, help='dataset path') #调用 add_argument() 方法添加参数
parser.add_argument('--tmp-root', default=paths.tmp_root, help='intermediate result path') #中间结果路径
return parser.parse_args() #使用 parse_args() 解析添加的参数
finetune.py
74. import shutil 大量的文件的高级操作
shutil.copyfile(os.path.join(args.resume, filename), os.path.join(args.resume, 'model_best.pth'))
#将filename文件赋值并重命名为model_best.pth
shutil.rmtree(path)删除整个path指向的整个目录树;!!!项目中的args好像是个目录树(.resume应该是个路径)
75. 在Python编程语言中可以使用os.path.isdir(path)函数判断某一路径是否为目录。
os.path.isfile(path)函数判断某一路径是否为文件。
os.remove(path)函数删除指定路径的文件
76. torch.backends.cudnn.benchmark = True (pytorch=0.3.1) ???
在底层优化卷积层,进而在完全不改变输入的卷积神经网络模型的情况下提高效率.可以提升一点训练速度,没什么额外开销。
77. torch.utils.data.DataLoader
DataLoader是PyTorch中数据读取的一个重要接口,只要是用PyTorch来训练模型基本都会用到该接口(除非用户重写…)
该接口的目的:将Dataset根据batch size大小、是否shuffle等封装成一个Batch Size大小的Tensor,用于后面的训练。
torch.utils.data.DataLoader(
dataset,#数据加载
batch_size = 1,#批处理大小设置
shuffle = False,#是否进项洗牌操作
sampler = None,#指定数据加载中使用的索引/键的序列
batch_sampler = None,#和sampler类似
num_workers = 0,#是否进行多进程加载数据设置
collate_fn = None,#是否合并样本列表以形成一小批Tensor
pin_memory = False,#如果True,数据加载器会在返回之前将Tensors复制到CUDA固定内存
drop_last = False,#True如果数据集大小不能被批处理大小整除,则设置为删除最后一个不完整的批处理。
timeout = 0,#如果为正,则为从工作人员收集批处理的超时值
worker_init_fn = None )
78. model.eval() 固定BN和dropout层,使得偏置参数不随着发生变化
79. .data是对象的属性,若有变量用到.data,说明肯定最后继承了object。
80. np.argmax(a) 取出元素a中最大值对应的索引
81. Python中‘\t’表示四个空格,即按下一个tab键
82. is_best = prec1 > best_prec1
is_best = prec1(赋值), 若is_best> best_prec1则返回true
83. torch.save(state,dir) [state=dict{} dir要保存的路径]
保存模型参数,优化器参数以及epoch;可以恢复前一阶段训练(或测试)
84. model.train() #启用 BatchNormalization 和 Dropout (在训练中加入) ;测试中是model.eval() 不启用
85.
optimizer.zero_grad() #把梯度置零,也就是把loss关于weight的导数变成0. 即将模型参数 梯度初始化为零
loss.backward() #反向传播求梯度
optimizer.step() #更新所有参数
86. Python 运算符
lr = args.lr * (0.8 ** (epoch // 2)) //:取整除 - 返回商的整数部分(9//2 = 4) ; a**b:a的b次幂
2020.5.7 logutil.py
87. import tensorboard_logger
tensorboard_logger
是由TeamHG-Memex
开发的使用tensorboard
的库(可视化),可以访问文档界面,安装也略微有点繁琐,需要安装tensorflow
和他们开发的tensorboard_logger
,安装完成之后按照文档的使用说明就可以使用tensorboard
了。 (①pip install tensorflow==2.0.0 ②pip install tensorboard_logger)
tensorboard_logger.configure(logdir, flush_secs=2) 配置日志记录:将一个文件写入 logdir,并刷新每个 flush_secs。tensorboard_logger.log_value(name, value, step=None) 在给定的step 上记录给定 name的新 value。
visualization_utils.py
88. python关于list[::-1]翻转的用法
89. np.ceil(ndarray) 计算ndarray中每个值大于等于的最小整数(向上取整)
90. tuple() 函数将列表转换为元组。
91. if np.any(np.logical_or(mask > 1.0, mask < 0.0)):
any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False;如果有一个为 True,则返回 True。
np.logical_or()返回mask > 1.0和mask < 0.0或逻辑后的布尔值。
92. solid_color = np.expand_dims( np.ones_like(mask), axis=2) * np.reshape(list(rgb), [1, 1, 3])
np.expand_dims扩展数组维度;np.ones_like创建同shape的全1矩阵
2020.5.8
93. Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
94. Numpy中ndim、shape、dtype、astype的用法
95. 关于PIL(pillow)的一些模块介绍:Image模块 ;ImageColor模块 ;ImageFont模块 ;ImageDraw模块
96. collections.defaultdict(list)
import six #six是为了解决Python2 和 Python3 代码兼容性而产生的
import collections #collections.defaultdict(list)
import PIL.Image as Image #Python图像处理库(Pillow)
import PIL.ImageColor as ImageColor
import PIL.ImageDraw as ImageDraw
import PIL.ImageFont as ImageFont
box_to_display_str_map = collections.defaultdict(list) #返回一个类似字典的对象。可以很容易将键-值对序列转换为列表字典
datasets/utils.py (收集数据集的边点特征,标签,数量序号;best checkpoint)
python/utils.py ()
97. import itertools #用于操作迭代对象的函数
【Python】itertools之product函数
98. sequence_ids = np.random.permutation(sequence_ids) #随机排序
99. import matplotlib.gridspec #加入后72行阴影消失,gridspec是.py文件,需要调用
gridspec = matplotlib.gridspec.GridSpec(len(labels_list), 1) #调整子图的位置和大小
hico_graph.py
100. torch.nn.MultiLabelSoftMarginLoss(weight=weight_mask).cuda()(output, target)
MultiLabelMarginLoss 用于一个样本属于多个类别时的分类任务
PyTorch的十八个损失函数 weight搞不懂!!!
101.
optimizer.zero_grad() #梯度(loss关于weight的导数)置零, 如果不清零,那么使用的这个grad就得同上一个mini-batch有关,这不是我们需要的结果
train_loss.backward() #求loss关于weight的导数
optimizer.step() #使用当前参数空间对应的梯度
hico.py (看完这个打算整体看一下HICO和对应论文)
102.
avg_prec = sklearn.metrics.average_precision_score(y_true, y_score, average=None) #AP
mean_avg_prec = np.nansum(avg_prec) / len(avg_prec) #MAP np.nansum数据相加
103. sio.savemat(os.path.join(args.tmp_root, 'results', 'HICO', 'detections_' + str(obj_idx).zfill(2) + '.mat'), {'all_boxes': obj_arr})
zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
104. timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
fromtimestamp 时间戳转换成字符串日期时间
2020.5.15 整体看一遍gpnn论文对应代码,大致能理顺下来,但是具体的路径及保存的文件有点蒙
105.今天发现了Ubuntu截图的一种方式,系统自带“截图”软件,搜索后打开就可以用了,非常简单。
并且学会了在终端Python下编写for循环程序,要结束循环按“enter”键即可