in aiops/ContraLSP/attribution/gatemasknn.py [0:0]
def _triplet_loss(self, condition):
_, ts_dim, num_dim = condition.shape
points = condition.reshape(-1, ts_dim * num_dim).detach().numpy()
num_cluster = 2
kmeans = KMeans(n_clusters=num_cluster)
kmeans.fit(points)
cluster_label = kmeans.labels_
num_cluster_set = Counter(cluster_label)
# loss of each cluster
loss_cluster = condition.abs().mean() # placeholder
for i in range(num_cluster):
if num_cluster_set[i] < 2:
continue
cluster_i = points[np.where(cluster_label == i)]
distance_i = kmeans.transform(cluster_i)[:, i]
dist_positive = th.DoubleTensor([1])
dist_negative = th.DoubleTensor([1])
if num_cluster_set[i] >= 250:
num_positive = 50
else:
num_positive = int(num_cluster_set[i] / 5 + 1)
# select anchor and positive
anchor_positive = np.argpartition(distance_i, num_positive)[:(num_positive + 1)]
# torch anchor
representation_anc = th.from_numpy(points[anchor_positive[0]])
# transfer 1D to 3D
representation_anc = th.reshape(representation_anc, (1, 1, np.shape(points)[1]))
# positive part
for l in range(1, num_positive + 1):
# torch positive
representation_pos = th.from_numpy(points[anchor_positive[l]])
# transfer 1D to 3D
representation_pos = th.reshape(representation_pos, (1, 1, np.shape(points)[1]))
anchor_minus_positive = representation_anc - representation_pos
dist_positive += th.norm(anchor_minus_positive, p=1)/np.shape(points)[1]
dist_positive = dist_positive / num_positive
# negative part
for k in range(num_cluster):
dist_cluster_k_negative = th.DoubleTensor([1])
if k == i:
continue
else:
# select negative
if num_cluster_set[k] >= 250:
num_negative_cluster_k = 50
else:
num_negative_cluster_k = int(num_cluster_set[k] / 5 + 1)
negative_cluster_k = random.sample(range(points[kmeans.labels_ == k][:, 0].size),
num_negative_cluster_k)
for j in range(num_negative_cluster_k):
# torch negative
representation_neg = th.from_numpy(points[kmeans.labels_ == k][negative_cluster_k[j]])
# transfer 1D to 3D
representation_neg = th.reshape(representation_neg, (1, 1, np.shape(points)[1]))
anchor_minus_negative = representation_anc - representation_neg
dist_cluster_k_negative += th.norm(anchor_minus_negative, p=1)/np.shape(points)[1]
dist_cluster_k_negative = dist_cluster_k_negative / num_negative_cluster_k
dist_negative += dist_cluster_k_negative
dist_negative = dist_negative / (num_cluster - 1)
# loss = -(margin + positives - negatives)
if self.preservation_mode:
loss_values = th.max((-dist_positive + dist_negative - 1)[0], th.tensor(0.)) / num_cluster
else:
loss_values = th.max(-(-dist_positive + dist_negative - 1)[0], th.tensor(0.)) / num_cluster
loss_cluster += loss_values
return loss_cluster