Я создаю сеть, которая использует регуляризованное расстояние Синхорна в качестве функции потерь. Я использую определение, сделанное https://arxiv.org/pdf/1811.10943.pdf, я нашел здесь надежную реализацию https://pot.readthedocs.io/en/stable/all.html от ot.sinkhorn (a, b, M, reg, method = 'sinkhorn').
Однако у меня возникли проблемы с реализацией этой функции в моей уже существующей сети.
Функция ot.sinkhorn (a, b, M, reg, method = 'sinkhorn'), принимает a, b и M в качестве параметров, а reg = 0,001 - это константа, значение которой я уже знаю. a, b и M - переменные, которые должны быть закодированы в слоях, однако я не знаю, как их получить:
- a: (np.ndarray (ns,)) - выборка весов в исходной области
- b: (np.ndarray (nt,) или np.ndarray (nt, nbb)) - выборки в целевой области, вычисление рожка с несколькими целевыми объектами и фиксированное значение M, если b является матрицей (возврат потерь OT + двойные переменные) в журнале)
- M: (np.ndarray (ns, nt)) - матрица потерь
Другой способ, которым я думал о реализации этой функции потерь, - реализовать функцию потерь, как показано в статье, однако я бы знал, с чего начать.
Мой код вы можете увидеть ниже, первая часть - это просто обработка данных:
from __future__ import absolute_import, division, print_function
import pathlib
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import socket
import math
import os
import sys
import ot
import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
data = []
#Open and save data
file = open("sphere.txt", "r")
for line in file:
data.append(line.split())
file.close()
# getting rid of empty lines
data = list(filter(None, data))
#getting rid of header
del data[0]
#mapping from string to float
for line in range(0,len(data)):
data[line] =list(map(float,data[line]))
# saving number of slices
slices = int(data[0][0])
# Get the contours
numline = 0
vertices_per_slice = 0
number_of_contours = 0
vertices = []
contour = []
contours = [] #Every contour
#Iterate by slice
for slice in range (0,slices):
numline = numline + vertices_per_slice + number_of_contours + 1
vertices_per_slice = int(data[numline][1])
number_of_contours = int(data[numline][2])
#Iterate by vertex to get all the vertex in a slice
for vertex in range(0,vertices_per_slice):
vertices.append(data[numline + vertex + 1])
#Iterate by contour to safe each of them
for cont in range(0,number_of_contours):
vertices_in_contour = data[cont + numline + vertices_per_slice + 1]
for ver in range(0,len(vertices_in_contour)):
vertex = int(vertices_in_contour[ver]) - 1
contour.append(vertices[vertex])
#Get the contour and save it
contours.append(contour)
contour = []
vertices = []
Здесь я создаю несколько случайных выборок единичной сферы, где у каждой точки есть функция, которая обнаруживает, находится ли точка внутри, снаружи или на определенном радиусе:
#Sample a point cloud in shape of unit sphere that has an value function.
sample = [] # sample per contour
samples = [] #every sample
for cont in range(0,len(contours)):
for samples_per_contour in range(0,len(contours[cont])):
samp = [2,2,2]
while math.sqrt(samp[0]) + math.sqrt(samp[1]) > 1: #do it until it satisfies the constrain
samp = [np.random.uniform(0,1),np.random.uniform(0,1),0] #sample w = 0
sample.append(samp)
samples.append(sample) #sample per countour it has the same size as the contour that is related to
sample = []
# is there a difference between this and making point cloud and sample that
# Add a function of each point maping to -1, 0 or 1 based if they are inside, in or outside the r = 0.5
for sample in range(0,len(samples)):
for points in range(0,len(samples[sample])):
if math.sqrt(samples[sample][points][0]) + math.sqrt(samples[sample][points][1]) > 0.25:
samples[sample][points].append(1)
elif math.sqrt(samples[sample][points][0]) + math.sqrt(samples[sample][points][1]) < 0.25:
samples[sample][points].append(-1)
else:
samples[sample][points].append(0)
И, наконец, сеть, которую я хочу создать без функции потери Синхорна.
#Define Model
def build_model():
model = keras.Sequential() # create a model that has K(depending on the amount of max vertices) layers K >> 3max vertices
model.add(layers.Dense(2, activation=tf.nn.relu, input_shape=[4]))
model.add(layers.Dense(128, activation=tf.nn.relu))
model.add(layers.Dense(256, activation=tf.nn.relu))
model.add(layers.Dense(512, activation=tf.nn.relu))
model.add(layers.Dense(512, activation=tf.nn.relu))
layers.Dense(3)
optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss= 'mean_squared_error',
optimizer=optimizer,
metrics=['mean_absolute_error', 'mean_squared_error']) # ToDo use Sinkhorn regularized distance use OT
return model
model = build_model()
На данный момент код не должен давать никаких результатов, так как мне нужно изменить некоторые размеры входов и выходов сети. Тем не менее, я хочу сначала определить функцию потерь.
Если бы вы, ребята, могли указать мне правильное направление функции потерь и размеров моей сети, я был бы очень признателен.