| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- # Copyright 2020 The HuggingFace Team. All rights reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import copy
- import re
- class TrialShortNamer:
- PREFIX = "hp"
- DEFAULTS = {}
- NAMING_INFO = None
- @classmethod
- def set_defaults(cls, prefix, defaults):
- cls.PREFIX = prefix
- cls.DEFAULTS = defaults
- cls.build_naming_info()
- @staticmethod
- def shortname_for_word(info, word):
- if len(word) == 0:
- return ""
- short_word = None
- if any(char.isdigit() for char in word):
- raise Exception(f"Parameters should not contain numbers: '{word}' contains a number")
- if word in info["short_word"]:
- return info["short_word"][word]
- for prefix_len in range(1, len(word) + 1):
- prefix = word[:prefix_len]
- if prefix in info["reverse_short_word"]:
- continue
- else:
- short_word = prefix
- break
- if short_word is None:
- # Paranoid fallback
- def int_to_alphabetic(integer):
- s = ""
- while integer != 0:
- s = chr(ord("A") + integer % 10) + s
- integer //= 10
- return s
- i = 0
- while True:
- sword = word + "#" + int_to_alphabetic(i)
- if sword in info["reverse_short_word"]:
- continue
- else:
- short_word = sword
- break
- info["short_word"][word] = short_word
- info["reverse_short_word"][short_word] = word
- return short_word
- @staticmethod
- def shortname_for_key(info, param_name):
- words = param_name.split("_")
- shortname_parts = [TrialShortNamer.shortname_for_word(info, word) for word in words]
- # We try to create a separatorless short name, but if there is a collision we have to fallback
- # to a separated short name
- separators = ["", "_"]
- for separator in separators:
- shortname = separator.join(shortname_parts)
- if shortname not in info["reverse_short_param"]:
- info["short_param"][param_name] = shortname
- info["reverse_short_param"][shortname] = param_name
- return shortname
- return param_name
- @staticmethod
- def add_new_param_name(info, param_name):
- short_name = TrialShortNamer.shortname_for_key(info, param_name)
- info["short_param"][param_name] = short_name
- info["reverse_short_param"][short_name] = param_name
- @classmethod
- def build_naming_info(cls):
- if cls.NAMING_INFO is not None:
- return
- info = {
- "short_word": {},
- "reverse_short_word": {},
- "short_param": {},
- "reverse_short_param": {},
- }
- field_keys = list(cls.DEFAULTS.keys())
- for k in field_keys:
- cls.add_new_param_name(info, k)
- cls.NAMING_INFO = info
- @classmethod
- def shortname(cls, params):
- cls.build_naming_info()
- assert cls.PREFIX is not None
- name = [copy.copy(cls.PREFIX)]
- for k, v in params.items():
- if k not in cls.DEFAULTS:
- raise Exception(f"You should provide a default value for the param name {k} with value {v}")
- if v == cls.DEFAULTS[k]:
- # The default value is not added to the name
- continue
- key = cls.NAMING_INFO["short_param"][k]
- if isinstance(v, bool):
- v = 1 if v else 0
- sep = "" if isinstance(v, (int, float)) else "-"
- e = f"{key}{sep}{v}"
- name.append(e)
- return "_".join(name)
- @classmethod
- def parse_repr(cls, repr):
- repr = repr[len(cls.PREFIX) + 1 :]
- if repr == "":
- values = []
- else:
- values = repr.split("_")
- parameters = {}
- for value in values:
- if "-" in value:
- p_k, p_v = value.split("-")
- else:
- p_k = re.sub("[0-9.]", "", value)
- p_v = float(re.sub("[^0-9.]", "", value))
- key = cls.NAMING_INFO["reverse_short_param"][p_k]
- parameters[key] = p_v
- for k in cls.DEFAULTS:
- if k not in parameters:
- parameters[k] = cls.DEFAULTS[k]
- return parameters
|