Download model/src/mrl_te_optimization/models/Baseline_models.py from OneScience-Group/UTRGAN: direct link, hf CLI and curl.
- Browser
- Download file 5.89 kB
-
https://huggingface.co/OneScience-Group/UTRGAN/resolve/main/model/src/mrl_te_optimization/models/Baseline_models.py
- Command line
-
hf download hf://OneScience-Group/UTRGAN/model/src/mrl_te_optimization/models/Baseline_models.py
-
curl -L -o Baseline_models.py https://huggingface.co/OneScience-Group/UTRGAN/resolve/main/model/src/mrl_te_optimization/models/Baseline_models.py
5.89 kB
| import os | |
| import sys | |
| import torch | |
| from torch import nn | |
| import numpy as np | |
| from .CNN_models import Conv_AE,Conv_VAE,cal_conv_shape | |
| from .Self_attention import self_attention | |
| class Baseline(nn.Module): | |
| def __init__(self,channel_ls,padding_ls,diliat_ls,latent_dim,kernel_size,dropout_ls,num_label,loss_fn,pad_to): | |
| """ | |
| Conv - Dense Framework DL Regressor to predict ribosome load (rl) from 5' UTR sequence | |
| Arguments: | |
| ...channel_ls,padding_ls,diliat_ls,latent_dim,kernel_size,num_label : parameter to define the Conv layers | |
| ...loss_fn : regression loss function `MSELoss` or `MyHingeLoss` | |
| """ | |
| super(Baseline,self).__init__() | |
| # ==<<| properties |>>== | |
| self.kernel_size = kernel_size | |
| self.loss_fn = loss_fn | |
| self.channel_ls = channel_ls | |
| self.padding_ls = padding_ls | |
| self.diliat_ls = diliat_ls | |
| self.L_in = pad_to | |
| self.loss_dict_keys = ['Total','MAE','R.M.S.E'] | |
| # the basic element block of CNN | |
| # ==<<| Conv layers |>>== | |
| # 3 layers in the 5'UTR paper | |
| self.encoder = nn.ModuleList( | |
| [self.Conv_block(channel_ls[i],channel_ls[i+1],padding_ls[i],diliat_ls[i],dropout_rate=dropout_ls[i]) for i in range(len(channel_ls)-1)] | |
| ) | |
| # compute the output shape of conv layer | |
| self.out_len = int(self.compute_out_dim(kernel_size,L_in=self.L_in)) | |
| self.out_dim = self.out_len * channel_ls[-1] | |
| # ==<<| Dense layers |>>== | |
| self.fc_out = nn.Sequential( | |
| nn.Linear(self.out_dim,40), | |
| nn.Dropout(0.2), | |
| nn.ReLU(), | |
| nn.Linear(40,num_label) | |
| ) | |
| self.define_loss() | |
| self.acc_hinge = MyHingeLoss(None) | |
| self.apply(self.weight_initialize) | |
| self.rl_posi = None # single output | |
| def weight_initialize(self, model): | |
| if type(model) in [nn.Linear]: | |
| nn.init.xavier_uniform_(model.weight) | |
| nn.init.zeros_(model.bias) | |
| elif type(model) in [nn.LSTM, nn.RNN, nn.GRU]: | |
| nn.init.orthogonal_(model.weight_hh_l0) | |
| nn.init.xavier_uniform_(model.weight_ih_l0) | |
| nn.init.zeros_(model.bias_hh_l0) | |
| nn.init.zeros_(model.bias_ih_l0) | |
| elif isinstance(model, nn.Conv1d): | |
| nn.init.kaiming_normal_(model.weight, nonlinearity='leaky_relu',) | |
| elif isinstance(model, nn.BatchNorm1d): | |
| nn.init.constant_(model.weight, 1) | |
| nn.init.constant_(model.bias, 0) | |
| def Conv_block(self,inChan,outChan,padding,diliation,stride=1,dropout_rate=0): | |
| """ | |
| Building Block of stack conv | |
| """ | |
| net = nn.Sequential( | |
| nn.Conv1d(inChan,outChan,self.kernel_size,stride=1,padding=padding,dilation=diliation), | |
| # nn.BatchNorm1d(outChan), | |
| nn.ReLU(), | |
| nn.Dropout(dropout_rate)) | |
| return net | |
| def define_loss(self): | |
| if self.loss_fn in ['mse','MSE']: | |
| self.regression_loss = nn.MSELoss(reduction='mean') | |
| else: | |
| self.regression_loss = MyHingeLoss(reduction='mean') | |
| def encode(self,X): | |
| X = X.transpose(1,2) # to B*4*100 | |
| Z = X | |
| for model in self.encoder: | |
| Z = model(Z) | |
| return Z | |
| def forward(self,X): | |
| """ | |
| Conv -> flatten -> Dense | |
| """ | |
| batch_size = X.shape[0] | |
| z = self.encode(X) | |
| z_flat = z.view(batch_size,-1) | |
| out = self.fc_out(z_flat) # no activation for the last layer | |
| return out | |
| def compute_acc(self,out,X,Y,popen): | |
| """ | |
| for this regression task, accuracy is the percentage that prediction error < epsilon (Lambda) | |
| """ | |
| epsilon = popen.epsilon | |
| batch_size = Y.shape[0] | |
| rl_pred = out[self.rl_posi] if type(out) == tuple else out | |
| if rl_pred.shape != Y.shape: | |
| if len(rl_pred.shape) == 2: | |
| rl_pred = rl_pred.squeeze() | |
| if len(Y.shape) == 2: | |
| Y = Y.squeeze() | |
| with torch.no_grad(): | |
| loss = self.acc_hinge(rl_pred,Y,epsilon=0.3) | |
| n_inrange = (loss==0).squeeze().sum().item() | |
| return {"Acc":n_inrange / batch_size} | |
| def compute_loss(self,out,X,Y,popen): | |
| """ | |
| it's termed `chimela_loss` to keep compatability with MTL MODELS (the same dataset was used) | |
| `chiemela_loss` requires three input : | |
| ...out: | |
| ...Y: | |
| ...Lambda : which is the epsilon of hinge loss if possible | |
| """ | |
| self.Lambda = popen.chimerla_weight | |
| batch_size = Y.shape[0] | |
| rl_pred = out[self.rl_posi] if type(out) == tuple else out | |
| # Hinge or MSE | |
| if self.loss_fn in ['mse','MSE']: | |
| loss = self.regression_loss(rl_pred,Y) | |
| else: | |
| loss = self.regression_loss(rl_pred,Y,self.Lambda).squeeze() | |
| with torch.no_grad(): | |
| MAE = torch.abs(rl_pred-Y).mean() # Mean Absolute Error | |
| RMSE = torch.sqrt( torch.sum((rl_pred-Y)**2) / batch_size) # Root Mean Square Error | |
| return {"Total":loss,"MAE":MAE,"R.M.S.E":RMSE} | |
| def compute_out_dim(self,kernel_size,L_in = 100,num_layer=None): | |
| """ | |
| manually compute the final length of convolved sequence | |
| """ | |
| loop_times = num_layer if type(num_layer) == int else len(self.channel_ls)-1 | |
| for i in range(loop_times): | |
| L_out = cal_conv_shape(L_in,kernel_size,stride=1,padding=self.padding_ls[i],diliation=self.diliat_ls[i]) | |
| L_in = L_out | |
| return L_out |