Edited at

kerasでcos類似度レイヤーを作る

More than 1 year has passed since last update.


環境


  • keras (2.1.4)

  • tensorflow-gpu (1.3.0)


cosレイヤー作る

実際に書くのは 1-cos(x) のタイプ

ここでは10次元のベクトル2つのcos類似度?を求めます

Sequentialじゃなくてfunctional APIでモデル構築

from keras.models import Model

from keras.layers import Input, Dot, Reshape, Lambda
import keras.backend as K

import numpy as np

input_dim = 10
input_a = Input(shape=(input_dim, 1))
input_b = Input(shape=(input_dim, 1))

# --------------------------------------------------------------
# ここで 2入力のcos類似度レイヤーを定義しています
# --------------------------------------------------------------
cos_distance = Dot(axes = 1, normalize=True)([input_a, input_b]) # ここで cos(x)
cos_distance = Reshape((1,))(cos_distance)
cos_similarity = Lambda(lambda x: 1-x)(cos_distance) # ここで 1-cos(x) (こっちのほうが使いやすい的な)

model = Model(inputs=[input_a, input_b], outputs=[cos_similarity])

v1 = np.random.uniform(-1,1,10).reshape(1, 10, 1)
v2 = np.random.uniform(-1,1,10).reshape(1, 10, 1)

[[y]] = model.predict([v1, v2])
print("model: ", y)

def cos_sim(v1, v2):
return 1-(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))

cs = cos_sim(v1[0].reshape(10), v2[0].reshape(10))
print("numpy: ", cs)

出力はこんな感じ

model:  0.6803855

numpy: 0.6803854938830672

正しくcos類似度を求めるレイヤーが作れましたっ


蛇足

参考にしたissueにある、mergeを使った書き方(古い)(需要ない)

from keras.models import Model

from keras.layers import Input, merge, Reshape, Lambda
import keras.backend as K

~~
~~

cos_distance = merge([input_a, input_b], mode='cos', dot_axes=1) # ここで cos(x)
cos_distance = Reshape((1,))(cos_distance)
cos_similarity = Lambda(lambda x: 1-x)(cos_distance) # ここで 1-cos(x) (こっちのほうが使いやすい的な)

~~
~~


UserWarning: The merge function is deprecated and will be removed after 08/2017. Use instead layers from keras.layers.merge, e.g. add, concatenate, etc.


はい。


追記

1次元(データ数の次元もカウントすると2次元)でもよかった

from keras.models import Model

from keras.layers import Input, Dot, Reshape, Lambda
import keras.backend as K

import numpy as np

input_dim = 10
input_a = Input(shape=(input_dim,))
input_b = Input(shape=(input_dim,))

# --------------------------------------------------------------
# ここで 2入力のcos類似度レイヤーを定義しています
# --------------------------------------------------------------
cos_distance = Dot(axes = 1, normalize=True)([input_a, input_b])
cos_distance = Reshape((1,))(cos_distance)
cos_similarity = Lambda(lambda x: 1-x)(cos_distance)

model = Model(inputs=[input_a, input_b], outputs=[cos_similarity])

v1 = np.random.uniform(-1,1,10).reshape(1, 10)
v2 = np.random.uniform(-1,1,10).reshape(1, 10)

[[y]] = model.predict([v1, v2])
print("model: ", y)

def cos_sim(v1, v2):
return 1-(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))

cs = cos_sim(v1[0].reshape(10), v2[0].reshape(10))
print("numpy: ", cs)


参考

https://github.com/keras-team/keras/issues/2672


いじょうっ!

最後まで読んでくださってありがとうございますっ

(よかったらいいねくださいっ!励みになります!!!!!)

twitter: https://twitter.com/namahoge