본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 2. · 14 Views
Tensor 기본 개념과 연산 완벽 가이드
TensorFlow의 핵심 자료구조인 Tensor에 대해 알아봅니다. 생성 방법부터 차원, 연산, Broadcasting, NumPy 변환까지 초급 개발자가 꼭 알아야 할 내용을 담았습니다.
목차
1. Tensor의 정의와 특징
김개발 씨는 최근 머신러닝 프로젝트에 투입되었습니다. 팀장님이 건네준 코드를 열어보니 낯선 용어가 눈에 들어옵니다.
"Tensor라... 이게 대체 뭐지?" 수학 시간에 배운 텐서와 같은 건지, 아니면 완전히 다른 개념인지 궁금해졌습니다.
Tensor는 TensorFlow에서 데이터를 담는 가장 기본적인 그릇입니다. 마치 엑셀 스프레드시트가 숫자와 문자를 담듯이, Tensor는 다차원 배열 형태로 데이터를 저장합니다.
NumPy 배열과 비슷하지만, GPU 연산과 자동 미분을 지원한다는 점에서 더 강력합니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
# 스칼라(0차원): 단일 값
scalar = tf.constant(42)
print(f"스칼라: {scalar}")
# 벡터(1차원): 일렬로 늘어선 값
vector = tf.constant([1, 2, 3, 4, 5])
print(f"벡터: {vector}")
# 행렬(2차원): 행과 열로 이루어진 값
matrix = tf.constant([[1, 2, 3], [4, 5, 6]])
print(f"행렬 shape: {matrix.shape}")
# 3차원 텐서: 여러 장의 행렬을 쌓은 형태
tensor_3d = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(f"3차원 텐서 shape: {tensor_3d.shape}")
김개발 씨는 입사 3개월 차 주니어 개발자입니다. 최근 회사에서 AI 프로젝트를 시작하면서 TensorFlow를 배우게 되었습니다.
튜토리얼을 따라 하던 중, 가장 먼저 마주친 개념이 바로 Tensor였습니다. "Tensor가 뭔가요?" 김개발 씨가 선배 박시니어 씨에게 물었습니다.
박시니어 씨는 잠시 생각하더니 이렇게 설명했습니다. "쉽게 말해서, Tensor는 데이터를 담는 상자야.
근데 이 상자가 좀 특별해." 그렇다면 Tensor란 정확히 무엇일까요? 쉽게 비유하자면, Tensor는 마치 러시아 마트료시카 인형과 같습니다.
가장 작은 인형 하나가 스칼라입니다. 이 인형들을 한 줄로 세우면 벡터가 됩니다.
인형들을 격자 모양으로 배열하면 행렬이 됩니다. 그리고 이 격자들을 여러 층으로 쌓으면 3차원 이상의 텐서가 됩니다.
"그럼 그냥 배열이랑 뭐가 달라요?" 김개발 씨가 다시 물었습니다. 핵심적인 차이가 있습니다.
일반 배열은 CPU에서만 연산됩니다. 하지만 Tensor는 GPU에서 병렬 연산이 가능합니다.
수백만 개의 데이터를 동시에 처리해야 하는 딥러닝에서 이 차이는 엄청납니다. 또한 Tensor는 자동 미분을 지원합니다.
딥러닝에서는 미분을 통해 학습이 이루어지는데, Tensor를 사용하면 복잡한 미분 계산을 자동으로 처리해줍니다. 위의 코드를 살펴보겠습니다.
먼저 스칼라는 차원이 없는 단일 값입니다. 숫자 42 하나만 담고 있습니다.
벡터는 1차원으로, 값들이 일렬로 늘어서 있습니다. 행렬은 2차원으로, 행과 열로 이루어져 있습니다.
3차원 텐서는 여러 장의 행렬을 겹쳐 놓은 것과 같습니다. 실제 현업에서는 어떻게 활용할까요?
이미지 데이터를 다룬다고 가정해봅시다. 컬러 이미지 한 장은 보통 (높이, 너비, 채널) 형태의 3차원 텐서입니다.
여러 장의 이미지를 묶으면 4차원 텐서가 됩니다. 이처럼 Tensor는 복잡한 데이터를 체계적으로 표현할 수 있게 해줍니다.
주의할 점도 있습니다. Tensor는 생성된 후에는 값을 변경할 수 없습니다.
이를 **불변성(immutability)**이라고 합니다. 값을 바꾸고 싶다면 새로운 Tensor를 만들어야 합니다.
박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, Tensor가 딥러닝의 기본 단위인 거군요!" 맞습니다.
Tensor를 제대로 이해하면 TensorFlow의 절반은 이해한 것이나 다름없습니다. 여러분도 다양한 차원의 Tensor를 직접 만들어보면서 감을 익혀보세요.
실전 팁
💡 - Tensor의 차원은 rank라고도 부르며, tf.rank()로 확인할 수 있습니다
- 실무에서는 보통 2차원 이상의 Tensor를 다루게 됩니다
2. Tensor 생성 방법
김개발 씨가 Tensor의 개념을 이해하고 나서 다음 질문을 던졌습니다. "그럼 Tensor를 어떻게 만드나요?" 박시니어 씨는 두 가지 방법이 있다고 말했습니다.
constant와 Variable, 이 둘의 차이를 아는 것이 중요하다고요.
Tensor를 생성하는 방법은 크게 두 가지입니다. tf.constant는 변경할 수 없는 상수 텐서를 만들고, tf.Variable은 학습 과정에서 값이 변하는 텐서를 만듭니다.
딥러닝에서 가중치처럼 학습되어야 하는 값은 Variable로, 입력 데이터처럼 고정된 값은 constant로 생성합니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
# constant: 변경 불가능한 상수 텐서
const_tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
print(f"Constant: {const_tensor}")
# Variable: 변경 가능한 변수 텐서
var_tensor = tf.Variable([[1.0, 2.0], [3.0, 4.0]])
print(f"Variable: {var_tensor}")
# Variable 값 변경하기
var_tensor.assign([[5.0, 6.0], [7.0, 8.0]])
print(f"변경 후: {var_tensor}")
# 특정 위치만 변경
var_tensor[0, 0].assign(100.0)
print(f"부분 변경 후: {var_tensor}")
# 특수한 텐서 생성
zeros = tf.zeros([3, 3]) # 0으로 채워진 텐서
ones = tf.ones([2, 4]) # 1로 채워진 텐서
random = tf.random.normal([2, 2]) # 정규분포 난수 텐서
김개발 씨는 코드를 작성하다가 이상한 점을 발견했습니다. 어떤 코드에서는 tf.constant를 쓰고, 어떤 코드에서는 tf.Variable을 씁니다.
둘 다 Tensor를 만드는 건 같은데, 왜 굳이 구분해서 쓰는 걸까요? 박시니어 씨가 칠판에 그림을 그리며 설명했습니다.
"은행 금고를 생각해봐. 금고 안에 있는 금괴는 함부로 꺼낼 수 없잖아?
그게 constant야." tf.constant로 만든 텐서는 마치 금고 안의 금괴와 같습니다. 한번 넣어두면 절대 바꿀 수 없습니다.
입력 데이터나 하이퍼파라미터처럼 변하지 않아야 하는 값에 적합합니다. "그럼 Variable은요?" 김개발 씨가 물었습니다.
"Variable은 지갑 속 현금이야. 쓰면 줄어들고, 받으면 늘어나잖아." tf.Variable은 학습 과정에서 계속 업데이트되는 값을 담습니다.
신경망의 가중치와 편향이 대표적입니다. 역전파 과정에서 이 값들이 조금씩 조정되면서 모델이 학습합니다.
위의 코드에서 constant와 Variable의 차이를 확인할 수 있습니다. const_tensor는 생성 후 값을 바꾸려고 하면 오류가 발생합니다.
반면 var_tensor는 assign 메서드로 언제든 값을 변경할 수 있습니다. 특히 주목할 점은 부분 변경입니다.
var_tensor[0, 0].assign(100.0)처럼 특정 위치의 값만 바꿀 수도 있습니다. 이런 유연성 덕분에 복잡한 학습 알고리즘을 구현할 수 있습니다.
또한 코드 하단에는 특수한 텐서를 생성하는 방법도 있습니다. tf.zeros는 0으로 가득 찬 텐서를, tf.ones는 1로 가득 찬 텐서를 만듭니다.
tf.random.normal은 정규분포를 따르는 난수로 채워진 텐서를 생성합니다. 가중치 초기화에 자주 사용됩니다.
실무에서는 어떻게 구분할까요? 일반적으로 모델의 입력 데이터는 constant로, 학습할 파라미터는 Variable로 만듭니다.
Keras 같은 고수준 API를 사용하면 이런 구분을 자동으로 해주지만, 기본 원리를 알아두면 디버깅할 때 큰 도움이 됩니다. 흔한 실수 중 하나는 constant를 Variable처럼 변경하려고 시도하는 것입니다.
이러면 오류가 발생합니다. 값이 변해야 한다면 처음부터 Variable로 만들어야 합니다.
김개발 씨는 이제 상황에 맞게 constant와 Variable을 구분해서 사용할 수 있게 되었습니다. "용도에 따라 적절한 도구를 선택하는 게 중요하군요!"
실전 팁
💡 - 학습할 파라미터는 반드시 tf.Variable로 생성해야 합니다
- tf.zeros_like()나 tf.ones_like()를 사용하면 기존 텐서와 같은 shape의 특수 텐서를 만들 수 있습니다
3. 차원과 데이터 타입
김개발 씨가 작성한 코드에서 오류가 발생했습니다. "shape이 맞지 않습니다"라는 에러 메시지입니다.
분명히 같은 데이터인데 왜 연산이 안 되는 걸까요? 박시니어 씨는 shape과 dtype의 중요성을 설명하기 시작했습니다.
shape은 텐서의 각 차원별 크기를 나타내는 튜플입니다. dtype은 텐서에 저장된 데이터의 타입을 의미합니다.
이 두 가지를 정확히 맞추지 않으면 연산 시 오류가 발생하거나 예상치 못한 결과가 나올 수 있습니다. 딥러닝에서 shape 관리는 실력의 척도라고 할 수 있습니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
# 텐서 생성
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
# shape 확인: (행, 열)
print(f"Shape: {tensor.shape}") # (2, 3)
print(f"Rank: {tf.rank(tensor)}") # 2 (차원 수)
print(f"Size: {tf.size(tensor)}") # 6 (전체 원소 수)
# dtype 확인 및 변환
print(f"Dtype: {tensor.dtype}") # int32
float_tensor = tf.cast(tensor, tf.float32)
print(f"변환 후 Dtype: {float_tensor.dtype}")
# shape 변경 (reshape)
reshaped = tf.reshape(tensor, [3, 2]) # (2,3) -> (3,2)
print(f"Reshape 후: {reshaped}")
# 차원 추가/제거
expanded = tf.expand_dims(tensor, axis=0) # (2,3) -> (1,2,3)
squeezed = tf.squeeze(expanded) # (1,2,3) -> (2,3)
김개발 씨는 두 텐서를 더하려다가 오류를 만났습니다. 분명히 둘 다 숫자인데, 왜 연산이 안 되는 걸까요?
박시니어 씨가 코드를 보더니 문제점을 짚었습니다. "shape이 안 맞아서 그래.
텐서는 shape이 생명이야." shape이란 무엇일까요? 쉽게 비유하면 택배 상자의 규격과 같습니다.
가로 30cm, 세로 20cm, 높이 10cm라면 이 상자의 shape은 (30, 20, 10)입니다. 텐서도 마찬가지입니다.
(2, 3)이라는 shape은 2행 3열의 데이터를 의미합니다. "그럼 같은 shape끼리만 연산할 수 있나요?" 김개발 씨가 물었습니다.
기본적으로는 그렇습니다. (2, 3) shape의 텐서와 (3, 2) shape의 텐서는 바로 더할 수 없습니다.
하지만 나중에 배울 Broadcasting이라는 규칙이 있어서, 특정 조건에서는 다른 shape끼리도 연산이 가능합니다. 코드를 살펴보겠습니다.
tensor.shape으로 텐서의 형태를 확인할 수 있습니다. tf.rank()는 차원의 수를 반환합니다.
2차원이면 2, 3차원이면 3입니다. tf.size()는 전체 원소의 개수를 알려줍니다.
dtype도 중요합니다. 데이터 타입이 다르면 연산 결과가 달라질 수 있습니다.
정수형(int32)과 부동소수점(float32)을 섞어서 계산하면 예상치 못한 결과가 나올 수 있습니다. tf.cast()를 사용하면 데이터 타입을 변환할 수 있습니다.
tf.reshape()은 텐서의 shape을 바꿔줍니다. 단, 전체 원소 수는 같아야 합니다.
(2, 3) 텐서는 6개의 원소가 있으므로, (3, 2), (6,), (1, 6) 등으로 바꿀 수 있지만 (2, 2)로는 바꿀 수 없습니다. tf.expand_dims()와 tf.squeeze()도 자주 사용됩니다.
expand_dims는 차원을 추가하고, squeeze는 크기가 1인 차원을 제거합니다. 배치 처리나 모델 입력을 맞출 때 유용합니다.
실무에서 가장 많이 하는 실수가 shape 불일치입니다. 특히 신경망 레이어 사이에서 shape이 맞지 않으면 오류가 발생합니다.
항상 중간중간 shape을 출력해서 확인하는 습관을 들이세요. 김개발 씨는 자신의 코드를 다시 살펴보았습니다.
아, 한쪽은 (10, 5)이고 다른 쪽은 (5, 10)이었군요! reshape으로 맞춰주니 문제가 해결되었습니다.
실전 팁
💡 - 디버깅할 때는 print(tensor.shape)을 습관처럼 사용하세요
- 딥러닝에서는 보통 float32 타입을 사용합니다
4. 기본 수학 연산
이제 김개발 씨는 Tensor를 만들고 shape도 다룰 줄 알게 되었습니다. 다음 단계는 연산입니다.
"행렬 곱셈이요? 그거 대학교 선형대수 시간에 배웠는데..." 김개발 씨가 머리를 긁적였습니다.
박시니어 씨는 TensorFlow가 다 해준다며 안심시켰습니다.
TensorFlow는 덧셈, 뺄셈, 곱셈, 나눗셈 같은 기본 연산부터 행렬 곱셈, 지수, 로그 등 다양한 수학 연산을 지원합니다. **요소별 연산(element-wise)**과 행렬 연산을 구분하는 것이 중요합니다.
같은 곱셈이라도 tf.multiply와 tf.matmul은 완전히 다른 결과를 냅니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
a = tf.constant([[1.0, 2.0], [3.0, 4.0]])
b = tf.constant([[5.0, 6.0], [7.0, 8.0]])
# 요소별 연산 (Element-wise operations)
add = tf.add(a, b) # 또는 a + b
sub = tf.subtract(a, b) # 또는 a - b
mul = tf.multiply(a, b) # 또는 a * b (요소별 곱)
div = tf.divide(a, b) # 또는 a / b
print(f"요소별 곱: \n{mul}")
# 행렬 곱셈 (Matrix multiplication)
matmul = tf.matmul(a, b) # 또는 a @ b
print(f"행렬 곱: \n{matmul}")
# 수학 함수들
square = tf.square(a) # 제곱
sqrt = tf.sqrt(a) # 제곱근
exp = tf.exp(a) # 지수 (e^x)
log = tf.math.log(a) # 자연로그
# 집계 연산
sum_all = tf.reduce_sum(a) # 전체 합
mean_all = tf.reduce_mean(a) # 전체 평균
max_val = tf.reduce_max(a) # 최댓값
김개발 씨가 처음 마주친 혼란은 곱셈에서 시작되었습니다. a * b를 했는데 예상과 다른 결과가 나왔습니다.
박시니어 씨가 웃으며 말했습니다. "요소별 곱셈과 행렬 곱셈을 헷갈린 거야." **요소별 연산(element-wise)**은 같은 위치의 원소끼리 계산하는 것입니다.
마치 두 반의 학생들이 짝을 지어 경쟁하는 것과 같습니다. 1번 학생은 1번끼리, 2번은 2번끼리.
tf.multiply(a, b)나 a * b는 요소별 곱셈입니다. a의 (0,0) 위치 값과 b의 (0,0) 위치 값을 곱합니다.
결과의 shape은 입력과 같습니다. 반면 행렬 곱셈은 완전히 다릅니다.
tf.matmul(a, b)나 a @ b를 사용합니다. 행렬 곱셈은 첫 번째 행렬의 행과 두 번째 행렬의 열을 내적합니다.
선형대수의 규칙을 따르며, shape도 달라집니다. (m, n)과 (n, k)를 곱하면 (m, k)가 됩니다.
위의 코드에서 같은 텐서 a, b에 대해 tf.multiply와 tf.matmul의 결과를 비교해보세요. 숫자가 완전히 다릅니다.
이 차이를 모르면 신경망 구현에서 큰 실수를 하게 됩니다. TensorFlow는 다양한 수학 함수도 제공합니다.
tf.square는 제곱, tf.sqrt는 제곱근, tf.exp는 지수 함수입니다. 딥러닝에서 자주 쓰이는 함수들이니 익숙해지세요.
집계 연산도 중요합니다. tf.reduce_sum은 모든 원소의 합을, tf.reduce_mean은 평균을 계산합니다.
손실 함수를 계산할 때 자주 사용됩니다. axis 매개변수를 지정하면 특정 축을 따라 집계할 수도 있습니다.
실무에서 신경망을 구현할 때, 가중치와 입력의 연산은 대부분 행렬 곱셈입니다. 활성화 함수 적용은 요소별 연산입니다.
이 구분을 명확히 하면 코드를 읽고 쓰기가 훨씬 수월해집니다. 김개발 씨는 이제 곱셈 기호를 볼 때마다 "요소별인가, 행렬인가?"를 먼저 생각하게 되었습니다.
작은 차이가 큰 결과의 차이를 만든다는 것을 배웠습니다.
실전 팁
💡 - 행렬 곱셈은 @ 연산자로 간결하게 쓸 수 있습니다 (Python 3.5+)
- tf.reduce_sum(a, axis=0)처럼 axis를 지정하면 특정 축만 합산합니다
5. Broadcasting 이해하기
김개발 씨가 이상한 코드를 발견했습니다. shape이 다른 두 텐서를 더하는데 오류가 안 납니다.
"아까는 shape이 맞아야 한다면서요?" 박시니어 씨가 미소 지으며 말했습니다. "Broadcasting이라는 마법이 있거든."
Broadcasting은 shape이 다른 텐서들 사이에서 연산을 가능하게 해주는 규칙입니다. 작은 텐서가 자동으로 확장되어 큰 텐서와 같은 shape이 됩니다.
불필요한 메모리 복사 없이 효율적으로 연산을 수행할 수 있습니다. NumPy의 Broadcasting 규칙과 동일합니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
# 기본 Broadcasting: 스칼라와 텐서
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
scalar = tf.constant(10)
result = tensor + scalar # 모든 원소에 10이 더해짐
print(f"스칼라 Broadcasting:\n{result}")
# 벡터와 행렬의 Broadcasting
matrix = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
row_vector = tf.constant([10, 20, 30]) # shape: (3,)
col_vector = tf.constant([[100], [200], [300]]) # shape: (3, 1)
# 행 벡터는 각 행에 더해짐
row_result = matrix + row_vector
print(f"행 벡터 Broadcasting:\n{row_result}")
# 열 벡터는 각 열에 더해짐
col_result = matrix + col_vector
print(f"열 벡터 Broadcasting:\n{col_result}")
# Broadcasting 규칙 확인
# 뒤쪽 차원부터 맞춰가며, 1이거나 같으면 호환됨
김개발 씨는 코드를 보면서 혼란스러워졌습니다. (3, 3) 텐서에 (3,) 텐서를 더했는데 오류 없이 결과가 나옵니다.
분명히 shape이 다른데 어떻게 가능한 걸까요? 박시니어 씨가 설명했습니다.
"Broadcasting을 이해하려면 복사기를 떠올려봐." Broadcasting은 마치 복사기와 같습니다. 작은 종이를 복사해서 큰 종이 크기에 맞추는 것처럼, 작은 텐서를 자동으로 복제해서 큰 텐서와 같은 shape으로 만들어줍니다.
실제로 메모리를 복사하지는 않고, 연산 시에만 그렇게 동작합니다. Broadcasting의 규칙은 간단합니다.
두 텐서의 shape을 오른쪽(뒤쪽)부터 비교합니다. 각 차원이 같거나, 둘 중 하나가 1이면 호환됩니다.
호환되면 작은 쪽이 자동으로 확장됩니다. 코드를 보겠습니다.
scalar는 shape이 ()입니다. 어떤 텐서와도 호환됩니다.
tensor + scalar를 하면 scalar가 tensor의 모든 위치에 더해집니다. row_vector의 shape은 (3,)입니다.
matrix의 shape (3, 3)과 비교하면, 뒤에서부터 맞춰서 (3,)과 (3,)이 같으므로 호환됩니다. row_vector가 각 행에 반복 적용됩니다.
col_vector의 shape은 (3, 1)입니다. (3, 3)과 비교하면, 첫 번째 차원 3은 같고, 두 번째 차원 1은 3으로 확장됩니다.
결과적으로 col_vector가 각 열에 반복 적용됩니다. Broadcasting이 없었다면 어떻게 해야 할까요?
직접 tf.tile()로 텐서를 복제해야 합니다. 코드가 길어지고, 메모리도 낭비됩니다.
Broadcasting 덕분에 이런 수고를 덜 수 있습니다. 하지만 주의할 점이 있습니다.
Broadcasting이 예상치 못하게 적용되면 버그를 찾기 어렵습니다. (4, 3) 텐서와 (4,) 텐서를 더하면 오류가 납니다.
뒤에서부터 비교하면 3과 4가 다르기 때문입니다. 이런 상황에서는 명시적으로 reshape을 해주어야 합니다.
김개발 씨는 Broadcasting 규칙을 메모해두었습니다. "오른쪽부터 비교, 같거나 1이면 OK!" 이 규칙만 기억하면 shape 오류를 훨씬 쉽게 해결할 수 있습니다.
실전 팁
💡 - Broadcasting이 의도대로 동작하는지 확인하려면 결과의 shape을 출력해보세요
- 헷갈리면 tf.broadcast_to()로 명시적으로 확장하는 것도 방법입니다
6. NumPy와의 상호 변환
김개발 씨는 기존에 NumPy로 작성된 코드를 TensorFlow로 마이그레이션해야 했습니다. "전부 다 새로 짜야 하나요?" 걱정이 앞섰습니다.
박시니어 씨가 말했습니다. "걱정 마, TensorFlow와 NumPy는 찰떡궁합이야."
TensorFlow와 NumPy는 매우 긴밀하게 연동됩니다. numpy() 메서드로 Tensor를 NumPy 배열로 변환하고, **tf.convert_to_tensor()**로 NumPy 배열을 Tensor로 변환합니다.
대부분의 TensorFlow 연산은 NumPy 배열을 직접 받을 수도 있습니다. 기존 NumPy 코드를 활용하면서 점진적으로 TensorFlow로 전환할 수 있습니다.
다음 코드를 살펴봅시다.
import tensorflow as tf
import numpy as np
# NumPy 배열 생성
np_array = np.array([[1, 2, 3], [4, 5, 6]])
print(f"NumPy 배열: {type(np_array)}")
# NumPy -> Tensor 변환
tensor = tf.convert_to_tensor(np_array)
print(f"Tensor로 변환: {type(tensor)}")
# Tensor -> NumPy 변환
back_to_numpy = tensor.numpy()
print(f"다시 NumPy로: {type(back_to_numpy)}")
# TensorFlow 연산에 NumPy 배열 직접 사용
result = tf.add(np_array, tensor) # NumPy와 Tensor 혼합 가능
print(f"혼합 연산 결과: {result}")
# 주의: GPU Tensor는 .numpy() 전에 CPU로 이동 필요
# cpu_tensor = gpu_tensor.cpu().numpy() # GPU 사용 시
# NumPy의 편리한 기능 활용
np_random = np.random.randn(3, 3)
tensor_from_random = tf.constant(np_random)
김개발 씨의 팀에는 NumPy로 작성된 데이터 전처리 코드가 많았습니다. 이걸 모두 TensorFlow로 다시 작성해야 한다면 엄청난 작업량입니다.
다행히 TensorFlow는 NumPy와 아주 잘 어울립니다. 박시니어 씨가 비유했습니다.
"NumPy와 TensorFlow는 같은 언어를 쓰는 이웃 나라야. 통역 없이도 대화가 돼." 변환은 간단합니다. NumPy 배열을 Tensor로 바꾸려면 tf.convert_to_tensor()를 사용합니다.
반대로 Tensor를 NumPy 배열로 바꾸려면 .numpy() 메서드를 호출합니다. 더 놀라운 것은 대부분의 TensorFlow 연산이 NumPy 배열을 직접 받아들인다는 점입니다.
tf.add(np_array, tensor)처럼 NumPy와 Tensor를 섞어서 연산할 수 있습니다. TensorFlow가 내부적으로 자동 변환을 해줍니다.
코드를 보면, np_array와 tensor를 tf.add로 더하고 있습니다. 타입이 다른데도 오류 없이 동작합니다.
이런 유연성 덕분에 기존 NumPy 코드를 조금씩 TensorFlow로 전환할 수 있습니다. 주의할 점도 있습니다.
GPU에서 실행 중인 Tensor는 바로 .numpy()를 호출할 수 없습니다. 먼저 CPU로 데이터를 가져와야 합니다.
GPU 연산의 장점을 살리려면 변환을 최소화하는 것이 좋습니다. 또한 변환 시 데이터가 복사됩니다.
대용량 데이터를 자주 변환하면 메모리와 성능에 영향을 줄 수 있습니다. 가능하면 한 번 변환한 후 해당 형식으로 계속 작업하는 것이 효율적입니다.
실무에서는 데이터 로딩과 전처리는 NumPy로, 모델 학습은 TensorFlow로 하는 패턴이 흔합니다. 이 두 라이브러리의 장점을 모두 활용할 수 있습니다.
김개발 씨는 기존 NumPy 코드를 그대로 활용하면서 필요한 부분만 TensorFlow로 전환하기로 했습니다. "전부 다시 짤 필요가 없어서 다행이네요!"
실전 팁
💡 - 대용량 데이터는 변환 횟수를 최소화하세요
- GPU Tensor를 NumPy로 변환할 때는 .cpu().numpy() 패턴을 기억하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.