[TensorFlow] 텐서 형태 변환 (tf.reshape()), 텐서 행과 열 전치 (tf.transpose())
데이터 전처리를 하다보면 필요에 맞게 데이터 형태, 구조를 변경하는 일이 빈번하게 생깁니다. 이번 포스팅에서는 텐서의 형태를 변환, 재구조화, 전치하는 방법을 소개하겠습니다.
이미 numpy (https://rfriend.tistory.com/345 , https://rfriend.tistory.com/289)에 익숙한 분이라면, 사용법이 비슷하기 때문에 그리 어렵지 않게 금방 이해할 수 있을 거예요.
(1) tf.reshape(): 텐서의 형태 변환
(2) tf.transpose(): 텐서의 행과 열 전치
(1) tf.reshape(): 텐서의 형태 변환
먼저, 0~11까지 12개의 원소를 가지는 벡터(vector) 로 텐서를 만들어보겠습니다.
t1 = tf.constant(range(12))
print(t1)
# tf.Tensor([ 0 1 2 3 4 5 6 7 8 9 10 11],
#. shape=(12,), dtype=int32)
tf.rank(t1) # rank 1
# <tf.Tensor: shape=(), dtype=int32, numpy=1>
위의 벡터 (12,) 형태를 가지는 텐서 t1을, 행렬 (3, 4) 형태를 가지는 텐서로 tf.reshape(tensor, shape, name=None) 메소드를 사용해서 변환(reshape)해보겠습니다.
## reshaping a shape of Tensor from (12,) to (3, 4)
t2 = tf.reshape(t1, [3, 4])
print(t2)
# tf.Tensor(
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]], shape=(3, 4), dtype=int32)
tf.rank(t2) # rank 2
# <tf.Tensor: shape=(), dtype=int32, numpy=2>
tf.reshape(tensor, shape) 의 shape 란에 원하는 형태를 [ ] 안에 콤마로 구분해서 넣어주면 됩니다. 이번에는 rank 3 을 가지는 (2, 2, 3) 형태의 텐서로 형태를 변환해보겠습니다.
## reshaping a Tensor with a shape of (12,) to (2,2,3)
t3 = tf.reshape(t1, [2, 2, 3])
print(t3)
# tf.Tensor(
# [[[ 0 1 2]
# [ 3 4 5]]
# [[ 6 7 8]
# [ 9 10 11]]], shape=(2, 2, 3), dtype=int32)
tf.rank(t3) # rank 3
# <tf.Tensor: shape=(), dtype=int32, numpy=3>
tf.reshape(tensor, shape) 의 shape 에 '-1' 이 들어있으면, 숫자가 기입된 부분의 축을 변환하고 난 후에, "남은 축의 형태는 원래 텐서의 총 크기와 같도록 알아서 추정"해준다는 뜻입니다.
아래 예에서는 원래 텐서 t1 이 (12,) 형태였으며, tf.reshape(t1, [-1, 3]) 으로 재구조화시켰더니 (4, 3) 형태의 텐서로 변환되었네요.
## If one component of shape is the special value -1,
## the size of that dimension is computed
## so that the total size remains constant.
t4 = tf.reshape(t1, [-1, 3])
print(t4)
# tf.Tensor(
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]], shape=(4, 3), dtype=int32)
tf.rank(t4) # rank 2
# <tf.Tensor: shape=(), dtype=int32, numpy=2>
특히, tf.reshape(tensor, [-1]) 처럼 shape 에 [-1] 은 1차원의 벡터인 1-D 텐서로 변환을 한다는 뜻입니다.
아래 예에서 텐서 t4 는 (4, 3) 형태를 가지는 행렬이었는데요, tf.reshape(t4, [-1]) 해주었더니 (12,) 의 형태를 가지는 1차원의 벡터로 변환이 되었습니다.
## In particular, a shape of [-1] flattens into 1-D.
## At most one component of shape can be -1.
t5 = tf.reshape(t4, [-1])
print(t5)
# tf.Tensor([ 0 1 2 3 4 5 6 7 8 9 10 11],
# shape=(12,), dtype=int32)
tf.rank(t5) # rank 1
# <tf.Tensor: shape=(), dtype=int32, numpy=1>
tf.reshape(tensor, []) 의 [ ] 는 텐서를 1개의 원소를 가지는 스칼라(scalar) 로 변환합니다.
## tf.reshape(t, []) reshapes a tensor t with one element to a scalar.
t6 = tf.constant([5])
print(t6) # rank 1, vector
# tf.Tensor([5], shape=(1,), dtype=int32)
t7 = tf.reshape(t6, [])
print(t7) # rank 0, scalar
# tf.Tensor(5, shape=(), dtype=int32)
tf.rank(t7) # rank 0
# <tf.Tensor: shape=(), dtype=int32, numpy=0>
(2) tf.transpose(): 텐서의 행과 열 전치
tf.transpose(tensor)는 텐서의 행과 열의 위치를 전치(transpose) 시켜 줍니다.
아래의 예에서는 shape=(3,4) 의 텐서를 shape=(4,3)의 텐서로 행과 열을 전치시켜주었습니다. 행과 열이 전치를 시키기 전과 후에 어떻게 바뀌었는지 살펴보면 금방 이해하실 수 있을 거예요.
print(t2)
# tf.Tensor(
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]], shape=(3, 4), dtype=int32)
t8 = tf.transpose(t2)
print(t8)
# tf.Tensor(
# [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]], shape=(4, 3), dtype=int32)
[ Reference ]
- tf.reshape(): https://www.tensorflow.org/api_docs/python/tf/reshape
- tf.transpose(): https://www.tensorflow.org/api_docs/python/tf/transpose
이번 포스팅이 많은 도움이 되었기를 바랍니다.
행복한 데이터 과학자 되세요! :-)