File size: 3,331 Bytes
3d75a04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import torch
import numpy as np

def score_to_modality(scores: torch.Tensor):
    tensor_list = scores.tolist()
    modality = []
    for row in tensor_list:
        modality.append(row.index(max(row)))
    return modality

class ValTest:
    accuracy = []

    def __init__(self, dl_generator, net, trip_dim, batch_size, device, loss_function, num_modes, datasize):
        self.dl_generator = dl_generator
        self.net = net
        self.trip_dim = trip_dim
        self.batch_size = batch_size
        self.device = device
        self.loss_function = loss_function
        self.num_modes = num_modes
        self.datasize = datasize

    def run(self):

        correct = 0
        total = 0
        val_losses = []
        total_per_mode = [0] * self.num_modes
        correct_per_mode = [0] * self.num_modes
        journeys_eighty_percent_correct = 0

        self.net.eval()  # put net in eval mode

        for data, labels in self.dl_generator():

            self.net.zero_grad()
            lengths = [len(x) for x in data]
            for i, elem in enumerate(data):
               while len(elem) < lengths[0]:
                   elem.append([-1] * self.trip_dim)

            X = np.asarray(data, dtype=np.float)
            input_tensor = torch.from_numpy(X)
            input_tensor = input_tensor.to(self.device)

            output, max_padding_for_this_batch = self.net(input_tensor, lengths)

            for labelz in labels:
               while len(labelz) < max_padding_for_this_batch:
                   labelz.append(-1)

            labels_for_loss = torch.tensor(labels) \
               .view(max_padding_for_this_batch * self.batch_size, -1).squeeze(1).long().to(self.device)

            loss = self.loss_function(output.view(
               max_padding_for_this_batch * self.batch_size, -1),
               labels_for_loss)
            val_losses.append(loss.item())

            for k, journey in enumerate(output):
                journey_correct = 0
                predicted = score_to_modality(journey)

                o = 0
                for o, elem in enumerate(predicted):
                    if labels[k][o] == -1:
                        break
                    total_per_mode[int(labels[k][o])] += 1
                    if labels[k][o] == predicted[o]:
                        correct_per_mode[predicted[o]] += 1
                        correct += 1
                        journey_correct += 1
                    total += 1
                if journey_correct >= (o * 0.80):
                    journeys_eighty_percent_correct += 1

            mode_statistics = []
            for k in range(len(correct_per_mode)):
                if correct_per_mode[k] == 0 or total_per_mode[k] == 0:
                    mode_statistics.append(0)
                    continue
                mode_statistics.append(1 / (total_per_mode[k] / correct_per_mode[k]))

        print('Accuracy: %d %%' % (100 * correct / total))
        print('%% of journeys at least 80%% correct: %d of %d, %d %%' % (
            journeys_eighty_percent_correct, self.datasize, (100 * journeys_eighty_percent_correct / self.datasize)))
        print("Loss: {:.6f}".format(np.mean(val_losses)))
        print("Mode-correct:")
        print(total_per_mode)
        print(mode_statistics)

        self.net.train()