我想获取每个输入向量之间的距离。但是由于张量流没有直接获取距离的函数,我将公式用作(a+b)^2 = a^2 + 2ab + b^2
。但是,由于输入向量的维是动态的(例如[None, 64]
),因此我无法正确获得乘法结果。那么如何获得两个动态tensor
之间的乘积?
这是我在具有tensorflow背景的keras中使用的代码。
import numpy as np
from keras.layers import Input, Conv2D, LeakyReLU, MaxPooling2D, Flatten, Dense, BatchNormalization, Lambda
from keras.models import Model
from keras import backend as K
from keras.layers import Layer
from keras import backend as K
from keras.engine.topology import Layer
from keras.datasets import mnist
from keras import optimizers
from keras.utils import to_categorical
class MyLayer(Layer):
def __init__(self,
output_dim,
distant_parameter = 0.05,
**kwargs):
self.output_dim = output_dim
self.distant_parameter = distant_parameter
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
self.kernel = self.add_weight(name = 'MyKernel',
shape = (self.output_dim, input_shape[-1]),
initializer = 'uniform',
trainable = True)
super(MyLayer, self).build(input_shape)
def call(self, inputs):
import tensorflow as tf
test = True
outputs = ()
with tf.variable_scope('pairwise_dist'):
na = tf.reduce_sum(tf.square(self.kernel), 1)
nb = tf.reduce_sum(tf.square(inputs), 1)
# nb cannot be calculated accuracy and the output a [none, none, none, ..., none]
na = tf.reshape(na, [1, -1])
nb = tf.reshape(nb, [-1, 1])
Tul = tf.exp(- self.distant_parameter * tf.sqrt(tf.maximum(nb - 2*tf.matmul(inputs, self.kernel, False, True) + na, 0.0)))
SumTul = tf.reduce_sum(Tul, 1)
SumTul = tf.reshape(SumTul, [-1, 1])
outputs = tf.divide(Tul, SumTul)
return outputs
def compute_output_shape(self, input_shape):
output_shape = list(input_shape)
output_shape[-1] = self.output_dim
#output_shape[-1] = input_shape[0]
return tuple(output_shape)
def TestModel():
InpLay = Input(shape=(3, 28, 28))
Block1 = Conv2D(7, kernel_size=(3, 3),activation='linear', input_shape=(3, 28, 28), padding='same')(InpLay)
Block1 = LeakyReLU(alpha=0.1)(Block1)
Block1 = MaxPooling2D((2, 2),padding='same')(Block1)
Block2 = Conv2D(14, (3, 3), activation='linear',padding='same')(Block1)
Block2 = LeakyReLU(alpha=0.1)(Block2)
Block2 = MaxPooling2D(pool_size=(2, 2),padding='same')(Block2)
Block3 = Conv2D(28, (3, 3), activation='linear',padding='same')(Block2)
Block3 = LeakyReLU(alpha=0.1)(Block3)
Block3 = MaxPooling2D(pool_size=(2, 2),padding='same')(Block3)
Finals = Flatten()(Block3)
Finals = Dense(64, activation='linear')(Finals)
Finals = LeakyReLU(alpha=0.1)(Finals)
Finals = BatchNormalization(axis = -1)(Finals)
Finals = MyLayer(10)(Finals)
model = Model(inputs = InpLay, outputs = Finals)
model.summary()
return model
def RWTrain():
#Import MNIST dataset
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_new_train = []
for i in range(0, len(x_train)):
x_new_train.append([x_train[i], x_train[i], x_train[i]])
y_new_train = to_categorical(y_train)
x_new_train = np.array(x_new_train)
y_new_train = np.array(y_new_train)
#Import Model
model = TestModel()
sgd = optimizers.SGD(lr=0.02, decay=1e-6, momentum=0.9, nesterov=True)
#Using Stochastic gradient descent(SGD) for optimizer
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer = sgd)
#Training model
model.fit(x = x_new_train, y = y_new_train, validation_split=0.1, epochs = 1)
model.save_weights("./Output/Model.h5")
if __name__ == '__main__':
import sys
RWTrain()
答案 0 :(得分:0)
计算两个张量之间的欧几里得距离非常简单。考虑下面的例子。第一维未知(None
),我们计算x
和y
中相应批处理位置中两个张量之间的距离:
import tensorflow as tf
x = tf.placeholder(tf.float32, shape=(None, 2))
y = tf.placeholder(tf.float32, shape=(None, 2))
squared_distance = tf.reduce_sum(tf.square(tf.subtract(x, y)),
axis=1)
distance = tf.sqrt(squared_distance)
with tf.Session() as sess:
res = sess.run(distance,
feed_dict={x:[[1., 1.], [3., 3.]],
y:[[2., 2.], [1., 1.]]})
print('Euclidean distance:')
print(res) # [1.4142135 2.828427 ] <-- sqrt(2), sqrt(8)
res = sess.run(squared_distance,
feed_dict={x:[[1., 1.], [3., 3.]],
y:[[2., 2.], [1., 1.]]})
print('Squared Euclidean distance:')
print(res) # [2. 8.]
# Euclidean distance:
# [1.4142135 2.828427 ]
# Squared Euclidean distance:
# [2. 8.]
使用自定义keras图层也是如此:
class DistanceLayer(tf.keras.layers.Layer):
def __init__(self, distance='euclidean'):
self.distance = distance
def __call__(self, x, y):
distance = tf.reduce_sum(tf.square(tf.subtract(x, y)), axis=1)
if self.distance == 'euclidean':
distance = tf.sqrt(distance)
return distance
distlayer = DistanceLayer()
x = tf.constant([[1., 1.], [3., 3.]])
y = tf.constant([[2., 2.], [1., 1.]])
res = distlayer(x, y)
with tf.Session() as sess:
print(res.eval()) # [1.4142135 2.828427 ]