花园宝宝战队 ----- 一阶段代码注释成果 #10
|
|
@ -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_param,first_key,second_param,second_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
|
||||
Loading…
Reference in New Issue