Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / components / optim / builders.py: 95%
39 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
1# Copyright 2026 Huawei Technologies Co., Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ============================================================================
15"""YAML-targeted optimizer builders: AdamW/Muon selection.
17Parameter-name and parameter-group logic lives in
18:mod:`hyper_parallel.components.optim.parameter_groups`; the optimizer
19algorithm implementations stay in ``hyper_parallel.core.optimizer``.
20"""
22__all__ = ["AdamW", "Muon"]
24import logging
25from typing import Any, Dict, List, Optional, Sequence, Tuple
27from torch import nn # pylint: disable=forbidden-backend-import
29from hyper_parallel.core.optimizer import get_hyper_optimizer
30from hyper_parallel.components.optim.parameter_groups import (
31 _DEFAULT_ADAMW_NAME_KEYWORDS,
32 get_adamw_param_groups,
33 split_muon_adamw_params,
34)
36logger = logging.getLogger(__name__)
39class AdamW:
40 """Build a core AdamW optimizer from YAML configuration."""
42 def __init__(
43 self,
44 adamw_config: dict,
45 model: nn.Module,
46 no_decay_params: Optional[List[str]] = None,
47 excluded_param_ids: Optional[Sequence[int]] = None,
48 ) -> None:
49 """Initialize AdamW optimizer configuration.
51 Args:
52 adamw_config: AdamW hyperparameters resolved from YAML.
53 model: Module whose trainable parameters are optimized.
54 no_decay_params: Optional names excluded from weight decay.
55 """
56 self.config = adamw_config
57 self.model = model
59 adamw_groups, _ = self.get_adamw_param_groups(
60 self.model,
61 weight_decay=adamw_config.get("adamw_weight_decay", 1e-2),
62 no_decay_params=no_decay_params,
63 excluded_param_ids=excluded_param_ids,
64 )
65 if not adamw_groups:
66 raise ValueError("AdamW requires at least one trainable parameter")
68 self.optimizer = get_hyper_optimizer(
69 model=self.model,
70 muon_params=[],
71 adamw_params=adamw_groups,
72 adamw_kwargs=adamw_config,
73 )
75 @staticmethod
76 def get_adamw_param_groups(
77 model: "nn.Module",
78 weight_decay: float = 1e-2,
79 no_decay_params: Optional[Sequence[str]] = None,
80 param_groups: Optional[Sequence[Dict[str, Any]]] = None,
81 allowed_param_ids: Optional[Sequence[int]] = None,
82 excluded_param_ids: Optional[Sequence[int]] = None,
83 ) -> Tuple[List[Dict[str, Any]], List[str]]:
84 """Split model parameters into decaying and non-decaying groups.
86 Delegates to
87 :func:`hyper_parallel.components.optim.parameter_groups.get_adamw_param_groups`;
88 retained on the class so existing call sites keep working.
90 Args:
91 model: Module whose trainable parameters are routed.
92 weight_decay: Default decay coefficient for trainable parameters.
93 no_decay_params: Name keywords excluded from weight decay.
94 param_groups: Optional prebuilt groups to return unchanged.
95 allowed_param_ids: Optional parameter identities eligible for routing.
97 Returns:
98 Parameter groups and names routed to AdamW.
99 """
100 return get_adamw_param_groups(
101 model,
102 weight_decay=weight_decay,
103 no_decay_params=no_decay_params,
104 param_groups=param_groups,
105 allowed_param_ids=allowed_param_ids,
106 excluded_param_ids=excluded_param_ids,
107 )
109 def get_optimizer(self) -> Any:
110 """Return the core chained optimizer runtime."""
111 return self.optimizer
114class Muon:
115 """Build a mixed Muon and AdamW optimizer from YAML configuration."""
117 _DEFAULT_ADAMW_NAME_KEYWORDS = _DEFAULT_ADAMW_NAME_KEYWORDS
119 def __init__(
120 self,
121 muon_config: dict,
122 adamw_config: dict,
123 model: nn.Module,
124 extra_adamw_name_keywords: Optional[List[str]] = None,
125 no_decay_params: Optional[List[str]] = None,
126 excluded_param_ids: Optional[Sequence[int]] = None,
127 ) -> None:
128 """Build a mixed Muon and fallback AdamW runtime for ``model``.
130 Args:
131 muon_config: Muon hyperparameters resolved from YAML.
132 adamw_config: Fallback AdamW hyperparameters resolved from YAML.
133 model: Module whose trainable parameters are optimized.
134 extra_adamw_name_keywords: Additional names routed to AdamW.
135 no_decay_params: Optional names excluded from weight decay.
136 """
137 self.muon_config = muon_config
138 self.adamw_config = adamw_config
139 self.model = model
141 muon_params, adamw_params, muon_names, adamw_names = self.split_muon_adamw_params(
142 model,
143 extra_adamw_name_keywords=extra_adamw_name_keywords or (),
144 excluded_param_ids=excluded_param_ids,
145 )
146 if not muon_params:
147 raise ValueError("Muon requires at least one eligible matrix parameter")
149 adamw_groups, _ = AdamW.get_adamw_param_groups(
150 model,
151 weight_decay=adamw_config.get("adamw_weight_decay", 1e-2),
152 no_decay_params=no_decay_params,
153 allowed_param_ids=[id(parameter) for parameter in adamw_params],
154 excluded_param_ids=excluded_param_ids,
155 )
157 logger.info_rank0(
158 "Muon optimizer split: %s Muon parameters, %s AdamW parameters",
159 len(muon_names),
160 len(adamw_names),
161 )
162 logger.info_rank0("Muon parameters (first 5): %s", muon_names[:5])
163 logger.info_rank0("AdamW parameters (first 5): %s", adamw_names[:5])
165 self.optimizer = get_hyper_optimizer(
166 model=self.model,
167 muon_params=muon_params,
168 adamw_params=adamw_groups,
169 muon_kwargs=muon_config,
170 adamw_kwargs=adamw_config,
171 )
173 @staticmethod
174 def split_muon_adamw_params(
175 model: nn.Module,
176 extra_adamw_name_keywords: Sequence[str] = (),
177 excluded_param_ids: Optional[Sequence[int]] = None,
178 ) -> Tuple[List[nn.Parameter], List[nn.Parameter], List[str], List[str]]:
179 """Route matrix parameters to Muon and remaining parameters to AdamW.
181 Delegates to
182 :func:`hyper_parallel.components.optim.parameter_groups.split_muon_adamw_params`;
183 retained on the class so existing call sites keep working.
185 Args:
186 model: Module whose trainable parameters are routed.
187 extra_adamw_name_keywords: Additional names reserved for AdamW.
189 Returns:
190 Muon parameters, AdamW parameters, and their respective names.
191 """
192 return split_muon_adamw_params(
193 model,
194 extra_adamw_name_keywords=extra_adamw_name_keywords,
195 excluded_param_ids=excluded_param_ids,
196 )
198 def get_optimizer(self) -> Any:
199 """Return the core chained optimizer runtime."""
200 return self.optimizer