-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmmd.py
More file actions
57 lines (42 loc) · 1.68 KB
/
Copy pathmmd.py
File metadata and controls
57 lines (42 loc) · 1.68 KB
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
from functools import partial
import torch
import numpy as np
from torch.autograd import Variable
def gaussian_kernel_matrix(x, y, sigmas):
sigmas = sigmas.view(sigmas.shape[0], 1)
beta = 1. / (2. * sigmas)
dist = pairwise_distance(x, y).contiguous()
dist_ = dist.view(1, -1)
s = torch.matmul(beta, dist_)
return torch.sum(torch.exp(-s), 0).view_as(dist)
def pairwise_distance(x, y):
if not len(x.shape) == len(y.shape) == 2:
raise ValueError('Both inputs should be matrices.')
if x.shape[1] != y.shape[1]:
raise ValueError('The number of features should be the same.')
x = x.view(x.shape[0], x.shape[1], 1)
y = torch.transpose(y, 0, 1)
output = torch.sum((x - y) ** 2, 1)
output = torch.transpose(output, 0, 1)
return output
def maximum_mean_discrepancy(x, y, kernel= gaussian_kernel_matrix):
cost = torch.mean(kernel(x, x))
cost += torch.mean(kernel(y, y))
cost -= 2 * torch.mean(kernel(x, y))
return cost
def mmd_loss(source_features, target_features, use_gpu = True):
sigmas = [
1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 20, 25, 30, 35, 100,
1e3, 1e4, 1e5, 1e6
]
if use_gpu:
gaussian_kernel = partial(
gaussian_kernel_matrix, sigmas = Variable(torch.cuda.FloatTensor(sigmas))
)
else:
gaussian_kernel = partial(
gaussian_kernel_matrix, sigmas = Variable(torch.FloatTensor(sigmas))
)
loss_value = maximum_mean_discrepancy(source_features, target_features, kernel= gaussian_kernel)
loss_value = loss_value / source_features.size(0)
return loss_value