forked from huawei/mindspore2022
Compare commits
No commits in common. "master" and "master" have entirely different histories.
|
|
@ -1,5 +1,5 @@
|
|||

|
||||
X
|
||||
|
||||
[](https://pypi.org/project/mindspore)
|
||||
[](https://badge.fury.io/py/mindspore)
|
||||
[](https://pepy.tech/project/mindspore)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ class Base;
|
|||
}
|
||||
|
||||
namespace mindspore::api {
|
||||
|
||||
/// \brief Base is the base class of many api classes, which provides basic interfaces.
|
||||
class MIND_API Base {
|
||||
public:
|
||||
|
|
@ -46,9 +45,9 @@ class MIND_API Base {
|
|||
/// \return The id of this class.
|
||||
static uint32_t ClassId();
|
||||
|
||||
/// \brief Get the shared_ptr to the underlying implementation object.
|
||||
/// \brief Get the shared_ptr to the underly implementation object.
|
||||
///
|
||||
/// \return The shared_ptr to the underlying implementation object.
|
||||
/// \return The shared_ptr to the underly implementation object.
|
||||
const std::shared_ptr<mindspore::Base> &impl() const { return impl_; }
|
||||
|
||||
/// \brief Get the string representation of this object.
|
||||
|
|
|
|||
|
|
@ -632,111 +632,72 @@ class GeneratorDataset(MappableDataset, UnionBaseDataset):
|
|||
def __init__(self, source, column_names=None, column_types=None, schema=None, num_samples=None,
|
||||
num_parallel_workers=1, shuffle=None, sampler=None, num_shards=None, shard_id=None,
|
||||
python_multiprocessing=True, max_rowsize=6):
|
||||
#调用父类构造函数,将num_parallel_workers sampler sampler shuffle num_shards shard_id传入
|
||||
super().__init__(num_parallel_workers=num_parallel_workers, sampler=sampler, num_samples=num_samples,
|
||||
shuffle=shuffle, num_shards=num_shards, shard_id=shard_id)
|
||||
##如果source是一个zip对象,转换为列表
|
||||
if isinstance(source, builtins.zip):
|
||||
# Although zip is iterable, it does not have the feature of repeated iteration, so pass it to the array.
|
||||
#zip是迭代器 不能重复迭代,这里把zip转换成列表再赋值给source
|
||||
# Although zip is iteratable, it does not have the feature of repeated iteration, so pass it to the array.
|
||||
self.source = [item for item in source]
|
||||
#若source不是zip对象,输入的直接赋值给self.source
|
||||
else:
|
||||
self.source = source
|
||||
#self.prepared_source赋值为none
|
||||
self.prepared_source = None # source to be sent to C++
|
||||
|
||||
##若对象有operator_mixed属性,且该属性为true
|
||||
if hasattr(self, 'operator_mixed') and getattr(self, 'operator_mixed') is True:
|
||||
#对象的num_parallel_workers赋值为1
|
||||
self.num_parallel_workers = 1
|
||||
#输出警告信息:存在一些不支持多线程编译的运算符,建议将它们替换为 Python 实现的运算符
|
||||
logger.warning(
|
||||
"Input 'source' of 'GeneratorDataset' includes network computing operators like in mindspore.nn, "
|
||||
"mindspore.ops, mindspore.numpy module and etc, which do not support multi-thread compiling, recommend"
|
||||
" to replace it with python implemented operator like numpy etc. Here decrease 'num_parallel_workers' "
|
||||
"into 1.")
|
||||
#若当前平台为windows,且num_parallel_workers > 1,输出警告信息“Python 的多进程功能在 Windows 平台上不受支持”
|
||||
if platform.system().lower() == 'windows' and num_parallel_workers > 1 and python_multiprocessing:
|
||||
logger.warning("Python multiprocessing is not supported on Windows platform.")
|
||||
#若当前操作系统是windows,把python_multiprocessing赋值给self.python_multiprocessing,若不是,后者赋值为false
|
||||
self.python_multiprocessing = python_multiprocessing if platform.system().lower() != 'windows' else False
|
||||
#若self.python_multiprocessing 属性的值为 True,且当前处于调试模式,警告:多进程功能在调试模式下不受支持,并把python_multiprocessing设置回false
|
||||
if self.python_multiprocessing and get_debug_mode():
|
||||
logger.warning("Python multiprocessing is not supported in debug mode."
|
||||
" Ignoring Python multiprocessing for GeneratorDataset.")
|
||||
self.python_multiprocessing = False
|
||||
#把column_names转换成列表,赋值给self.column_names
|
||||
|
||||
self.python_multiprocessing = python_multiprocessing
|
||||
|
||||
self.column_names = to_list(column_names)
|
||||
#若column_types不为None,调用mstypelist_to_detypelist函数把column_types赋值给self.column_types
|
||||
#mstypelist_to_detypelist函数将 MindSpore 类型列表转换为 DE 类型列表。
|
||||
|
||||
if column_types is not None:
|
||||
self.column_types = mstypelist_to_detypelist(column_types)
|
||||
else:
|
||||
self.column_types = []
|
||||
#把self.schema赋值为schema值,仅在None值时有用
|
||||
|
||||
self.schema = schema
|
||||
##若schema不为None,即构造时传入了schema的值时,将传入的 schema 参数赋值给 self.schema,并保证schema是Schema 类的实例
|
||||
if schema is not None:
|
||||
self.schema = schema
|
||||
#若schema 不为 Schema 类的实例,使用 Schema 类的构造函数创建一个新的 Schema 对象,并将其赋值给 self.schema
|
||||
if not isinstance(schema, Schema):
|
||||
self.schema = Schema(schema)
|
||||
# Move get dataset_size by len from parse to here, because self.source will
|
||||
# lose attribution of '__len__' after deepcopy.
|
||||
#self.source 在进行deepcopy后会丢失 __len__ 属性
|
||||
self.source_len = -1 # 表示未知
|
||||
|
||||
#若self.source 对象有 __len__ 属性,获取self.source长度到self.source_len里
|
||||
self.source_len = -1 # unknown
|
||||
if hasattr(self.source, "__len__"):
|
||||
self.source_len = len(self.source)
|
||||
|
||||
# if user defined sampler, update the self.source_len
|
||||
#如果用户定义了采样器,要更新数据集的大小
|
||||
#若self.sampler为samplers.Sampler类的实例,或者self.sampler有__iter__属性
|
||||
#然后将 sampler 转换为列表并获取其长度,然后将结果赋值给 self.source_len
|
||||
if isinstance(self.sampler, samplers.Sampler) or hasattr(self.sampler, "__iter__"):
|
||||
self.source_len = len(list(sampler))
|
||||
|
||||
self.max_rowsize = max_rowsize
|
||||
self.sample_fn = None
|
||||
#该函数进行深拷贝处理
|
||||
|
||||
def __deepcopy__(self, memodict):
|
||||
#如果memodict 里已经存在当前对象的拷贝(已经拷贝过)(检查了 memodict 字典中是否存在键为 id(self) 的项),直接返回拷贝
|
||||
if id(self) in memodict:
|
||||
return memodict[id(self)]
|
||||
#用 __safe_deepcopy__创建新对象,排除了"source", "__transfer_dataset__"
|
||||
new_op = self.__safe_deepcopy__(memodict, exclude=("source", "__transfer_dataset__"))
|
||||
|
||||
|
||||
sample_fn = None
|
||||
## 如果new_op中的 sampler 不是空的,而且原对象的source可以操作索引(`__getitem__` 方法存在)
|
||||
if new_op.sampler is not None and hasattr(self.source, "__getitem__"):
|
||||
# The reason why there is a try catch here is because when the new op is being constructed with shared
|
||||
# memory enabled, there will be an exception thrown if there is not enough shared memory available
|
||||
#内存不够可能会错误
|
||||
if self.source_len == -1:#若长度还是未知,警告 需要“__len__”方法
|
||||
if self.source_len == -1:
|
||||
raise RuntimeError("Attempt to construct a random access dataset, '__len__' method is required!")
|
||||
try:
|
||||
#若num_parallel_workers 大于 1
|
||||
if new_op.num_parallel_workers > 1:
|
||||
#调用此方法 似乎是检查内存使用情况
|
||||
self.__validate_memory_usage()
|
||||
#创建SamplerFn对象
|
||||
|
||||
sample_fn = SamplerFn(self.source, new_op.num_parallel_workers, self.python_multiprocessing,
|
||||
self.max_rowsize)
|
||||
new_op.prepared_source = (lambda sample_ids: _cpp_sampler_fn_mp(sample_ids, sample_fn))
|
||||
else:
|
||||
new_op.prepared_source = (lambda sample_ids: _cpp_sampler_fn(sample_ids, self.source))
|
||||
new_op.sample_fn = sample_fn
|
||||
#遇到问题抛出异常
|
||||
except RuntimeError as e:
|
||||
raise Exception(str(e))
|
||||
else:
|
||||
try:
|
||||
#如果新对象的sampler为空,设置sample_fn为None
|
||||
new_op.sampler = None
|
||||
new_op.sample_fn = sample_fn
|
||||
#设置source_len为num_samples和source_len中的较小值
|
||||
new_op.source_len = min(new_op.source_len,
|
||||
new_op.num_samples) if new_op.num_samples != 0 else new_op.source_len
|
||||
iter(self.source)
|
||||
|
|
@ -749,30 +710,18 @@ class GeneratorDataset(MappableDataset, UnionBaseDataset):
|
|||
new_op.prepared_source = (lambda: _iter_fn(self.source, new_op.num_samples))
|
||||
|
||||
return new_op
|
||||
#查询其是否已经打乱
|
||||
|
||||
def is_shuffled(self):
|
||||
if self.sampler:
|
||||
return self.sampler.is_shuffled()
|
||||
return False
|
||||
#查询是否sharded分片
|
||||
return self.sampler.is_shuffled()
|
||||
|
||||
def is_sharded(self):
|
||||
if self.sampler:
|
||||
return self.sampler.is_sharded()
|
||||
return False
|
||||
#似乎用来分割元素
|
||||
def split(self, sizes, randomize=True):
|
||||
if hasattr(self.source, "__getitem__"):
|
||||
# If the source has __getitem__ attribute, call the split method of MappableDataset.
|
||||
# Otherwise, call the split method of Dataset.
|
||||
return super().split(sizes, randomize)
|
||||
return super(MappableDataset, self).split(sizes, randomize)
|
||||
|
||||
return self.sampler.is_sharded()
|
||||
|
||||
def parse(self, children=None):
|
||||
if self.schema is None:
|
||||
return cde.GeneratorNode(self.prepared_source, self.column_names, self.column_types, self.source_len,
|
||||
self.sampler, self.num_parallel_workers)
|
||||
schema = self.schema
|
||||
#如果schema是Schema对象,赋值为self.schema.cpp_schema
|
||||
if isinstance(schema, Schema):
|
||||
schema = self.schema.cpp_schema
|
||||
return cde.GeneratorNode(self.prepared_source, schema, self.source_len, self.sampler,
|
||||
|
|
@ -785,7 +734,6 @@ class GeneratorDataset(MappableDataset, UnionBaseDataset):
|
|||
if self.python_multiprocessing:
|
||||
# if use num_parallel_workers is to large when python_multiprocessing=True which would cause
|
||||
# OOM error get the num_shards
|
||||
#检查内存的使用情况,在多进程模式下,当内存使用量达到 85% 时丢出警告,达到 100% 时报错。
|
||||
valid_num_shards = 1
|
||||
if isinstance(self.sampler, samplers.DistributedSampler):
|
||||
valid_num_shards = self.sampler.num_shards
|
||||
|
|
@ -796,7 +744,7 @@ class GeneratorDataset(MappableDataset, UnionBaseDataset):
|
|||
process = psutil.Process(os.getpid())
|
||||
process_memory = process.memory_info().rss
|
||||
sys_memory_free = psutil.virtual_memory().free
|
||||
#内存使用量超过可用内存的85%,警告
|
||||
|
||||
total_memory_maybe_used = process_memory * self.num_parallel_workers * valid_num_shards
|
||||
if total_memory_maybe_used / sys_memory_free > 0.85:
|
||||
valid_num_worker = math.floor(sys_memory_free * 0.85 / valid_num_shards / process_memory)
|
||||
|
|
@ -808,7 +756,6 @@ class GeneratorDataset(MappableDataset, UnionBaseDataset):
|
|||
logger.warning(info)
|
||||
|
||||
|
||||
|
||||
class _NumpySlicesDataset:
|
||||
"""
|
||||
Mainly for dealing with several kinds of formats of Python data, and return one row each time.
|
||||
|
|
|
|||
|
|
@ -28,12 +28,11 @@ from .c_transforms import TensorOperation
|
|||
|
||||
def not_random(function):
|
||||
"""
|
||||
将函数标记为“非随机”,即它生成确定性结果。
|
||||
只有在将函数标记为“非随机”后,Python 函数才能被缓存。
|
||||
Specify the function as "not random", i.e., it produces deterministic result.
|
||||
A Python function can only be cached after it is specified as "not random".
|
||||
"""
|
||||
function.random = False #将函数的 random 属性设置为 False
|
||||
return function #返回标记为“非随机”的函数
|
||||
|
||||
function.random = False
|
||||
return function
|
||||
|
||||
|
||||
class PyTensorOperation:
|
||||
|
|
@ -41,108 +40,78 @@ class PyTensorOperation:
|
|||
Base Python Tensor Operations class
|
||||
"""
|
||||
|
||||
def to_json(self):
|
||||
"""
|
||||
将 Python 张量操作对象序列化为 JSON 格式的字符串表示形式。
|
||||
def to_json(self):
|
||||
"""
|
||||
Base to_json for Python tensor operations class
|
||||
"""
|
||||
json_obj = {}
|
||||
json_trans = {}
|
||||
if "transforms" in self.__dict__.keys():
|
||||
# operations which have transforms as input, need to call _to_json() for each transform to serialize
|
||||
json_list = []
|
||||
for transform in self.transforms:
|
||||
json_list.append(json.loads(transform.to_json()))
|
||||
json_trans["transforms"] = json_list
|
||||
self.__dict__.pop("transforms")
|
||||
if "output_type" in self.__dict__.keys():
|
||||
json_trans["output_type"] = np.dtype(
|
||||
self.__dict__["output_type"]).name
|
||||
self.__dict__.pop("output_type")
|
||||
json_obj["tensor_op_params"] = self.__dict__
|
||||
# append transforms to the tensor_op_params of the operation
|
||||
json_obj["tensor_op_params"].update(json_trans)
|
||||
json_obj["tensor_op_name"] = self.__class__.__name__
|
||||
json_obj["python_module"] = self.__class__.__module__
|
||||
return json.dumps(json_obj)
|
||||
|
||||
返回:
|
||||
str: 表示序列化对象的 JSON 格式字符串。
|
||||
|
||||
"""
|
||||
json_obj = {} #创建一个空字典来存储 JSON 数据
|
||||
json_trans = {} #创建一个空字典来存储与数据
|
||||
|
||||
if "transforms" in self.__dict__.keys():
|
||||
#检查对象是否具有“transforms”属性(转换列表)
|
||||
json_list = []
|
||||
|
||||
#遍历每个转换并将其序列化为 JSON
|
||||
for transform in self.transforms:
|
||||
json_list.append(json.loads(transform.to_json()))
|
||||
|
||||
json_trans["transforms"] = json_list#将序列化的转换添加到 JSON 数据中
|
||||
self.__dict__.pop("transforms") #从对象中移除“transforms”属性
|
||||
|
||||
if "output_type" in self.__dict__.keys():
|
||||
#检查对象是否有“output_type”属性
|
||||
json_trans["output_type"] = np.dtype(
|
||||
self.__dict__["output_type"]).name # 将数据类型序列化为名称形式
|
||||
self.__dict__.pop("output_type") # 从对象中移除“output_type”属性
|
||||
|
||||
json_obj["tensor_op_params"] = self.__dict__ #将对象的属性添加到 JSON 数据中
|
||||
json_obj["tensor_op_params"].update(json_trans) #合并与转换相关的数据
|
||||
json_obj["tensor_op_name"] = self.__class__.__name__ #添加类名
|
||||
json_obj["python_module"] = self.__class__.__module__ #添加模块名(?)
|
||||
|
||||
return json.dumps(json_obj) #序列化整个 JSON 数据并以字符串形式返回
|
||||
|
||||
|
||||
@classmethod
|
||||
@classmethod
|
||||
def from_json(cls, json_string):
|
||||
#从JSON字符串反序列化操作并构建新实例
|
||||
#传入的JSON字符串解析为 Python 字典
|
||||
"""
|
||||
Base from_json for Python tensor operations class
|
||||
"""
|
||||
json_obj = json.loads(json_string)
|
||||
|
||||
#创建一个新的操作实例
|
||||
new_op = cls.__new__(cls)
|
||||
|
||||
#将该实例的内部字典(__dict__)替换为从 JSON 中解析的字典
|
||||
new_op.__dict__ = json_obj
|
||||
|
||||
#检查是否存在"transforms" 键,如果存在,则需要对其中的 transforms 进行反序列化
|
||||
if "transforms" in json_obj.keys():
|
||||
# operations which have transforms as input, need to call _from_json() for each transform to deseriallize
|
||||
transforms = []
|
||||
|
||||
#遍历transforms列表中的每个 JSON 表示的操作,并将其解析
|
||||
for json_op in json_obj["transforms"]:
|
||||
#获取操作所在的 Python 模块并根据模块和操作名称创建相应的操作实例
|
||||
transforms.append(getattr(
|
||||
sys.modules[json_op["python_module"]], json_op["tensor_op_name"]).from_json(
|
||||
json.dumps(json_op["tensor_op_params"])))
|
||||
#将反序列化后的操作列表赋值给新操作实例的 transforms 属性
|
||||
new_op.transforms = transforms
|
||||
#检查是否存在"output_type"的键,如存在,转换为numpy.dtype数据类型,并赋值给新实例的output_type
|
||||
if "output_type" in json_obj.keys():
|
||||
output_type = np.dtype(json_obj["output_type"])
|
||||
new_op.output_type = output_type
|
||||
#返回一个新操作实例
|
||||
return new_op
|
||||
|
||||
|
||||
|
||||
class OneHotOp(PyTensorOperation):
|
||||
"""
|
||||
对输入标签应用独热编码变换,使标签更平滑和连续化。
|
||||
Apply one hot encoding transformation to the input label, make label be more smoothing and continuous.
|
||||
|
||||
Args:
|
||||
num_classes (int): 数据集中的对象类别数量。
|
||||
应大于数据集中的最大标签数。
|
||||
smoothing_rate (float, 可选): 标签平滑级别的可调超参数。
|
||||
(默认值=0.0 表示不应用平滑处理。)
|
||||
num_classes (int): Number of classes of objects in dataset.
|
||||
It should be larger than the largest label number in the dataset.
|
||||
smoothing_rate (float, optional): Adjustable hyperparameter for label smoothing level.
|
||||
(Default=0.0 means no smoothing is applied.)
|
||||
|
||||
Raises:
|
||||
TypeError: `num_classes` 不是整数类型。
|
||||
TypeError: `smoothing_rate` 不是浮点数类型。
|
||||
ValueError: `smoothing_rate` 不在范围 [0.0, 1.0] 内。
|
||||
TypeError: `num_classes` is not of type int.
|
||||
TypeError: `smoothing_rate` is not of type float.
|
||||
ValueError: `smoothing_rate` is not in range [0.0, 1.0].
|
||||
|
||||
Supported Platforms:
|
||||
``CPU``
|
||||
|
||||
Examples:
|
||||
>>> # 假设数据集有 10 个类别,因此标签范围从 0 到 9
|
||||
>>> # Assume that dataset has 10 classes, thus the label ranges from 0 to 9
|
||||
>>> transforms_list = [py_transforms.OneHotOp(num_classes=10, smoothing_rate=0.1)]
|
||||
>>> transform = py_transforms.Compose(transforms_list)
|
||||
>>> mnist_dataset = mnist_dataset.map(input_columns=["label"], operations=transform)
|
||||
"""
|
||||
|
||||
@check_one_hot_op
|
||||
#数据迁移处理
|
||||
"""
|
||||
self.num_classes = num_classes
|
||||
self.smoothing_rate = smoothing_rate
|
||||
self.random = False
|
||||
"""
|
||||
def __init__(self, num_classes, smoothing_rate=0.0):
|
||||
self.num_classes = num_classes
|
||||
self.smoothing_rate = smoothing_rate
|
||||
|
|
@ -150,19 +119,17 @@ class OneHotOp(PyTensorOperation):
|
|||
|
||||
def __call__(self, label):
|
||||
"""
|
||||
调用方法。
|
||||
Call method.
|
||||
|
||||
Args:
|
||||
label (numpy.ndarray): 要应用标签平滑处理的标签。
|
||||
label (numpy.ndarray): label to be applied label smoothing.
|
||||
|
||||
Returns:
|
||||
label (numpy.ndarray): 经过平滑处理后的标签。
|
||||
label (numpy.ndarray), label after being Smoothed.
|
||||
"""
|
||||
#将其转换为独热编码
|
||||
return util.one_hot_encoding(label, self.num_classes, self.smoothing_rate)
|
||||
|
||||
|
||||
|
||||
class Compose(PyTensorOperation):
|
||||
"""
|
||||
Compose a list of transforms.
|
||||
|
|
@ -243,8 +210,8 @@ class Compose(PyTensorOperation):
|
|||
return util.compose(self.transforms, *args)
|
||||
|
||||
@staticmethod
|
||||
def reduce(operations):
|
||||
"""
|
||||
def reduce(operations):
|
||||
"""
|
||||
Wraps adjacent Python operations in a Compose to allow mixing of Python and C++ operations.
|
||||
|
||||
Args:
|
||||
|
|
@ -252,46 +219,32 @@ def reduce(operations):
|
|||
|
||||
Returns:
|
||||
list, the reduced list of operations.
|
||||
"""
|
||||
#从mindspore 模块中局部导入nn和ops
|
||||
from mindspore import nn, ops
|
||||
|
||||
#寻找列表中是否包含网络计算操作符
|
||||
for item in operations:
|
||||
if isinstance(item, (nn.Cell, ops.Primitive)):
|
||||
raise ValueError("Input operations should not contain network computing operator like in "
|
||||
"mindspore.nn or mindspore.ops, got operation:", str(item))
|
||||
|
||||
# 如果操作列表中只有一个操作
|
||||
if len(operations) == 1:
|
||||
# 如果该操作是 C++ 操作或 TensorOperation 的实例,返回该操作
|
||||
if str(operations).find("c_transform") >= 0 or isinstance(operations[0], TensorOperation):
|
||||
return operations
|
||||
# 将该操作包装在 util.FuncWrapper 中,并返回包装后的列表
|
||||
return [util.FuncWrapper(operations[0])]
|
||||
|
||||
# 如果操作列表包含多个
|
||||
new_ops, start_ind, end_ind = [], 0, 0
|
||||
|
||||
# 遍历
|
||||
for i, op in enumerate(operations):
|
||||
if str(op).find("c_transform") >= 0:
|
||||
# 如果有 C++ 操作,将之前的所有操作打包成一个Compose操作
|
||||
if start_ind != end_ind:
|
||||
new_ops.append(Compose(operations[start_ind:end_ind]))
|
||||
new_ops.append(op)
|
||||
start_ind, end_ind = i + 1, i + 1
|
||||
else:
|
||||
end_ind += 1
|
||||
|
||||
#在循环结束后,检查并确保最后一组操作也被打包成 Compose 操作,并添加到新的操作列表中(
|
||||
#(?
|
||||
if start_ind != end_ind:
|
||||
new_ops.append(Compose(operations[start_ind:end_ind]))
|
||||
|
||||
# 返回经过优化的操作列表
|
||||
return new_ops
|
||||
"""
|
||||
# import nn and ops locally for type check
|
||||
from mindspore import nn, ops
|
||||
for item in operations:
|
||||
if isinstance(item, (nn.Cell, ops.Primitive)):
|
||||
raise ValueError("Input operations should not contain network computing operator like in "
|
||||
"mindspore.nn or mindspore.ops, got operation:", str(item))
|
||||
if len(operations) == 1:
|
||||
if str(operations).find("c_transform") >= 0 or isinstance(operations[0], TensorOperation):
|
||||
return operations
|
||||
return [util.FuncWrapper(operations[0])]
|
||||
|
||||
new_ops, start_ind, end_ind = [], 0, 0
|
||||
for i, op in enumerate(operations):
|
||||
if str(op).find("c_transform") >= 0:
|
||||
# reset counts
|
||||
if start_ind != end_ind:
|
||||
new_ops.append(Compose(operations[start_ind:end_ind]))
|
||||
new_ops.append(op)
|
||||
start_ind, end_ind = i + 1, i + 1
|
||||
else:
|
||||
end_ind += 1
|
||||
# do additional check in case the last operation is a Python operation
|
||||
if start_ind != end_ind:
|
||||
new_ops.append(Compose(operations[start_ind:end_ind]))
|
||||
return new_ops
|
||||
|
||||
|
||||
class RandomApply(PyTensorOperation):
|
||||
|
|
@ -412,31 +365,19 @@ class RandomOrder(PyTensorOperation):
|
|||
... py_vision.ToTensor()])
|
||||
>>> image_folder_dataset = image_folder_dataset.map(operations=transforms, input_columns=["image"])
|
||||
"""
|
||||
|
||||
@check_transforms_list
|
||||
def __init__(self, transforms):
|
||||
"""
|
||||
初始化 Compose 类的实例。
|
||||
|
||||
Args:
|
||||
transforms (list): 一个包含要应用的转换操作的列表。
|
||||
|
||||
Raises:
|
||||
TypeError: 如果 `transforms` 不是列表类型。
|
||||
ValueError: 如果 `transforms` 列表为空。
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
self.transforms = transforms # 将传入的转换操作列表存储在对象属性 transforms 中
|
||||
self.transforms = transforms
|
||||
|
||||
def __call__(self, img):
|
||||
"""
|
||||
调用方法,用于将一组转换操作应用到输入图像上。
|
||||
Call method.
|
||||
|
||||
Args:
|
||||
img: 需要进行转换操作的图像。
|
||||
img (PIL image): Image to apply transformations in a random order.
|
||||
|
||||
Returns:
|
||||
img: 转换后的图像。
|
||||
Raises:
|
||||
TypeError: 如果输入图像或任何转换操作无效。
|
||||
img (PIL image), Transformed image.
|
||||
"""
|
||||
return util.random_order(img, self.transforms) # 调用 random_order 函数,以随机顺序应用转换操作并返回转换后的图像
|
||||
return util.random_order(img, self.transforms)
|
||||
|
|
|
|||
|
|
@ -24,29 +24,15 @@ from ..core.py_util_helpers import is_numpy, ExceptionHandler
|
|||
|
||||
|
||||
def all_numpy(args):
|
||||
"""
|
||||
检查给定的参数是否全部为 NumPy 数组。
|
||||
|
||||
Args:
|
||||
args: 可以是单个值或一个包含多个值的元组。
|
||||
|
||||
Returns:
|
||||
bool: 如果全部都是 NumPy 数组,则返回 True;否则返回 False。
|
||||
"""
|
||||
""" for multi-input lambdas"""
|
||||
if isinstance(args, tuple):
|
||||
#若参数是一个tuple,则迭代遍历元组中的每个值
|
||||
for value in args:
|
||||
#使用 is_numpy 函数检查每个值是否为 NumPy 数组
|
||||
if not is_numpy(value):
|
||||
#如果发现任何一个值不是 NumPy 数组,则返回 False
|
||||
return False
|
||||
#如果所有的值都是 NumPy 数组,则返回 True
|
||||
return True
|
||||
#如果参数不是元组,而是单个值
|
||||
return is_numpy(args)
|
||||
|
||||
|
||||
|
||||
def compose(transforms, *args):
|
||||
"""
|
||||
Compose a list of transforms and apply on the image.
|
||||
|
|
@ -72,39 +58,35 @@ def compose(transforms, *args):
|
|||
|
||||
|
||||
def one_hot_encoding(label, num_classes, epsilon):
|
||||
#独热编码处理并进行平滑转换
|
||||
"""
|
||||
对输入的标签进行独热编码并应用标签平滑转换,使标签更平滑和连续。
|
||||
Apply label smoothing transformation to the input label, and make label be more smoothing and continuous.
|
||||
|
||||
Args:
|
||||
label (numpy.ndarray): 要应用标签平滑的标签。
|
||||
num_classes (int): 数据集中的对象类别数,必须大于0。
|
||||
epsilon (float): 可调整的超参数。默认值为0.0。
|
||||
label (numpy.ndarray): label to be applied label smoothing.
|
||||
num_classes (int): Num class of object in dataset, value should over 0.
|
||||
epsilon (float): The adjustable Hyper parameter. Default is 0.0.
|
||||
|
||||
Returns:
|
||||
one_hot_label (numpy.ndarray): 经过独热编码和标签平滑后的标签。
|
||||
img (numpy.ndarray), label after being one hot encoded and done label smoothed.
|
||||
|
||||
Examples:
|
||||
>>> # 假设 num_classes = 5
|
||||
>>> # 1) 输入 np.array(3) 输出 [0, 0, 0, 1, 0]
|
||||
>>> # 2) 输入 np.array([4, 2, 0]) 输出 [[0, 0, 0, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0]]
|
||||
>>> # 3) 输入 np.array([[4], [2], [0]]) 输出 [[[0, 0, 0, 0, 1]], [[0, 0, 1, 0, 0][, [[1, 0, 0, 0, 0]]]
|
||||
>>> # assume num_classes = 5
|
||||
>>> # 1) input np.array(3) output [0, 0, 0, 1, 0]
|
||||
>>> # 2) input np.array([4, 2, 0]) output [[0, 0, 0, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 0, 0]]
|
||||
>>> # 3) input np.array([[4], [2], [0]]) output [[[0, 0, 0, 0, 1]], [[0, 0, 1, 0, 0][, [[1, 0, 0, 0, 0]]]
|
||||
"""
|
||||
if isinstance(label, np.ndarray): # 检查输入是否为 NumPy 数组
|
||||
#判断label的数据类型是否为指定的整数类型(np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64)之一。
|
||||
if isinstance(label, np.ndarray): # the numpy should be () or (1, ) or shape: (n, 1)
|
||||
if label.dtype not in [np.int8, np.int16, np.int32, np.int64,
|
||||
np.uint8, np.uint16, np.uint32, np.uint64]:
|
||||
raise ValueError('the input numpy type should be int, but the input is: ' + str(label.dtype))
|
||||
|
||||
if label.ndim == 0: # 处理标量标签的情况
|
||||
if label.ndim == 0:
|
||||
if label >= num_classes:
|
||||
raise ValueError('the num_classes is smaller than the category number.')
|
||||
|
||||
#创建一个全零的独热编码数组,将标签对应的位置设为1
|
||||
one_hot_label = np.zeros((num_classes), dtype=int)
|
||||
one_hot_label[label] = 1
|
||||
else: # 处理多维标签的情况
|
||||
# 使用.flatten()将多维标签展平成一维数组,以便于处理
|
||||
else:
|
||||
label_flatten = label.flatten()
|
||||
for item in label_flatten:
|
||||
if item >= num_classes:
|
||||
|
|
@ -112,46 +94,38 @@ def one_hot_encoding(label, num_classes, epsilon):
|
|||
' is smaller than the category number:' + str(item))
|
||||
|
||||
num_elements = label_flatten.size
|
||||
#创建一个形状为(num_elements, num_classes)的使用零填充的numpy数组
|
||||
one_hot_label = np.zeros((num_elements, num_classes), dtype=int)
|
||||
for index in range(num_elements):
|
||||
one_hot_label[index][label_flatten[index]] = 1
|
||||
|
||||
#设置新的数组形状
|
||||
new_shape = []new_shape
|
||||
#将原label.shape移到里面
|
||||
new_shape = []
|
||||
for dim in label.shape:
|
||||
new_shape.append(dim)
|
||||
#对象类别扔到维度里面
|
||||
new_shape.append(num_classes)
|
||||
one_hot_label = one_hot_label.reshape(new_shape)
|
||||
else:
|
||||
#报错:数据格式无效,应该是一个 NumPy 数组
|
||||
raise ValueError('the input is invalid, it should be numpy.ndarray.')
|
||||
|
||||
# 应用标签平滑,通过将原始独热编码乘以 (1 - epsilon) 并加上 epsilon / num_classes 来平滑标签,epsilon默认为0
|
||||
return (1 - epsilon) * one_hot_label + epsilon / num_classes
|
||||
|
||||
|
||||
def random_order(img, transforms):
|
||||
"""
|
||||
将一系列变换以随机顺序应用到图像上。
|
||||
Applies a list of transforms in a random order.
|
||||
|
||||
Args:
|
||||
img: 要以随机顺序应用变换的图像。
|
||||
transforms (list): 要应用的变换的列表。
|
||||
img: Image to be applied transformations in a random order.
|
||||
transforms (list): List of the transformations to be applied.
|
||||
|
||||
Returns:
|
||||
img: 经过变换的图像。
|
||||
img, Transformed image.
|
||||
"""
|
||||
# 随机打乱transforms元素顺序
|
||||
random.shuffle(transforms)
|
||||
for transform in transforms:
|
||||
# 对图像应用每个变换
|
||||
img = transform(img)
|
||||
#返回img
|
||||
return img
|
||||
|
||||
|
||||
def random_apply(img, transforms, prob):
|
||||
"""
|
||||
Apply a list of transformation, randomly with a given probability.
|
||||
|
|
@ -182,51 +156,42 @@ def random_choice(img, transforms):
|
|||
Returns:
|
||||
img, Transformed image.
|
||||
"""
|
||||
#用 Python 的 random.choice 函数从 transforms 列表中随机选择一个变换方法,非常ez
|
||||
return random.choice(transforms)(img)
|
||||
|
||||
|
||||
class FuncWrapper:
|
||||
"""
|
||||
用于包装函数并添加 try except 逻辑,主要用于包装 Python 函数。
|
||||
包装后的函数会捕获异常并重新引发,以便处理 Python 函数的错误。
|
||||
Wrap function with try except logic, mainly for warping python function.
|
||||
|
||||
Args:
|
||||
transform: 可调用的 Python 函数。
|
||||
transform: Callable python function.
|
||||
|
||||
Returns:
|
||||
result, 应用变换后的数据。
|
||||
result, data after apply transformation.
|
||||
"""
|
||||
def __init__(self, transform):
|
||||
#检查输入是否是可以调用的 Python 函数
|
||||
if not callable(transform):
|
||||
raise ValueError("Input operations should be callable python function, but got: " + str(transform))
|
||||
self.transform = transform
|
||||
try:
|
||||
#如果函数有属性"random"并且其值为 False,则将 self.random 设置为 False
|
||||
if hasattr(self.transform, "random") and not self.transform.random:
|
||||
self.random = False
|
||||
except KeyError:
|
||||
# 如果属性 "random" 不存在,把self.random设置为 True
|
||||
self.random = True
|
||||
|
||||
def __call__(self, *args):
|
||||
result = None
|
||||
try:
|
||||
#调用包装的函数,并捕获可能的异常
|
||||
result = self.transform(*args)
|
||||
except Exception:
|
||||
#发生异常后,创建一个异常处理器对象,并重新引发异常
|
||||
result = ExceptionHandler(where="in map(or batch) worker and execute python function")
|
||||
result.reraise()
|
||||
return result
|
||||
|
||||
def to_json(self):
|
||||
# 如果包装的函数是 FunctionType 类型,将其序列化为 JSON 对象
|
||||
if isinstance(self.transform, FunctionType):
|
||||
json_obj = {}
|
||||
json_obj["tensor_op_name"] = self.transform.__name__
|
||||
json_obj["python_module"] = self.__class__.__module__
|
||||
return json.dumps(json_obj)
|
||||
# 否则,调用包装的函数的 to_json 方法
|
||||
return self.transform.to_json()
|
||||
|
|
|
|||
|
|
@ -43,35 +43,39 @@ class FileWriter:
|
|||
Args:
|
||||
file_name (str): File name of MindRecord file.
|
||||
shard_num (int, optional): The Number of MindRecord files.
|
||||
It should be between [1, 1000]. Default: ``1`` .
|
||||
overwrite (bool, optional): Whether to overwrite if the file already exists. Default: ``False`` .
|
||||
It should be between [1, 1000]. Default: 1.
|
||||
overwrite (bool, optional): Whether to overwrite if the file already exists. Default: False.
|
||||
|
||||
Raises:
|
||||
ParamValueError: If `file_name` or `shard_num` or `overwrite` is invalid.
|
||||
|
||||
Examples:
|
||||
from mindspore.mindrecord import FileWriter
|
||||
|
||||
writer = FileWriter(file_name="test.mindrecord", shard_num=1, overwrite=True)
|
||||
schema_json = {"file_name": {"type": "string"}, "label": {"type": "int32"}, "data": {"type": "bytes"}}
|
||||
schema_id = writer.add_schema(schema_json, "test_schema")
|
||||
indexes = ["file_name", "label"]
|
||||
status = writer.add_index(indexes)
|
||||
for i in range(10):
|
||||
... data = [{"file_name": str(i) + ".jpg", "label": i,
|
||||
... "data": b"\x10c\xb3w\xa8\xee$o&<q\x8c\x8e(\xa2\x90\x90\x96\xbc\xb1\x1e\xd4QER\x13?\xff"}]
|
||||
... status = writer.write_raw_data(data)
|
||||
status = writer.commit()
|
||||
>>> from mindspore.mindrecord import FileWriter
|
||||
>>> schema_json = {"file_name": {"type": "string"}, "label": {"type": "int32"}, "data": {"type": "bytes"}}
|
||||
>>> indexes = ["file_name", "label"]
|
||||
>>> data = [{"file_name": "1.jpg", "label": 0,
|
||||
... "data": b"\x10c\xb3w\xa8\xee$o&<q\x8c\x8e(\xa2\x90\x90\x96\xbc\xb1\x1e\xd4QER\x13?\xff"},
|
||||
... {"file_name": "2.jpg", "label": 56,
|
||||
... "data": b"\xe6\xda\xd1\xae\x07\xb8>\xd4\x00\xf8\x129\x15\xd9\xf2q\xc0\xa2\x91YFUO\x1dsE1"},
|
||||
... {"file_name": "3.jpg", "label": 99,
|
||||
... "data": b"\xaf\xafU<\xb8|6\xbd}\xc1\x99[\xeaj+\x8f\x84\xd3\xcc\xa0,i\xbb\xb9-\xcdz\xecp{T\xb1"}]
|
||||
>>> writer = FileWriter(file_name="test.mindrecord", shard_num=1, overwrite=True)
|
||||
>>> writer.add_schema(schema_json, "test_schema")
|
||||
0
|
||||
>>> writer.add_index(indexes)
|
||||
MSRStatus.SUCCESS
|
||||
>>> writer.write_raw_data(data)
|
||||
MSRStatus.SUCCESS
|
||||
>>> writer.commit()
|
||||
MSRStatus.SUCCESS
|
||||
"""
|
||||
|
||||
def __init__(self, file_name, shard_num=1, overwrite=False):
|
||||
#若平台是windows 将文件名中\\替换成/
|
||||
if platform.system().lower() == "windows":
|
||||
file_name = file_name.replace("\\", "/")
|
||||
#检查文件名,并使用
|
||||
check_filename(file_name)
|
||||
self._file_name = file_name
|
||||
#若有shard_num,检查其数值存在,且数值为整数,且在MIN_SHARD_COUNT和MAX_SHARD_COUNT之间,否则抛出异常
|
||||
|
||||
if shard_num is not None:
|
||||
if isinstance(shard_num, int):
|
||||
if shard_num < MIN_SHARD_COUNT or shard_num > MAX_SHARD_COUNT:
|
||||
|
|
@ -81,7 +85,7 @@ class FileWriter:
|
|||
raise ParamValueError("Parameter shard_num's type is not int.")
|
||||
else:
|
||||
raise ParamValueError("Parameter shard_num is None.")
|
||||
#若overwrite类型不是bool,也抛出异常
|
||||
|
||||
if not isinstance(overwrite, bool):
|
||||
raise ParamValueError("Parameter overwrite's type is not bool.")
|
||||
|
||||
|
|
@ -95,7 +99,7 @@ class FileWriter:
|
|||
self._paths = ["{}{}".format(self._file_name,
|
||||
str(x).rjust(suffix_shard_size, '0'))
|
||||
for x in range(self._shard_num)]
|
||||
|
||||
|
||||
self._overwrite = overwrite
|
||||
self._append = False
|
||||
self._flush = False
|
||||
|
|
@ -103,13 +107,6 @@ class FileWriter:
|
|||
self._writer = ShardWriter()
|
||||
self._generator = None
|
||||
|
||||
# parallel write mode
|
||||
self._parallel_writer = None
|
||||
self._writers = None
|
||||
self._queue = None
|
||||
self._workers = None
|
||||
self._index_workers = None
|
||||
|
||||
@classmethod
|
||||
def open_for_append(cls, file_name):
|
||||
r"""
|
||||
|
|
@ -128,22 +125,22 @@ class FileWriter:
|
|||
MRMOpenForAppendError: If failed to open file for appending data.
|
||||
|
||||
Examples:
|
||||
from mindspore.mindrecord import FileWriter
|
||||
|
||||
data = [{"file_name": "0.jpg", "label": 0,
|
||||
>>> from mindspore.mindrecord import FileWriter
|
||||
>>> schema_json = {"file_name": {"type": "string"}, "label": {"type": "int32"}, "data": {"type": "bytes"}}
|
||||
>>> data = [{"file_name": "1.jpg", "label": 0,
|
||||
... "data": b"\x10c\xb3w\xa8\xee$o&<q\x8c\x8e(\xa2\x90\x90\x96\xbc\xb1\x1e\xd4QER\x13?\xff"}]
|
||||
writer = FileWriter(file_name="test.mindrecord", shard_num=1, overwrite=True)
|
||||
schema_json = {"file_name": {"type": "string"}, "label": {"type": "int32"}, "data": {"type": "bytes"}}
|
||||
schema_id = writer.add_schema(schema_json, "test_schema")
|
||||
status = writer.write_raw_data(data)
|
||||
status = writer.commit()
|
||||
|
||||
write_append = FileWriter.open_for_append("test.mindrecord")
|
||||
for i in range(9):
|
||||
... data = [{"file_name": str(i+1) + ".jpg", "label": i,
|
||||
... "data": b"\x10c\xb3w\xa8\xee$o&<q\x8c\x8e(\xa2\x90\x90\x96\xbc\xb1\x1e\xd4QER\x13?\xff"}]
|
||||
... status = write_append.write_raw_data(data)
|
||||
status = write_append.commit()
|
||||
>>> writer = FileWriter(file_name="test.mindrecord", shard_num=1, overwrite=True)
|
||||
>>> writer.add_schema(schema_json, "test_schema")
|
||||
0
|
||||
>>> writer.write_raw_data(data)
|
||||
MSRStatus.SUCCESS
|
||||
>>> writer.commit()
|
||||
MSRStatus.SUCCESS
|
||||
>>> write_append = FileWriter.open_for_append("test.mindrecord")
|
||||
>>> write_append.write_raw_data(data)
|
||||
MSRStatus.SUCCESS
|
||||
>>> write_append.commit()
|
||||
MSRStatus.SUCCESS
|
||||
"""
|
||||
if platform.system().lower() == "windows":
|
||||
file_name = file_name.replace("\\", "/")
|
||||
|
|
@ -175,49 +172,11 @@ class FileWriter:
|
|||
The schema is added to describe the raw data to be written.
|
||||
|
||||
Note:
|
||||
Please refer to the Examples of :class:`mindspore.mindrecord.FileWriter` .
|
||||
|
||||
.. list-table:: The data types supported by MindRecord.
|
||||
:widths: 25 25 50
|
||||
:header-rows: 1
|
||||
|
||||
* - Data Type
|
||||
- Data Shape
|
||||
- Details
|
||||
* - int32
|
||||
- /
|
||||
- integer number
|
||||
* - int64
|
||||
- /
|
||||
- integer number
|
||||
* - float32
|
||||
- /
|
||||
- real number
|
||||
* - float64
|
||||
- /
|
||||
- real number
|
||||
* - string
|
||||
- /
|
||||
- string data
|
||||
* - bytes
|
||||
- /
|
||||
- binary data
|
||||
* - int32
|
||||
- [-1] / [-1, 32, 32] / [3, 224, 224]
|
||||
- numpy ndarray
|
||||
* - int64
|
||||
- [-1] / [-1, 32, 32] / [3, 224, 224]
|
||||
- numpy ndarray
|
||||
* - float32
|
||||
- [-1] / [-1, 32, 32] / [3, 224, 224]
|
||||
- numpy ndarray
|
||||
* - float64
|
||||
- [-1] / [-1, 32, 32] / [3, 224, 224]
|
||||
- numpy ndarray
|
||||
Please refer to the Examples of class: `mindspore.mindrecord.FileWriter`.
|
||||
|
||||
Args:
|
||||
content (dict): Dictionary of schema content.
|
||||
desc (str, optional): String of schema description, Default: ``None`` .
|
||||
desc (str, optional): String of schema description, Default: None.
|
||||
|
||||
Returns:
|
||||
int, schema id.
|
||||
|
|
@ -226,14 +185,7 @@ class FileWriter:
|
|||
MRMInvalidSchemaError: If schema is invalid.
|
||||
MRMBuildSchemaError: If failed to build schema.
|
||||
MRMAddSchemaError: If failed to add schema.
|
||||
|
||||
Examples:
|
||||
# Examples of available schemas
|
||||
schema1 = {"file_name": {"type": "string"}, "label": {"type": "int32"}, "data": {"type": "bytes"}}
|
||||
schema2 = {"input_ids": {"type": "int32", "shape": [-1]},
|
||||
... "input_masks": {"type": "int32", "shape": [-1]}}
|
||||
"""
|
||||
#加入schema,若无效,抛出MRMInvalidSchemaError
|
||||
ret, error_msg = self._validate_schema(content)
|
||||
if ret is False:
|
||||
raise MRMInvalidSchemaError(error_msg)
|
||||
|
|
@ -243,14 +195,13 @@ class FileWriter:
|
|||
def add_index(self, index_fields):
|
||||
"""
|
||||
Select index fields from schema to accelerate reading.
|
||||
schema is added through `add_schema` .
|
||||
|
||||
Note:
|
||||
The index fields should be primitive type. e.g. int/float/str.
|
||||
If the function is not called, the fields of the primitive type
|
||||
in schema are set as indexes by default.
|
||||
|
||||
Please refer to the Examples of :class:`mindspore.mindrecord.FileWriter` .
|
||||
Please refer to the Examples of class: `mindspore.mindrecord.FileWriter`.
|
||||
|
||||
Args:
|
||||
index_fields (list[str]): fields from schema.
|
||||
|
|
@ -266,7 +217,7 @@ class FileWriter:
|
|||
"""
|
||||
if not index_fields or not isinstance(index_fields, list):
|
||||
raise ParamTypeError('index_fields', 'list')
|
||||
#若index_fields其中元素在_header.blob_fields中,是字符串类型才可通过。(不是原始数据),抛出MRMDefineIndexError
|
||||
|
||||
for field in index_fields:
|
||||
if field in self._header.blob_fields:
|
||||
raise MRMDefineIndexError("Failed to set field {} since it's not primitive type.".format(field))
|
||||
|
|
@ -274,13 +225,66 @@ class FileWriter:
|
|||
raise ParamTypeError('index field', 'str')
|
||||
return self._header.add_index_fields(index_fields)
|
||||
|
||||
def _verify_based_on_schema(self, raw_data):
|
||||
"""
|
||||
Verify data according to schema and remove invalid data if validation failed.
|
||||
|
||||
1) allowed data type contains: "int32", "int64", "float32", "float64", "string", "bytes".
|
||||
|
||||
Args:
|
||||
raw_data (list[dict]): List of raw data.
|
||||
"""
|
||||
error_data_dic = {}
|
||||
schema_content = self._header.schema
|
||||
for field in schema_content:
|
||||
for i, v in enumerate(raw_data):
|
||||
if i in error_data_dic:
|
||||
continue
|
||||
|
||||
if field not in v:
|
||||
error_data_dic[i] = "for schema, {} th data is wrong, " \
|
||||
"there is not '{}' object in the raw data.".format(i, field)
|
||||
continue
|
||||
field_type = type(v[field]).__name__
|
||||
if field_type not in VALUE_TYPE_MAP:
|
||||
error_data_dic[i] = "for schema, {} th data is wrong, " \
|
||||
"data type for '{}' is not matched.".format(i, field)
|
||||
continue
|
||||
|
||||
if schema_content[field]["type"] not in VALUE_TYPE_MAP[field_type]:
|
||||
error_data_dic[i] = "for schema, {} th data is wrong, " \
|
||||
"data type for '{}' is not matched.".format(i, field)
|
||||
continue
|
||||
|
||||
if field_type == 'ndarray':
|
||||
if 'shape' not in schema_content[field]:
|
||||
error_data_dic[i] = "for schema, {} th data is wrong, " \
|
||||
"data type for '{}' is not matched.".format(i, field)
|
||||
else:
|
||||
try:
|
||||
np.reshape(v[field], schema_content[field]['shape'])
|
||||
except ValueError:
|
||||
error_data_dic[i] = "for schema, {} th data is wrong, " \
|
||||
"data type for '{}' is not matched.".format(i, field)
|
||||
error_data_dic = sorted(error_data_dic.items(), reverse=True)
|
||||
for i, v in error_data_dic:
|
||||
raw_data.pop(i)
|
||||
logger.warning(v)
|
||||
|
||||
def open_and_set_header(self):
|
||||
#该接口将在未来被删除或隐藏
|
||||
logger.warning("This interface will be deleted or invisible in the future.")
|
||||
#若_writer没被打开,打开文件
|
||||
"""
|
||||
Open writer and set header which stores meta information. The function is only used for parallel \
|
||||
writing and is called before the `write_raw_data`.
|
||||
|
||||
Returns:
|
||||
MSRStatus, SUCCESS or FAILED.
|
||||
|
||||
Raises:
|
||||
MRMOpenError: If failed to open MindRecord file.
|
||||
MRMSetHeaderError: If failed to set header.
|
||||
"""
|
||||
if not self._writer.is_open:
|
||||
ret = self._writer.open(self._paths, self._overwrite)
|
||||
#若无文件头则获取
|
||||
if not self._writer.get_shard_header():
|
||||
return self._writer.set_shard_header(self._header)
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"""
|
||||
Cifar10 convert tool for MindRecord.
|
||||
"""
|
||||
#用于把CIFAR-10数据转换为MindRecord
|
||||
|
||||
from importlib import import_module
|
||||
import os
|
||||
import numpy as np
|
||||
|
|
@ -27,34 +27,30 @@ from ..filewriter import FileWriter
|
|||
from ..shardutils import check_filename, ExceptionThread, SUCCESS, FAILED
|
||||
|
||||
try:
|
||||
cv_import = import_module("cv2")
|
||||
cv2 = import_module("cv2")
|
||||
except ModuleNotFoundError:
|
||||
cv_import = None
|
||||
cv2 = None
|
||||
|
||||
__all__ = ['Cifar10ToMR']
|
||||
|
||||
# Cifar10ToMR 类 把CIFAR-10数据转换为MindRecord
|
||||
#The CIFAR-10 dataset consists of 60000 32x32 colour images in 10 classes, with 6000 images per class. There are 50000 training images and 10000 test images.
|
||||
|
||||
class Cifar10ToMR:
|
||||
|
||||
"""
|
||||
用于将 CIFAR-10 数据转换为 MindRecord 格式的一个类
|
||||
|
||||
参数:
|
||||
source (str) - 待转换的CIFAR-10数据集文件所在目录的路径。
|
||||
destination (str) - 转换生成的MindRecord文件路径,需提前创建目录并且目录下不能存在同名文件。
|
||||
|
||||
报错:
|
||||
ValueError: 如果 source 或 destination 无效。
|
||||
|
||||
Examples:
|
||||
from mindspore.mindrecord import Cifar10ToMR
|
||||
|
||||
cifar10_dir = "/path/to/cifar10"
|
||||
mindrecord_file = "/path/to/mindrecord/file"
|
||||
cifar10_to_mr = Cifar10ToMR(cifar10_dir, mindrecord_file)
|
||||
status = cifar10_to_mr.transform()
|
||||
"""
|
||||
A class to transform from cifar10 to MindRecord.
|
||||
|
||||
Note:
|
||||
For details about Examples, please refer to `Converting the CIFAR-10 Dataset <https://
|
||||
www.mindspore.cn/docs/programming_guide/en/master/dataset_conversion.html#converting-the-cifar-10-dataset>`_.
|
||||
|
||||
Args:
|
||||
source (str): The cifar10 directory to be transformed.
|
||||
destination (str): MindRecord file path to transform into, ensure that no file with the same name
|
||||
exists in the directory.
|
||||
|
||||
Raises:
|
||||
ValueError: If source or destination is invalid.
|
||||
"""
|
||||
|
||||
def __init__(self, source, destination):
|
||||
check_filename(source)
|
||||
self.source = source
|
||||
|
|
@ -63,12 +59,10 @@ class Cifar10ToMR:
|
|||
train_data_flag = False
|
||||
test_data_flag = False
|
||||
for file in files:
|
||||
#检查当前文件名是否以data_batch_或者test_batch开头
|
||||
if file.startswith("data_batch_"):
|
||||
train_data_flag = True
|
||||
if file.startswith("test_batch"):
|
||||
test_data_flag = True
|
||||
#若没有(train_data_flag或者test_data_flag为False),报错
|
||||
if not train_data_flag:
|
||||
raise PathNotExistsError("data_batch_*")
|
||||
|
||||
|
|
@ -79,30 +73,36 @@ class Cifar10ToMR:
|
|||
self.destination = destination
|
||||
self.writer = None
|
||||
|
||||
# pylint: disable=missing-docstring
|
||||
def run(self, fields=None):
|
||||
#若fields不是列表,报错The parameter fields should be None or list
|
||||
"""
|
||||
Execute transformation from cifar10 to MindRecord.
|
||||
|
||||
Args:
|
||||
fields (list[str], optional): A list of index fields. Default: None.
|
||||
|
||||
Returns:
|
||||
MSRStatus, SUCCESS or FAILED.
|
||||
"""
|
||||
|
||||
if fields and not isinstance(fields, list):
|
||||
raise ValueError("The parameter fields should be None or list")
|
||||
# 创建一个Cifar10类的实例
|
||||
|
||||
cifar10_data = Cifar10(self.source, False)
|
||||
cifar10_data.load_data()
|
||||
|
||||
|
||||
images = cifar10_data.images
|
||||
logger.info("train images: {}".format(images.shape))
|
||||
#加载并记录数据集图像的形状
|
||||
labels = cifar10_data.labels
|
||||
logger.info("train images label: {}".format(labels.shape))
|
||||
|
||||
|
||||
test_images = cifar10_data.Test.images
|
||||
logger.info("test images: {}".format(test_images.shape))
|
||||
#记录测试标签的形状
|
||||
test_labels = cifar10_data.Test.labels
|
||||
logger.info("test images label: {}".format(test_labels.shape))
|
||||
|
||||
data_list = _construct_raw_data(images, labels)
|
||||
test_data_list = _construct_raw_data(test_images, test_labels)
|
||||
# 若有转换MindRecord文件的失败则返回FAILED
|
||||
|
||||
if _generate_mindrecord(self.destination, data_list, fields, "img_train") != SUCCESS:
|
||||
return FAILED
|
||||
if _generate_mindrecord(self.destination + "_test", test_data_list, fields, "img_test") != SUCCESS:
|
||||
|
|
@ -111,36 +111,15 @@ class Cifar10ToMR:
|
|||
|
||||
def transform(self, fields=None):
|
||||
"""
|
||||
Execute transformation from cifar10 to MindRecord.
|
||||
|
||||
Note:
|
||||
Please refer to the Examples of :class:`mindspore.mindrecord.Cifar10ToMR` .
|
||||
Encapsulate the run function to exit normally
|
||||
|
||||
Args:
|
||||
fields (list[str], optional): A list of index fields. Default: ``None`` . For index field settings,
|
||||
please refer to :func:`mindspore.mindrecord.FileWriter.add_index` .
|
||||
fields (list[str], optional): A list of index fields. Default: None.
|
||||
|
||||
Returns:
|
||||
MSRStatus, SUCCESS or FAILED.
|
||||
|
||||
Raises:
|
||||
ParamTypeError: If index field is invalid.
|
||||
MRMOpenError: If failed to open MindRecord file.
|
||||
MRMValidateDataError: If data does not match blob fields.
|
||||
MRMSetHeaderError: If failed to set header.
|
||||
MRMWriteDatasetError: If failed to write dataset.
|
||||
TypeError: If `parallel_writer` is not bool.
|
||||
ValueError: If parameter `fields` is invalid.
|
||||
|
||||
异常: ParamTypeError: 如果索引字段无效。
|
||||
MRMOpenError: 如果无法打开 MindRecord 文件。
|
||||
MRMValidateDataError: 如果数据与 blob 字段不匹配。
|
||||
MRMSetHeaderError: 如果无法设置标题。
|
||||
MRMWriteDatasetError: 如果无法写入数据集。
|
||||
TypeError: 如果 parallel_writer 不是布尔值。
|
||||
ValueError: 如果参数 fields 无效。
|
||||
"""
|
||||
#一个ExceptionThread线程类对象(? 目标为 self.run
|
||||
|
||||
t = ExceptionThread(target=self.run, kwargs={'fields': fields})
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
|
@ -150,66 +129,55 @@ class Cifar10ToMR:
|
|||
return t.res
|
||||
|
||||
|
||||
def _construct_raw_data(images, labels):
|
||||
#从cifar10中构建原始数据
|
||||
"""
|
||||
Construct raw data from cifar10 data.
|
||||
def _construct_raw_data(images, labels):
|
||||
"""
|
||||
Construct raw data from cifar10 data.
|
||||
|
||||
Args:
|
||||
images (list): image list from cifar10.
|
||||
labels (list): label list from cifar10.
|
||||
Args:
|
||||
images (list): image list from cifar10.
|
||||
labels (list): label list from cifar10.
|
||||
|
||||
Returns:
|
||||
list[dict], data dictionary constructed from cifar10.
|
||||
"""
|
||||
#images,labels表示来自cifar10的图像和标签
|
||||
Returns:
|
||||
list[dict], data dictionary constructed from cifar10.
|
||||
"""
|
||||
|
||||
#若没有导入opencv-python模块,报错
|
||||
if not cv_import:
|
||||
raise ModuleNotFoundError("opencv-python module not found, please use pip install it.")
|
||||
if not cv2:
|
||||
raise ModuleNotFoundError("opencv-python module not found, please use pip install it.")
|
||||
|
||||
raw_data = []
|
||||
#遍历图像数据和标签数据
|
||||
for i, img in enumerate(images):
|
||||
label = np.int(labels[i][0])
|
||||
_, img = cv_import.imencode(".jpeg", img[..., [2, 1, 0]])
|
||||
#创建一个整合信息用的字典
|
||||
row_data = {"id": int(i),
|
||||
"data": img.tobytes(),#将数组的内容转换为一个字节字符串对象
|
||||
"label": int(label)}#将标签转换为整数
|
||||
raw_data.append(row_data)
|
||||
return raw_data
|
||||
raw_data = []
|
||||
for i, img in enumerate(images):
|
||||
label = np.int(labels[i][0])
|
||||
_, img = cv2.imencode(".jpeg", img[..., [2, 1, 0]])
|
||||
row_data = {"id": int(i),
|
||||
"data": img.tobytes(),
|
||||
"label": int(label)}
|
||||
raw_data.append(row_data)
|
||||
return raw_data
|
||||
|
||||
|
||||
def _generate_mindrecord(file_name, raw_data, fields, schema_desc):
|
||||
"""
|
||||
Generate MindRecord file from raw data.
|
||||
def _generate_mindrecord(file_name, raw_data, fields, schema_desc):
|
||||
"""
|
||||
Generate MindRecord file from raw data.
|
||||
|
||||
Args:
|
||||
file_name (str): File name of MindRecord File.
|
||||
fields (list[str]): Fields would be set as index which
|
||||
could not belong to blob fields and type could not be 'array' or 'bytes'.
|
||||
raw_data (dict): dict of raw data.
|
||||
schema_desc (str): String of schema description.
|
||||
# 参数:
|
||||
# file_name (str): MindRecord文件的文件名。
|
||||
# fields (list[str]): 将被设置为索引的字段,不能属于blob字段且类型不能为 'array' 或 'bytes'。
|
||||
# raw_data (dict): 原始数据的字典。
|
||||
# schema_desc (str): schema 描述的字符串。
|
||||
Returns:
|
||||
MSRStatus, SUCCESS or FAILED.
|
||||
"""
|
||||
Args:
|
||||
file_name (str): File name of MindRecord File.
|
||||
fields (list[str]): Fields would be set as index which
|
||||
could not belong to blob fields and type could not be 'array' or 'bytes'.
|
||||
raw_data (dict): dict of raw data.
|
||||
schema_desc (str): String of schema description.
|
||||
|
||||
schema = {"id": {"type": "int64"}, "label": {"type": "int64"},
|
||||
"data": {"type": "bytes"}}
|
||||
#记录MindRecord schema
|
||||
logger.info("transformed MindRecord schema is: {}".format(schema))
|
||||
Returns:
|
||||
MSRStatus, SUCCESS or FAILED.
|
||||
"""
|
||||
|
||||
writer = FileWriter(file_name, 1)
|
||||
writer.add_schema(schema, schema_desc)
|
||||
# 若有fields参数且它是一个列表,为它添加索引字段
|
||||
if fields and isinstance(fields, list):
|
||||
writer.add_index(fields)
|
||||
writer.write_raw_data(raw_data)
|
||||
#返回结果
|
||||
return writer.commit()
|
||||
schema = {"id": {"type": "int64"}, "label": {"type": "int64"},
|
||||
"data": {"type": "bytes"}}
|
||||
|
||||
logger.info("transformed MindRecord schema is: {}".format(schema))
|
||||
|
||||
writer = FileWriter(file_name, 1)
|
||||
writer.add_schema(schema, schema_desc)
|
||||
if fields and isinstance(fields, list):
|
||||
writer.add_index(fields)
|
||||
writer.write_raw_data(raw_data)
|
||||
return writer.commit()
|
||||
|
|
|
|||
|
|
@ -99,22 +99,20 @@ class ReduceLogSumExp(Cell):
|
|||
def __init__(self, axis, keep_dims=False):
|
||||
"""Initialize ReduceLogSumExp."""
|
||||
super(ReduceLogSumExp, self).__init__()
|
||||
# Checking and assigning the axis and keep_dims values
|
||||
validator.check_value_type('axis', axis, [int, list, tuple], self.cls_name)
|
||||
validator.check_value_type('keep_dims', keep_dims, [bool], self.cls_name)
|
||||
self.axis = axis
|
||||
# Creating necessary operators for calculation
|
||||
self.exp = P.Exp()
|
||||
self.sum = P.ReduceSum(keep_dims)
|
||||
self.log = P.Log()
|
||||
|
||||
def construct(self, x):
|
||||
# Performing the ReduceLogSumExp operation
|
||||
exp = self.exp(x)
|
||||
sumexp = self.sum(exp, self.axis)
|
||||
logsumexp = self.log(sumexp)
|
||||
return logsumexp
|
||||
|
||||
|
||||
class Range(Cell):
|
||||
r"""
|
||||
Creates a sequence of numbers in range [start, limit) with step size delta.
|
||||
|
|
@ -134,7 +132,7 @@ class Range(Cell):
|
|||
delta (Union[int, float]): Increment of the range. It can not be equal to zero. Default: 1.
|
||||
|
||||
Outputs:
|
||||
Tensor, the dtype is int if the dtype of `start`, `limit`, and `delta` all are int. Otherwise, dtype is float.
|
||||
Tensor, the dtype is int if the dtype of `start`, `limit` and `delta` all are int. Otherwise, dtype is float.
|
||||
|
||||
Supported Platforms:
|
||||
``Ascend`` ``GPU`` ``CPU``
|
||||
|
|
@ -149,24 +147,16 @@ class Range(Cell):
|
|||
def __init__(self, start, limit=None, delta=1):
|
||||
"""Initialize Range."""
|
||||
super(Range, self).__init__()
|
||||
# Checking if delta is zero, which is not allowed
|
||||
if delta == 0:
|
||||
raise ValueError(f"For '{self.cls_name}', the 'delta' can not be zero.")
|
||||
|
||||
# Creating a numpy array with the specified range
|
||||
data = np.arange(start, limit, delta)
|
||||
|
||||
# Determining the dtype of the tensor based on the data type of start, limit, and delta
|
||||
if data.dtype == np.float:
|
||||
self.ms_dtype = mstype.float32
|
||||
else:
|
||||
self.ms_dtype = mstype.int32
|
||||
|
||||
# Creating a MindSpore tensor with the specified data and dtype
|
||||
self.result_tensor = Tensor(data, dtype=self.ms_dtype)
|
||||
|
||||
def construct(self):
|
||||
# Returning the result tensor
|
||||
return self.result_tensor
|
||||
|
||||
|
||||
|
|
@ -256,13 +246,10 @@ class LGamma(Cell):
|
|||
self.isfinite = P.IsFinite()
|
||||
|
||||
def construct(self, x):
|
||||
# Checking the dtype of the input x
|
||||
input_dtype = self.dtype(x)
|
||||
_check_input_dtype("x", input_dtype, [mstype.float16, mstype.float32], self.cls_name)
|
||||
# Defining some constant values
|
||||
infinity = self.fill(input_dtype, self.shape(x), self.inf)
|
||||
|
||||
# Using Euler's reflection formula if x is less than 0.5
|
||||
need_to_reflect = self.less(x, 0.5)
|
||||
neg_input = -x
|
||||
z = self.select(need_to_reflect, neg_input, x - 1)
|
||||
|
|
@ -363,10 +350,8 @@ class DiGamma(Cell):
|
|||
self.logicaland = P.LogicalAnd()
|
||||
|
||||
def construct(self, x):
|
||||
# Checking the dtype of the input x
|
||||
input_dtype = self.dtype(x)
|
||||
_check_input_dtype("x", input_dtype, [mstype.float16, mstype.float32], self.cls_name)
|
||||
# Applying Euler's reflection formula if x is less than 0.5
|
||||
need_to_reflect = self.less(x, 0.5)
|
||||
neg_input = -x
|
||||
z = self.select(need_to_reflect, neg_input, x - 1)
|
||||
|
|
@ -395,7 +380,6 @@ class DiGamma(Cell):
|
|||
nan, real_result)
|
||||
|
||||
|
||||
|
||||
eps_fp32 = Tensor(np.finfo(np.float32).eps, mstype.float32)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ class RMSELoss(LossBase):
|
|||
r"""
|
||||
RMSELoss creates a criterion to measure the root mean square error between :math:`x` and :math:`y`
|
||||
element-wise, where :math:`x` is the input and :math:`y` is the labels.
|
||||
|
||||
|
||||
For simplicity, let :math:`x` and :math:`y` be 1-dimensional Tensor with length :math:`N`,
|
||||
the loss of :math:`x` and :math:`y` is given as:
|
||||
|
||||
|
|
@ -354,30 +354,29 @@ class RMSELoss(LossBase):
|
|||
>>> print(output)
|
||||
1.0
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize RMSELoss."""
|
||||
super(RMSELoss, self).__init__() # 调用父类的初始化方法
|
||||
self.MSELoss = MSELoss() # 创建一个MSELoss的实例,用于后续的计算
|
||||
super(RMSELoss, self).__init__()
|
||||
self.MSELoss = MSELoss()
|
||||
|
||||
def construct(self, logits, label):
|
||||
# 计算均方误差,并取平方根,得到RMSE
|
||||
rmse_loss = F.sqrt(self.MSELoss(logits, label))
|
||||
|
||||
return rmse_loss # 返回RMSE作为损失值
|
||||
return rmse_loss
|
||||
|
||||
|
||||
class MAELoss(LossBase):
|
||||
r"""
|
||||
MAELoss creates a criterion to measure the average absolute error between :math:`x` and :math:`y`
|
||||
element-wise, where :math:`x` is the input and :math:`y` is the labels.
|
||||
|
||||
|
||||
For simplicity, let :math:`x` and :math:`y` be 1-dimensional Tensor with length :math:`N`,
|
||||
the unreduced loss (i.e. with argument reduction set to 'none') of :math:`x` and :math:`y` is given as:
|
||||
|
||||
.. math::
|
||||
\ell(x, y) = L = \{l_1,\dots,l_N\}^\top, \quad \text{with } l_n = \left| x_n - y_n \right|,
|
||||
|
||||
|
||||
where :math:`N` is the batch size. If `reduction` is not 'none', then:
|
||||
|
||||
.. math::
|
||||
|
|
@ -428,14 +427,14 @@ class MAELoss(LossBase):
|
|||
|
||||
def __init__(self, reduction='mean'):
|
||||
"""Initialize MAELoss."""
|
||||
super(MAELoss, self).__init__(reduction) # 调用父类的初始化方法,同时传入 reduction 参数
|
||||
self.abs = P.Abs() # 创建一个 P.Abs() 的实例并存储在 self.abs 中
|
||||
super(MAELoss, self).__init__(reduction)
|
||||
self.abs = P.Abs()
|
||||
|
||||
def construct(self, logits, label):
|
||||
_check_is_tensor('logits', logits, self.cls_name) # 检查 logits 是否是 Tensor 类型
|
||||
_check_is_tensor('labels', label, self.cls_name) # 检查 labels 是否是 Tensor 类型
|
||||
x = self.abs(logits - label) # 计算 |logits - label|
|
||||
return self.get_loss(x) # 调用 get_loss 方法计算损失值,并返回
|
||||
_check_is_tensor('logits', logits, self.cls_name)
|
||||
_check_is_tensor('labels', label, self.cls_name)
|
||||
x = self.abs(logits - label)
|
||||
return self.get_loss(x)
|
||||
|
||||
|
||||
class SmoothL1Loss(LossBase):
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ class CrossEntropyLoss(Cell):
|
|||
if not isinstance(parallel_config, OpParallelConfig) and not isinstance(parallel_config):
|
||||
raise TypeError("For 'CrossEntropyLoss', the class variable 'parallel_config' must be OpParallelConfig"
|
||||
", but got the type: {}.".format(type(parallel_config)))
|
||||
#确保 parallel_config 的类型是 OpParallelConfig 或者其子类,如果不是则提供一个错误信息
|
||||
dp = parallel_config.data_parallel
|
||||
mp = parallel_config.model_parallel
|
||||
self.sum = P.ReduceSum().shard(((dp, mp),))
|
||||
|
|
@ -94,38 +93,38 @@ class CrossEntropyLoss(Cell):
|
|||
self.div2 = P.RealDiv()
|
||||
|
||||
def construct(self, logits, label, input_mask):
|
||||
self._check_input(logits, label, input_mask)#检查数据是否符合要求
|
||||
self._check_input(logits, label, input_mask)
|
||||
|
||||
# the shape is [bs*seq_length, vocab_size]
|
||||
logits = F.cast(logits, mstype.float32)#将logits强制转换为32位float的形式
|
||||
logits = F.cast(logits, mstype.float32)
|
||||
# LogSoftmax for logits over last dimension
|
||||
_, logit_max = self.max(logits)#计算logits样本中的最大值
|
||||
logit_sub = self.sub(logits, logit_max)#令logits减去最大值
|
||||
logit_exp = self.exp(logit_sub)#计算logit_sub的指数值
|
||||
_, logit_max = self.max(logits)
|
||||
logit_sub = self.sub(logits, logit_max)
|
||||
logit_exp = self.exp(logit_sub)
|
||||
exp_sum = self.sum(logit_exp, -1)
|
||||
exp_sum = P.Reshape()(exp_sum, (F.shape(exp_sum)[0], 1))#对指数值进行求和
|
||||
softmax_result = self.div(logit_exp, exp_sum)#计算softmax
|
||||
log_softmax_result = self.log(self.add(softmax_result, self.eps_const))#计算对数softmax
|
||||
exp_sum = P.Reshape()(exp_sum, (F.shape(exp_sum)[0], 1))
|
||||
softmax_result = self.div(logit_exp, exp_sum)
|
||||
log_softmax_result = self.log(self.add(softmax_result, self.eps_const))
|
||||
|
||||
# Flatten label to [bs*seq_length]
|
||||
label = P.Reshape()(label, (-1,))#将label变为一维向量
|
||||
label = P.Reshape()(label, (-1,))
|
||||
# Get onehot label [bs*seq_length, vocab_size]
|
||||
one_hot_label = self.onehot(label, F.shape(logits)[-1], self.on_value,
|
||||
self.off_value)#将label转换为独热编码格式
|
||||
self.off_value)
|
||||
# Cross-Entropy loss
|
||||
loss = self.mul(log_softmax_result, one_hot_label)#将softmax的对数值与标签的独热编码相乘
|
||||
loss_unsum = self.neg(loss)#将计算的loss取负数
|
||||
loss_reduce = self.sum(loss_unsum, -1)#对损失进行求和
|
||||
loss = self.mul(log_softmax_result, one_hot_label)
|
||||
loss_unsum = self.neg(loss)
|
||||
loss_reduce = self.sum(loss_unsum, -1)
|
||||
# input_mask indicates whether there is padded inputs and for padded inputs it will not be counted into loss
|
||||
input_mask = P.Reshape()(input_mask, (-1,))#将input_mask变为一维向量
|
||||
numerator = self.sum2(self.mul2(loss_reduce, input_mask))#计算分子,将损失值与input_mask相乘并将结果相加
|
||||
input_mask = P.Reshape()(input_mask, (-1,))
|
||||
numerator = self.sum2(self.mul2(loss_reduce, input_mask))
|
||||
|
||||
denominator = self.add2(
|
||||
self.sum2(input_mask),
|
||||
P.Cast()(F.tuple_to_array((1e-5,)), mstype.float32))#计算分母部分,将input_mask进行求和,并且加上一个1e-5避免分母为0
|
||||
loss = self.div2(numerator, denominator)#计算最终的损失值,将分子除以分母
|
||||
return loss#返回损失值
|
||||
|
||||
P.Cast()(F.tuple_to_array((1e-5,)), mstype.float32))
|
||||
loss = self.div2(numerator, denominator)
|
||||
return loss
|
||||
|
||||
def _check_input(self, logits, label, input_mask):
|
||||
r"""Check the input tensor shape and type"""
|
||||
_check_is_tensor('logits', logits, self.cls_name)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ Note:
|
|||
- dtypes.py defines all the mindspore.numpy dtypes (mainly redirected from mindspore)
|
||||
"""
|
||||
|
||||
# Importing necessary modules and functions from other files
|
||||
from .array_ops import (transpose, expand_dims, squeeze, rollaxis, swapaxes, reshape,
|
||||
ravel, concatenate, where, atleast_1d, atleast_2d, atleast_3d,
|
||||
column_stack, hstack, dstack, vstack, stack, unique, moveaxis,
|
||||
|
|
@ -34,7 +33,6 @@ from .array_ops import (transpose, expand_dims, squeeze, rollaxis, swapaxes, res
|
|||
flip, flipud, fliplr, hsplit, dsplit, take_along_axis, take, repeat,
|
||||
rot90, select, array_split, choose, size, array_str, apply_along_axis,
|
||||
piecewise, unravel_index, apply_over_axes)
|
||||
|
||||
from .array_creations import copy_ as copy
|
||||
from .array_creations import (array, asarray, asfarray, ones, zeros, full, randn, rand, randint, arange,
|
||||
linspace, logspace, eye, identity, empty, empty_like,
|
||||
|
|
@ -43,11 +41,9 @@ from .array_creations import (array, asarray, asfarray, ones, zeros, full, randn
|
|||
diag, diag_indices, ix_, indices, geomspace, vander, hamming,
|
||||
hanning, bartlett, blackman, triu_indices, tril_indices,
|
||||
triu_indices_from, tril_indices_from, histogram_bin_edges, pad)
|
||||
|
||||
from .dtypes import (int_, int8, int16, int32, int64, uint, uint8, uint16,
|
||||
uint32, uint64, float_, float16, float32, float64, bool_, inf, nan, pi,
|
||||
numeric_types, PINF, NINF)
|
||||
|
||||
from .math_ops import (mean, inner, add, subtract, multiply, divide, true_divide, power,
|
||||
dot, outer, tensordot, absolute, std, var, average, minimum,
|
||||
matmul, square, sqrt, reciprocal, log, maximum, heaviside, amax, amin,
|
||||
|
|
@ -62,13 +58,11 @@ from .math_ops import (mean, inner, add, subtract, multiply, divide, true_divide
|
|||
histogramdd, histogram2d, matrix_power, around, polyadd, polysub, polyval,
|
||||
polyder, polymul, polyint, result_type, unwrap, cumprod, ravel_multi_index,
|
||||
norm, bitwise_and, bitwise_or, bitwise_xor, invert, rint, correlate, radians)
|
||||
|
||||
from .logic_ops import (not_equal, less_equal, less, greater_equal, greater, equal, isfinite,
|
||||
isnan, isinf, isposinf, isneginf, isscalar, logical_and, logical_not,
|
||||
logical_or, logical_xor, in1d, isin, isclose, signbit, sometrue,
|
||||
array_equal, array_equiv)
|
||||
|
||||
# Aliasing some functions for convenience
|
||||
mod = remainder
|
||||
fabs = absolute
|
||||
round = around # pylint: disable=redefined-builtin
|
||||
|
|
@ -81,7 +75,6 @@ sum = sum_ # pylint: disable=redefined-builtin
|
|||
del sum_
|
||||
bitwise_not = invert
|
||||
|
||||
# Creating module-specific lists for easy management
|
||||
array_ops_module = ['transpose', 'expand_dims', 'squeeze', 'rollaxis', 'swapaxes', 'reshape',
|
||||
'ravel', 'concatenate', 'where', 'atleast_1d', 'atleast_2d', 'atleast_3d',
|
||||
'column_stack', 'hstack', 'dstack', 'vstack', 'stack', 'unique', 'moveaxis',
|
||||
|
|
@ -120,8 +113,6 @@ logic_module = ['not_equal', 'less_equal', 'less', 'greater_equal', 'greater', '
|
|||
'logical_or', 'logical_xor', 'in1d', 'isin', 'isclose', 'signbit', 'sometrue',
|
||||
'array_equal', 'array_equiv']
|
||||
|
||||
# Combining all the modules and functions into a single list
|
||||
__all__ = array_ops_module + array_creations_module + math_module + logic_module + numeric_types
|
||||
|
||||
# Sorting the list alphabetically
|
||||
__all__.sort()
|
||||
|
|
|
|||
|
|
@ -34,9 +34,8 @@ def _check_mul():
|
|||
finally:
|
||||
pass
|
||||
|
||||
print(f"MindSpore version: ", ms.__version__) # Print MindSpore version
|
||||
print(f"MindSpore version: ", ms.__version__)
|
||||
|
||||
# Create tensors and perform multiplication
|
||||
input_x = ms.Tensor(np.array([1.0, 2.0, 3.0]), ms.float32)
|
||||
input_y = ms.Tensor(np.array([4.0, 5.0, 6.0]), ms.float32)
|
||||
mul = ms.ops.Mul()
|
||||
|
|
@ -56,10 +55,10 @@ def run_check():
|
|||
The result of multiplication calculation is correct, MindSpore has been installed successfully!
|
||||
"""
|
||||
try:
|
||||
_check_mul() # Call _check_mul function to perform the check
|
||||
_check_mul()
|
||||
# pylint: disable=broad-except
|
||||
except Exception as e:
|
||||
print("MindSpore running check failed.") # Print error message if check fails
|
||||
print(str(e)) # Print specific error message
|
||||
print("MindSpore running check failed.")
|
||||
print(str(e))
|
||||
finally:
|
||||
pass # Cleanup code if needed
|
||||
pass
|
||||
|
|
|
|||
Loading…
Reference in New Issue