Browse Source

Update ftrl.py

pull/1/head
bjutsecurity22 2 years ago
parent
commit
c71b4d8b82
1 changed files with 63 additions and 5 deletions
  1. +63
    -5
      mindspore/nn/optim/ftrl.py

+ 63
- 5
mindspore/nn/optim/ftrl.py View File

@@ -13,13 +13,15 @@
# limitations under the License.
# ============================================================================
"""FTRL"""
# 本文件为FTRL优化器的构建
from mindspore.ops import functional as F, composite as C, operations as P
from mindspore.common import Tensor
import mindspore.common.dtype as mstype
from mindspore._checkparam import Validator as validator
from mindspore._checkparam import Rel
from .optimizer import Optimizer, _apply_decay, _grad_scale
from.optimizer import Optimizer, _apply_decay, _grad_scale

# 定义_ftrl_opt函数,用于接收四个参数:opt(优化器),spars_opt(模式优化器),push(推送),pull(拉取),l1(L1正则化),l2(L2正则化),lr_power(学习率指数),learning_rate(学习率),linear(线性),gradient(梯度),weight(权重),moment(动量),ps_parameter(参数),cache_enable(是否使用缓存)
_ftrl_opt = C.MultitypeFuncGraph("ftrl_opt")


@@ -28,14 +30,23 @@ _ftrl_opt = C.MultitypeFuncGraph("ftrl_opt")
def _tensor_run_opt_with_sparse(opt, spars_opt, push, pull, l1, l2, lr_power, learning_rate, linear,
gradient, weight, moment, ps_parameter, cache_enable):
"""Apply sparse ftrl optimizer to the weight parameter when the gradient is sparse."""
# 对为稀疏矩阵的参数权重使用FTRL优化器
# 判断是否满足条件
success = True
# 获取梯度的索引和值
indices = gradient.indices
values = gradient.values
# 如果没有指定ps参数,且不满足cache_enable条件
if ps_parameter and not cache_enable:
# 获取操作的形状
op_shape = P.Shape()
# 获取形状
shapes = (op_shape(weight), op_shape(moment), op_shape(linear), op_shape(values), op_shape(indices))
# 执行pull操作
success = F.depend(success, pull(push((values, indices), shapes), weight))
# 如果指定了ps参数,且满足cache_enable条件
else:
# 执行spars_opt操作
success = F.depend(success, spars_opt(weight, moment, linear, values, indices))
return success

@@ -44,35 +55,52 @@ def _tensor_run_opt_with_sparse(opt, spars_opt, push, pull, l1, l2, lr_power, le
"Tensor", "Tensor", "Tensor", "Bool", "Bool")
def _tensor_run_opt(opt, spars_opt, push, pull, l1, l2, lr_power, learning_rate, linear,
gradient, weight, moment, ps_parameter, cache_enable):
# 对权重参数应用FTRL优化器
"""Apply ftrl optimizer to the weight parameter."""
success = True
# 如果ps_parameter为True,且不支持缓存,则使用pull函数拉取push函数的输出
if ps_parameter and not cache_enable:
op_shape = P.Shape()
success = F.depend(success, pull(push((gradient, learning_rate, l1, l2, lr_power),
(op_shape(weight), op_shape(moment), op_shape(linear))), weight))
# 否则,使用opt函数计算weight的梯度,并使用push函数推送梯度
else:
success = F.depend(success, opt(weight, moment, linear, gradient, learning_rate, l1, l2, lr_power))
# 返回更新成功标志
return success


def _check_param(initial_accum, lr_power, l1, l2, use_locking, prim_name=None):
"""Check param."""
"""
检查参数
"""
# 检查initial_accum的类型是否为float
validator.check_value_type("initial_accum", initial_accum, [float], prim_name)
# 检查initial_accum的值是否在0.0以上
validator.check_number("initial_accum", initial_accum, 0.0, Rel.GE, prim_name)

# 检查lr_power的类型是否为float
validator.check_value_type("lr_power", lr_power, [float], prim_name)
# 检查lr_power的值是否在0.0和Rel.LE之间
validator.check_number("lr_power", lr_power, 0.0, Rel.LE, prim_name)

# 检查l1的类型是否为float
validator.check_value_type("l1", l1, [float], prim_name)
# 检查l1的值是否在0.0和Rel.GE之间
validator.check_number("l1", l1, 0.0, Rel.GE, prim_name)

# 检查l2的类型是否为float
validator.check_value_type("l2", l2, [float], prim_name)
# 检查l2的值是否在0.0和Rel.GE之间
validator.check_number("l2", l2, 0.0, Rel.GE, prim_name)

# 检查use_locking的类型是否为bool
validator.check_value_type("use_locking", use_locking, [bool], prim_name)


class FTRL(Optimizer):
# FTRL优化器
r"""
Implements the FTRL algorithm with ApplyFtrl Operator.

@@ -193,59 +221,89 @@ class FTRL(Optimizer):
"""
def __init__(self, params, initial_accum=0.1, learning_rate=0.001, lr_power=-0.5, l1=0.0, l2=0.0,
use_locking=False, loss_scale=1.0, weight_decay=0.0):
# 初始化FTRL类
super(FTRL, self).__init__(learning_rate, params, weight_decay, loss_scale=loss_scale)
# 检查参数
if self.dynamic_lr or self.is_group_lr:
raise ValueError('Dynamic learning rate or group learning rate is currently not supported.')
_check_param(initial_accum, lr_power, l1, l2, use_locking, self.cls_name)
# 初始化参数
self.moments = self.parameters.clone(prefix="moments", init=initial_accum)
self.linear = self.parameters.clone(prefix="linear", init='zeros')
self.l1 = l1
self.l2 = l2
self.lr = learning_rate
self.lr_power = lr_power
# 判断是否是分组
if not self.is_group:
# 如果不是组,则将decay_flags设置为True
self.decay_flags = tuple((lambda: True)() for x in self.parameters)
# 初始化优化器
self.hyper_map = C.HyperMap()
self.opt = P.ApplyFtrl(use_locking=use_locking)
self.use_locking = use_locking
# 初始化sparse优化器
self.sparse_opt = P.SparseApplyFtrl(learning_rate, l1, l2, lr_power, use_locking=use_locking)
# 初始化sparse_opt
self._ps_pull = P.Pull()
# 初始化_ps_pull
self._ps_push = P.Push("Ftrl", [0, 1, 2])
# 初始化_ps_push
self._ps_push.add_prim_attr("init_accum", initial_accum)
# 向_ps_push中添加init_accum属性
self._ps_push.add_prim_attr("lr", learning_rate)
# 向_ps_push中添加lr属性
self._ps_push.add_prim_attr("l1", l1)
# 向_ps_push中添加l1属性
self._ps_push.add_prim_attr("l2", l2)
# 向_ps_push中添加l2属性
self._ps_push.add_prim_attr("lr_power", lr_power)

def construct(self, grads):
'''
构建FTRL优化器
:param grads: 梯度
:return: 更新后的参数
'''
params = self.parameters
moments = self.moments
linear = self.linear
# 对梯度权重衰减
grads = self.decay_weight(grads)
# 对梯度中心化
grads = self.gradients_centralization(grads)
# 对梯度进行缩放
grads = self.scale_grad(grads)
# 对梯度进行去重
grads = self._grad_sparse_indices_deduplicate(grads)
# 更新参数
lr = self.get_lr()

# 将_ftrl_opt函数放入参数
success = self.map_(F.partial(_ftrl_opt, self.opt, self.sparse_opt, self._ps_push, self._ps_pull,
self.l1, self.l2, self.lr_power, lr),
linear, grads, params, moments, self.ps_parameters, self.cache_enable)
self.l1, self.l2, self.lr_power, lr),
linear, grads, params, moments, self.ps_parameters, self.cache_enable)
return success

@Optimizer.target.setter
# 优化器target设置
def target(self, value):
"""If the input value is set to "CPU", the parameters will be updated on the host using the Fused
optimizer operation."""
# 如果value不为str类,则抛出TypeError异常
if not isinstance(value, str):
raise TypeError("The value must be str type, but got value type is {}".format(type(value)))
# 如果value值不在三者之中,则抛出ValueError异常
if value not in ('CPU', 'Ascend', 'GPU'):
raise ValueError("The value must be 'CPU', 'Ascend' or 'GPU', but got value {}".format(value))

if value == 'CPU':
# 如果输入值为CPU,则使用FusedSparseFtrl优化器更新参数
self.sparse_opt = P.FusedSparseFtrl(self.lr, self.l1, self.l2, self.lr_power, self.use_locking)
self.sparse_opt.add_prim_attr("primitive_target", "CPU")
else:
# 如果输入值为GPU,则使用SparseApplyFtrl优化器更新参数
self.sparse_opt = P.SparseApplyFtrl(self.lr, self.l1, self.l2, self.lr_power, self.use_locking)

self._target = value
# 设置目标值
self._target = value

Loading…
Cancel
Save