참고 블로그 : https://mozenworld.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EB%AA%A8%EB%8D%B8-%EC%86%8C%EA%B0%9C-1-%EC%84%A0%ED%98%95-%ED%9A%8C%EA%B7%80-%EB%AA%A8%EB%8D%B8-Linear-Regression

 

머신러닝 모델 소개 (1) - 선형 회귀 모델 (Linear Regression)

머신러닝 모델 소개 시리즈의 첫 번째 글입니다. 가장 대표적이면서도 기본적인 머신러닝 모델인 선형 회귀 모델 (Linear Regression model)을 소개하고, 파이썬의 Scikit-learn 라이브러리를 활용하여 실

mozenworld.tistory.com

 

선형 회귀란?

출처 : https://godongyoung.github.io/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D/2018/01/20/ISL-linear-regression_ch3.html

독립 변수와 종속 변수의 관계 설명에 있어 선형 방정식으로 나타낸 것이다.

다만, 독립 변수의 개수는 여러개여도 상관이 없으며 가장 대표적인 방법으론 least squared 방법이 쓰인다.

이는 곧 MSE를 최소화하는 계수를 구하는 것과 동일하다.

 

단순 선형회귀와 다중 선형 회귀 등이 있지만 이는 나중에 설명하도록 한다.

 

 

 

이제 scikit-learn을 이용하여 선형 회귀 모델을 연습해보자.

일단 scikit-learn을 install 해준다. (Google colab을 사용하면 설치가 필요없다.)

 

 

scikit-learn에서 제공하는 dataset 중 당뇨병 데이터 세트를 이용해보자.

 

(데이터 세트 관한 공식 documentation : https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_diabetes.html#sklearn.datasets.load_diabetes)

 

load_diabetes

Gallery examples: Release Highlights for scikit-learn 1.2 Gradient Boosting regression Plot individual and voting regression predictions Model Complexity Influence Model-based and sequential featur...

scikit-learn.org

해당 데이터 세트는 442명을 대상으로한 10가지 생리적 변화(나이, 성별 등)와 1년 후 질병 진행 지표가 있다.

 

return_X_y :

If True, returns (data,target)instead of a Bunch object. See below for more information about the data and targe tobject.

 

as_frame을 True로 하고 다시 뽑아보니 다음과 같이 column명이 나온다.

 

다음과 같이 8:2의 비율로 train / test set을 구분해주며

fit method를 통해 모델을 학습시킨다.

 

예측값 y_pred과 실제 값 y_test의 mean squared error를 구한다.

 

해당 plot 띄워보면 다음과 같다.

 

 

Linear Regression 관련 내용은 다음과 같다.

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html

 

LinearRegression

Gallery examples: Principal Component Regression vs Partial Least Squares Regression Plot individual and voting regression predictions Comparing Linear Bayesian Regressors Linear Regression Example...

scikit-learn.org

 

'ML & AI' 카테고리의 다른 글

Object Detection for All  (0) 2024.11.24
Machine-Learning in Github + etc  (0) 2024.06.06

선형 회귀와 자동 미분

  • 데이터에 대한 이해(Data Definition) : 학습할 데이터에 대해서 알아봅니다.
  • 가설(Hypothesis) 수립 : 가설을 수립하는 방법에 대해서 알아봅니다.
  • 손실 계산하기(Compute loss) : 학습 데이터를 이용해서 연속적으로 모델을 개선시키는데 이 때 손실(loss)를 이용합니다.
  • 경사 하강법(Gradient Descent) : 학습을 위한 핵심 알고리즘인 경사 하강법(Gradient Descent)에 대해서 이해합니다.

 

데이터에 대한 이해

- 훈련 데이터셋과 테스트 데이터 셋 : 훈련에 사용되는 데이터를 train dataset, 학습이 끝난 후 이 모델이 얼마나 잘 작동하는지 판별하는 데이터셋을 test dataset.

- x_train과 y_train은 맵핑되어야함.

 

가설 수립

- 머신러닝에서 식을 세울때 이를 가설이라고함. 이는 추정일수도, 경험에서 나오는 것일 수도 있음. 맞는 가설이 아니라면 계속 수정해나가면 됨.

- y = Wx + b 와 같은 형식 혹은 가설(hypothesis)의 h를 따서 H(x) = Wx + b라고도 표현.

- W를 가중치(Weight), b를 편향(bias)이라고함.

 

비용 함수(Cost function)에 대한 이해

- 비용 함수(cost function) = 손실 함수(loss function) = 오차 함수(error function) = 목적 함수(objective function)

 

출처 : https://wikidocs.net/53560

- 다음과 같은 그림에서 점 4개를 가장 잘 표현하는 직선이 무엇인지 수학적 근거가 필요. -> '오차'라는 개념 도입

- 단순 '실제값 - 예측값'으로 정의한다면 여러 문제가 생김 -> 그럼 오차는 어떻게 정의할 것인가.

-> 각 오차들을 전부 제곱해준 후 더하는 방식(MSE) 사용. (물론 다른 방법도 많지만 여기선 평균 제곱 오차 설명)

- 제곱을 하여 더해주면 음수의 데이터에 영향을 받지 않고, 각 오차가 클수록 더 심각하게 좋지 않다는 가중치의 의미도 부여.

Cost(W,b)를 MSE로 위와 같이 정의한다면 훈련 데이터를 가장 잘 나타내는 직선은 Cost(W,b)를 최소로 만드는 직선이다.

 

옵티마이저 - 경사 하강법(Gradient Descent)

- 위에서 어떤 경우가 가장 훈련 데이터를 잘 나타내는 경우인지 정의함 (cost function을 정의)

- 그럼 이제 그 최적의 cost function을 어떻게 찾을 것인가? => 옵티마이저(Optimizer) 알고리즘

 

가장 기본적인 옵티마이저 알고리즘인 경사 하강법

우선 b를 고려하지 않고 y = Wx와 같은 기준으로 진행. 해당 선형 방정식에서 W는 기울기임.

위 그림서 주황색선은 W=20, 초록색선은 W=1일 때의 case.

-> 기울기가 너무 커도 오차가 커지고, 너무 작아도 오차가 커짐.

x축 : Weight, y축 : cost

=> 그럼 그 중간 어딘가에서 오차가 제일 작아지는 지점이 있을 것임. (위 사진 파란선 참조)

=> 함수의 극소점의 향해 가도록 해야함. -> 이것이 경사 하강법의 아이디어.

 

경사 하강법의 아이디어는 비용 함수를 미분하여 현재 W에서 접선의 기울기를 구하고, 접선의 기울기가 낮은 방향으로 W값을 변경하는 작업을 반복하는 것. 이 반복 작업서 특정 숫자 알파를 곱해 새로운 W로 사용하는 방식.

 

Case 1. 만일 기울기가 음수라면

=> W값이 증가하여 기울기가 0인 방향으로 조정 됨.

 

Case 2. 만일 기울기가 음수라면 

=> W값이 감소하여 기울기가 0인 방향으로 조정 됨.

 

여기서 '알파'라고 하는 곱해지는 특정 숫자는 학습률(learning rate)라고 한다. 이를 먼저 생각해보면 W에 gradient 값을 빼가며 반복 작업을 할 것인데, 어느 정도의 scale로써 점차 맞춰 나갈지에 대한 변수이다. 만일 너무 크다면 수렴하지 않고 발산하거나, 추후 특정 구간 내에서 반복한다고 하여도 이 구간이 충분히 작지 못할 수 있다. 만일 learning rate가 너무 작다면 수렴을 하는 것에 있어선 안정적일 수 있지만 학습에 시간이 많이 소요되고 불필요하게 리소스를 낭비할 수 있다. 이런 적당한 learning rate을 찾아내는 것도 중요할 것 같다.

 

파이토치로 선형 회귀 구현하기

필요한 라이브러리들을 import 한 후 추후 동일하게 실습을 하더라도 같은 결과 출력을 위해 random seed를 준다.

(110은 내 생일이다.)

 

Float type tensor에 train dataset을 만든 후 shape을 print해보자.

x train set과 y train set의 size는 모두 3X1임을 알 수 있다.

 

가중치와 편향의 초기화

선형 회귀는 학습 데이터와 가장 잘 맞는 하나의 직선을 찾는 일

그리고 가장 잘 맞는 직선을 정의하는 것이 바로 W와 b이다.

(여기서 하나 빠뜨린 점이 있는데 '가장 잘 맞는'이라는 것 또한 정의가 되어야 한다. 맥락상으론 MSE가 최소일때를 말한다.)

 

가중치 W를 0으로 초기화 하고 requires_grad=True가 인자를 통해 학습을 통해 값이 변경되는 변수임을 명시.

마찬가지로 편향 b도 0으로 동일하게 세팅.

현재 세팅에선 다음과 같은 직선이 표현되고 있으며 x에 어떤 값이 들어가도 0을 예측하게 됨.

 

파이토치 코드 상으로 직선의 방정식에 해당하는 가설 선언

 

가설(직선의 방정식)을 선언하였으니 비용 함수 또한 선언 필요.

다음과 같은 MSE를 나타내는 cost function을 선언.

(여기서 좋은 점. Summation의 과정이 필요 없이 각 torch에 대한 element-wise하게 뺄셈이 수행되고 각 element에 대해 square값이 적용된다. 또한 그렇게 만들어진 하나의 tensor(사실 아직도 array로 생각하는게 편하긴 하다)에 대해 mean값을 구해주게 되어 cost function의 value가 print out 되는 듯. 만일 이게 아니라면 for-loop를 통해 n에 대한 loop를 돌려주며 각 개체에 value를 update하는 식으로 했어야되지 않을까 ... 그렇지만 torch가 없었다면 np를 사용하면 torch와 사실상 동일하긴 했을듯)

 

지금까지 한 일.

x, y train set 정의, hypothesis 선언, cost function 선언.

train set의 dataset에 대해 현재의 방정식은 이정도의 loss를 가짐. 까지 왔다.

그럼 이제 이 크나큰 loss를 점차 이런 방법으로 개선하여 hypothesis를 수정하는 방식을 반복 필요.

 

경사 하강법 구현

SGD는 경사 하강법의 일종.

(찾아보니 BGD(배치 경사 하강법), SGD(확률적 경사 하강법), MGD(미니배치 경사 하강법)이 있다. 이 부분도 추가적 공부 필요)

출처 : https://bruders.tistory.com/91

 

학습 대상인 W와 b가 SGD의 입력이 되며 lr은 Learning Rate를 의미.

 

zero_grad()를 실행하여 미분을 통해 얻은 기울기를 0으로 초기화 한다는데 이부분은 뒤에서 추가 설명.

cost.backward() 함수 호출을 통해 가중치 W와 b에 대한 기울기가 계산 된다는데 어떤 의미인지 모르겠음.

(이 부분 추가 공부 필요. 참고 1. : https://hongl.tistory.com/158#google_vignette , 참고 2. https://deepdata.tistory.com/1166#google_vignette 이해한 바로는 computational graph에서 역전파(backpropagation) 관한 내용인 것 같은데 CS231n에서 나와서 이해가 조금 편했던 것 같다. 근데 우선은 가볍게 이정도가 있다 ~ 로만 알고 넘어가도록 하자. 알고보니 뒤쪽에서 별도 정리가 되어있다고한다.)

 

전체 코드

  1. 데이터 train set을 정의하고
  2. 기본 hypothesis를 W=0, b=0으로 세팅을 해두고
  3. optimizer에 대해 SGD의 method를 사용할 것이며, W와 b에 대해 최적화를 이룰 것이다. lr은 0.01로 할 것이다.
  4. 그 후 epoch를 설정해주며 얼마나 반복할 것인지를 정한다.
  5. for문에서 해당 횟수만큼 반복을 하며 점차 W와 b의 값을 변화시켜 나간다.

좌측부터 순서대로 lr = 0.01일때, 0.0001일때, 0.5일때

동일한 횟수의 epoch를 기준으로 lr을 다르게 설정함에 따라 최적화 되는 정도가 다르거나 아예 발산해버림을 알 수 있다.

이는 learning rate의 적당한 수치 조절이 중요함을 알 수 있다.

 

실 정답은 H(x) = 2x이므로 0.01일때 가장 근접한 정답을 알 수 있다.

(혹은 epoch를 1만회 이상으로 증가시키면 더 근접한 정답을 얻을 수 있다.)

 

optimizer.zero_grad()가 필요한 이유

미분값인 2가 계속 누적되는 것을 볼 수 있음.

따라서 zero_grad()를 통해 계속 0으로 초기화 시켜주어야함.

 

torch.manual_seed()를 하는 이유

 
좌측부터 순서대로 실행한 코드.
이는 random하게 난수를 발생시켜도 seed 값을 동일하게 유지하면 이전과 동일한 값을 얻을 수 있음.
 
 
 
 

자동 미분(Autograd) 실습

requires_grad = True가 적용된 텐서에 연산을 하면 계산 그래프가 생성된다 !

backward 함수를 호출하면 그래프로부터 자동으로 미분 계산

 

원래는 8이 나오는 과정은 다음과 같다.

각 변수에 대한 미분과 Chain Rule을 이용하면 다음의 순서를 따른다.

(이전에 CS231n 강의에서 다음과 비슷한 compuatational Graph가 있을 때 그냥 수학적 계산을 하면 안되는 것인가 물어본 학생이 있었는데 각 node끼리 연결된 과정에서 multiple or addition만 적용된 경우 단순 연산의 차원을 쭉 내려 연산하는 것이 수행 능력이 더 좋았다고 들었던 것 같다.)

 

 

다중 선형 회귀(Multivariable Linear Regression)

위에서 진행한 것은 모두 1개의 x에 의해 y를 추론하는 단순 선형 회귀 였음.

하지만 x가 1개가 아닌 여러개가 될 경우 사용하게 될 다중 선형 회귀에 대해 이해해보자.

다음과 같이 3개의 퀴즈 점수로부터 최종 점수를 예측하는 모델을 만들어보자.

hypothesis는 다음과 같을 것이다.

 

다음과 같이 필요한 것들을 import 한 후 train data들을 정의해준다. 그 후 가중치와 bias에 대해 0으로 초기화 해준다.

(TMI : 일상생활에서 초기화는 어떤 존재하는 값을 없애는 느낌이 크지만, CS에서는 '무언인가를 초기에 준비시키는 것'이라는 의미로 쓴다. 따라서 초깃값 세팅의 의미로 생각하면 된다.)

 

다음과 같이 선언한 후 1만회 반복을 통해 최적값을 찾는다.

 

(Q. 여기서부터 갑자기 궁금한 점이 생겼다. zero_grad()를 통해 누적값이 안 생기도록 계속 0으로 초기화까진 이해 되었다. 다만, backward()를 통해 어떤 작업을 하는 것인가 ? GPT한테 물어보니 각 변수 w1, w1에 grad 속성에 기울기 값을 저장한다고 한다. 그 후 step()단계에서 파라미터 업데이트를 진행한다고 한다. 여기까지도 순서에 대한 이해 자체는 되었다. 다만, Single Variable이 아닌 Multi variable일 때 과연 Cost Function의 Optimize는 어떻게 진행되는가. 각 cost function에 대한 편미분으로 grad값이 진행되어 각 파라미터들은 자신의 grad값에만 영향을 받는가 ? => GPT피셜 Yes. (만일 그렇다면 learning rate를 변수마다 다르게 지정하여 더 최적화 할 수 있지 않을까). 또한 자신의 grad값으로만 update가 된다면 과연 그것이 정말 옳은 방향으로서 업데이트가 된다고 생각할 수 있을까. 이는 다시 gradient의 정의까지 가게 되는 것 같아서 나중에 다시 공부해봐야될듯.
참고자료 : https://www.humanunsupervised.com/post/linear-regression-multivariate-cost-function-hypothesis-gradient

=> 크게 각 Weight에 대한 update 방향을 1. 그래프로, 2. computational graph로, 3. Cost function의 정의로 이해하였지만 1, 2는 이해 완료. 3은 나중에 다시 생각해보자.)

 

 

벡터와 행렬 연산으로 바꾸기

 

여기서 issue 발생. 현재는 3개라는 매우 적은 controlable한 개수이지만 이가 만일 100만개와 같이 늘어나게 된다면 우리는 하나하나 변수 선언과 다 해줄 것인가 ? no. 또한 컴퓨터적 연산 계산에 있어서도 비효율적.

 

1) 벡터 연산으로 이해

의 가설은

와 같이 이해할 수 있고 각 벡터를 X와 W로 표현한다면 H(X) = XW로 나타낼 수 있다.

 

2) 행렬 연산으로 이해

와 같이 나타낼 수 있다.

 

 

파이토치로 재구현

다음과 같이 train set 작성 및 출력.

Weight Matrix는 결국 최종적으로 5X1이 나와야되니 3X1 size여야하고

b도 5X1이어야되는거 아닌가 ? 라고 생각했지만 어차피 브로드캐스팅이 잘 되겠구나 싶었다.

 

실제로 b의 크기를 정의 해주지 않았을 때와 정의를 해주었을 때 다음과 같이 차이가 난다. 왜 ?

 

기존의 hypothesis에서는 단순 상수의 b이다. 이를 Matirx연산을 위해 사이즈를 맞춰준 것이지 사실은 동일한 하나의 상수이다.

만일 b를 (5,1)로 두게 된다면 각 equation에서 b가 각각 optimized 되게 된다.

그래서 그냥 size를 두지 않는 것이 의도에 부합한 방법인듯.

 

이제 train된 model을 사용하여 어떤 Input이 들어왔을 때 output을 출력해보자.

 

사실 python에서 with문을 처음 보았다.

(물론 항상 쓰는 건 SQL이도 내용이 완전히 다르지만 ,,)

 

GPT피셜

 

  • 컨텍스트 관리자(Context Manager): with 문은 파이썬의 컨텍스트 관리자를 사용할 때 쓰입니다.
  • 목적: 특정 블록 내에서 리소스의 초기화 및 해제를 자동으로 관리합니다.

구문

 

with 컨텍스트_관리자:
    코드_블록

 

예시

with open('file.txt', 'r') as f:
    data = f.read()

와 같다고 한다.

 

with torch.no_grad(): 이 블록 안에서 수행되는 모든 연산에 대해 역전파(즉, 기울기 계산)를 비활성화

예측을 할 때는 가중치를 업데이트할 필요가 없기 때문에, 메모리와 계산 자원을 절약하기 위해 torch.no_grad()를 사용하는 것이 좋음.

 

nn.Module과 클래스로 구현하기

pytorch에서는 이미 구현되어져 제공되는 함수들이 많이 존재. 해당 제공되는 함수들을 불러와 구현해보자.

 

단순 선형 회귀

2개의 값이 출력되는데 첫번째가 W값이고 두번째가 b에 해당된다.

두 값 모두 현재는 랜덤 초기화가 되어 있다. 또한, 두 값 모두 학습의 대상이기에 requires_grad=True가 되어있음.

 

그 후, 옵티마이저를 정의. model.parameters()를 사용하여 W와 b를 옵티마이저에 전달.

W값이 2에 가깝고, b값이 0에 가까우며 학습이 잘 된 것을 확인 가능.

 

forward vs backward 연산

- H(x)식에 입력 x로부터 예측된 y를 얻는 것 -> forward 연산

- 학습 전, prediction 은 x_train으로부터 예측값을 리턴하므로 forward 연산

- 학습 후, pred_y 는 임의의 값 new_var로부터 예측값을 리턴하므로 forward 연산

- 학습 과정에서 cost function을 미분하여 기울기를 구하는 것 backward 연산

- cost.backward()는 비용함수로부터 기울기를 구하라는 의미이며 backward 연산

 

다중 선형 회귀 구현

train dataset 정의 및 model 선언.

model.parameters를 list로 변환했을 때 length는 2개인데 앞에 것에 들어있는 3개의 수는 w1~w3이며, 뒤의 것은 b이다.

모두 랜덤 초기화가 되어있으며 학습값이기에 requires_grad=True로 되어있음.

 

(learning rate은 0.00001로 정의. 만일 0.01로 하게 된다면 발산함)

-> 그럼 이 발산의 기준을 미리 파악할 수는 없을까 ? 적당한 learning rate을 설정하는 것의 기준이 있으려나.

 

또한 이하의 코드는 단순 선형 회귀와 동일.

x에 임의의 입력 [73, 80, 75]를 넣어 모델이 예측하는 y값 출력.

사실 이 데이터는 학습 데이터에 포함되어있는 값임. 실제 값은 152였는데 예측값이 151에 가까운 값이 나온 것을 통해 어느 정도 잘 최적화 된 것으로 보임.

 

모델을 클래스로 구현하기

 

단순 선형 회귀 모델

대부분의 파이토치 구현체에서 위와 같이 클래스를 사용한 모델 구현 형식은 많이 사용하기에 꼭 숙지해두기 !

 

위 코드 설명

class형태의 모델은 torch.nn.Module을 상속 받음.

__int__() : 클래스의 생성자. 객체가 생성될 때 호출됨.

super().__init__() : 부모(torch.nn.Module)의 생성자를 호출하여 그 기능을 상속 받음.

self.linear = nn.Linear(1,1) : 선형 변환 정의.

forward() : 입력 데이터를 받아 모델의 연산을 수행.

 

다중 선형 회귀 모델

다음과 같이 구현.

 

다중 선형 회귀 클래스로 구현

기본 세팅 및 class로 다중 선형 회귀 구현.

 

MultivariateLinearRegressionModel라는 클래스는 pytorch의 nn.Module을 상속 받음.

클래스 초기화 메서드(__init__)에서 super()를 통해 부모 클래스의 nn.Module을 상속받으며 nn.Linear 객체를 생성하여 모델의 선형층을 설정함. 이는 input dim = 3, output dim=1로 설정되어있음.

 

코드는 이전과 다른 바가 없음.

 

옵티마이저 설정을 해주며, 여러 경사 하강법 중 확률적 경사 하강법인 SGD로 설정. 학습률 또한 적당히 작은 수로 설정.

 

에포크를 2,000으로 설정하며 그만큼 for-loop를 돌게 됨.

학습은 x_train을 사용하여 예측 값을 계산하는 것으로 시작 됨.

 

모델이 처음 만들어 질때 초기화 된 값들은 임의의 값들이지만 어차피 학습을 하며 점차 나아진다.

계속 똑같은 문제를 가지고 돌리며 더 근접한 prediction으로 수렴하게 되는 것이다.

 

코드 입장에선 이러한 임의의 수로 맨 처음 prediction을 진행하게 되고 실제 목표값인 y_train과 얼마나 차이가 나는지를 계산하게 된다. 이 오차는 MSE로 계산하게 된다.

모델은 cost function 기준으로 각 파라미터에 대한 기울기를 계산하여 파라미터 값들을 점차 업데이트 해나간다.

이를 통해 더 정확한 예측을 하게 된다.

 

더 정확한 예측을 위해선 epoch값을 늘리거나, Learning rate을 더 작게 설정해주며 (이 때 epoch값은 늘어나야한다.)하면 될듯.

 

미니 배치와 데이터 로더

이 부분은 선형 회귀에 한정되는 부분은 아니고 데이터를 로드하는 방법과 미니 배치 경사 하강법에 대해서 공부.

 

이전에 다중 선형 회귀에서 사용한 데이터의 샘플의 개수는 5개이다.

이를 하나의 행렬로 선언하여 전체 데이터에 대해 경사 하강법을 수행함.

 

근데 만일 학습 데이터가 엄청 커지게 된다면 이를 하나의 행렬로 만들어 경사 하강법을 진행할 수 있을까 ?

-> 계산량이 많아지며 매우 느리고, 메모리의 한계로 계산이 불가할 수 있다.

출처 :  https://wikidocs.net/55580

 

이러한 문제를 대체하기 위해 더 작은 단위로 쪼개 학습하는 개념 출현.

이 단위를 미니 배치(Mini Batch)라고 함.

 

러프하게 생각해봤을 때 미니 배치 : 작은 단위로 쪼개어 학습하기 때문에 메모리 할당에 이슈는 없을 듯. 만일 존재한다면 더 작은 단위로 쪼개면 되기 때문.

 

미니 배치 학습에서는 미니 배치의 개수만큼 경사 하강법을 수행해야 전체 데이터가 한 번 전부 사용되어 1 에포크가 됨.

미니 배치의 크기를 배치 크기(batch size)라고 함.

 

 

- 전체 데이터에 대해 한 번에 경사 하강법 수행 : 배치 경사 하강법

- 미니 배치 단위로 경사 하강법 수행 : 미니 배치 경사 하강법

+ 배치 크기는 보통 2 제곱수를 사용. CPU와 GPU의 메모리가 2의 배수이므로 배치 크기가 2의 제곱수일 때 데이터 송수신의 효율을 높일 수 있기 때문.

 

이터레이션(Iteration)

출처 : https://wikidocs.net/55580

위 그림은 에포크와 batch size와 iteration의 관계를 보여줌.

이터레이션은 한 번의 에포크 내에서 이루어지는 매개변수인 Weight W와 bias b의 업데이트 횟수

전체 size가 2,000인데 batch size를 200으로한다면 iteration의 수는 10개.

-> 이는 한 번의 에포크 당 매개변수 업데이트가 10번 이루어짐을 의미함.

(사실 Mini batch로 쪼개며 update를 어느 시점에 하는가에 대한 의문이 있었는데 위 내용으로 풀림.)

 

데이터 로드하기(Data Load)

파이토치에서는 데이터셋(Dataset)과 데이터 로더(Data Loader)를 제공.

-> 이를 통해 미니 배치 학습, 데이터 셔플(shuffle), 병렬 처리까지 간단히 수행 가능.

TensorDataset은 텐서를 입력으로 받음. 이를 입력으로 정의 후 dataset으로 저장.

 

DataLoader는 기본적으로 2개의 인자를 입력 받음. 하나는 데이터셋, 하나는 미니 배치의 크기.

+  추가로 많이 사용되는 인자는 shuffle. shuffle=True로 사용하면 Epoch마다 데이터셋을 섞어 학습되는 순서를 바꿈.

모델과 옵티마이저를 정의 후 훈련 실행.

Cost 값이 점차 작아지긴 하지만 충분히 작지 않다 생각하여 epoch값을 늘려 다시 실행.

(이때 주의해야할 점이 모델과 옵티마이저를 다시 정의 해주고 가야지 아니면 이전 모델에 추가로 학습하는 꼴이다.)

 

epoch를 2,000까지 늘린 후 실행했을 때의 결과. 그 후 임의의 값을 넣어 예측.

 

커스텀 데이터셋(Custom Dataset) & 커스텀 데이터셋으로 선형 회귀 구현

torch.utils.data.Dataset을 상속받아 직접 커스텀 데이터셋(Custom Dataset)을 만드는 경우도 있음.

Dataset을 상속받아 메소드들을 오버라이드 하여 커스텀 데이터셋을 만들어보자.

가장 기본적인 뼈대

위 코드는 Pytorch의 Dataset 클래스를 상속받아 사용자 정의 데이터셋 클래스를 만드는 방법.

해당 클래스는 두 가지 데이터 포함(x_data, y_data).

 

클래스가 초기화될 때, 이 두 데이터를 내부 변수로 저장. 데이터 셋의 길이를 반환하는 메서드가 정의되어 있음, 이는 해당 개수를 반환.

(이는 x_data에서 sample의 개수를 의미함.)

 

가장 중요한 메서드는 (__getitem__) 인덱스를 입력으로 받아 해당 인덱스에 맵핑된 데이터를 반환하는 것.

이 메서드는 x_data와 y_data의 특정 인덱스에 해당하는 데이터를 torch.FloatTensor 형식으로 변환하여 반환.

(기존에 __init__에서 넣은 것은 단순한 list type이었음.)

 

위 코드는 Customdataset 클래스를 인스턴스화 하여 데이터셋 객체(dataset)를 만듦.

이 데이터셋으로 Pytorch의 DataLoader 객체를 생성하며 기타 param 결정.

 

그 후, input dim = 3, output dim = 1인 선형 회귀 모델을 정의.

(갑자기 든 생각인데 output dimension이 2 이상이면 어떨까. 또한 어떤 예시가 있을까)

또한, 옵티마이저 설정. 항상 하던대로 SGD 사용.

nb_epochs = 20
for epoch in range(nb_epochs + 1):
  for batch_idx, samples in enumerate(dataloader):
    # print(batch_idx)
    # print(samples)
    x_train, y_train = samples
    # H(x) 계산
    prediction = model(x_train)

    # cost 계산
    cost = F.mse_loss(prediction, y_train)

    # cost로 H(x) 계산
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    print('Epoch {:4d}/{} Batch {}/{} Cost: {:.6f}'.format(
        epoch, nb_epochs, batch_idx+1, len(dataloader),
        cost.item()
        ))

그 후 이전과 동일한 코드로 학습.

 

nb_epochs : 전체 학습 횟수.

해당 횟수만큼 반복문을 돌리며, 그 내무에서 enumerate(dataloader):에서는 미니 배치 단위로 데이터를 가져와 모델을 학습 시킴.

데이터 로더에서 가져온 각 배치는 samples라는 변수에 저장되고 이를 x_train과 y_train으로 분리한다. samples는 길이가 2인 list type을 갖기에 다음과 같이 잘 찢어줄 수 있다.

 

모델은 prediction을 생성하고 해당 값의 MSE로 cost를 계산한다. 계산된 cost 값으 기반으로 모델의 가중치를 업데이트 하기 위해 기울기를 초기화 하고 (zero_grad), 손실에 대한 역전파를 수행하고(backward), 파라미터를 업데이트 한다.(step).

 

해당 for-loop 돌아가는 내부 데이터를 좀 더 확인해보자.

 

(enumerate() 함수는 기본적으로 인덱스와 원소로 이루어진 튜플(tuple)을 만들어줌. batch_idx는 torch나 기타 세팅에 의해 생성되는 것이 아닌 enumerate에서 tuple의 앞단 값을 찢어 만든 python 내장 함수 값임. 또한, samples가 shuffle=True로 했기에 잘 섞여들어가는 것을 볼 수 있다. 이 부분 False로 해보고 실행도 해보길..)

 

 

벡터와 행렬 연산 복습하기

이 단원도 써야할까 생각을 해보았지만, 항상 배우는 자세로 겸손하자.라 생각하여 쓴다.

 

배운 것 : 기본적인 epoch, mini batch, shuffle, customdataset class, dataload 등

 

벡터와 행렬과 텐서

추후 머신 러닝의 입, 출력이 복잡해지며 3차원 텐서에 대한 이해가 필수로 요구됨. (ex. RNN)

 

numpy로 텐서 설명.

 

0차원, 1차원 텐서

스칼라 : 0차원 텐서, 0D tensor

ndim의 값에 주목. 이때 나오는 값이 축의 개수 or tensor의 차원이라고 부름. (이 내용 중요하답니다.)

혼동 주의할 부분. 위 벡터는 4차원이지만, tensor의 차원에선 1차원임. (텐서의 차원으론 [] 개수로 세는 것이 편할듯. 혹은 데이터 구조를 그냥 그대로 받아들이는 정도..)

주의 : 벡터의 차원은 하나의 축에 놓인 원소의 개수를 의미하는 것, 텐서의 차원은 축의 개수를 의미

 

2차원 텐서(행렬)

'행과 열'의 두 축이 존재하니 해당 텐서의 차원은 2차원.

shape(텐서의 크기)란 각 축을 따라서 얼마나 많은 차원지를 나타냄.

(큰 방향에서 가보면 3개의 list내에 4개의 데이터로 이루어져있기에 -> 3X4)

(만일 주로 3차원(텐서 dim기준)까지만 쓰인다면 matrix로 뻐팅겨도 괜찮을듯.)

 

3차원 텐서

! 이 부분 중요하니 잘 이해하고 넘어갈 것

자연어 처리(NLP)에서 자주 보게 되는 것이 다음의 3D tensor. 이는 시퀀스 데이터 표현서 자주 사용되기 때문.

예시로 3D는 (samples, timesteps, word_dim)이 된다.

추후 배치 개념에 대해서도 배울 때 (batch_size, timesteps, word_dim)과 같이 볼 수도 있다.

 

그 이상의 텐서

다음과 같다.

 

 

벡터와 행렬의 연산

다음과 같은 두 벡터가 (혹은 3X1 행렬이) 있다고 생각해보자.

해당 벡터에 대한 덧셈과 뺄셈 연산은 다음과 같이 element-wise하게 이루어진다.

 

행렬 또한 마찬가지다.

 

벡터의 내적과 행렬의 곱셈

내적은 dot product 혹은 inner product라고도 한다.

벡터 내적의 결과값으로는 스칼라 값이 나온다.

 

행렬의 곱셉은 딥 러닝을 이해하는 데에 필수적인 개념임으로 반드시 숙지 필요 !

추가로 다음의 두 가지 조건 또한 기억

  • 두 행렬의 곱 A × B이 성립되기 위해서는 행렬 A의 열의 개수와 행렬 B의 행의 개수는 같아야 한다.
  • 두 행렬의 곱 A × B의 결과로 나온 행렬 AB의 크기는 A의 행의 개수와 B의 열의 개수를 가진다.

(위 내용은 matrix의 dimension을 보며 생각하면 되겠다.)

 

다중 선형 회귀 행렬 연산으로 이해하기

다중 선형 회귀는 곧 2개 이상의 독립변수로부터 창출되는 종속 변수 1개를 예측하는 문제.

이를 행렬 연산으로 표현한다면 ?

다음과 같이 weight vector와 input vector에 대한 inner product + bias의 덧셈으로 이해할 수 있다.

 

이는 하나의 test case에 대한 얘기이고 만일 input(test set)이 많다면 ?

 

다음과 같이 얘기할 수 있다.

 

샘플(Sample)과 특성(Feature)

출처 : https://wikidocs.net/217269

Feature은 '특성'이라 생각하며 되고 독립 변수의 개수이다.

Sample의 수는 sample의 개수이다. (너무 당연한가)

 

가중치와 편향 행렬의 크기 결정

Weight Matrix와 input Matrix이 각각 몇 by 몇 이어야 하는 지에 대한 얘기이다.

너무 당연한 부분이라 넘어가도록..

 

추가로

입력 행렬과 출력 행렬의 크기로부터 가중치 행렬과 편향 행렬의 크기를 추정할 수 있다면, 딥 러닝 모델을 구현하였을 때 해당 모델에 존재하는 총 매개변수의 개수를 계산하기 쉽습니다. 어떤 딥 러닝 모델의 총 매개변수의 개수는 해당 모델에 존재하는 가중치 행렬과 편향 행렬의 모든 원소의 수이기 때문입니다.

보통 딥 러닝 모델의 매개변수 수로 AI 모델의 크기가 얼마나 크냐를 의미하고, 성능 또한 대략적으로 알 수 있다.

0. Pytorch(파이토치)란

파이토치는 2017년 초에 공개된 딥러닝 프레임워크로 개발자들과 연구자들이 쉽게 GPU를 활용하여 인공 신경망 모델을 만들고 학습시킬 수 있게 도와준다. 파이토치의 전신이라고 할 수 있는 토치(torch)는 루아 프로그래밍 언어로 되어 있었지만, 파이토치는 파이썬으로 작성되어 파이썬의 언어 특징을 많이 가지고 있다. 

 

파이토치는 페이스북의 인공지능 연구팀 멤버들이 주로 관리하며, 독자적으로 운영되는 파이토치 포럼은 사람들이 질문을 올리면 프레임워크 개발자를 비롯한 많은 사람이 답을 해주는 등 활발히 교류가 일어나고 있다.

 

참고 : https://jfun.tistory.com/238

 

Pytorch란?

1. 파이토치란 무엇일까? 출처 : 파이토치 첫걸음 - 최건호 파이토치는 2017년 초에 공개된 딥러닝 프레임워크로 개발자들과 연구자들이 쉽게 GPU를 활용하여 인공 신경망 모델을 만들고 학습시킬

jfun.tistory.com

 

1. 파이토치 패키지의 기본 구성

  • torch : 메인 네임스페이스입니다. 텐서 등의 다양한 수학 함수가 포함되어져 있으며 Numpy와 유사한 구조를 가집니다.
  • torch.autograd :자동 미분을 위한 함수들이 포함되어져 있습니다. 자동 미분의 on/off를 제어하는 콘텍스트 매니저(enable_grad/no_grad)나 자체 미분 가능 함수를 정의할 때 사용하는 기반 클래스인 'Function' 등이 포함되어져 있습니다.
  • torch.nn : 신경망을 구축하기 위한 다양한 데이터 구조나 레이어 등이 정의되어져 있습니다. 예를 들어 RNN, LSTM과 같은 레이어, ReLU와 같은 활성화 함수, MSELoss와 같은 손실 함수들이 있습니다.
  • torch.optim : 확률적 경사 하강법(Stochastic Gradient Descent, SGD)를 중심으로 한 파라미터 최적화 알고리즘이 구현되어져 있습니다.
  • torch.utils.data : SGD의 반복 연산을 실행할 때 사용하는 미니 배치용 유틸리티 함수가 포함되어져 있습니다.
  • torch.onnx : ONNX(Open Neural Network Exchange)의 포맷으로 모델을 익스포트(export)할 때 사용합니다. ONNX는 서로 다른 딥 러닝 프레임워크 간에 모델을 공유할 때 사용하는 포맷입니다.

 

2. 텐서 조작하기(Tensor Manipulation)

벡터, 행렬 그리고 텐서

기본적인 개념인 vector(벡터), matrix(행렬), tensor(텐서)에 관해 알아보자.

사실 본인 전공은 수학과(수리과학부)라 벡터와 행렬은 정말 익숙하다. 또한 차원 개념에 대해서도 편안하게 받아들여진다. 다만 딥러닝에서는 이를 '차원' 개념에서의 n-th dimension의 입장이 아닌 nd-tensor로 표기하며 이해한다. 사실 이는 다차원 행렬 혹은 다차원 배열과 동일하다.

 

(관련 도움이 될 포스트: https://coding-kindergarten.tistory.com/147)

 

출처 : https://wikidocs.net/231831

Tip

- [1,2,3]과 같은 1차원 tensor의 size는 3이다.

- [[1,2,3],[4,5,6]]과 같은 2차원 tensor의 사이즈는 (2,3)인지 (3,2)인지 헷갈리기 시작한다.

   => 항상 size를 확인할때는 바깥쪽의 괄호부터 카운팅한다. 결국 (2,3) 이다.

 

Tensor Example

출처 : https://wikidocs.net/52460

읽다보니 batch_size라는 것이 있다. 이 batch가 data 작업서 사용하는 batch처리와 일관된 맥락인 것 같아 이해가 편했다.

 

*NLP 분야의 3D tensor 이해

[[나는 사과를 좋아해], [나는 바나나를 좋아해], [나는 사과를 싫어해], [나는 바나나를 싫어해]]

다음과 같은 4개의 문장으로 구성된 훈련 데이터가 있다.

컴퓨터 입력을 위해 각 문장을 단어 단위로 쪼갠다.

[['나는', '사과를', '좋아해'], ['나는', '바나나를', '좋아해'], ['나는', '사과를', '싫어해'], ['나는', '바나나를', '싫어해']]

이제 위 데이터는 4X3의 크기를 갖는 2D tensor이다. 컴퓨터에 입력을 위해 각 단어를 벡터로 변환한다.

예시로 각 단어를 다음과 같은 벡터로 변환한다하자.

'나는' = [0.1, 0.2, 0.9]
'사과를' = [0.3, 0.5, 0.1]
'바나나를' = [0.3, 0.5, 0.2]
'좋아해' = [0.7, 0.6, 0.5]
'싫어해' = [0.5, 0.6, 0.7]

이 내용을 바탕으로 맨 위의 훈련 데이터를 재구성 하면 다음과 같다.

[[[0.1, 0.2, 0.9], [0.3, 0.5, 0.1], [0.7, 0.6, 0.5]],
 [[0.1, 0.2, 0.9], [0.3, 0.5, 0.2], [0.7, 0.6, 0.5]],
 [[0.1, 0.2, 0.9], [0.3, 0.5, 0.1], [0.5, 0.6, 0.7]],
 [[0.1, 0.2, 0.9], [0.3, 0.5, 0.2], [0.5, 0.6, 0.7]]]

이 훈련 데이터는 4X3X3의 size를 갖는 3d tensor이다. 

 

만일 Batch size를 2로 한다면

첫번째 배치 #1
[[[0.1, 0.2, 0.9], [0.3, 0.5, 0.1], [0.7, 0.6, 0.5]],
 [[0.1, 0.2, 0.9], [0.3, 0.5, 0.2], [0.7, 0.6, 0.5]]]

두번째 배치 #2
[[[0.1, 0.2, 0.9], [0.3, 0.5, 0.1], [0.5, 0.6, 0.7]],
 [[0.1, 0.2, 0.9], [0.3, 0.5, 0.2], [0.5, 0.6, 0.7]]]

다음과 같이 두 번의 연산으로 수행할 것이다.

 

각 배치의 훈련 데이터 tensor의 크기는 2X3X3이다.

 

3. Numpy로 텐서 만들기

이미 어느 정도 아는 내용이라 따라만 쳐보고 넘어간다.

- ndim은 몇차원인지를 출력

- shape은 크기를 출력. (7,)은 1X7의 size를 의미.

 

인덱스는 0부터 시작이며 (python이니까..), list와 동일한 문법.

 

당연히 slicing도 마찬가지.

 

2차원의 경우도 동일하다.

2차원부턴 shape이 (4,3)인지 (3,4)인지 헷갈리지 말도록 하자.

 

4. 파이토치 텐서 선언하기

위에서 선언한 t는 1차원이며 print 했을때 list나 array와는 다르게 tensor라는 표기가 같이 나온다.

 

2차원의 경우 Size가 [4,3]으로 표기된다. 이 맥락에서 1차원에 대해 (7,)과 같이 표기되었던 np.array에 비해 좀 더 직관적인 표현이 아닌가 싶다. (1차원 한정이긴하지만..)

 

:를 통해 첫번째 차원에 대해 전체를 선택하며 두번째 차원에 대해 1번 인덱스 (즉, 두번째 값)을 가져온다.

 

 

브로드캐스팅

같은 크기의 행렬들에 대해 덧셈이나 뺄셈을 할 때는 우리가 생각하는 대로 계산하면 된다.

같은 크기의 행렬에 대한 계산

다만, 현실세계는 녹록치 않다. 불가피하게 크기가 다른 두 행렬에 대해서도 계산을 해야하는 상황이 온다.

파이토치에서는 알아서(자동으로) 크기를 맞춰 연산을 수행하게 하는 브로드캐스팅이라는 기능을 제공한다.

 

다음과 같이 크기가 다른 두 행렬에 대해 연산이 원래는 되면 안되지만 m2가 자연스레 [10,10]으로 바뀌며 연산이 되었다.

 

다음과 같이 2 by 1 matrix와 1 by 2 matrix에 대한 연산도 하기의 수정본과 같이 브로드캐스팅 된 이후 이루어진다.

=> 이는 굉장히 편리하지만 주의해서 이용해야한다. (python의 eval()과 비슷한 향기..)

 

자주 사용되는 기능들

행렬 곱셈 vs 곱셈

matmul : 이는 선형대수학에서 아는 평범한 행렬 곱셈을 의미한다.

 

mul : element-wise한 곱셈이다.

이는 m2가 브로드캐스팅 된 이후 각 동일한 위치의 element끼리 곱해졌다.

 

(관련하여 numpy의 dot과 matmul에 대해서도 공부하면 좋을듯

관련 링크 : https://jimmy-ai.tistory.com/104)

 

 

 

mean : 평균 계산

다만 1차원 tensor에서는 각 element에 대한 mean value가 나오지만

 

2차원에서 dimension에 대한 인자를 설정함에 따라 값이 소폭 다르게 나온다.

설명 : dimension을 인자로 주면 해당 차원을 제거한다는 의미라고 한다.

 

sum : mean과 동일하게 작동하지만 평균이 아닌 합을 구하는 것 뿐. 이하 동일.

 

max : 원소의 최댓값을 리턴

argmax : 최댓값을 가진 인덱스를 리턴

 

dimension을 설정하지 않은 상태에서 max를 쓰면 전체 element 중 maximum이 나온다.

하지만 dim=0을 설정하면 위에서 말했듯이 1번째 차원(행)을 삭제하며 (1,2)행렬이 되고 이에 대한 값의 계산은 [3,4]가 된다.

 

뒤에 딸려나오는 indices(index의 복수형)은 함께 리턴되는 argmax 값이다.

 

사실 다음과 같이 type을 확인해보니 t.max(dim~)에 대한 값이 tuple이나 다른걸로 나올줄 알았는데 torch관련 class로 정의된 것이 조금 신기했다.

 

뷰(View) - 원소의 수를 유지하면서 텐서의 크기 변경.

pytorch에서의 view는 numpy에서의 reshape과 같은 역할. -> 텐선의 크기(shape)을 변경해주는 역할.

 

위 텐서의 크기는 (2,2,3)

 

3차원 텐서 -> 2차원 텐서로 변경

-1의 경우 pytorch에게 맡기는 의미이며 두번째 차운의 길이는 3이 되도록 한다는 것이다.

reshape처럼 일렬로 배열 후 다시 합친다 생각하면 좋을 것 같다.

 

만일 [-1,7]의 값을 넣는 경우 

RuntimeError: shape '[-1, 7]' is invalid for input of size 12

와 같은 에러가 발생한다. 12의 약수를 넣어야 변환되기 때문이다.

 

 

사이즈를 3차원 -> 3차원도 된다.

-1로 두 자리 이상을 pytorch에게 맡기는 것은 안된다.

 

 

스퀴즈(Squeeze) & 언스퀴즈(Unsqueeze)

[3,1] 사이즈의 텐서 ft를 정의한 후 squeeze를 사용하면 [3]의 크기를 갖는 텐서로 변경된다.

 

궁금한 점 : 꼭 맨뒤의 차원을 내리는 것인지.

 

결론 (예시에 매몰되지말며 글을 잘 읽자)

- 맨 뒤의 차원은 아님. 1인 차원을 없애는 것임.

- 그리고 1인 차원을 제거하는 것임 (글을 잘 읽기.)

- 1인 차원이 없다면 이전과 동일한 텐서 출력

- 1인 차원이 여러개 있다면 다 제거함.

 

unsqueeze : 특정 위치에 1인 차원 추가

이는 view를 통해 만든 것과 동일한 결과를 만들 수 있음

 

=> view(), squeeze(), unsqueeze()는 텐서의 원소 수를 그대로 유지하면서 모양과 차원을 조절.

 

타입 캐스팅 (Type casting)

텐서에는 자료형 존재. CPU 연산이 아닌 GPU 연산을 위한 자료형 또한 존재.

 

이런 자료형 변환을 하는 것 => 타입 캐스팅

 

long type => 64bit 정수형

float type => 32bit 실수형 (각 element에 . 붙어있음)

 

연결(Concatenate)

pandas dataframe concat과 큰 차이가 없는듯.

 

스택킹(stacking)

처음에 생각했을때는 concatenate과 무슨 차이가 있지 ? 했지만

print된 shape을 보았을때 놀랐다.

 

이는 각 tensor끼리 쌓으며 하나의 dimension을 추가로 구성한 것이고

concat의 경우 list의 append마냥 그저 붙이기에 불과한 것이었다.

 

이 또한 dim=0 or 1을 통해 stacking할 방향을 정해줄 수 있다.

 

ones_like와 zeros_like

이는 numpy array에 zeros나 ones와 동일한 기능을 하는 것 같다.

 

In-place Operation (덮어쓰기 연산)

[2,2] tensor 하나 만들고 mul(2.)를 통해 element-wise하게 곱한 결과 및 기존 값 출력

 

다만, mul이 아닌 mul_ 사용시 원래의 값에 덮어쓰기 하며 출력

(이는 dataframe에 대한 연산을 할 때 inplace=True 와 같은 기능인듯하다.)

 

 

파이썬 클래스(class)

pytorch의 구현체들은 대부분 class 개념을 애용하고 있어 설명한다고 한다.

다만 본인도 class를 건너건너 배웠기에 이번 기회에 다시 쌓아나가보자.

 

함수로 덧셈기 구현

(result를 전역 변수로 선언. 다만 실제 사용한적은 정말 오랜만인듯)

함수 외부에서 정의된 result가 함수 내에서도 전역변수로서 정의가 되었고 이 객체에 그대로 더해지는 모습.

만약 두 개의 객체에 대해 계속하여 덧샘기를 구현하려면 다음과 같이 별도의 함수를 계속 독립적으로 만들어주어야함.

 

클래스(class)로 덧셈기 구현

클래스 생성 후 cal1, cal2라는 각각의 객체 생성.

동일한 method로도 각 객체에 대해 개별적으로 계산되는 모습.

 

 

참고 자료

https://wikidocs.net/book/2788

 

Pytorch로 시작하는 딥 러닝 입문

이 책은 딥 러닝 프레임워크 `PyTorch`와 허깅페이스의 `Transformers`를 사용하여 딥 러닝에 입문하는 것을 목표로 합니다. **AI의 완전 쌩 입문자**…

wikidocs.net

본 카테고리는 해당 책의 wikidocs 기준으로 만들어졌다.

 

기존에 알고 있던 Pytorch에 대해 다시 한 번 기초를 재정립할 겸 이 책을 기준으로 정리하고자 한다.

 

깃허브 주소: https://github.com/ukairia777/pytorch-nlp-tutorial

 

GitHub - ukairia777/pytorch-nlp-tutorial: pytorch를 사용하여 텍스트 전처리부터, BERT, GPT와 같은 모델의 다

pytorch를 사용하여 텍스트 전처리부터, BERT, GPT와 같은 모델의 다운스트림 태스크들을 정리한 Deep Learning NLP 저장소입니다. - ukairia777/pytorch-nlp-tutorial

github.com

 

 

01-01 코랩(Colab)과 아나콘다

 

우선 아나콘다부터 설치를 해준다. 다만, 본 책은 Window기준으로 설치를 진행하고 있기에 Mac(M2)의 설치 방법을 찾아 그대로 따라준다.

 

참고 링크: https://applecoconut.tistory.com/entry/M1-M2-ARM-Mac%EC%97%90%EC%84%9C-%EC%95%84%EB%82%98%EC%BD%98%EB%8B%A4-%EC%84%A4%EC%B9%98%EC%99%80-%EC%A0%9C%EA%B1%B0-%EB%B0%A9%EB%B2%95

 

아나콘다를 설치하는 주요 이유는 다음과 같다. (GPT Thank you)

  • 패키지 관리 및 의존성 해결: 아나콘다는 Conda라는 패키지 관리 도구를 제공하여 파이썬 패키지의 설치 및 의존성을 쉽게 관리할 수 있습니다. 특히, 여러 패키지가 서로 다른 버전을 요구하는 상황에서 환경을 분리하여 문제를 방지할 수 있습니다.
  • 가상 환경 관리: Conda는 가상 환경을 쉽게 만들고 관리할 수 있는 도구로, 프로젝트마다 별도의 환경을 설정하여 서로 다른 버전의 파이썬이나 패키지를 사용할 수 있게 해줍니다.
  • 다양한 과학 및 데이터 분석 패키지 기본 제공: 아나콘다는 데이터 과학, 기계 학습, 통계 분석에 자주 사용되는 패키지들(예: NumPy, Pandas, Matplotlib, Scikit-learn, TensorFlow 등)을 기본적으로 포함하고 있어 따로 설치할 필요가 없습니다.
  • 편리한 설치: 아나콘다는 파이썬과 다양한 패키지를 한 번에 설치할 수 있는 통합 환경을 제공합니다. 이를 통해 초보자들도 번거로움 없이 필요한 도구를 빠르게 설치하고 사용할 수 있습니다.
  • Jupyter Notebook 통합: 아나콘다에는 Jupyter Notebook이 포함되어 있어 데이터 분석 및 학습 과정에서 매우 유용합니다. 이를 통해 코드를 실시간으로 실행하고 시각화할 수 있습니다.

 

설치 완료 후 terminal 오픈 시 다음과 같이 (base)가 앞에 붙어있으며 conda에 대한 command를 확인하였을 때 잘 나오는 것을 볼 수 있다.

> conda update -n base conda
> conda update --all

의 명령어로 모든 파이썬 패키지들을 업데이트 해준다. Proceed [Y/N] 나오는 경우는 Y 후 엔터를 쳐주자.

 

Colaboratory

Colab 주소 : https://colab.research.google.com/

-> 학교 이메일 계정으로 만들었다가 별도의 이점은 없는 것 같아 개인 계정으로 재생성.

 

 

CPU에서 GPU로 런타임 유형 변경을 하려는데 TPU가 존재하여 찾아보니 TPU가 더 맞을 것 같아 TPU로 설정하였다.

(추후 여러 코드를 번갈아 돌려가보며 테스트 진행해보고자한다.)

참고 링크 : https://8terabyte.com/7#google_vignette

 

 

머신 러닝 워크 플로우(Machine Learning Workflow)

출처 : https://wikidocs.net/217160

 

1. 수집

데이터 수집에 있어 어떤 데이터를 수집할 것인지, 어느 범위까지 수집할 것인지 생각해야한다.

DSP 입장에서는 어떤 소스를 통해 (ex. from DMP인지 어느 bundle들로부터 데이터를 가져올 것인지, 그 외의 검색 데이터, 혹은 행동 데이터를 가져올 것인지) 데이터를 수집할 지 결정하여야한다.

개인적인 생각으론 수집 단계에선 최대한 많은 데이터를 가져오는 것이 중요하지 않을까 생각한다. 어차피 후의 전처리 및 정제 단계에서 무의미한 데이터들이라면 줄이면 되기 때문이고, 모델링 단계에서 feature 및 factor의 수를 줄이며 연산을 최적화 하고자 하려하기 때문이다.

 

2. 점검 및 탐색

데이터들의 어떤 구조를 띄고 있는지, 데이터의 특징 파악 단계이다.

 

3. 전처리 및 정제

DA로 일을 하며 이 부분이 가장 어렵지 않나 라고 생각된다. 주관적이면서도 객관적이게 데이터를 정제하며 남들을 설득시킬 수 있어야하고 이 부분에서 얼마나 전처리가 잘 되었는 지가 추후 Model의 성능을 결정하기도 하기 때문이다.

또한 Outlier들에 대한 처리를 무조건적으로 제거하는 것이 아닌 각 상황에 따라 알맞게 통제해야 더 좋은 insight를 얻을 수 있다.

 

4. 모델링 및 훈련

모델을 만든 후 Train / Test set을 구분하여 훈련시키거나 hyperparameter에 대한 조정이 필요하면 Validation set 또한 만들어 훈련을 진행하곤 한다. 항상 Overfitting과 Bias에 주의하자.

 

5. 평가

완성된 모델을 평가한다.

 

6. 배포

모델이 성공적이라 판단되면 배포한다.

 

Pandas, Numpy, Matplotlib

pandas

주로 사용하는 데이터 타입은 Dataframe과 Series이다.

numpy

list와 비슷한 구조를 가지지만 더 빠른 연산과 차이점이 조금 있다.

matplotlib

시각화 툴이다. seaborn까지 같이 이용하면 더 아름다운 시각화를 할 수 있다.

 

위 내용들은 이미 잘 알고 있는 부분이라 넘어간다.

 

 

01-05 데이터의 분리(Splitting Data)

출처 : https://wendys.tistory.com/169

학습의 종류에는 크게 세 종류가 있다.

1. 지도 학습(Supervised Learning), 2. 비지도 학습(Unsupervised Learning), 3. 강화 학습(Reinforcement Learning)

 

다만, 이 책에서는 대부분 지도 학습(Supervised Learning)에 대해 배울 예정이다.

지도 학습은 라벨링된 정답이 있는 데이터를 학습 시킨다.

 

그럼 정답이 있는 데이터들을 모두 학습 시키는 것이 아닌 일부는 훈련(train)에 사용, 일부는 테스트(test)에 사용한다.

보통 7:3이나 8:2로 진행하는 것 같다.

 

위 작업을 진행하기 위해서는 데이터를 나눠야하는데 pandas의 Dataframe을 이용할 수도 있고, numpy를 이용할 수도 있다.

다만, scikit-learn을 사용하는 것이 조금 더 편해보인다.

 

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2, random_state=1234)

 

다음과 같은 코드로 분리를 할 수 있다.

 

test_size는 해당 데이터 중 test set의 비율을 얼마나 할 것인지 정하는 param이다.

위 0.2는 20%를 test size로 사용하겠다는 의미이다.

 

random_state는 랜덤으로 데이터를 분할할 때의 시드값이다.

이를 지정하지 않으면 위 코드를 돌릴때마다 다르게 분리가 된다. 하지만 특정 값을 사용하면 계속하여 동일하게 분리된 set들을 얻을 수 있다.

0. 포스팅 목적

주변 지인이 자신이 들었던 수업의 모든 강의 노트를 레이텍으로 쓴 문서를 보여주었는데 굉장히 많은 수식과 Notation을 아름답게 정리하여 감명을 받았고, 언젠간 쓸 일이 있을 것 같아 조금이라도 미리 알아두고자 한다.

 

또한, 현재 Data Analyst로 복무 중인 회사에서도 Notion을 사용할 때 글을 더 잘 작성할 수 있을 것 같다.

알고보니 노션은 TeX 기반인듯. 그래도 뭐라도 알아두면 좋을 것 같다.

 

 

1. LaTeX란 무엇이며, 어디에서 사용되는가?

LaTeX(pronounced "Lah-tech" or "Lay-tech")는 주로 학술 문서 작성에 사용되는 문서 준비 시스템.

LaTeX는 수학, 물리학, 컴퓨터 과학 등의 분야에서 널리 사용되며, 복잡한 수식이나 표, 그림을 포함한 문서를 정교하게 작성할 수 있도록 돕습니다. 특히 학술 논문, 기술 보고서, 책과 같은 긴 문서를 작성할 때 유용합니다.

LaTeX는 TeX라는 시스템을 기반으로 하며, 문서의 구조와 형식을 사용자에게 부담을 주지 않고 관리해 주는 강력한 도구입니다.

 

주요 특징으로는 다음과 같은 부분이 있습니다:

  • 복잡한 수식과 수학 기호를 손쉽게 입력할 수 있다.
  • 문서의 일관된 스타일을 유지하며, 서지 및 참고문헌 관리를 자동화한다.
  • 표, 이미지, 목차 등을 쉽게 작성하고 조정할 수 있다.
  • 고품질의 출판물 수준의 PDF 출력을 지원한다.

주로 학술 논문을 작성하는 대학 교수, 대학원생, 연구자들이 많이 사용하며, IEEE, ACM, APS 같은 학술 기관에서는 LaTeX 포맷으로 논문 제출을 권장하고 있습니다.

 

2. TeX와 LaTeX의 차이점

TeX는 도널드 크누스(Donald Knuth)가 1978년에 개발한 문서 조판 시스템입니다. TeX는 매우 강력하고 유연한 시스템이지만, 사용자가 세부적인 문서 형식을 직접 지정해야 하기 때문에 복잡한 구조의 문서를 작성하는 데 시간이 많이 걸릴 수 있습니다. TeX는 기본적으로 텍스트와 수식을 입력하고, 이를 고품질의 출력물로 변환하는 도구입니다. 그러나 사용자가 서식 지정과 같은 부분까지 직접 다뤄야 하기 때문에 초보자에게는 다소 어려울 수 있습니다.

반면, LaTeX는 Leslie Lamport가 1980년대에 TeX 위에 개발한 패키지로, 문서 형식을 자동으로 관리해주는 도구입니다. 사용자는 문서의 내용을 입력하는 데 집중하고, 서식이나 구조는 LaTeX가 처리하도록 할 수 있습니다. 이는 사용자가 복잡한 조판 작업에 시간을 쓰지 않고도 고품질의 문서를 만들 수 있도록 도와줍니다.

 

요약하자면:

  • TeX: 문서의 내용을 입력하고, 형식과 구조를 세밀하게 조작할 수 있는 기본 도구.
  • LaTeX: 문서의 형식을 자동으로 처리해 주며, TeX보다 사용자 친화적이고, 대규모 문서 작성에 적합.

 

3. LaTeX와 일반적인 워드 프로세서의 차이점

일반적인 워드 프로세서(예: Microsoft Word, Google Docs)는 사용자가 직접 문서의 레이아웃과 스타일을 지정하며, 'WYSIWYG'(What You See Is What You Get) 방식으로 실시간으로 문서의 최종 출력을 확인하면서 작업합니다. 이는 직관적이고 접근성이 좋아서 일상적인 문서 작성에 적합하지만, 복잡한 수식 입력이나 대규모 문서 관리에서는 한계가 있을 수 있습니다.

 

반면 LaTeX는 텍스트 기반의 마크업 언어를 사용하여 문서의 구조와 내용을 지정하고, 이를 컴파일하여 최종 PDF 파일을 생성합니다. 사용자는 실시간으로 최종 결과를 볼 수는 없지만, LaTeX는 문서의 형식과 서식을 자동으로 관리하기 때문에 대규모 문서의 일관성을 유지하는 데 매우 효율적입니다. 주요 차이점을 정리하면:

  • 문서 작성 방식:
    • 워드 프로세서: 실시간으로 보이는 대로 편집(WYSIWYG).
    • LaTeX: 텍스트 기반 명령어로 문서 구조를 지정하고, 나중에 컴파일하여 출력물 생성.
  • 서식 관리:
    • 워드 프로세서: 사용자가 서식을 직접 설정.
    • LaTeX: LaTeX가 문서 서식과 레이아웃을 자동으로 관리.
  • 수학적 표현:
    • 워드 프로세서: 수식을 삽입할 수 있지만, 복잡한 수식은 다루기 어려움.
    • LaTeX: 고급 수식과 기호를 쉽게 입력하고 관리할 수 있음.
  • 대규모 문서 관리:
    • 워드 프로세서: 긴 문서에서 서식 일관성 유지가 어려울 수 있음.
    • LaTeX: 긴 문서에서 일관성 있는 스타일을 유지하며 참고문헌, 목차 등을 자동으로 관리.

LaTeX는 높은 학습 곡선을 가질 수 있지만, 한 번 익히면 특히 학술적인 문서 작성에서 큰 이점 제공.

 

 

기초 문법 연습

사용 사이트

(프로그램 설치 없이 온라인으로 작성 가능)

https://www.sharelatex.com/

 

ShareLaTeX, Online LaTeX Editor

An online LaTeX editor that's easy to use. No installation, real-time collaboration, version control, hundreds of LaTeX templates, and more.

www.sharelatex.com

 

sharelatex project 화면

로그인을 잘 하고 Blank Project를 새로 생성하면 다음과 같은 화면이 표기된다.

 

좌측은 LaTeX 혹은 Visual Editor로 수정할 수 있는 화면이고

우측은 Complie시 보이는 화면이다.

 

다음과 같이 표기가 된다.

 

 

 

인라인 수식 : 텍스트 중간에 수식을 삽입할 때 사용. 수식은 $ ... $와 같이 $ 사이에 작성.

 

예시 :

The quadratic formula is $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$.

 

결과 : 

 

 

수식 블록: 수식을 한 줄로 표현하고 싶을 때는 \[ ... \]를 사용.

 

예시: 

\[ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \]
결과:
 
 
 
 
기본 수식

 

- 제곱, n승, 수열

a^2, a^n, a_{i+1}

 

- 루트

\sqrt{a+b}, \sqrt[3]{x}

 

- 시그마
\sum_{i=1}^{n} i^2

 

- 적분

\int_{0}^{1} x^2 \, dx

 
- 그리스 문자
\alpha + \beta = \gamma, \pi \approx 3.14159

 

LaTeX로 논문을 부드럽게 쓰려면 갈 길이 멀다고 느껴진다.

하기 내용은 teddylee777의 Github을 바탕으로 구성됨.

 

https://github.com/teddylee777/machine-learning

 

GitHub - teddylee777/machine-learning: 머신러닝 입문자 혹은 스터디를 준비하시는 분들에게 도움이 되고

머신러닝 입문자 혹은 스터디를 준비하시는 분들에게 도움이 되고자 만든 repository입니다. (This repository is intented for helping whom are interested in machine learning study) - teddylee777/machine-learning

github.com

https://github.com/ml-tooling/best-of-ml-python

 

GitHub - ml-tooling/best-of-ml-python: 🏆 A ranked list of awesome machine learning Python libraries. Updated weekly.

🏆 A ranked list of awesome machine learning Python libraries. Updated weekly. - ml-tooling/best-of-ml-python

github.com

이것도 도움 많이 될 것 같기도 하고..

 

우선 내가 관심 있는 분야가 무엇인지 생각해보자.

1. Computer Vision

2. NLP

3. Ranking Algorithm System

4. (비슷하지만) Recommendation System

 

굳이 따지자면 NLP보단 CV쪽 좋아하는 듯.

특히 LLM은 안 좋아하는듯.

Reinforcement Learning하고 그래도 LLM 공부도 해보고 싶은데 갈 길이 머네.

 

 

논문 리뷰를 한다면 굵직한 것들 위주로 할 것 같다.

NLP 부분에선 다음과 같이 진행할듯하다.

  1. Attention is all you need(2017)
  2. BERT: Pre-traning of Deep Bidrectional Tranformers for Language Understanding(2018)
  3. GPT(Generative Pre-trained Transformer)(2018)
  4. GPT-2: Language Models are Unsupervised Multitask Learners(2019)
  5. Transformer-XL: Attentive Language Models with Long-Range Dependencies (Dai et al., 2019)
  6. XLNet: Generalized Autoregressive Pretraining for Language Understanding (2019)
  7. T3: Exploring the Limits of Transfer Learning with Text-to-Text Transfomer (2020)
  8. GPT-3: Language Models are Few-Shot Learners(2020)
  9. LaMDA: Language Models for Dialogue Applications (2021)
  10. Pathway Language Model: A Novel Neural Architecture for Natural Language Processing (2022)
  11. LLaMa: Open and Efficient Foundation Language Models(2023)
  12. GPT_4: A Large Multimodal Model for Generating Text, Translating Languages, Writing defferent Kinds of Creative Content, and Answering Your Questions in a Informative Way(2023)
  13. PaLM-E: An Embodied Multimodal Language Model (2023)
  14. Claude 2: A Large Language Model for the Next Generation of (2023)
  15. HyperCLOVAX: A Korean-specific Large Language Model for the Next Generation (2023)

다만, 기존 RNN이나 CNN 기반에 대해서도 다져놓고 가고 싶은데 더 찾아봐야겠다.

 

아마 컴퓨터 비전 쪽에선

1. ImageNet Classification with Deep Convolutional Neural Networks(AlexNet)

2. You Only Look Once: Unified, Real-Time Object Detection

3. Generative Adversarial Networks(GAN)

의 순서로 갈 거 같은데 맞는 지는 잘 모르겠다.

 

고민하지 말고 일단 해보고 생각하자.

꾸준히만 가면 누구든 내가 다 이긴다.

'ML & AI' 카테고리의 다른 글

Object Detection for All  (0) 2024.11.24
머신러닝 모델 - 1. 선형 회귀 모델 (Linear Regression)  (0) 2024.09.21

Before to Start

     I currently work as a data analyst in the ad-tech field. As I mainly deal with the publisher and SSP sides, I haven't had much opportunity to consider the strategies of DSPs and other ecosystem participants. This time, I want to gain a deeper understanding of the strategies employed by these other players in the ecosystem.

  There are lots of participants in the ad-tech ecosystem, such as Publisher, SSP (supply-side platform), DSP (demand-side platform), Advertiser, ad-exchange, and more. Since their roles and the scope of their possible responses vary, their strategies also differ significantly. By understanding these differences, I aim to learn more about the other participants.

 

Ad tech Landscape 2023 for Playwire

 

Publisher (매체)

  Publisher(매체)는 inventory라고 하는 '지면'을 제공한다. 이러한 지면을 광고 게재를 통해 수익을 창출한다. 머나먼 이전에는 광고주들과 다이렉트로 계약하여 광고를 게재하고 수익화를 하였지만 현재는 SSP나 Ad exchange를 통해 더욱 안정적이고 다양한 수익화를 실현한다. 기술의 발전으로 인한 RTB(Real-Time Bidding)가 큰 몫을 하였다.

 

Amazon Ads Example. 다음과 같이 매체 내에 광고를 게재할 수 있는 공간을 Inventory 혹은 지면 이라고 한다.

 

  퍼블리셔가 할 수 있는 몇가지 수익화 방안들이 있다.

 

  1. 다양한 SSP 연동 및 자체 미디에이션 구축

Header Bidding Example (from: https://clearcode.cc/blog/adtech-for-publishers/)

     여러 SSP의 SDK들을 직접 어플에 탑재하여 Inhouse Mediation을 구축하는 방안이 있다. Waterfall mediation이나 Header Bidding을 통해 직접 미디에이션을 구축할 수도 있다. 또한, 퍼블리셔의 데모그래피 혹은 타겟 국가에 따라 최적화가 잘 되는 특정 SSP가 존재할 수 있다(이는 SSP와 연동된 dsp나 ssp의 자체 물량 조달에 의존). 혹은 직접 Inhouse-Mediation을 구축하는 것이 아닌 Mediation Platform을 도입하여 다양한 네트워크를 연동할 수 있다.

  2. 여러 지면 발굴

     여러 어플들을 사용하다보면 광고가 하나도 없는 앱이 있고, 광고가 덕지덕지 붙어있는 앱들이 있다. 수익화 측면에서는 당연히 광고가 많을 수록 기대수익이 올라간다. 또한 사용자 경험을 해치지 않는 선에서 Interstitial 광고나 Rewarded Video를 노출시킬 수도 있다.

3. SSP의 Bid floor 조정

     만일 Publisher가 자체 Waterfall Mediation을 구축하였다면 각 SSP들의 bid floor를 조정하여 Revenue를 최적화할 수 있다.

 

Fill Rate과 eCPM의 적절한 조화가 수익에 매우 중요하다.

https://www.linkedin.com/pulse/your-waterfall-how-publishers-monetise-ad-inventory-vinnakota/

다음과 같이 여러 SSP를 사용함으로서 하나의 SSP로 만들 수 있는 최대 수익보다 더 많은 수익을 창출할 수 있다.

(위와 같은 사진에서는 Waterfall Mediation을 이용하여 서로 다른 eCPM을 Targeting(Bid floor를 조정하거나, CPC 물량의 비중을 파악하여) 하여 No Fill을 최소화 하여 매출을 최대화 할 수 있다.)

 

또한, 개인정보 활용안을 이용하여 ssp나 dsp쪽으로 유저 식별값들(ex. hashed 된 email, 성별, geolocation 정보들)을 보내주면 더 잘 사거나 비싸게 살 수 있다.

 

다만 해당과 같이 최대 수익을 창출하기 위해선 SDK 탑재 및 여러 세팅이 정상적으로 이루어져야한다.

해당 Format에 올바른 사이즈의 광고들이 불러지는지, SSP측과 discrepancy가 발생하지 않기 위해 SDK에서 측정하는 impression이나 Click이 잘 작동하도록 세팅되었는지, Mediation에 연동된 Network들이 정상적으로 작동하는 지 등 개발적 측면에서도 원활하게 작동해야 한다.

 

최종적으로 Publisher는 본인의 지면을 Selling하는 것이기에 최대한 높은 가격으로, 최대한 많이 파는 것이 중요하다.

 

SSP(Supply-Side Platform)

SSP의 수익 모델에는 무엇이 있을까. 아마 수수료 장사일 것이다.

DSP -> SSP -> 매체 를 통해 광고가 송출되기에 사이에서 15~30% 정도의 수수료를 받는다.

또한, dsp를 통한 것이 아닌 ssp 자체적으로 광고를 조달하여 (물론 기술력이 된다면) 팔 수도 있다.

나가는 것은 인건비, 서버 유지비 등이 있을 것인데 대규모 트래픽 처리가 필요하여 어느 정도의 기술력은 요구된다.

 

SSP 입장에선 Bidder들(DSP)의 관리가 중요할 것이라 생각한다. 무작정 많은 Bidder들을 연동한다면 bid request에 대한 response가 늦게 들어올 수 있고, 혹은 문제를 일으킬 수 있다. 빠른 response는 Auction의 종료를 빠르게 하며 Auction이 빠르게 종료될 수록 매체에 보내는 응답이 빨라지게 된다. 유저가 해당 지면에 얼마나 오래 머무를 지 모르기에 빠른 응답도 수익 증대에 도움이 되는 방향이다.

 

https://www.leadswork.net/en/leadswork-en/rtb-tmax-understanding-and-utilization/

물론 tmax(최대입찰시간)를 설정하여 자체적으로 request에 대한 response 응답을 종료하고 이후 flow로 넘어갈 수 있다.

 

추가로 일반 open auction이 아닌 Guaranteed Deal, Preferred Deal, Private Market Placd 등으로 추가 수익화를 노려볼 수 있다. (어차피 수수료 장사이기에 매체 입장에서 매출이 늘어날 수록 SSP의 매출도 늘어난다.)

 

또한, 많은 다양한 Publisher들을 연동하는 것이 중요하다. 예를 들면 특정 오래된 Publisher에 연동된 SSP들이 몇 없는 경우가 있다. 이런 경우 특정 DSP들이 큰 비용을 지불하고서라도 해당 SSP에 입찰하는 경우가 있다.

 

SSP는 기술력보단 영업력이 중요한 것이 아닐까 생각한다. Meta의 경우 뛰어난 기술력은 있지만 매체 관리 측면에서 힘들어서인지(?) SSP 사업을 접은 것처럼말이다.

 

DSP(Demand-Side Platform)

DSP는 광고주가 다양한 광고 인벤토리에 실시간으로 접근하고 구매할 수 있도록 돕는 플랫폼이다.

DSP는 광고 캠페인을 관리하고, 타겟팅을 최적화하며, 실시간 입찰(RTB)을 통해 효율적으로 광고를 구매할 수 있게 함.

 

RTB의 발전으로 인해 가장 많은 수혜를 본 것이 DSP이자 가장 많이 머리가 아픈 것도 DSP가 아닐까 싶다.

이전에는 적당한 CPC나 CPM으로 정산을 하며 (광고주와 exchange) 중간에서 커미션을 받으면 되었지만 현재는 최소한의 비용으로 최대한의 효율을 내기 위해 노력을 많이 하는 것 같다.

 

이 부분은 뇌피셜적인 부분이 있지만 많은 SSP 혹은 DSP들이 점차 Ad-Exchange로까지 확장하는 이유는 본인들의 효율을 더 객관적으로 평가하고 타 DSP들의 Bidding 및 Performance를 확인하며 Bench-marking 할 수 있기 때문이 아닐까. 또한 Bench Marking 뿐 아닌 커미션을 독자적으로 흡수할 수 있는 platform 사업이 되어가는 것 아닐까.

예를 들면 MAX에서의 AppLovin이나 ironsource에서의 unityads나 본인들의 수준을 평가하며 개선 - 보완해나갈 수 있지 않을까.

또한 Admob의 경우도 타 미디에이션 플랫폼을 이용한 admob 보다 admob sdk를 선호하긴 한다.  

 

Real-world에서 생각을 해보자면 정말 '효율적인' 방법으로만 입찰을 하여 진행을 할 수 있지만 광고주들의 특정 압력이 존재할 수도 있을 것 같다. 광고주 입장에서 광고를 통해 원하는 점은 '특정 페이지에 인입되는 유저 수 증대' 혹은 '특정 어플 설치' 등이 있을 수 있다. 하지만 특정 어플의 특정 지면들에 대해서는 '실수로 클릭을 유발하는' 지면들이 존재하고 이러한 클릭을 통한 성과는 제외하여야하기에 Conversion을 높이는 유저들을 더욱 타겟팅해야할 것이다. 그래서 CTR Prediction 뿐만 아닌 CVR Prediction도 유의미하게 발전해나가야한다.

 

그리고 월별로 광고비를 설정하다보니 '이번달 내에는 최소 이만큼의 유저는 끌어들여야해' 혹은 '이만큼의 PV는 찍어야해'라는 압박이 있을 수도 있을 것 같다. 그렇다보니 정말 '효율적인 입찰'뿐만 아니라 조금은 비 효율적이더라도 더 많은 물량을 때려박아 적당한 (최고의 효율과 최대한의 매출의) 타협을 하는 것도 있지 않을까 싶다.

 

그외에도 DSP - Publisher의 직접 연동도 가능한 것으로 알고 있다. 중간에 SSP나 Ad-Exchange를 거치지 않다보니 더 적은 비용으로 지면을 구매할 수 있기에 비용적으로 유리하다. 다만 Publisher 입장에서 DSP와 다이렉트로 연동하며 (SDK 탑재든 S2S 연동이든) 공수가 들텐데 Fill Rate을 못 채우거나 만족스러운 eCPM이 나오지 않으면 상생이 어려울 수 있을 것 같다.

 

그럼 DSP는 입찰할 때 무엇을 기준으로 입찰하는가? => 유저의 adid 및 기타 device, geo 정보들이다.

bid request가 보내올때 adid를 비롯한 여러 정보가 있기에 본인들이 소유한 데이터 혹은 DMP에서 어떠한 유저인지 알 수 있다. 기존에 어떤 물품들에 대해 구매를 하였고 구매 패턴이 어떻고 관심사는 어떻고 데모그래피는 어떤 사람이고 등. 또한 다른 웹사이트 및 앱 데이터, 제3자 데이터, CRM 데이터, 쿠키 및 픽셀 등 을 사용하면 정말 많은 정보들이 있을 것 같다. 어떤 페이지에 머문 기간을 통해 해당 유저의 관심사가 어떤지, 어떤 물품 구매를 희망하는 지 알 수 있고 유저가 구매할 확률을 계산할 수도 있다. 이러한 확률을 통해 기댓값보다 낮게 입찰하여 낙찰된다면 수익을 내는 것이 아닐까.

이러한 확률 계산은 매우 어렵다. 데모그래피적 특성, 매체의 특성, 최근의 CTR이 어떤지 등이 모두 고려되어야 하지 않을까. 그래서 요즘은 ML 기술력이 중요하다 생각한다.

 

ROAS를 증대시켜야 광고주들로부터 더 많은 물량을 받게 되고 그로 인한 수익은 더 증가할 것이다.

그래서 내가 DSP에서 일을 해보고 싶다. (결국 못하고 ad-tech 업계를 떠나게 되었다.)

 

DMP

데이터 저장소 역할.

다만, 어느 소스로부터 adid를 수집하고, 동일 유저에 대한 판별은 어떻게 할 것이고 등의 적당한 기술력은 지녀야 할 것 같다.

예를 들어 ad-exchange와 협약을 맺어 adid들에 대한 정보를 가져온다면 (어떤 dsp에서 집행한 광고인지는 몰라도) 어느 종류의 광고 (ex. 신발광고)를 클릭(혹은 전환)에 대한 데이터를 얻는다면 유저 - 관심사에 대한 맵핑이 가능하고 더 높은 단가에 팔 수 있을 것이라 생각한다. 최대한 많은, 정확한, 최근의 관심사를 반영할 수록 DSP에게 더욱 환영받을 것 같다.

 

Advertiser

광고주는 어떤 식으로 진행하는 지 잘 모르겠다.

경험해본 바로는 구글 애즈 / 애플 서치 애즈 / 메타 밖에 안 틀었던 것 같은데 Criteo 같은 곳에서 광고를 집행하는 회사들이 진짜 있는 지는 잘 모르겠다. 그리고 사실상 현재 한국은 쿠팡이 굉장히 큰 손인 것으로 알고있다. 쿠팡 광고를 집행하는 것이 쿠팡에서 spending을 태우는 것인지, 구매까지의 Conversion에 자신 있는 dsp들이 본인들의 커미션을 생각하고 태우는 것인지는 잘 모르겠다.

 

 

 

 

공식 Documentation

https://matplotlib.org/stable/plot_types/basic/index.html

 

Pairwise data — Matplotlib 3.8.2 documentation

Pairwise data Plots of pairwise \((x, y)\), tabular \((var\_0, \cdots, var\_n)\), and functional \(f(x)=y\) data.

matplotlib.org

 

0. 목적

 

본 포스팅의 목적은 Matplotlib의 위 documentation에서 설명하는 가장 기본적인 시각화 툴을 보다 자세히 이해하고자 한다.

 

1. plot(x,y)

예제 코드

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('_mpl-gallery')

# make data
x = np.linspace(0, 10, 100)
y = 4 + 2 * np.sin(2 * x)

# plot
fig, ax = plt.subplots()

ax.plot(x, y, linewidth=2.0)

ax.set(xlim=(0, 8), xticks=np.arange(1, 8),
       ylim=(0, 8), yticks=np.arange(1, 8))

plt.show()

 

결과

 

코드 해석

필요한 라이브러리들 호출

import matplotlib.pyplot as plt
import numpy as np

 

plot 스타일 정의

plt.style.use('_mpl-gallery')

해당 스타일 외에도

plt.style.use('bmh')
plt.style.use('ggplot')
plt.style.use('classic')
plt.style.use('Solarize_Light2')
plt.style.use('default')

와 같이 다양한 스타일 사용 가능

 

예시

bmh
ggplot
classic

 

 

관련 공식 문서

https://matplotlib.org/stable/api/style_api.html

 

matplotlib.style — Matplotlib 3.8.2 documentation

matplotlib.style Styles are predefined sets of rcParams that define the visual appearance of a plot. Customizing Matplotlib with style sheets and rcParams describes the mechanism and usage of styles. The Style sheets reference gives an overview of the buil

matplotlib.org

 

데이터 생성

x = np.linspace(0, 10, 100)
y = 4 + 2 * np.sin(2 * x)

 

np.linspace에 들어가는 세 param은 각각 구간 시작점, 구간 끝점, 구간 내 숫자 개수 을 의미

 

예시

import numpy as np

x = np.linspace(1,10,100)

x

 

출력 결과

 

1부터 10까지, 처음을 1 마지막을 10으로 하는 100개 element를 가지는 1차원의 array를 만듦.

 

y는 해당 x에 대응되는 각각의 함수 값을 갖게 됨.

x는 numpy.ndarray의 타입을 갖게 되므로 위와 같은 연산이 가능

(list의 경우 해당 연산이 불가하는 것으로 아는데 y식 정의에 np가 들어가있어 가능한 듯)

 

 

 

fig, ax = plt.subplots()

 

관련 문서

https://towardsdatascience.com/clearing-the-confusion-once-and-for-all-fig-ax-plt-subplots-b122bb7783ca

 

Clearing the confusion once and for all: fig, ax = plt.subplots()

Learn about figure and axes objects in Matplotlib

towardsdatascience.com

 

이 부분은 많은 예시 코드들에서 공통적으로 사용하고 있는 부분인데 어떤 의미일까.

(Note : subplot과 subplots는 다름)

 

#기본
plt.subplots(nrows, ncols)

 

예시 1

fig, ax = plt.subplots()
plt.show()

 

예시 2

fig, ax = plt.subplots(2,1)
plt.show()

 

nrows와 ncols에 m, n이라는 정수형 인자를 각가 넣으면 m by n matrix 느낌의 plot들이 구성된다.

 

예시 3

sub_plots = plt.subplots(3,2)
print(sub_plots)
print("TYPE IS : ", type(sub_plots))

이 부분에서 살짝 의외였다. sub_plots 객체의 type이 tuple이라니.

아마 fig, ax로 쪼개는 것을 통해 length가 2짜리인 (fig, ax)의 형태로 이루어진 tuple이 아니었을까

 

예시 4

fig, ax = plt.subplots(3,2)
print(fig)
print(ax)
print("TYPE IS : ", type(fig))
print("TYPE IS : ", type(ax))

 

예시 5

sub_plots = plt.subplots(3,2)
print(sub_plots[0])
print("##########")
print(sub_plots[1])
print("##########")
print(sub_plots[1][0])

확인을 해보니 fig, ax의 길이가 2짜리인 튜플이 맞는 것 같다.

ax 파트에는 3 by 2 형태의 2차원 array들이 들어있어 각각에 대한 정의를 해줄 수 있다.

'Data > Visualization' 카테고리의 다른 글

[Matplotlib] 3D Plot  (0) 2023.12.08

+ Recent posts