I think the good points of TensorFlow are that it is quite excellent as a tool for machine learning, and that the functions of numerical calculation systems are not hidden in the library and can be freely implemented outside. So, as the title suggests, * I calculated the angle between n-dimensional vectors *.
The calculation formula is a method that uses the inner product of vectors. Expressed as an expression, "cosx=a ・ b/ (|a||b|)So, find cosx and finally convert it to an angle.
First, consider the case of calculation between two-dimensional vectors. I want to set the input freely later, so use placeholder instead of variables and constants
import tensorflow as tf
a = tf.placeholder(tf.types.float32, [1, 2])
b = tf.placeholder(tf.types.float32, [1, 2])
Next, the inner product "a · b" is calculated.
Since each element of the two vectors is known, it can be calculated by the formula "a1 b1 + a2 b2".
Use tf.matmul ()
to multiply high-dimensional inputs.
a_dot_b = tf.matmul(a, b, transpose_b=True)
# transpose_b=If True, swap the number of dimensions of the second argument(Transpose)Willing to.
#This time the vector b is[1, 2] -> [2, 1]Changes to the shape of
Then, the magnitude of each vector|a|, |b|To ask. The magnitude of the vector can be calculated by taking the root of the sum of squares of each element. Writing using tensorflow looks like this.
a_abs = tf.sqrt(tf.matmul(a, a, transpose_b=True))
b_abs = tf.sqrt(tf.matmul(b, b, transpose_b=True))
After that, the first formula "a ・ b/ (|a||b|)Is applied to calculate cosx.
cos = tf.div(a_dot_b, tf.mul(a_abs, b_abs))
So far, we have created a formula to calculate "cosx = cosine calculated by the angle between vectors". Enter a concrete two-dimensional vector into this formula to calculate the cosine.
with tf.Session() as sess:
y = sess.run([cos], feed_dict={a: [[1, 1]], b: [[1, 0]]})[0][0]
# feed_Each value in the dictionary passed to dict corresponds to the input vectors a and b that cos has.
#Since this calculation result is taken out as the value of the matrix, only the contained constant part is assigned to y.
Now, the cosine calculated by the angle between the vectors has been obtained. After that, if you use the inverse cosine function arccos, you can find the angle, but unfortunately it was not implemented in tensorflow.
I was about to give up, then! I found that numpy implements the arccos function! ... So, at the end, use the numpy function to convert the cosine value to an angle.
import numpy as np
print np.arccos(y) * 180 / np.pi
#Since the calculation result of arccos is radian, the angle is calculated by multiplying by 180 and dividing by the pie.
did it. When I try to calculate a = [[1, 1]], b = [[1, 0]] that I entered above, it is displayed as [[45.]]. This is because the angle between a and b is the base and hypotenuse of the 1: 1: √2 isosceles triangle that is familiar in high school mathematics, so the angle between them is 45 degrees, which is correct. In addition, if a = [[1, 1.73205]], b = [[1, 0]](= 1: 2: √3 right triangle contains two sides), a value of almost 60 degrees is returned. Come on.
Now we know that we can calculate for a two-dimensional vector. Next, this is extended so that it can correspond to a vector of any number of dimensions as well as two dimensions.
All you have to do is set the dimension number of the first placeholder to None.
a = tf.placeholder(tf.types.float32, [1, None])
b = tf.placeholder(tf.types.float32, [1, None])
# shape(2nd argument of placeholder)If None is specified for the element of, it will be possible to handle any number of dimension values.
It's done. After that, put your favorite value in the input vector and try to calculate. For example
with tf.Session() as sess:
y = sess.run([cos], feed_dict={a: [[1, 1, 1]], b: [[1, 1, 0]]})[0][0]
print np.arccos(y) * 180 / np.pi
# => [35.26438522]
The input vectors a and b represent "the angle formed by the diagonal line of the bottom surface of the cube and the diagonal line penetrating the center". If you calculate, this is certainly around 35-36 degrees.
By using TensorFlow in this way, vector calculations can be easily performed. Similarly, it seems that you can calculate the matrix flexibly, so I will try that as well.
Below is the code implemented this time. (Corresponding to n-dimensional vector)
import tensorflow as tf
import numpy as np
a = tf.placeholder(tf.types.float32, [1, None])
b = tf.placeholder(tf.types.float32, [1, None])
a_dot_b = tf.matmul(a, b, transpose_b=True)
a_abs = tf.sqrt(tf.matmul(a, a, transpose_b=True))
b_abs = tf.sqrt(tf.matmul(b, b, transpose_b=True))
cos = tf.div(a_dot_b, tf.mul(a_abs, b_abs))
with tf.Session() as sess:
y = sess.run([cos], feed_dict={a: [[1, 1, 1]], b: [[1, 1, 0]]})[0][0]
print np.arccos(y) * 180 / np.pi
Recommended Posts