본문 바로가기
Python

[DL] Tensor: Transpose and Permute

by ds31x 2024. 3. 16.

Transpose

Transpose(전치)의 linear algebra에서의 정의는 다음과 같음.

Given an m x n matrix A,
the transpose of A is the n x m matrix,
denoted by AT whose columns are formed from the corresponding rows of A.

간단하게 말하면 행과 열을 바꾸는 처리이다.

 

Tensor의 경우

rank가 2 보다 클 수 있으며 해당  rank의 수만큼 축이 있다.
때문에

Tensor에서의 transpose는 여러 축들 중 2개를 서로의 위치를 바꾸는 것이라고 보면 된다.

 

주의할 것은

  • numpy와 pytorch의 경우, aixs(축)만 변경된 것이지, 여전히 같은 데이터 (the same underlying data)를 공유하는 방식이므로 
  • transpose 처리로 얻은 tensor인스턴스에서 데이터를 변경할 경우, 원래의 tensor인스턴스에서도 데이터가 변경된다.
  • tensorflow에서는 tensor가 immutable이라, 데이터를 변경을 하면 다른 tensor가 생성하는 것에 해당하므로 조금 다름.

다음 예를 참고할 것.


numpy

a = np.random.rand(2, 3)
t1 = np.transpose(a)
t2 = a.T
print(a.shape)  # (2,3)
print(t1.shape) # (3,2)
print(t2.shape) # (3,2)

t2[0,1] = 77
print(a[1,0])  # 77.0
print(t1[0,1]) # 77.0
print(t2[0,1]) # 77.0

pytorch

a_torch = torch.rand(2, 3)
t1_torch = torch.transpose(a_torch, 0, 1) #axis-0 (행) 과 axis-1 (열)을 교체.
t2_torch = a_torch.T
print(a_torch.shape)  #torch.Size([2,3])
print(t1_torch.shape) #torch.Size([3,2])
print(t2_torch.shape) #torch.Size([3,2])

t2_torch[0,1] = 77
print(a_torch[1,0])  # tensor(77.)
print(t1_torch[0,1]) # tensor(77.)
print(t2_torch[0,1]) # tensor(77.)
  • transpose 를 수행하면, 기존의  contiguous tensor 는 더이상 contiguous 이 아님: is_contiguous() 메서드(tensor인스턴스에서 지원)로 확인 가능.
  • storage() 를 이용하여 실제 저장된 underlying 1-D array 에서의 순서를 확인가능함.

 


tensorflow

a_tf = tf.random.normal([2, 3])
t1_tf = tf.transpose(a_tf)
t2_tf = tf.transpose(a_tf, perm=[1, 0]) # T 지원안함.
print(a_tf.shape, a_tf.dtype)
print(t1_tf.shape, t1_tf.dtype)
print(t2_tf.shape, t2_tf.dtype)

indices = tf.constant([[0, 1]]) # (2, 2) 위치를 변경하고자 함
updates = tf.constant([77], dtype=tf.float32) # 해당 위치에 넣고 싶은 값
t2_tf = tf.tensor_scatter_nd_update(t2_tf, indices, updates)
print(a_tf[1,0])
print(t1_tf[0,1])
print(t2_tf[0,1])

Permute (순열, 축의 위치를 변경)

Tensor의 축들의 순서를 임의로 바꾸는 데 사용됨.
transpose가 한번에 2개의 축의 위치를 바꾸는 것과 달리,
임의의 수의 축들을 임의의 순서로 자유롭게 변경할 수 있음.

 

참고로, numpy, tensorflow에서는 transpose를 통해 permute를 구현하고 있음.


numpy

a = np.random.rand(2, 3, 4)
t1 = np.transpose(a, (0, 2, 1)) # 기존의 axis 0,1,2 순서를 axis 0,2,1 순서로 변경.
print(a.shape)  # (2,3,4)
print(t1.shape) # (2,4,3)
t1[0,1,2] = 77
print(a[0,2,1])  # 77.0
print(t1[0,1,2]) # 77.0

pytorch

a_torch = torch.rand(2, 3, 4)
t1_torch = torch.permute(a_torch, (0, 2, 1)) # numpy의 transpose와 사용방법이 유사.
print(a_torch.shape)  # torch.Size([2, 3, 4])
print(t1_torch.shape) # torch.Size([2, 4, 3])
t1_torch[0,1,2] = 77
print(a_torch[0,2,1])  # tensor(77.)
print(t1_torch[0,1,2]) # tensor(77.)
  • permute의 경우도 역시 contiguous가 깨지게 됨.

tensorflow

a_tf = tf.random.normal([2, 3, 4])
t1_tf = tf.transpose(a_tf, perm=[0, 2, 1]) #perm 이라는 키워드로 변경될 축의 순서를 기재.
print(a_tf.shape)  # (2, 3, 4)
print(t1_tf.shape) # (2, 4, 3)

https://gist.github.com/dsaint31x/4b703b26775a826c978cb3d65cf607c8

 

dl_tensor_transpose_permute.ipynb

dl_tensor_transpose_permute.ipynb. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com