timm documentation

Planificateurs de taux d'apprentissage

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.0.30).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Planificateurs de taux d'apprentissage

Cette page contient la documentation de référence de l’API des planificateurs de taux d’apprentissage inclus dans timm, ainsi qu’un aperçu de leur création et de leur progression.

Utilisation

Les planificateurs sont créés par leur nom à l'aide de create_scheduler_v2, qui renvoie le planificateur et le nombre total d'époques d'entraînement (y compris tout préfixe de montée en charge, cycles et refroidissement, voir ci-dessous). Contrairement à torch.optim.lr_scheduler, les planificateurs de timm ne comptent pas eux-mêmes les étapes. Ils sont conçus pour être sans état : le taux d'apprentissage est une fonction de la configuration du planificateur et d'un nombre explicite d'époques ou de mises à jour, de sorte que la reprise d'une exécution n'a besoin que de l'époque, et aucun état de planificateur n'est stocké dans les points de contrôle. La boucle d'entraînement transmet explicitement l'époque ou le nombre de mises à jour :

  • scheduler.step(epoch) à la fin de chaque époque, avec l'index de l'époque suivante (epoch + 1)
  • scheduler.step_update(num_updates) après chaque mise à jour de l’optimiseur, avec le nombre de mises à jour effectuées jusqu’à présent

Un planificateur est incrémenté par époque ou par mise à jour (step_on_epochs) ; l'autre appel est un no-op, de sorte qu'une boucle d'entraînement peut effectuer les deux appels et prendre en charge les deux modes.

import timm
from timm.optim import create_optimizer_v2
from timm.scheduler import create_scheduler_v2

model = timm.create_model('resnet50')
optimizer = create_optimizer_v2(model, opt='adamw', lr=1e-3, weight_decay=0.05)
updates_per_epoch = len(loader)  # optimizer updates per epoch

# Cosine decay w/ 5 epochs of linear warmup, stepped per update for a smooth schedule.
scheduler, num_epochs = create_scheduler_v2(
    optimizer,
    sched='cosine',
    num_epochs=100,
    warmup_epochs=5,
    min_lr=1e-6,
    step_on_epochs=False,
    updates_per_epoch=updates_per_epoch,
)

num_updates = 0
for epoch in range(num_epochs):
    for batch in loader:
        ...  # forward, backward, optimizer.step()
        num_updates += 1
        scheduler.step_update(num_updates=num_updates)
    scheduler.step(epoch + 1)  # pass the eval metric too for 'plateau', scheduler.step(epoch + 1, metric)

Les durées (num_epochs, warmup_epochs, decay_epochs, …) sont toujours exprimées en époques ; la fabrique les convertit en mises à jour lorsque step_on_epochs=False. Les planificateurs peuvent également être construits directement à partir de leurs classes, les durées étant alors exprimées dans l’unité dans laquelle ils sont incrémentés (t_in_epochs).

Le script d’entraînement (train.py) expose les arguments de la fabrique via ces drapeaux :

  • --sched sélectionne le planning.
  • --epochs définit la durée du planning.
  • --sched-on-updates étapes par mise à jour au lieu de par époque.
  • --warmup-epochs définit la durée du warmup.
  • --warmup-lr définit le taux d'apprentissage initial de la phase de montée en charge.
  • --warmup-prefix ajoute un échauffement avant le planning au lieu de superposer son début.
  • --min-lr définit le taux d'apprentissage minimal.
  • --decay-epochs définit l'intervalle de décroissance par étape ou la durée finale de la décroissance pour WSD / rsqrt.
  • --decay-milestones définit les époques de décroissance pour le planning multistep.
  • --decay-rate définit le facteur d'atténuation, ou l'exposant pour le plan polynomial.
  • --cooldown-epochs ajoute des époques au taux d'apprentissage minimal après la fin du planning.
  • --patience-epochs définit la patience du planificateur plateau.
  • --lr-noise sélectionne la partie du calendrier avec du bruit sur le taux d'apprentissage.
  • --lr-noise-pct limite l'amplitude du bruit.
  • --lr-noise-std définit l'écart-type du bruit.
  • --lr-cycle-mul définit le multiplicateur de la longueur du cycle.
  • --lr-cycle-decay définit le multiplicateur du taux d'apprentissage de pointe entre les cycles.
  • --lr-cycle-limit définit le nombre de cycles.
  • --lr-k-decay définit le k-decay pour les calendriers cosinus / polynomiaux.
  • --lr-decay-fn sélectionne la fonction de décroissance finale pour WSD / rsqrt.
  • --lr-stable-timescale définit l'échelle de temps de la phase stable rsqrt.

Planifications

schedClassePlanification
cosineCosineLRSchedulerRecuit cosinus depuis le lr de base jusqu'à min_lr (SGDR), redémarrages facultatifs (cycles) et k-decay
tanhTanhLRSchedulerDécroissance par tangente hyperbolique (article), redémarrages optionnels
polyPolyLRSchedulerDécroissance polynomiale vers min_lr, la puissance est donnée par decay_rate, redémarrages facultatifs et k-décroissance
stepStepLRSchedulerlr multipliée par decay_rate toutes les decay_epochs
multistepMultiStepLRSchedulerlr multiplié par decay_rate à chacun des epochs decay_milestones
plateauPlateauLRSchedulerDéprécié. lr multiplié par decay_rate lorsque la métrique d’évaluation n’a pas progressé depuis patience_epochs, uniquement par pas d’époque
wsdWSDLRSchedulerWarmup-stable-decay (MiniCPM), lr constant puis une décroissance vers min_lr sur les decay_epochs finaux, décroissance 1-sqrt par défaut (paper)
rsqrtWSDLRSchedulerDécroissance de l'inverse de la racine carrée avec un refroidissement linéaire sur les decay_epochs derniers (Big Vision)

Options courantes

  • Warmup. warmup_epochs de réchauffement linéaire depuis warmup_lr jusqu'au taux d'apprentissage de base, pris en charge par tous les plans de progression.
    • warmup_prefix : par défaut, le warmup chevauche le début du planning (le planning est calculé à partir de l'époque 0, le warmup remplace ses premières époques), de sorte que num_epochs est la longueur totale. Avec warmup_prefix=True, le planning commence après le warmup et le warmup est ajouté au total.
    • Pour wsd et rsqrt, la phase stable commence toujours après le warmup, sans warmup_prefix les phases stable et de décroissance sont ajustées sur num_epochs - warmup_epochs de sorte que num_epochs reste le total.
  • min_lr : le taux d'apprentissage auquel les calendriers de décroissance (cosine, tanh, poly, wsd, rsqrt) parviennent à la fin, et une borne inférieure pour plateau.

Le planificateur plateau est obsolète et sera supprimé dans une future version. Il ne correspondait jamais à la conception sans état décrite ci-dessus : son lr dépend de l’historique de la métrique d’évaluation plutôt que de l’époque, et cet historique (meilleure métrique, compteurs de patience et de refroidissement) n’est pas sauvegardé dans les points de contrôle, si bien qu’une exécution reprise redémarre la logique de plateau. La prise en charge des points de contrôle ne sera pas ajoutée. Un plateau de validation est également un signal faible pour déterminer quand effectuer l’annealing ; un planificateur fixe tel que cosine ou wsd est reproductible et se reprend exactement, et un balayage WSD (voir Balayages d’hyperparamètres) compare les périodes de refroidissement à plusieurs budgets à partir d’une seule exécution stable.

  • cooldown_epochs : nombre d’époques maintenues à min_lr après la fin du planning (cosine, tanh, poly, wsd, rsqrt), ajouté au num_epochs retourné. Comme le planning atteint min_lr une étape après sa dernière étape, une époque de refroidissement est également un moyen d’entraîner à min_lr lors d’un pas par époque.
  • Cycles (cosine, tanh, poly) : cycle_limit > 1 redémarre le planning, chaque cycle étant cycle_mul fois plus long et son pic de lr étant multiplié par cycle_decay par rapport au précédent. Le num_epochs retourné couvre tous les cycles.
  • k_decay (cosine, poly) : k-decay modifie la forme du déclin (t ** k), k > 1 maintient le taux d'apprentissage élevé plus longtemps.
  • Bruit : noise ajoute un bruit multiplicatif aléatoire au taux d'apprentissage sur une plage du planning, définie par des fractions de num_epochs (un début, ou un début et une fin), limitée par noise_pct.

WSD et rsqrt

Le WSDLRScheduler comporte trois phases : un réchauffement linéaire, une phase stable et un déclin jusqu'à min_lr.

  • decay_epochs définit la durée finale du déclin. Une valeur comprise entre 0 et 1 représente une fraction de la longueur stable + déclin, 20 % par défaut.
  • decay_fn (--lr-decay-fn) sélectionne 1-sqrt (par défaut pour wsd), linear (par défaut pour rsqrt), cosine, power ou exp.
  • stable_timescale (--lr-stable-timescale, en époques) contrôle la phase stable rsqrt, qui décroît selon (1 + t / timescale) ** -0.5 à partir de la fin du warmup. Sa valeur par défaut est la durée du warmup et elle doit être définie lorsqu'il n'y a pas de warmup.

La classe prend également en charge une phase stable power généralisée et des fonctions de décroissance personnalisées.

L’anneal final est l’étape où les calendriers WSD tirent le plus de bénéfice. Utilisez donc un pas par mise à jour (--sched-on-updates) ou ajoutez une époque de refroidissement lorsque la phase de décroissance ne dure que quelques époques. Avec un pas par époque, la dernière époque d’une courte décroissance est nettement supérieure à min_lr (environ 10 % du taux d’apprentissage de base pour la dernière des 5 époques de décroissance avec 1-sqrt).

# 300 epochs, 5 epoch warmup, constant lr, then a 1-sqrt decay over the final 20%
scheduler, num_epochs = create_scheduler_v2(
    optimizer, sched='wsd', num_epochs=300, warmup_epochs=5, decay_epochs=0.2,
    step_on_epochs=False, updates_per_epoch=updates_per_epoch,
)

Échelles de lr des groupes de paramètres

Les groupes de paramètres avec un champ lr_scale (par exemple, les groupes de décroissance du taux d'apprentissage par couche issus de param_groups_layer_decay) voient leur taux d'apprentissage planifié multiplié par leur échelle. Le taux d'apprentissage de base de chaque groupe est enregistré en tant que initial_lr dans le groupe lors de la création du planificateur.

Reprise

À mesure que les nombres d’étapes sont transmis, un planificateur pour une exécution reprise est mis en place en le créant comme pour l’exécution d’origine puis en l’avançant jusqu’au point de reprise, scheduler.step(start_epoch) ou scheduler.step_update(start_epoch * updates_per_epoch). state_dict() / load_state_dict() sauvegardent et restaurent les attributs du planificateur.

API

Fonctions d'usine

timm.scheduler.create_scheduler

< >

( argsoptimizer: Optimizerupdates_per_epoch: int = 0 )

timm.scheduler.create_scheduler_v2

< >

( optimizer: Optimizersched: str = 'cosine'num_epochs: int = 300decay_epochs: typing.Optional[float] = Nonedecay_milestones: typing.List[int] = (90, 180, 270)cooldown_epochs: int = 0patience_epochs: int = 10decay_rate: float = 0.1min_lr: float = 0.0warmup_lr: float = 1e-05warmup_epochs: int = 0warmup_prefix: bool = Falsenoise: typing.Union[float, typing.List[float]] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42cycle_mul: float = 1.0cycle_decay: float = 0.1cycle_limit: int = 1k_decay: float = 1.0decay_fn: typing.Optional[str] = Nonestable_timescale: typing.Optional[float] = Noneplateau_mode: str = 'max'step_on_epochs: bool = Trueupdates_per_epoch: int = 0 )

Paramètres

  • optimizer — optimiseur à planifier
  • sched — nom du planificateur, l’un des éléments suivants : ‘cosine’, ‘tanh’, ‘step’, ‘multistep’, ‘poly’, ‘wsd’, ‘rsqrt’, ‘constant’, ‘plateau’ (obsolète) ou ‘none’ pour aucun planificateur (renvoie None, le lr de l’optimiseur est laissé inchangé). ‘constant’ maintient le lr après le warmup avec l’application de lr_scale du groupe de paramètres (décroissance du lr par couche).
  • num_epochs — nombre d'époques dans le planning (excluant le warmup si warmup_prefix, excluant le cooldown)
  • decay_epochs — interval de décroissance du taux d'apprentissage (étape), ou longueur de la phase de décroissance (wsd / rsqrt) en époques, une valeur dans (0, 1) est une fraction de la longueur du planning. None = 90 (étape), 0.2 (wsd / rsqrt)
  • decay_milestones — époques à laquelle diminuer le lr (multistep)
  • cooldown_epochs — nombre d'époques pendant lesquelles le taux d'apprentissage est maintenu à min_lr après la fin du planning
  • patience_epochs — nombre d'époques sans amélioration avant de réduire le taux d'apprentissage (plateau, obsolète)
  • decay_rate — taux de décroissance du taux d'apprentissage (step, multistep, plateau), puissance polynomiale (poly)
  • min_lr — borne inférieure du taux d'apprentissage pour les planificateurs qui y convergent
  • warmup_lr — lr au début du warmup
  • warmup_epochs — époques de réchauffage linéaire
  • warmup_prefix — exclut la période de warmup de num_epochs (ajoutée au total), wsd / rsqrt sont toujours préfixés par warmup, avec warmup_prefix=False leurs phases stable + decay s'insèrent dans num_epochs
  • noise — points d’activation/désactivation du bruit de lr, exprimés en fractions de la longueur du planning
  • noise_pct — pourcentage de la limite de bruit du taux d'apprentissage
  • noise_std — écart-type du bruit du taux d'apprentissage
  • noise_seed — graine de bruit pour lr
  • cycle_mul — multiplicateur de la longueur du cycle (cosine, tanh, poly)
  • cycle_decay — décroissance du taux d'apprentissage par cycle (cosinus, tanh, poly)
  • cycle_limit — nombre de cycles (cosine, tanh, poly)
  • k_decay — k-décroissance (cosinus, poly)
  • decay_fn — fonction de phase de décroissance (wsd / rsqrt), None = ‘1-sqrt’ pour wsd, ‘linear’ pour rsqrt
  • stable_timescale — échelle temporelle rsqrt en époques (rsqrt), None = warmup_epochs
  • plateau_mode — « max » ou « min », la direction de la métrique (plateau)
  • step_on_epochs — faire avancer le planning par époque, sinon par mise à jour (nécessite updates_per_epoch)
  • updates_per_epoch — nombre de mises à jour de l'optimiseur par époque (step_on_epochs=False)

Créer un planificateur de taux d'apprentissage par nom.

Classes de planificateur

classe timm.scheduler.CosineLRScheduler

< >

( optimizer: Optimizert_initial: intlr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )

Décroissance cosinus avec redémarrages. Cela est décrit dans l'article https://arxiv.org/abs/1608.03983.

Inspiré de https://github.com/allenai/allennlp/blob/master/allennlp/training/learning_rate_schedulers/cosine.py

option k-decay basée sur k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909

classe timm.scheduler.MultiStepLRScheduler

< >

( optimizer: Optimizerdecay_t: typing.List[int]decay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )

Planification du taux d'apprentissage multi-étapes avec échauffement et bruit.

En dehors de la phase de montée en charge, les jalons de décroissance sont comparés à t + 1, où t exclut la montée en charge lorsque warmup_prefix=True. Par exemple, sans montée en charge, un jalon de 10 s’applique à l’indice 9 du planning.

Cette convention de longue date diffère de MultiStepLR de PyTorch et est conservée pour assurer la compatibilité avec les calendriers d’entraînement existants.

classe timm.scheduler.PlateauLRScheduler

< >

( optimizer: Optimizerdecay_rate: float = 0.1patience_t: int = 10threshold: float = 0.0001cooldown_t: int = 0warmup_t: int = 0warmup_lr_init: float = 0.0lr_min: float = 0.0mode: str = 'max'noise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_type: str = 'normal'noise_pct: float = 0.67noise_std: float = 1.0noise_seed: typing.Optional[int] = Noneinitialize: bool = True )

Faites décroître le taux d'apprentissage d'un facteur chaque fois que la perte de validation stagne.

Obsolète : ce planificateur sera supprimé dans une future version. Les planificateurs timm sont conçus comme des fonctions sans état de l'époque ou du nombre de mises à jour, ce que ce planificateur piloté par métriques n'a jamais été. Son état (meilleure métrique, compteurs de patience et de refroidissement) n'est pas enregistré dans les points de contrôle d'entraînement, de sorte qu'une exécution reprise redémarre la logique de plateau, et le support des points de contrôle ne sera pas ajouté. Préférez un planificateur fixe tel que cosine ou wsd, la branche de refroidissement WSD dans sweep.py compare l'annealing à plusieurs budgets avec des planificateurs reproductibles.

classe timm.scheduler.PolyLRScheduler

< >

( optimizer: Optimizert_initial: intpower: float = 0.5lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )

Planificateur de taux d'apprentissage polynomial avec échauffement, bruit et décroissance k

option k-decay basée sur k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909

classe timm.scheduler.StepLRScheduler

< >

( optimizer: Optimizerdecay_t: floatdecay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )

classe timm.scheduler.TanhLRScheduler

< >

( optimizer: Optimizert_initial: intlb: float = -7.0ub: float = 3.0lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )

Décroissance hyperbolique avec redémarrages. Cela est décrit dans l'article https://arxiv.org/abs/1806.01593

classe timm.scheduler.WSDLRScheduler

< >

( optimizer: Optimizert_initial: intdecay_t: intlr_min: float = 0.0stable_fn: str = 'constant'stable_timescale: typing.Optional[float] = Nonestable_power: float = 0.5decay_fn: typing.Union[str, typing.Callable[[float], float]] = '1-sqrt'decay_power: float = 0.5decay_ratio: float = 0.1warmup_t: int = 0warmup_lr_init: float = 0.0t_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )

Paramètres

  • optimizer — optimiseur à planifier
  • t_initial — durée des phases stable et de décroissance (époques ou mises à jour, voir t_in_epochs)
  • decay_t — durée de la phase de décroissance, les decay_t dernières étapes de t_initial
  • lr_min — lr à la fin de la phase de décroissance
  • stable_fn — fonction de phase stable, l’une des valeurs ‘constant’, ‘rsqrt’, ‘power’
  • stable_timescale — échelle de temps des fonctions stables ‘rsqrt’ / ‘power’, par défaut warmup_t
  • stable_power — exposant de la fonction stable « power »
  • decay_fn — fonction de phase de décroissance, l’une des valeurs ‘linear’, ‘1-sqrt’, ‘cosine’, ‘power’, ‘exp’ ou un objet appelable
  • decay_power — exposant de la fonction de décroissance « power »
  • decay_ratio — fraction finale (avant normalisation) de la fonction de décroissance « exp »
  • warmup_t — durée du warmup, un préfixe de t_initial
  • warmup_lr_init — lr au début du warmup
  • t_in_epochs — t est en époques (step()), sinon en mises à jour (step_update())
  • noise_range_t — plage de bruit du taux d'apprentissage, voir Scheduler
  • noise_pct — pourcentage de la limite de bruit du taux d'apprentissage
  • noise_std — écart-type du bruit du taux d'apprentissage
  • noise_seed — graine de bruit pour lr
  • initialize — initialise le champ initial_lr du groupe de paramètres à partir de la lr actuelle

Planification du taux d'apprentissage Warmup-Stable-Decay (WSD) avec fonctions de stabilisation et de décroissance sélectionnables.

Trois phases : un réchauffement linéaire sur warmup_t étapes, une phase stable, et un décroissement vers lr_min sur les decay_t dernières étapes. t_initial est la longueur des phases stable et de décroissement, le réchauffement étant toujours un préfixe, le planning a donc une longueur totale de warmup_t + t_initial (voir get_cycle_length()), après quoi lr_min est maintenu.

NOTE : comme pour les autres planificateurs, lr_min est atteint à t = warmup_t + t_initial, soit une étape après la dernière étape planifiée, de sorte que la dernière étape planifiée est en deçà de celle-ci d'une étape de décroissance. Avec une phase de décroissance courte, exécutée par époque, cela est significatif (par exemple, la dernière des 5 époques de décroissance avec « 1-sqrt » est à environ 10 % du lr stable). L'annealing final est important pour WSD, il faut donc exécuter par mise à jour (t_in_epochs=False, --sched-on-updates dans train.py) ou ajouter une époque de refroidissement (maintenue à lr_min, --cooldown-epochs).

La fonction stable est évaluée en fonction du temps écoulé depuis la fin du warmup (t_s) et vaut 1 à t_s = 0, de sorte que le warmup transmet toujours au taux d'apprentissage de base. La fonction de décroissance mappe la progression de la décroissance frac dans [0, 1] vers un facteur allant de 1 à 0 et multiplie la valeur stable, si bien qu'une fonction stable décroissante continue de décroître pendant la phase de décroissance (comme dans le calendrier Big Vision rsqrt + refroidissement linéaire).

lr(t) = lr_min + (base_lr stable(t_s) - lr_min) decay(frac)

Fonctions stables :

  • constant : 1, le planning WSD
  • rsqrt : (1 + t_s / timescale) ** -0.5, le plan de racine carrée réciproque Big Vision lorsque stable_timescale == warmup_t (par défaut)
  • power : (1 + t_s / timescale) ** -stable_power, rsqrt généralisé (planificateur Power)

Fonctions de décroissance :

  • 1-sqrt : 1 - sqrt(frac), le meilleur refroidissement selon https://arxiv.org/abs/2405.18392 (par défaut)
  • linear : 1 - frac, le plan « trapézoïdal » et le refroidissement Big Vision
  • cosine : 0.5 (1 + cos(pi frac))
  • power : 1 - frac ** decay_power, 0.5 == ‘1-sqrt’, 1.0 == ‘linear’, 2.0 est un déclin ‘square’
  • exp : décroissance exponentielle jusqu'à une fraction decay_ratio de la valeur stable, normalisée pour atteindre lr_min
  • une fonction appelable fn(frac) -> factor pour tout autre cas
Update on GitHub