<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Math Part 3
Step1:  NOTE on notation
* _x, _y, _z, ...
Step2:  Q2. Compute the cumulative product of X along the second axis.
Step3:  Segmentation
Q3. Compute the sum along the first two elements and 
the last two elements of X separately.
Step4:  Q4. Compute the product along the first two elements and the last two elements of X separately.
Step5:  Q5. Compute the minimum along the first two elements and the last two elements of X separately.
Step6:  Q6. Compute the maximum along the first two elements and the last two elements of X separately.
Step7:  Q7. Compute the mean along the first two elements and the last two elements of X separately.
Step8:  Q8. Compute the sum along the second and fourth and 
the first and third elements of X separately in the order.
Step9:  Sequence Comparison and Indexing
Q9. Get the indices of maximum and minimum values of X along the second axis.
Step10:  Q10. Find the unique elements of x that are not present in y.
Step11:  Q11. Return the elements of X, if X < 4, otherwise X*10.
Step12:  Q12. Get unique elements and their indices from x.
Step13:  Q13. Compute the edit distance between hypothesis and truth.
<ASSISTANT_TASK:>
Python Code:
from __future__ import print_function
import tensorflow as tf
import numpy as np
from datetime import date
date.today()
author = "kyubyong. https://github.com/Kyubyong/tensorflow-exercises"
tf.__version__
np.__version__
sess = tf.InteractiveSession()
Explanation: Math Part 3
End of explanation
_X = np.array([[1,2,3], [4,5,6]])
X = tf.convert_to_tensor(_X)
out = tf.cumsum(X, axis=1)
print(out.eval())
_out = np.cumsum(_X, axis=1)
assert np.array_equal(out.eval(), _out) # tf.cumsum == np.cumsum
Explanation: NOTE on notation
* _x, _y, _z, ...: NumPy 0-d or 1-d arrays
* _X, _Y, _Z, ...: NumPy 2-d or higer dimensional arrays
* x, y, z, ...: 0-d or 1-d tensors
* X, Y, Z, ...: 2-d or higher dimensional tensors
Scan
Q1. Compute the cumulative sum of X along the second axis.
End of explanation
_X = np.array([[1,2,3], [4,5,6]])
X = tf.convert_to_tensor(_X)
out = tf.cumprod(X, axis=1)
print(out.eval())
_out = np.cumprod(_X, axis=1)
assert np.array_equal(out.eval(), _out) # tf.cumprod == np.cumprod
Explanation: Q2. Compute the cumulative product of X along the second axis.
End of explanation
_X = np.array(
    [[1,2,3,4], 
     [-1,-2,-3,-4], 
     [-10,-20,-30,-40],
     [10,20,30,40]])
X = tf.convert_to_tensor(_X)
out = tf.segment_sum(X, [0, 0, 1, 1])
print(out.eval())
Explanation: Segmentation
Q3. Compute the sum along the first two elements and 
the last two elements of X separately.
End of explanation
_X = np.array(
    [[1,2,3,4], 
     [1,1/2,1/3,1/4], 
     [1,2,3,4],
     [-1,-1,-1,-1]])
X = tf.convert_to_tensor(_X)
out = tf.segment_prod(X, [0, 0, 1, 1])
print(out.eval())
Explanation: Q4. Compute the product along the first two elements and the last two elements of X separately.
End of explanation
_X = np.array(
    [[1,4,5,7], 
     [2,3,6,8], 
     [1,2,3,4],
     [-1,-2,-3,-4]])
X = tf.convert_to_tensor(_X)
out = tf.segment_min(X, [0, 0, 1, 1])
print(out.eval())
Explanation: Q5. Compute the minimum along the first two elements and the last two elements of X separately.
End of explanation
_X = np.array(
    [[1,4,5,7], 
     [2,3,6,8], 
     [1,2,3,4],
     [-1,-2,-3,-4]])
X = tf.convert_to_tensor(_X)
out = tf.segment_max(X, [0, 0, 1, 1])
print(out.eval())
Explanation: Q6. Compute the maximum along the first two elements and the last two elements of X separately.
End of explanation
_X = np.array(
    [[1,2,3,4], 
     [5,6,7,8], 
     [-1,-2,-3,-4],
     [-5,-6,-7,-8]])
X = tf.convert_to_tensor(_X)
out = tf.segment_mean(X, [0, 0, 1, 1])
print(out.eval())
Explanation: Q7. Compute the mean along the first two elements and the last two elements of X separately.
End of explanation
_X = np.array(
    [[1,2,3,4], 
     [-1,-2,-3,-4], 
     [-10,-20,-30,-40],
     [10,20,30,40]])
X = tf.convert_to_tensor(_X)
out = tf.unsorted_segment_sum(X, [1, 0, 1, 0], 2)
print(out.eval())
Explanation: Q8. Compute the sum along the second and fourth and 
the first and third elements of X separately in the order.
End of explanation
_X = np.random.permutation(10).reshape((2, 5))
print("_X =", _X)
X = tf.convert_to_tensor(_X)
out1 = tf.argmax(X, axis=1)
out2 = tf.argmin(X, axis=1)
print(out1.eval())
print(out2.eval())
_out1 = np.argmax(_X, axis=1)
_out2 = np.argmin(_X, axis=1)
assert np.allclose(out1.eval(), _out1)
assert np.allclose(out2.eval(), _out2)
# tf.argmax == np.argmax
# tf.argmin == np.argmin
Explanation: Sequence Comparison and Indexing
Q9. Get the indices of maximum and minimum values of X along the second axis.
End of explanation
_x = np.array([0, 1, 2, 5, 0])
_y = np.array([0, 1, 4])
x = tf.convert_to_tensor(_x)
y = tf.convert_to_tensor(_y)
out = tf.setdiff1d(x, y)[0]
print(out.eval())
_out = np.setdiff1d(_x, _y)
assert np.array_equal(out.eval(), _out)
# Note that tf.setdiff1d returns a tuple of (out, idx),
# whereas np.setdiff1d returns out only.
Explanation: Q10. Find the unique elements of x that are not present in y.
End of explanation
_X = np.arange(1, 10).reshape(3, 3)
X = tf.convert_to_tensor(_X)
out = tf.where(X < 4, X, X*10)
print(out.eval())
_out = np.where(_X < 4, _X, _X*10)
assert np.array_equal(out.eval(), _out) # tf.where == np.where
Explanation: Q11. Return the elements of X, if X < 4, otherwise X*10.
End of explanation
_x = np.array([1, 2, 6, 4, 2, 3, 2])
x = tf.convert_to_tensor(_x)
out, indices = tf.unique(x)
print(out.eval())
print(indices.eval())
_out, _indices = np.unique(_x, return_inverse=True)
print("sorted unique elements =", _out)
print("indices =", _indices)
# Note that tf.unique keeps the original order, whereas
# np.unique sorts the unique members.
Explanation: Q12. Get unique elements and their indices from x.
End of explanation
# Check the documentation on tf.SparseTensor if you are not
# comfortable with sparse tensor.
hypothesis = tf.SparseTensor(
    [[0, 0],[0, 1],[0, 2],[0, 4]],
    ["a", "b", "c", "a"],
    (1, 5)) 
# Note that this is equivalent to the dense tensor.
# [["a", "b", "c", 0, "a"]]
truth = tf.SparseTensor(
    [[0, 0],[0, 2],[0, 4]],
    ["a", "c", "b"],
    (1, 6))
# This is equivalent to the dense tensor.
# [["a", 0, "c", 0, "b", 0]]
out1 = tf.edit_distance(hypothesis, truth, normalize=False)
out2 = tf.edit_distance(hypothesis, truth, normalize=True)
print(out1.eval()) # 2 <- one deletion ("b") and one substitution ("a" to "b")
print(out2.eval()) # 0.6666 <- 2 / 6
Explanation: Q13. Compute the edit distance between hypothesis and truth.
End of explanation
<END_TASK>