花园宝宝战队 ----- 一阶段代码注释成果 #10

Open
bjutsecurity22 wants to merge 139 commits from bjutsecurity22/mindspore2022:master into master
1 changed files with 129 additions and 23 deletions
Showing only changes of commit 90bd9f63b4 - Show all commits

View File

@ -19,60 +19,83 @@ from ..cell import Cell
__all__ = ['SequentialCell', 'CellList']
#用于检测搜索的值和类型是否有效,从而避免在神经网络中出现错误
def _valid_index(cell_num, index, op_name=None):
"""Internal function, used to detect the value and type of index."""
msg_prefix = f"For '{op_name}', the" if op_name else "The"
#检查索引类型是否为int
if not isinstance(index, int):
# 如果不是,抛出类型错误
raise TypeError(f"{msg_prefix} type of 'index' should be int, but got {type(index).__name__}.")
#检查索引是否在cell_num范围内
if not -cell_num <= index < cell_num:
#如果不在,抛出索引错误
raise IndexError(f"{msg_prefix} value of 'index' should be a number in range [{-cell_num}, {cell_num}), "
f"but got {index}.")
#返回索引对应的整数
return index % cell_num
#用于检查输入的Cell是否为Cell子类来处理卷积神经网络中Cell合并和连接
def _valid_cell(cell, op_name=None):
"""Internal function, used to check whether the input cell is a subclass of Cell."""
#判断cell是否是Cell的子类
if issubclass(cell.__class__, Cell):
# 如果是返回True
return True
#如果不是,拼接提示信息
msg_prefix = f"For '{op_name}'," if op_name else ""
#抛出异常
raise TypeError(f'{msg_prefix} each cell should be subclass of Cell, but got {type(cell).__name__}.')
#获得字符串前缀和索引
def _get_prefix_and_index(cells):
"""get prefix and index of parameter name in sequential cell or cell list."""
#给prefix和index赋值
prefix = ""
index = 0
#如果cells为空则返回prefix和index
if not cells:
return prefix, index
#将cells字典转换为列表
cell_list = list(cells.items())
#定义变量first_paramfirst_keysecond_paramsecond_key
first_param, first_key = None, None
second_param, second_key = None, None
#遍历cells字典
for key, cell in cell_list:
try:
#获取cell中的参数和名称
_, param = next(cell.parameters_and_names())
except StopIteration:
#如果遍历完cells字典则跳出循环
continue
#如果first_param为空则将参数和名称赋值给first_param和first_key
if first_param is None:
first_param = param
first_key = key
continue
#如果second_param为空则将参数和名称赋值给second_param和second_key
second_param = param
second_key = key
#跳出循环
break
#如果first_param为空返回prefix和index
if first_param is None:
return prefix, index
split_names = first_param.name.split(".")
#遍历split_names从第一个元素开始拆分出每一个元素
for idx, name in enumerate(split_names):
#如果拆分出的元素与first_key相同则将prefix设置为拆分出的元素
if name == first_key:
prefix = ".".join(split_names[:idx])
prefix = prefix + "." if prefix else prefix
index = idx
#如果second_param不为空且拆分出的元素与second_key相同则结束循环
if second_param is not None and second_param.name.split(".")[idx] == second_key:
break
#返回prefix和index
return prefix, index
@ -93,16 +116,18 @@ class _CellListBase:
@abstractmethod
def __len__(self):
#返回自身的长度
pass
@abstractmethod
def __getitem__(self, index):
#返回索引index对应的元素
pass
def construct(self):
raise NotImplementedError
#用于表示一个顺序存储的单元格列表构造Cell顺序容器
#其继承了_CellListBase来实现相关方法
class SequentialCell(Cell):
"""
Sequential Cell container. For more details about Cell, please refer to
@ -162,82 +187,122 @@ class SequentialCell(Cell):
def __init__(self, *args):
"""Initialize SequentialCell."""
super(SequentialCell, self).__init__()
#初始化参数
self._is_dynamic_name = []
#初始化变量
if len(args) == 1:
cells = args[0]
#如果参数是列表,则将其转换为字典
if isinstance(cells, list):
for index, cell in enumerate(cells):
#将子类插入到cell中
self.insert_child_to_cell(str(index), cell)
#将cell的参数名更新为index+"."
cell.update_parameters_name(str(index) + ".")
#将变量添加到变量列表中
self._is_dynamic_name.append(True)
#如果参数是字典,则将其转换为列表
elif isinstance(cells, OrderedDict):
for name, cell in cells.items():
#将子类插入到cell中
self.insert_child_to_cell(name, cell)
#将cell的参数名更新为name+"."
cell.update_parameters_name(name + ".")
#将变量添加到变量列表中
self._is_dynamic_name.append(False)
else:
#返回错误
raise TypeError(f"For '{self.__class__.__name__}', the 'args[0]' must be list or orderedDict, "
f"but got {type(cells).__name__}")
else:
for index, cell in enumerate(args):
#将cell插入到cell_list中
self.insert_child_to_cell(str(index), cell)
#将cell的参数名添加到_is_dynamic_name中
cell.update_parameters_name(str(index) + ".")
self._is_dynamic_name.append(True)
#将cells转换为列表
self.cell_list = list(self._cells.values())
#在这里我们来解释一下slice类其用于表示切片来用于从序列之中获取子序列的抽象概念
#用于实现索引访问单元列表操作
def __getitem__(self, index):
if isinstance(index, slice):
#如果index是一个slice则返回一个新的OrderedDict其中包含self._cells中的指定位置的元素
return self.__class__(
OrderedDict(list(self._cells.items())[index]))
#如果index是一个整数则检查index是否在self._cells中若在则返回self._cells中的指定位置的元素否则抛出异常
index = _valid_index(len(self), index, self.__class__.__name__)
#返回list
return list(self._cells.values())[index]
#用于实现索引访问单元列表操作
def __setitem__(self, index, cell):
cls_name = self.__class__.__name__
#检查cell是否符合要求
if _valid_cell(cell, cls_name):
#获取cell的前缀和索引
prefix, _ = _get_prefix_and_index(self._cells)
#检查索引是否合法
index = _valid_index(len(self), index, cls_name)
#获取cell的键
key = list(self._cells.keys())[index]
#将cell添加到self._cells中
self._cells[key] = cell
#更新cell的参数名
cell.update_parameters_name(prefix + key + ".")
#更新self.cell_list
self.cell_list = list(self._cells.values())
#用于实现删除索引单元列表操作
def __delitem__(self, index):
cls_name = self.__class__.__name__
if isinstance(index, int):
#如果index是int类型则将index转换为_valid_index函数的返回值
index = _valid_index(len(self), index, cls_name)
#获取key
key = list(self._cells.keys())[index]
#删除key
del self._cells[key]
#删除is_dynamic_name中index
del self._is_dynamic_name[index]
elif isinstance(index, slice):
#如果index是slice类型则获取keys
keys = list(self._cells.keys())[index]
#遍历keys删除key
for key in keys:
del self._cells[key]
#删除is_dynamic_name中index
del self._is_dynamic_name[index]
else:
#如果index不是int类型或者slice类型则抛出TypeError异常
raise TypeError(f"For '{cls_name}', the type of index should be int type or slice type, "
f"but got {type(index).__name__}")
#获取prefix和key_index
prefix, key_index = _get_prefix_and_index(self._cells)
#创建一个临时字典
temp_dict = OrderedDict()
#遍历cells将key和cell添加到temp_dict中
for idx, key in enumerate(self._cells.keys()):
cell = self._cells[key]
#如果is_dynamic_name中idx为True则将cell添加到temp_dict中
if self._is_dynamic_name[idx]:
for _, param in cell.parameters_and_names():
param.name = prefix + str(idx) + "." + ".".join(param.name.split(".")[key_index+1:])
temp_dict[str(idx)] = cell
else:
temp_dict[key] = cell
#将temp_dict中的值赋值给cells
self._cells = temp_dict
#将cells中的值赋值给self.cell_list
self.cell_list = list(self._cells.values())
#获取长度
def __len__(self):
#返回长度
return len(self._cells)
#设置单元表格梯度
def set_grad(self, flag=True):
self.requires_grad = flag
#检查是否设置梯度
for cell in self._cells.values():
cell.set_grad(flag)
def append(self, cell):
"""
Appends a given Cell to the end of the list.
@ -264,16 +329,23 @@ class SequentialCell(Cell):
[[26.999863 26.999863]
[26.999863 26.999863]]]]
"""
#_valid_cell函数用于检查给定的单元是否有效
if _valid_cell(cell, self.__class__.__name__):
prefix, _ = _get_prefix_and_index(self._cells)
#将当前cell的名称添加到prefix中
cell.update_parameters_name(prefix + str(len(self)) + ".")
#将当前cell添加到self._cells中
self._is_dynamic_name.append(True)
#将当前cell添加到self._is_dynamic_name中
self._cells[str(len(self))] = cell
#将self._cells中的值赋值给self.cell_list
self.cell_list = list(self._cells.values())
#创建表格
def construct(self, input_data):
for cell in self.cell_list:
#调用cell函数传入input_data参数
input_data = cell(input_data)
#返回input_data参数值
return input_data
@ -301,63 +373,84 @@ class CellList(_CellListBase, Cell):
>>> cell_ls.append(relu)
>>> cell_ls.extend([relu, relu])
"""
#初始化
def __init__(self, *args, **kwargs):
"""Initialize CellList."""
auto_prefix = kwargs["auto_prefix"] if "auto_prefix" in kwargs.keys() else True
#初始化CellListBase类
_CellListBase.__init__(self)
#初始化Cell类
Cell.__init__(self, auto_prefix)
#如果只有一个参数则将其追加到CellListBase中
if len(args) == 1:
self.extend(args[0])
#调用
def __getitem__(self, index):
cls_name = self.__class__.__name__
#如果index是slice类型则返回一个新的list其中包含self._cells中的值
if isinstance(index, slice):
return self.__class__(list(self._cells.values())[index])
#如果index是int类型则根据index的长度获取对应的index并返回self._cells中对应的值
if isinstance(index, int):
index = _valid_index(len(self), index, cls_name)
return self._cells[str(index)]
#如果index的类型不是int或slice则抛出TypeError异常
raise TypeError(f"For '{cls_name}', the type of 'index' should be int or slice, "
f"but got {type(index).__name__}.")
#修改对象数值
def __setitem__(self, index, cell):
cls_name = self.__class__.__name__
#判断索引是否为整数并且cell是否为有效cell
if not isinstance(index, int) and _valid_cell(cell, cls_name):
raise TypeError(f"For '{cls_name}', the type of 'index' should be int, "
f"but got {type(index).__name__}.")
#如果自动前缀为True则获取前缀和索引
index = _valid_index(len(self), index, cls_name)
#如果自动前缀为True则更新参数名
if self._auto_prefix:
prefix, _ = _get_prefix_and_index(self._cells)
cell.update_parameters_name(prefix + str(index) + ".")
#将索引和cell添加到self._cells中
self._cells[str(index)] = cell
#用于实现删除索引单元列表操作
def __delitem__(self, index):
cls_name = self.__class__.__name__
if isinstance(index, int):
#如果index是int类型则将index转换为_valid_index函数的返回值
index = _valid_index(len(self), index, cls_name)
#将_valid_index函数的返回值赋值给index
del self._cells[str(index)]
elif isinstance(index, slice):
#如果index是slice类型则遍历self._cells字典将每一项删除
keys = list(self._cells.keys())[index]
for key in keys:
del self._cells[key]
else:
#如果index不是int类型或slice类型则抛出TypeError异常
raise TypeError(f"For '{cls_name}', the type of 'index' should be int or slice, "
f"but got {type(index).__name__}.")
# adjust orderedDict
prefix, key_index = _get_prefix_and_index(self._cells)
#创建一个空用于存储cell
temp_dict = OrderedDict()
#遍历cells中的每一个cell
for idx, cell in enumerate(self._cells.values()):
#如果自动前缀则把cell中的参数名称添加到前缀中
if self._auto_prefix:
for _, param in cell.parameters_and_names():
param.name = prefix + str(idx) + "." + ".".join(param.name.split(".")[key_index+1:])
#添加cell
temp_dict[str(idx)] = cell
#更新cell
self._cells = temp_dict
#获取长度
def __len__(self):
#返回长度
return len(self._cells)
#返回迭代器
def __iter__(self):
return iter(self._cells.values())
#实现对象间加法
def __iadd__(self, cells):
self.extend(cells)
return self
@ -385,7 +478,7 @@ class CellList(_CellListBase, Cell):
self._cells[str(idx)] = cell
if self._auto_prefix:
cell.update_parameters_name(prefix + str(idx) + ".")
#迭代器,将 cells 中的每个元素添加到 MyContainer 对象的末尾
def extend(self, cells):
"""
Appends Cells from a Python iterable to the end of the list.
@ -397,15 +490,23 @@ class CellList(_CellListBase, Cell):
TypeError: If the argument cells are not a list of Cells.
"""
cls_name = self.__class__.__name__
#判断cells是否为list类型
if not isinstance(cells, list):
# 如果不是,抛出错误
raise TypeError(f"For '{cls_name}', the new cells wanted to append "
f"should be instance of list, but got {type(cells).__name__}.")
#获取cells的前缀和索引
prefix, _ = _get_prefix_and_index(self._cells)
#遍历cells
for cell in cells:
#判断cell是否有效
if _valid_cell(cell, cls_name):
#如果自动前缀更新cell的参数名
if self._auto_prefix:
cell.update_parameters_name(prefix + str(len(self)) + ".")
#将cell添加到self._cells中
self._cells[str(len(self))] = cell
#返回self
return self
def append(self, cell):
@ -416,15 +517,20 @@ class CellList(_CellListBase, Cell):
cell(Cell): The subcell to be appended.
"""
if _valid_cell(cell, self.__class__.__name__):
#如果cell是有效的cell则更新cell的参数名
if self._auto_prefix:
#获取cell的前缀和索引
prefix, _ = _get_prefix_and_index(self._cells)
#更新cell的参数名
cell.update_parameters_name(prefix + str(len(self)) + ".")
#将cell添加到self._cells中
self._cells[str(len(self))] = cell
#设置单元表格梯度
def set_grad(self, flag=True):
self.requires_grad = flag
#检查是否设置梯度
for cell in self._cells.values():
cell.set_grad(flag)
#创建表格
def construct(self, *inputs):
raise NotImplementedError
raise NotImplementedError