관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

텐서플로 4 - 인덱싱과 형태 변환 그리고 자동 미분까지 본문

인공지능/딥러닝

텐서플로 4 - 인덱싱과 형태 변환 그리고 자동 미분까지

huenuri 2024. 10. 4. 12:27

이번에는 인덱싱과 형태 변환에 대해서 학습해보려고 한다.


 

 

 

1. 인덱싱(indexing)

텐서를 구성하는 개별 원소의 위치 인덱스를 기준으로 원소를 추출하는 인덱싱 방법은 라이썬 리스트나 넘파이 배열 인덱싱 방법과 비슷하다. 

 

먼저 1차원 벡터의 인섹싱 방법을 알아본다. 숫자 원소 벡터를 정의하고 constant 함수에 파이썬 리스트를 입력하면 1차원 벡터 텐서로 변환된다.

 

 

텐서플로에서의 인덱싱은 넘파이 등의 인덱싱과 비슷하다.


 

 

 

대괄호 안에 [행 인덱스 범위, 열 인덱스 범위]와 같이 인덱스 범위를 지정하여 슬라이싱 방식을 적용할 수 있다. 랭크 3 이상의 고차원 텐서의 인덱싱은 2차원 구조인 행렬 텐서의 개념을 확장하여 처리한다. 먼저 다음 코드와 같이 (2, 2, 3) 크기의 텐서를 정의한다.


 

 

 

 


 

 

 

 

2. 형태 변환(tf.reshape)

예제를 통해 텐서 형태를 변환하는 방법을 알아본다. 먼저 숫자 0~23까지 24개의 원소를 갖는 랭크-1 텐서를 정의한다. 원소 24개를 갖는 1차원 벡터가 된다.

 

 

 

크기를 자유롭게 변환할 수 있다.


 

 

 

 

2 대신에 -1을 넣어도 같은 형렬이 출력된다.


 

 

 

 

3. 변수(tf.variable)

이번에는 텐서플로 변수의 기본 개념을 익혀본다. 텐서플로를 활용하여 딥러닝 모델을 만들고 학습할 때, 텐서플로 변수를 활용하면 정교하게 연산을 제어할 수 있다. 특히 딥러닝 모델의 가중치와 학습률처럼 모델 학습 및 추론 과정에서 값이 변경되는 경우 변수를 활용한다.

텐서플로는 그래프 구조를 이용하여 복잡한 미분 연산을 한다. 이때 수많은 미분 연산을 반복하게 되는데 각각의 중앙 연산 결과를 저장할 때 변수를 이용한다. 모델을 학습하는 중간 단계마다 모델의 가중치 행렬을 변수에 저장하고, 계산을 반복하면서 변수의 값을 업데이트한다.

 

또한 최적화 알고리즘을 적용할 때 모델이 학습하는 속도를 정하는 학습률을 지정하는 데도 사용된다. 최적화란 모델에 적용되는 학습률을 조금씩 바꾸면서 최적의 결과를 찾는 과정을 말한다. 이때 변수는 변화하는 학습률 값을 저장하게 된다. 

다음 예제는 텐서플로 변수를 정의하고 여러 가지 속성을 확인하는 방법에 대한 것이다.

 

 

텐서를 Variable 함수에 입력하면 텐서플로 텐서플로 변수가 생성된다. 여기서 입력 텐서는 텐서플로 변수의 초기값이 된다.


 

 

 

assign() 메소드를 이용하면 텐서플로 변수에 새로운 데이터를 할당할 수 있다. 단, 주의할 점은 입력하는 배열의 크기와 자료형이 원래 변수의 크기와 자료형과 동일해야 한다.


 

 

 

 

convert_to_tensor() 함수를 이용하면, 텐서플로 변수를 텐서로 변환할 수 있다. 텐서로 변환하고 나면, 텐서의 크기와 저장하고 있는 값을 변경할 수 없다. 

텐서플로는 name 속성을 갖는다. 연산을 처리할 때 텐서플로 변수가 저장하고 있는 텐서 값을 사용한다.


 

 

 

4. 자동 미분(Automatic Differentiation)

텐서플로는 딥러닝 모델을 구성하는 복잡한 인공 신경망의 각 노드에서 계산되는 미분을 자동으로 계산해 준다. 특히 각 변수의 기울기에 해당하는 그래디언트(gradient)를 계산하는데 특화되어 있다.

다음 예제는 Y = 3X - 2 함수식으로 표현되는 X, Y 데이터를 가지고 기울기와 y 절편 값을 텐서플로 자동 미분을 통해서 계산하는 과정을 볼 수 있다.

 

 

먼저 데이터셋을 생성한다. tf.random 모듈의 Generator를 활용해서 정규분포를 갖는 10개의 숫자 데이터를 추출하여 변수 X에 저장한다. Y 변수는 선형 함수식을 만족하는 값을 대입한다.

 

 

 

 

딥러닝 모델 학습은 모델이 예측하는 값과 실제 값(Y)의 차이(손실, loss)를 최소화하는 모델의 계수(a)와 상수항(b)을 찾는 과정이다 반복적인 계산을 통해 모델의 계수와 상수항을 조금씩 바꿔가면서 손실을 최소화하는 값을 찾는다.

다음과 같이 MSE(평균제곱오차)를 계산하는 cal_mse 손실함수를 정의한다.

 

 

 

tf.GradientTape를 활용하면 텐서플로가 자동 미분하는 중간 과정을 모두 기록할 수 있다. 먼저 모델의 계수와 상수항에 대항하는 a, b 변수를 생성하고 초기값으로 0.0을 입력한다. 자동 미분은 모두 200번(에포크) 진행하고 20번마다 중간 계산 결과를 print 함수로 출력한다.

with 구문 안에서 cal_mse 함수로 계산한 결과는 mse 변수에 저장되고, gradient() 함수를 사용하여 저장되어 있는 미분값을 추출하여 딕셔너리 형태로 grad 변수에 저장한다.

 

 

 

손실을 나타내는 MSE를 낮추는 방헝으로 a, b 값을 계속 업데이트하고, 이 과정을 tape 객체에 기록하게 된다. 이 계산을 200번 가까이 반복해 주면, MSE는 0에 가까워지고 선형 함수식의 모수에 해당하는 a = 3, b = -2 값을 근사하는 것을 볼 수 있다.

 


 

 

 

학습을 마치고

사실 이 공부는 며칠 전에 하려고 했던 내용인데 딥러닝을 조금 공부하다가 이해가 되지 않기도 해서 머신러닝을 한번 더 복습하는 게 좋겠다는 생각이 들었다. 머신러닝을 복습하자 이제 딥러닝이 보였고 이 코드로 어느 정도 잘 이해할 수 있었다. 이제 딥러닝 공부에 집중해도 될 것 같다.