Visualization approach 1

This commit is contained in:
Si11ium 2019-09-13 13:36:13 +02:00
parent 18305a9e7e
commit 1386cdfd33
9 changed files with 185 additions and 50 deletions

View File

@ -44,12 +44,6 @@ def build_parse_commands():
class AbstractDataset(ConcatDataset, ABC):
# maps = ['hotel', 'tum','gallery', 'queens', 'oet']
@property
def maps(self):
# return ['test', 'test2']
return ['hotel', 'tum','gallery', 'queens', 'oet']
@property
@abstractmethod
def raw_filenames(self):
@ -71,8 +65,13 @@ class AbstractDataset(ConcatDataset, ABC):
self.path = path
self.refresh = refresh
self.transforms = transforms or None
self.maps = list(set([x.name.split('_')[0] for x in os.scandir(os.path.join(self.path, 'raw'))]))
super(AbstractDataset, self).__init__(datasets=self._load_datasets())
def to(self, device):
self.datasets = [dataset.to(device) for dataset in self.datasets]
return self
@abstractmethod
def process(self, filepath):
raise NotImplementedError
@ -195,6 +194,10 @@ class Trajectories(Dataset):
total_len = self.data.size()[0]
return total_len - (self.size * self.step - (self.step - 1))
def to(self, device):
self.data = self.data.to(device)
return self
class MapContainer(AbstractDataset):

View File

@ -50,7 +50,7 @@ class AdversarialAELightningOverrides(LightningModuleOverrides):
# Calculate the mean over both the real and the fake acc
# ToDo: do i need to compute this seperate?
d_loss = 0.5 * torch.add(d_loss_real, d_loss_fake)
d_loss = 0.5 * torch.add(d_loss_real, d_loss_fake) * 0.001
return {'loss': d_loss}
elif optimizer_i == 1:
@ -69,7 +69,7 @@ class AdversarialAELightningOverrides(LightningModuleOverrides):
# This is Fucked up, why do i need to put an additional empty list here?
def configure_optimizers(self):
return [Adam(self.network.discriminator.parameters(), lr=0.02),
Adam([*self.network.encoder.parameters(), *self.network.decoder.parameters()], lr=0.02)],\
Adam([*self.network.encoder.parameters(), *self.network.decoder.parameters()], lr=0.02), ],\
[]

View File

@ -0,0 +1,48 @@
from torch.optim import Adam
from .modules import *
from torch.nn.functional import mse_loss
from torch import Tensor
#######################
# Basic AE-Implementation
class AutoEncoder(AbstractNeuralNetwork, ABC):
def __init__(self, latent_dim: int=0, features: int = 0, **kwargs):
assert latent_dim and features
super(AutoEncoder, self).__init__()
self.latent_dim = latent_dim
self.features = features
self.encoder = Encoder(self.latent_dim)
self.decoder = Decoder(self.latent_dim, self.features)
def forward(self, batch: Tensor):
# Encoder
# outputs, hidden (Batch, Timesteps aka. Size, Features / Latent Dim Size)
z = self.encoder(batch)
# Decoder
# First repeat the data accordingly to the batch size
z_repeatet = Repeater((batch.shape[0], batch.shape[1], -1))(z)
x_hat = self.decoder(z_repeatet)
return z, x_hat
class AutoEncoderLightningOverrides(LightningModuleOverrides):
def __init__(self):
super(AutoEncoderLightningOverrides, self).__init__()
def training_step(self, x, batch_nb):
# ToDo: We need a new loss function, fullfilling all attention needs
# z, x_hat
_, x_hat = self.forward(x)
loss = mse_loss(x, x_hat)
return {'loss': loss}
def configure_optimizers(self):
return [Adam(self.parameters(), lr=0.02)]
if __name__ == '__main__':
raise PermissionError('Get out of here - never run this module')

View File

@ -14,6 +14,9 @@ from torch.utils.data import DataLoader
from dataset import DataContainer
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
class LightningModuleOverrides:
@property
@ -25,8 +28,8 @@ class LightningModuleOverrides:
@data_loader
def tng_dataloader(self):
num_workers = 0 # os.cpu_count() // 2
return DataLoader(DataContainer('data', self.size, self.step),
num_workers = 0 # os.cpu_count() // 2
return DataLoader(DataContainer(os.path.join('data', 'training'), self.size, self.step),
shuffle=True, batch_size=10000, num_workers=num_workers)
@ -236,6 +239,19 @@ class Encoder(Module):
return tensor
class AttentionEncoder(Module):
def __init__(self):
super(AttentionEncoder, self).__init__()
self.l_stack = TimeDistributed(EncoderLinearStack())
def forward(self, x):
tensor = self.l_stack(x)
torch.bmm() # TODO Add Attention here
return tensor
class PoolingEncoder(Module):
def __init__(self, lat_dim, variational=False):

View File

@ -4,9 +4,6 @@ from networks.modules import *
import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
class SeperatingAdversarialAutoEncoder(Module):
def __init__(self, latent_dim, features):
@ -58,7 +55,7 @@ class SeparatingAdversarialAELightningOverrides(LightningModuleOverrides):
# Calculate the mean over bot the real and the fake acc
# ToDo: do i need to compute this seperate?
d_loss = 0.5 * torch.add(temporal_loss_real, temporal_loss_fake)
d_loss = 0.5 * torch.add(temporal_loss_real, temporal_loss_fake) * 0.001
return {'loss': d_loss}
if optimizer_i == 1:
@ -80,7 +77,7 @@ class SeparatingAdversarialAELightningOverrides(LightningModuleOverrides):
# Calculate the mean over bot the real and the fake acc
# ToDo: do i need to compute this seperate?
d_loss = 0.5 * torch.add(spatial_loss_real, spatial_loss_fake)
d_loss = 0.5 * torch.add(spatial_loss_real, spatial_loss_fake) * 0.001
return {'loss': d_loss}
elif optimizer_i == 2:

View File

@ -22,7 +22,6 @@ args.add_argument('--model', default='Model')
args.add_argument('--refresh', type=strtobool, default=False)
# ToDo: How to implement this better?
# other_classes = [AutoEncoder, AutoEncoderLightningOverrides]
class Model(AutoEncoderLightningOverrides, LightningModule):

30
viz/utils.py Normal file
View File

@ -0,0 +1,30 @@
import os
def search_for_weights(func, folder):
while not os.path.exists(folder):
if len(os.path.split(folder)) >= 50:
raise FileNotFoundError(f'The folder "{folder}" could not be found')
folder = os.path.join(os.pardir, folder)
if any([x.name.endswith('.png') for x in os.scandir(folder)]):
return
if any(['.ckpt' in element.name and element.is_dir() for element in os.scandir(folder)]):
_, _, filenames = next(os.walk(os.path.join(folder, 'weights.ckpt')))
filenames.sort(key=lambda f: int(''.join(filter(str.isdigit, f))))
func(os.path.join(folder, 'weights.ckpt', filenames[-1]))
return
for element in os.scandir(folder):
if os.path.exists(element):
if element.is_dir():
search_for_weights(func, element.path)
elif element.is_file() and element.name.endswith('.ckpt'):
func(element)
else:
continue
if __name__ == '__main__':
raise PermissionError('This file should not be called.')

View File

@ -1,6 +1,3 @@
from collections import defaultdict
from tqdm import tqdm
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
@ -12,57 +9,52 @@ from run_models import *
sns.set()
def search_for_weights(folder):
while not os.path.exists(folder):
if len(os.path.split(folder)) >= 50:
raise FileNotFoundError(f'The folder "{folder}" could not be found')
folder = os.path.join(os.pardir, folder)
for element in os.scandir(folder):
if os.path.exists(element):
if element.is_dir():
search_for_weights(element.path)
elif element.is_file() and element.name.endswith('.ckpt'):
load_and_predict(element)
else:
continue
def load_and_predict(path_like_element):
if any([x.name.endswith('.png') for x in os.scandir(os.path.dirname(path_like_element))]):
return
# Define Loop to search for models and folder with visualizations
model = globals()[path_like_element.path.split(os.sep)[-3]]
splitpath = path_like_element.split(os.sep)
base_dir = os.path.join(*splitpath[:4])
model = globals()[splitpath[2]]
print(f'... loading model named: "{Model.name}" from timestamp: {splitpath[3]}')
pretrained_model = model.load_from_metrics(
weights_path=path_like_element.path,
tags_csv=os.path.join(os.path.dirname(path_like_element), 'default', 'version_0', 'meta_tags.csv'),
weights_path=path_like_element,
tags_csv=os.path.join(base_dir, 'default', 'version_0', 'meta_tags.csv'),
on_gpu=True if torch.cuda.is_available() else False,
map_location=None
)
# Init model and freeze its weights ( for faster inference)
pretrained_model = pretrained_model.to(device)
pretrained_model.eval()
pretrained_model.freeze()
with torch.no_grad():
# Load the data for prediction
dataset = DataContainer(os.path.join(os.pardir, 'data'), 5, 5)
# TODO!!!!!!!!!:
# Hier müssen natürlich auch die date parameter geladen werden!
# Muss ich die val-sets automatisch neu setzen, also immer auf refresh haben, wenn ich validieren möchte?
# Was ist denn eigentlich mein Val Dataset?
# Hab ich irgendwo eine ganze karte?
# Wie sorge ich dafür, dass gewisse karten, also größenverhältnisse usw nicht überrepräsentiert sind?
dataset = DataContainer(os.path.join(os.pardir, 'data', 'validation'), 9, 6).to(device)
dataloader = DataLoader(dataset, shuffle=True, batch_size=len(dataset))
# Do the inference
prediction_dict = defaultdict(list)
for i in tqdm(range(len(dataset)), total=len(dataset)):
p_X = pretrained_model(dataset[i].unsqueeze(0))
for idx in range(len(p_X) - 1):
prediction_dict[idx].append(p_X[idx])
test_pred = [pretrained_model(test_sample)[:-1] for test_sample in dataloader][0]
predictions = [torch.cat(prediction).detach().numpy() for prediction in prediction_dict.values()]
for idx, prediction in enumerate(predictions):
for idx, prediction in enumerate(test_pred):
plot, _ = viz_latent(prediction)
plot.savefig(os.path.join(os.path.dirname(path_like_element), f'latent_space_{idx}.png'))
plot.savefig(os.path.join(base_dir, f'latent_space_{idx}.png'))
def viz_latent(prediction):
try:
prediction = prediction.cpu()
prediction = prediction.numpy()
except AttributeError:
pass
if prediction.shape[-1] <= 1:
raise ValueError('How did this happen?')
elif prediction.shape[-1] == 2:
@ -91,4 +83,4 @@ def viz_latent(prediction):
if __name__ == '__main__':
path = 'output'
search_for_weights(path)
search_for_weights(search_for_weights, path)

50
viz/viz_map.py Normal file
View File

@ -0,0 +1,50 @@
from dataset import *
# Plotting
# import matplotlib as mlp
from matplotlib import pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.collections import LineCollection, PatchCollection
import matplotlib.colors as mcolors
import matplotlib.cm as cmaps
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
import seaborn as sns
from argparse import ArgumentParser
from viz.utils import search_for_weights
from run_models import *
sns.set()
arguments = ArgumentParser()
arguments.add_argument('--data', default=os.path.join('data', 'validation'))
dataset = DataContainer(os.path.join(os.pardir, 'data', 'validation'), 9, 6).to(device)
dataloader = DataLoader(dataset, shuffle=True, batch_size=len(dataset))
def viz_map(self, base_map: MapContainer):
# Base Map Plotting
# filled Triangle
patches = [Polygon(base_map.get_triangle_by_key(i), True, color='k') for i in range(len(base_map))]
patch_collection = PatchCollection(patches, color='k')
self.ax.add_collection(patch_collection)
print('Basemap Plotted')
patches = [Polygon(base_map.get_triangle_by_key(i), True, color='k') for i in range(len(base_map))]
return PatchCollection(patches, color='k')
def load_and_predict(folder):
pass
if __name__ == '__main__':
search_for_weights(load_and_predict, arguments.data)
# ToDo: THIS