4 minute read

기초

텐서 생성하기

TensorFlow 임포트

import tensorflow as tf
import numpy as np

기본 텐서 생성하기

  • 스칼라: 단일, 순위0, 축 없음
  • 벡터: 순위1, 축 1개
  • 행렬: 순위2, 축 2개
  • n개의 축 가능
rank_0_tensor = tf.constant(4)    # 스칼라
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])    # 벡터
rank_2_tensor = tf.constant([[1, 2], [3, 4], [5, 6]], dtype = tf.float16)   # 행렬
rank_3_tensor = tf.constant([
  [[0, 1, 2, 3, 4],
   [5, 6, 7, 8, 9]],
  [[10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19]],
  [[20, 21, 22, 23, 24],
   [25, 26, 27, 28, 29]],])
  • 복소수, 문자열 가능
  • 기본 tf.Tensor 클래스에서는 텐서가 직사각형 이어야 함
  • 다양한 형상을 처리하는 특수 유형의 텐서: 비정형 텐서(RaggedTensor), 희소 텐서(SparseTensor)

텐서를 numpy배열로 변환

np.array(rank_2_tensor)     # 첫 번째 방법
rank_2_tensor.numpy()       # 두 번째 방법

텐서에 대한 기본 산술

a = tf.constant([[1, 2], [3, 4]])
b = tf.constant([[5, 6], [7, 8]])

# 표현법1
print(tf.add(a, b), "\n")       # 동일한 위치에 있는 원소의 합
print(tf.multiply(a, b), "\n")  # 동일한 위치에 있는 원소의 곱
print(tf.matmul(a, b), "\n")    # 행렬의 곱

print(a + b, "\n")    # 동일한 위치에 있는 원소의 합
print(a * b, "\n")    # 동일한 위치에 있는 원소의 곱
print(a @ b, "\n")    # 행렬의 곱
c = tf.constant([[4.0, 5.0], [10.0, 1.0]])

print(tf.reduce_max(c))     # 변수에서 가장 큰 값을 탐색
print(tf.math.argmax(c))    # 가장 큰 값의 인덱스 값을 찾음
print(tf.nn.softmax(c))     # 
  • softmax

형상 정보

텐서 관련 용어

  • 형상: 텐서의 각 차원의 길이(요소의 수)
  • 순위: 텐서 축의 수
  • 축/차원: 텐서의 특정 차원
  • 크기: 텐서의 총 항목 수, 형상 요소의 곱

텐서 관련 출력

rank_4_tensor = tf.zeros([3, 2, 4, 5])    # 각 축을 전부 0으로 설정

print("Type of every element: ", rank_4_tensor.dtype)   # 데이터 타입 확인

# ndim, shape(속성)는 텐서 객체를 반환하지 않음
print("Number of axes:", rank_4_tensor.ndim)      # 배열의 차원 확인            
print("Shape of tensor:", rank_4_tensor.shape)

print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0])
print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1])
print("Total number of elements (3*2*4*5): ", tf.size(rank_4_tensor).numpy())

텐서 객체가 필요한 경우

tf.rank(rank_4_tensor)
tf.shape(rank_4_tensor)

인덱싱

텐서에서 인덱싱 하는 방법

표준 Python 인덱싱 규칙을 따름

단일 축 인덱싱

rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])

print(rank_1_tensor)                        # 텐서 자체를 출력
print(rank_1_tensor.numpy())                # 텐서의 값을 출력
print("First: ", rank_1_tensor[0].numpy())  # 스칼라 사용 인덱싱 -> 축 제거
print("Slice from 2, before 7: ", rank_1_tensor[2:7].numpy()) # ':' 이용 슬라이싱 -> 축 유지
print("Jump item: ", rank_1_tensor[::2].numpy())    # 인덱스 2를 간격으로 뜀
print("Reversed: ", rank_1_tensor[::-1].numpy())    # 반대로 뒤집기

다중 축 인덱싱

print(rank_2_tensor.numpy())

print(rank_2_tensor[1, 1].numpy())    # 각 축에 정수 전잘 시 결과는 스칼라
print("Second row:", rank_2_tensor[1, :].numpy())     # 1번째 행 전부 출력
print("Second column:", rank_2_tensor[:, 1].numpy())  # 1번째 열 전부 출력
print("Skip the first row:")
print(rank_2_tensor[1:, :].numpy(), "\n")             # 0번째 행 제외 전부 출력(1번째 행부터 끝까지 출력)
  • 여러 인덱스 사용
  • 단일 축의 경우에서와 같은 규칙이 각 축에 독립적으로 작용

형상 조작하기

새로운 형상으로 변환하기

tf.reshape(tensor, shape, name=None)

새로운 형상으로 변환하기(1)

x = tf.constant([[1], [2], [3]])
print(x.shape.as_list())    # 파이썬 배열로 반환 가능
reshaped = tf.reshape(x, [1, 3])
print(x.shape)
print(reshaped.shape)

새로운 형상으로 변환하기(2)

print(rank_3_tensor)
print(tf.reshape(rank_3_tensor, [-1]))        # -1 일렬로 텐서를 나열
print(tf.reshape(rank_3_tensor, [2, 3, 5]))     # 원하는 shape 로 모양 변형
  • rank_3_tensor은 현재 325 = 30임
  • reshape를 할때 곱해서 도합 30이 나오게끔 shape 설정([1, 30], [2, 15], [2, 3, 5] 등)

Dtypes에 대한 추가 정보
tf.Tensor의 데이터 유형을 검사하려면, Tensor.dtype 속성을 사용 Python 객체에서 tf.Tensor를 만들 때 선택적으로 데이터 유형을 지정할 수 있음

  • Python 정수 -> tf.int32
  • Python 부동 소수점 -> tf.float32

브로드캐스팅
특정 조건에서 작은 텐서는 결합된 연산을 실행할 때 더 큰 텐서에 맞게 자동으로 ‘확장’을 함

  • 브로드캐스팅 한 값이 무엇인지 미리 확인 가능: .broadcast_to

비정형 텐서

비정형 텐서란?

각 축이 다양한 수요를 가진 텐서

ragged_list = [
    [0, 1, 2, 3],
    [4, 5],
    [6, 7, 8],
    [9]]

# rag = tf.constant(ragged_list)        # 정규텐서로 변환 불가
rag = tf.ragged.constant(ragged_list)   # ragged 사용할 것

print(rag)
  • 비정형 텐서는 바로 정형 텐서로 변형 불가, ragged사용

문자열 텐서

문자영 텐서에 대해

tf.string은 dtype

  • 문자열은 원자성이므로 Python 문자열과 같은 방식으로 인덱싱할 수 없음
  • 문자열을 조작하는 함수는 tf.strings 참고

문자열 텐서 다루기

# 출력 결과에 나오는 b는 tf.string dtype이 유니코드 문자열이 아닌 바이트 문자열임을 나타냄
scalar_string_tensor = tf.constant("Gray wolf")
print(scalar_string_tensor)
print(scalar_string_tensor.numpy())

# tf.strings를 이용한 문자열 조작
print(tf.strings.split(scalar_string_tensor, sep=" "))  # 공백을 기준으로 분리

# 문자열로 되어있는 숫자를 숫자로 변환
# tf.string.to_number
text = tf.constant("1 10 100")
print(tf.strings.to_number(tf.strings.split(text, " ")))
  • 접두사 b는 문자가 유니코드가 아닌 바이트 코드라는 것을 의미
  • sep를 통해 문자열 분리 가능

문자열을 바이트로 변환

byte_strings = tf.strings.bytes_split(tf.constant("Duck"))  # 각 바이트로 쪼갬
byte_ints = tf.io.decode_raw(tf.constant("Duck"), tf.uint8) # 바이트로 쪼갠 후 유니코드로 변환
print("Byte strings:", byte_strings)
print("Bytes:", byte_ints)
  • tf.string dtype: TensorFlow의 모든 원시 바이트 데이터에 사용
  • tf.io 모듈: 이미지 디코딩, csv 구문 분석 등 데이터를 바이트로 변환하거나 바이트에서 변환하는 함수가 포함

희소 텐서

희소 텐서란?

매우 넓은 공간에 데이터가 희소한 경우

  • tf.sparse.SparseTensor 및 관련 연산을 지원하여 희소 데이터를 효율적으로 저장

희소 텐서 예제

# Sparse tensors store values by index in a memory-efficient manner
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
                                       values=[24, 3.5],
                                       dense_shape=[5, 6])
print(sparse_tensor, "\n")

# You can convert sparse tensors to dense
print(tf.sparse.to_dense(sparse_tensor))
  • indices: 어떤 인덱스가 0이 아닌 원소인지 나타냄
  • values: indices의 인덱스 순서대로 값을 나타냄(indices의 인덱스 개수와 ㅍvalues의 원소 개수와 동일)
  • dense_shape: 공간의 크기를 나타냄



TensorFlow 텐서 소개