Spaces:
Sleeping
Sleeping
| # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/encoder.ipynb. | |
| # %% auto 0 | |
| __all__ = ['ENCODER_EMBS_MODULE_NAME', 'get_gpu_memory_', 'color_for_percentage', 'create_bar', 'gpu_memory_status_', | |
| 'DCAE_torch', 'get_enc_embs', 'get_enc_embs_set_stride_set_batch_size'] | |
| # %% ../nbs/encoder.ipynb 2 | |
| import subprocess | |
| def get_gpu_memory_(device = 0): | |
| total_memory = subprocess.check_output(["nvidia-smi", "--query-gpu=memory.total", "--format=csv,noheader,nounits", "--id=" + str(device)]) | |
| total_memory = int(total_memory.decode().split('\n')[0]) | |
| used_memory = subprocess.check_output(["nvidia-smi", "--query-gpu=memory.used", "--format=csv,noheader,nounits", "--id=" + str(device)]) | |
| used_memory = int(used_memory.decode().split('\n')[0]) | |
| percentage = round((used_memory / total_memory) * 100) | |
| return used_memory, total_memory, percentage | |
| def color_for_percentage(percentage): | |
| if percentage < 20: | |
| return "\033[90m" # Gray | |
| elif percentage < 40: | |
| return "\033[94m" # Blue | |
| elif percentage < 60: | |
| return "\033[92m" # Green | |
| elif percentage < 80: | |
| return "\033[93m" # Orange | |
| else: | |
| return "\033[91m" # Red | |
| def create_bar(percentage, color_code, length=20): | |
| filled_length = int(length * percentage // 100) | |
| bar = "█" * filled_length + "-" * (length - filled_length) | |
| return color_code + bar + "\033[0m" # Apply color and reset after bar | |
| def gpu_memory_status_(device=0): | |
| used, total, percentage = get_gpu_memory_(device) | |
| color_code = color_for_percentage(percentage) | |
| bar = create_bar(percentage, color_code) | |
| print(f"GPU | Used mem: {used}") | |
| print(f"GPU | Used mem: {total}") | |
| print(f"GPU | Memory Usage: [{bar}] {color_code}{percentage}%\033[0m") | |
| # %% ../nbs/encoder.ipynb 4 | |
| import pandas as pd | |
| import numpy as np | |
| from fastcore.all import * | |
| from tsai.callback.MVP import * | |
| from tsai.imports import * | |
| from tsai.models.InceptionTimePlus import InceptionTimePlus | |
| from tsai.models.explainability import get_acts_and_grads | |
| from tsai.models.layers import * | |
| from tsai.data.validation import combine_split_data | |
| import time | |
| # %% ../nbs/encoder.ipynb 7 | |
| class DCAE_torch(Module): | |
| def __init__(self, c_in, seq_len, delta, nfs=[64, 32, 12], kss=[10, 5, 5], | |
| pool_szs=[2,2,3], output_fsz=10): | |
| """ | |
| Create a Deep Convolutional Autoencoder for multivariate time series of `d` dimensions, | |
| sliced with a window size of `w`. The parameter `delta` sets the number of latent features that will be | |
| contained in the Dense layer of the network. The the number of features | |
| maps (filters), the filter size and the pool size can also be adjusted." | |
| """ | |
| assert all_equal([len(x) for x in [nfs, kss, pool_szs]], np.repeat(len(nfs), 3)), \ | |
| 'nfs, kss, and pool_szs must have the same length' | |
| assert np.prod(pool_szs) == nfs[-1], \ | |
| 'The number of filters in the last conv layer must be equal to the product of pool sizes' | |
| assert seq_len % np.prod(pool_szs) == 0, \ | |
| 'The product of pool sizes must be a divisor of the window size' | |
| layers = [] | |
| for i in range_of(kss): | |
| layers += [Conv1d(ni=nfs[i-1] if i>0 else c_in, nf=nfs[i], ks=kss[i]), | |
| nn.MaxPool1d(kernel_size=pool_szs[i])] | |
| self.downsample = nn.Sequential(*layers) | |
| self.bottleneck = nn.Sequential(OrderedDict([ | |
| ('flatten', nn.Flatten()), | |
| ('latent_in', nn.Linear(seq_len, delta)), | |
| ('latent_out', nn.Linear(delta, seq_len)), | |
| ('reshape', Reshape(nfs[-1], seq_len // np.prod(pool_szs))) | |
| ])) | |
| layers = [] | |
| for i in reversed(range_of(kss)): | |
| layers += [Conv1d(ni=nfs[i+1] if i != (len(nfs)-1) else nfs[-1], | |
| nf=nfs[i], ks=kss[i]), | |
| nn.Upsample(scale_factor=pool_szs[i])] | |
| layers += [Conv1d(ni=nfs[0], nf=c_in, kernel_size=output_fsz)] | |
| self.upsample = nn.Sequential(*layers) | |
| def forward(self, x): | |
| x = self.downsample(x) | |
| x = self.bottleneck(x) | |
| x = self.upsample(x) | |
| return x | |
| # %% ../nbs/encoder.ipynb 10 | |
| ENCODER_EMBS_MODULE_NAME = { | |
| InceptionTimePlus: 'backbone', # for mvp based models | |
| DCAE_torch: 'bottleneck.latent_in' | |
| } | |
| # %% ../nbs/encoder.ipynb 12 | |
| def get_enc_embs(X, enc_learn, module=None, cpu=False, average_seq_dim=True, to_numpy=True): | |
| """ | |
| Get the embeddings of X from an encoder, passed in `enc_learn as a fastai | |
| learner. By default, the embeddings are obtained from the last layer | |
| before the model head, although any layer can be passed to `model`. | |
| Input | |
| - `cpu`: Whether to do the model inference in cpu of gpu (GPU recommended) | |
| - `average_seq_dim`: Whether to aggregate the embeddings in the sequence dimensions | |
| - `to_numpy`: Whether to return the result as a numpy array (if false returns a tensor) | |
| """ | |
| print("--> Check CUDA") | |
| if cpu: | |
| print("--> Get enc embs CPU") | |
| enc_learn.dls.cpu() | |
| enc_learn.cpu() | |
| else: | |
| print("--> Ensure empty cache") | |
| torch.cuda.empty_cache() | |
| print("--> Use CUDA |Get enc embs GPU ") | |
| enc_learn.dls.cuda() | |
| enc_learn.cuda() | |
| if torch.cuda.is_available(): | |
| print("CUDA está disponible") | |
| print("Dispositivo CUDA actual: ", torch.cuda.current_device()) | |
| print("Nombre del dispositivo CUDA actual: ", torch.cuda.get_device_name(torch.cuda.current_device())) | |
| else: | |
| print("CUDA no está disponible ") | |
| print("Use CUDA -->") | |
| if enc_learn.dls.bs == 0: enc_learn.dls.bs = 64 | |
| print("--> Set dataset from X (enc_learn does not contain dls)") | |
| aux_dl = enc_learn.dls.valid.new_dl(X=X) | |
| aux_dl.bs = enc_learn.dls.bs if enc_learn.dls.bs>0 else 64 | |
| print("--> Get module") | |
| module = nested_attr(enc_learn.model,ENCODER_EMBS_MODULE_NAME[type(enc_learn.model)]) if module is None else module | |
| print("--> Get enc embs bs: ", aux_dl.bs) | |
| embs = [ | |
| get_acts_and_grads( | |
| model=enc_learn.model, | |
| modules=module, | |
| x=xb[0], | |
| cpu=cpu | |
| )[0] | |
| for xb in aux_dl | |
| ] | |
| print("--> Concat") | |
| if not cpu: | |
| total_emb_size = sum([emb.element_size() * emb.nelement() for emb in embs]) | |
| free_memory = torch.cuda.get_device_properties(0).total_memory - torch.cuda.memory_allocated() | |
| if (total_emb_size < free_memory): | |
| print("Fit in GPU") | |
| embs=[emb.cuda() for emb in embs] | |
| else: | |
| print("Dont fit in GPU --> Go to CPU") | |
| embs=[emb.cpu() for emb in embs] | |
| embs = to_concat(embs) | |
| print("--> reduce") | |
| if embs.ndim == 3 and average_seq_dim: embs = embs.mean(axis=2) | |
| print("--> 2 numpy") | |
| if to_numpy: embs = embs.numpy() if cpu else embs.cpu().numpy() | |
| return embs | |
| # %% ../nbs/encoder.ipynb 13 | |
| def get_enc_embs_set_stride_set_batch_size( | |
| X, enc_learn, stride, batch_size, module=None, cpu=False, average_seq_dim=True, to_numpy=True, | |
| print_flag = False, time_flag=False, chunk_size = 0, check_memory_usage = False | |
| ): | |
| """ | |
| Get the embeddings of X from an encoder, passed in `enc_learn as a fastai | |
| learner. By default, the embeddings are obtained from the last layer | |
| before the model head, although any layer can be passed to `model`. | |
| Input | |
| - `cpu`: Whether to do the model inference in cpu of gpu (GPU recommended) | |
| - `average_seq_dim`: Whether to aggregate the embeddings in the sequence dimensions | |
| - `to_numpy`: Whether to return the result as a numpy array (if false returns a tensor) | |
| """ | |
| if time_flag: | |
| t_start = time.time() | |
| if print_flag: | |
| print("--> get_enc_embs_set_stride_set_batch_size") | |
| if check_memory_usage: gpu_memory_status_() | |
| #print("get_enc_embs_set_stride_set_batch_size | Check versions") | |
| #import sys | |
| #print("get_enc_embs_set_stride_set_batch_size | Check versions | Python version", sys.version) | |
| #print("get_enc_embs_set_stride_set_batch_size | Check versions | PyTorch version", torch.__version__) | |
| #print("get_enc_embs_set_stride_set_batch_size | Check versions | CUDA version", torch.version.cuda) | |
| #print("get_enc_embs_set_stride_set_batch_size | Apply stride & batch size") | |
| X = X[::stride] | |
| enc_learn.dls.bs = batch_size | |
| if (print_flag): print("get_enc_embs_set_stride_set_batch_size | Check CUDA | X ~ ", X.shape[0]) | |
| if cpu: | |
| if (print_flag): print("get_enc_embs_set_stride_set_batch_size | Get enc embs CPU") | |
| enc_learn.dls.cpu() | |
| enc_learn.cpu() | |
| else: | |
| if torch.cuda.is_available(): | |
| if (print_flag): | |
| print("get_enc_embs_set_stride_set_batch_size | CUDA device id:", torch.cuda.current_device()) | |
| print("get_enc_embs_set_stride_set_batch_size | CUDA device name: ", torch.cuda.get_device_name(torch.cuda.current_device())) | |
| print("get_enc_embs_set_stride_set_batch_size | Ensure empty cache & move 2 GPU") | |
| torch.cuda.empty_cache() | |
| enc_learn.dls.cuda() | |
| enc_learn.cuda() | |
| else: | |
| if (print_flag): print("get_enc_embs_set_stride_set_batch_size | No cuda available. Set CPU = true") | |
| cpu = True | |
| if enc_learn.dls.bs is None or enc_learn.dls.bs == 0: enc_learn.dls.bs = 64 | |
| if (print_flag): print("get_enc_embs_set_stride_set_batch_size | Set dataset from X (enc_learn does not contain dls)") | |
| aux_dl = enc_learn.dls.valid.new_dl(X=X) | |
| aux_dl.bs = enc_learn.dls.bs if enc_learn.dls.bs>0 else 64 | |
| if (print_flag): print("get_enc_embs_set_stride_set_batch_size | Get module") | |
| module = nested_attr(enc_learn.model,ENCODER_EMBS_MODULE_NAME[type(enc_learn.model)]) if module is None else module | |
| if (print_flag): | |
| #print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | module ", module) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | aux_dl len", len(aux_dl)) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | aux_dl.batch_len ", len(next(iter(aux_dl)))) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | aux_dl.bs ", aux_dl.bs) | |
| if (not cpu): | |
| total = torch.cuda.get_device_properties(device).total_memory | |
| used = torch.cuda.memory_allocated(torch.cuda.current_device()) | |
| reserved = torch.cuda.memory_reserved(torch.cuda.current_device()) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | total_mem ", total) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | used_mem ", used) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | reserved_mem ", reserved) | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | available_mem ", total-reserved) | |
| sys.stdout.flush() | |
| if (cpu or ( chunk_size == 0 )): | |
| embs = [ | |
| get_acts_and_grads( | |
| model=enc_learn.model, | |
| modules=module, | |
| x=xb[0], | |
| cpu=cpu | |
| )[0] | |
| for xb in aux_dl | |
| ] | |
| if not cpu: embs=[emb.cpu() for emb in embs] | |
| else: | |
| embs = [] | |
| total_chunks=max(1,round(len(X)/chunk_size)) | |
| if print_flag: print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | aux_dl len | " + str(len(X)) + " chunk size: " + str(chunk_size) + " => " + str(total_chunks) + " chunks") | |
| for i in range(0, total_chunks): | |
| if print_flag: | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | Chunk [ " + str(i) + "/"+str(total_chunks)+"] => " + str(round(i*100/total_chunks)) + "%") | |
| sys.stdout.flush() | |
| chunk = [batch for (n, batch) in enumerate(aux_dl) if (chunk_size*i <= n and chunk_size*(i+1) > n) ] | |
| chunk_embs = [ | |
| get_acts_and_grads( | |
| model=enc_learn.model, | |
| modules=module, | |
| x=xb[0], | |
| cpu=cpu | |
| )[0] | |
| for xb in chunk | |
| ] | |
| # Mueve los embeddings del bloque a la CPU | |
| chunk_embs = [emb.cpu() for emb in chunk_embs] | |
| embs.extend(chunk_embs) | |
| torch.cuda.empty_cache() | |
| if print_flag: | |
| print("get_enc_embs_set_stride_set_batch_size | Get acts and grads | 100%") | |
| sys.stdout.flush() | |
| if print_flag: print("get_enc_embs_set_stride_set_batch_size | concat embeddings") | |
| embs = to_concat(embs) | |
| if print_flag: print("get_enc_embs_set_stride_set_batch_size | Reduce") | |
| if embs.ndim == 3 and average_seq_dim: embs = embs.mean(axis=2) | |
| if print_flag: print("get_enc_embs_set_stride_set_batch_size | Convert to numpy") | |
| if to_numpy: | |
| if cpu or chunk_size > 0: | |
| embs = embs.numpy() | |
| else: | |
| embs = embs.cpu().numpy() | |
| torch.cuda.empty_cache() | |
| if time_flag: | |
| t = time.time()-t_start | |
| if print_flag: | |
| print("get_enc_embs_set_stride_set_batch_size " + str(t) + " seconds -->") | |
| else: | |
| print("get_enc_embs_set_stride_set_batch_size " + str(t) + " seconds") | |
| if check_memory_usage: gpu_memory_status_() | |
| if print_flag: | |
| print("get_enc_embs_set_stride_set_batch_size -->") | |
| return embs | |