| import os |
| import torch |
| from torch import nn |
| import numpy as np |
|
|
|
|
| def softmax(x): |
| """ |
| one dimensional softmax designed for numpy array |
| """ |
| e_x = np.exp(x) |
| out = e_x / e_x.sum() |
| return out |
|
|
| class Dynamic_Weight_Averaging(): |
| def __init__(self,tasks,tau,init_weight): |
| """ |
| Dynamic Weight Averaging implementation |
| """ |
| |
| self.N = len(tasks) |
| |
| self.step = 0 |
| self.omega = np.array([init_weight]*self.N ) |
| self.tau = tau |
| |
| def _magnitude_adjust(self): |
| """ |
| automatic adjustment of loss magnitude |
| """ |
| self.relative_magnitude = self.loss_list.min() / self.loss_list |
| |
| def _update(self,loss_dict): |
| |
| self.step += 1 |
| if self.step < 2: |
| self.loss_list = np.array([loss_dict[t+'_loss'].detach().cpu().item() for t in self.tasks]) |
| return self.init_weight |
| else: |
| self._magnitude_adjust() |
| last_loss = self.loss_list |
| self.loss_list = np.array([loss_dict[t+'_loss'].detach().cpu().item() for t in self.tasks]) |
| |
| r_t = np.divide(self.loss_list,last_loss) / self.tau |
| self.omega = self.N * softmax(r_t) |
| weight_t = np.multiply(self.relative_magnitude,self.omega) |
| return {self.tasks[i]:weight_t[i] for i in range(len(self.tasks))} |
| |
| class Dynamic_Task_Priority(object): |
| def __init__(self,tasks,gamma,init_weight): |
| """ |
| Dynamic Task Priority (DTP) wish to weight more on tasks with lower KPI |
| In our cases, we take accuracy as the KPI |
| """ |
| self.gamma = np.array([gamma[t] for t in tasks]) if type(gamma) == dict else gamma |
| self.tasks = tasks |
| |
| self.omega = init_weight |
| self.init_weight = init_weight |
| self.step = 0 |
| |
| |
| def _magnitude_adjust(self): |
| """ |
| automatic adjustment of loss magnitude |
| """ |
| |
| self.relative_magnitude = self.kappa.min() / (self.kappa+1e-8) |
| if np.any(self.kappa==1): |
| self.kappa[np.where(self.kappa==1)[0]] -= 1e-8 |
| |
| def _update(self,loss_dict): |
| """ |
| weight is updated like belowing |
| `math` : w_i(t) = -(1-\kappa_i(t))^{\gamma_i} log \kappa_i(t) |
| """ |
| self.step += 1 |
| self.kappa = np.array([loss_dict[t+'_Acc'] for t in self.tasks]) |
| self._magnitude_adjust() |
| self.omega = -1 * np.multiply(np.power(1 - self.kappa,self.gamma),np.log(self.kappa+1e-8)) |
| |
| if self.step < 2: |
| return self.init_weight |
| else: |
| weight_t = np.multiply(self.relative_magnitude,self.omega) |
| return {self.tasks[i]:weight_t[i] for i in range(len(self.tasks))} |