시간 복잡도

  • 시간 복잡도란?
    • 반에 있는 사람들이 N명이라고 한다면B 방식은 N^2 만큼의 연산이 필요하다고 할게요.
  • 💡 시간복잡도는 입력값과 문제를 해결하는 데 걸리는 시간과의 상관관계를 말합니다!
    • 입력값이 2배로 늘어났을 때 문제를 해결하는 데 걸리는 시간은 몇 배로 늘어나는지를 보는 것이죠.
    • 우리는 시간이 적게 걸리는 알고리즘을 좋아하니 입력값이 늘어나도 걸리는 시간이 덜 늘어나는 알고리즘이 좋은 알고리즘이겠죠?
    • N 이 예를 들어서 30이라면 A 방식은 30번, B 방식은 900 번의 연산이 필요하겠죠
    • A 방식은 N 번 만큼의 연산이 필요하고
    • 예를 들어서 내가 반에 있는 사람들 중에서 가장 이성에게 호감이 높은 사람을 뽑는다고 해볼게요.

“입력값에 비해 얼마나 일을 수행해야 하는가?”

  • 1) 최댓값 찾기 알고리즘의 시간 복잡도 판단해보기
    • 첫 번째 방법
      • 이 해결 방법은 각 숫자마다 모든 다른 숫자와 비교해서 최대값인지 확인합니다. 만약 다른 모든 값보다 크다면 반복문을 중단합니다.
      • 이 함수가 시간이 얼마나 걸리는지 어떻게 분석할 수 있을까요?
      • 바로, 각 줄이 실행되는 걸 1번의 연산이 된다고 생각하고 계산하시면 됩니다. 아래와 같이 계산할 수 있습니다.
      • 위에서 연산된 것들을 더해보면
        • N * N * 2
      • array의 길이 X 비교 연산 1번
        • N
      • 그러면 우리는 이제 이 함수는 2* N^2 + N 만큼의 시간이 걸렸겠구나! 라고 말할 수 있습니다.
      • Q. 선생님 여기서 입력값이 뭔가요?
        • A. 함수에서 크기가 변경될 수 있는 값이라고 보시면 됩니다! 배열을 받고 있으니 이 함수에서는 배열이 입력값입니다.
      • Q. 선생님 그러면 여기서 N 이 6이니까, 78이라고 말하면 안되나요?
        • A. N 의 크기에 따른 시간의 상관관계를 시간복잡도라고 하는 것이라 수식으로 표현하셔야 합니다!
def find_max_num(array):
    for number in array:
        is_max_num = True
        for compare_number in array:
            if number < compare_number:
                is_max_num = False
        if is_max_num:
            return number

print("정답 = 6 / 현재 풀이 값 = ", find_max_num([3, 5, 6, 1, 2, 4]))
print("정답 = 6 / 현재 풀이 값 = ", find_max_num([6, 6, 6]))
print("정답 = 1888 / 현재 풀이 값 = ", find_max_num([6, 9, 2, 7, 1888]))
  • 2) 최댓값 찾기 알고리즘의 시간 복잡도 판단해보기
    • 두 번째 방법
for number in array:                 # array 의 길이만큼 아래 연산이 실행
    for compare_number in array:     # array 의 길이만큼 아래 연산이 실행
        if number < compare_number:  # 비교 연산 1번 실행
            is_max_num = False       # 대입 연산 1번 실행
    if is_max_num:                   # 비교 연산 1번 실행
        return number

 

공간 복잡도

  • 입력값과 문제를 해결하는 데 걸리는 공간과의 상관관계를 말합니다!
    • 입력값이 2배로 늘어났을 때 문제를 해결하는 데 걸리는 공간은 몇 배로 늘어나는지를 보는 것이죠.
    • 우리는 공간이 적게 걸리는 알고리즘을 좋아하니 입력값이 늘어나도 걸리는 공간이 덜 늘어나는 알고리즘이 좋은 알고리즘이겠죠?
    • 저장하는 데이터 양이 1개의 공간을 사용한다고 계산, 예 ) 리스트에서 원소 갯수가 공간의 갯수
alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

def find_max_occurred_alphabet(string):
    max_occurrence = 0 # 1개의 공간을 사용
    max_alphabet = alphabet_array[0] # 1개의 공간을 사용

    for alphabet in alphabet_array:
        occurrence = 0 # 1개의 공간을 사용

## 26 + 3의 공간을 사용

alphabet_occurrence_list = [0] * 26 # 26개의 공간을 사용

for char in string:
    if not char.isalpha():
        continue
    arr_index = ord(char) - ord('a') # 1개의 공간을 사용
    alphabet_occurrence_list[arr_index] += 1

max_occurrence = 0 # 1개의 공간을 사용
max_alphabet_index = 0 # 1개의 공간을 사용

for index in range(26):
    alphabet_occurrence = alphabet_occurrence_list[index] # 1개의 공간을 사용
    if alphabet_occurrence > max_occurrence:
        max_occurrence = alphabet_occurrence # 1개의 공간을 사용
        max_alphabet_index = index # 1개의 공간을 사용
  • 29나 30처럼 N과 상관이 없으면 공간복잡도는 성능에 영향을 주지 않는다. = 단순 대입연산만 늘어났으니
  • 단 N에 따라서 공간복잡도가 기하급수적으로 늘어나면 고려해봄직하다.

출처 : 38군데 합격 비법, 2024 코딩테스트 필수 알고리즘

사고의 지평: 직관과 분석 사이

개인적 성찰

나는 오랫동안 의사결정에 있어 직관에 크게 의존해왔다. "딱 봐도 이거 같은데?"라는 순간적인 직감은 때로는 놀라울 정도로 정확했지만, 때로는 치명적인 오류를 낳기도 했다.

직관은 우리의 빠른 판단 메커니즘이지만, 동시에 편향과 오류의 원천이기도 하다.

사고의 다차원적 접근

1. 직관의 역할과 한계

  • 빠른 판단과 즉각적인 통찰력 제공
  • 복잡한 상황에서 빠른 의사결정 가능
  • BUT, 개인의 경험과 편견에 깊이 영향받음

2. 종합적 사고: 다각도의 관점 수집

  • 단일 문제를 다양한 관점에서 접근
  • 각 관점의 장단점을 객관적으로 분석
  • 맥락과 상황에 따른 유연한 해석

실천 전략

  • 다양한 이해관계자의 관점 수집
  • 서로 다른 배경의 전문가 의견 청취
  • 자신의 초기 가설에 도전하는 반대 관점 적극 탐색

3. 비판적 사고: 논거의 엄밀한 검증

  • 각 관점의 논거를 체계적으로 평가
  • 증거의 신뢰성, 타당성 엄밀히 검증
  • 감정이나 편견이 아닌 논리와 근거 중심

검증 프레임워크

  1. 정보의 출처와 신뢰성 확인
  2. 논리적 일관성 평가
  3. 대안적 해석 가능성 탐색
  4. 잠재적 편향 인식

4. 메타인지: 자신의 사고 과정 성찰

  • 자신의 사고 과정을 객관적으로 관찰
  • 인지적 편향과 오류 지속적 인식
  • 사고 방식의 지속적 개선

실천적 통합 모델

의사결정 프로세스

  1. 직관적 통찰 포착
  2. 종합적 관점 수집
  3. 비판적 검증
  4. 메타인지적 성찰
  5. 최종 의사결정

결론: 사고의 생태계

사고는 고정된 것이 아니라 끊임없이 진화하는 동적 과정이다.

  • 직관은 출발점
  • 분석은 정제의 도구
  • 성찰은 지속적 개선의 엔진

"완벽한 사고란 존재하지 않으며, 중요한 것은 끊임없이 배우고 성장하는 태도다."

실천 권고

  1. 매일 최소 한 가지 자신의 믿음에 의문 제기
  2. 다른 관점의 글 읽기
  3. 자신의 의사결정 과정 기록하고 사후 분석
  4. 다양한 배경의 사람들과 대화

핵심: 사고는 기술이며, 훈련과 실천을 통해 끊임없이 발전한다.

컴퓨터는 숫자밖에 저장하지 못하기에, ASCII 코드 개념이 등장

  • ASCII (American Standard Code for Information Interchange) : 7비트를 사용하고, 암호화되지 않은 키로코드를 사용

 

문자 : ASCII 코드 예시

  • A : 65, a : 97

 

문자('a')-> ASCII 코드로 변환

  • print(ord('a'))
  • ASCII 코드(97) -> 문자로 변환
def find_alphabet_occurrence_array(string):
    alphabet_occurrence_array = [0] * 26
    for char in string:
        if not char.isalpha():
            continue arr_index = char - ord('a')
        alphabet_occurrence_array[arr_index] += 1
    return alphabet_occurrence_array

 

아스키/문자 변환 함수를 이용한 풀이

  • ord('char') / chr(num)
# 최빈값 중, 사전순으로 가장 첫번 째 값을 찾기

s = "hello my name is dingcodingco"

def find_alphabet_occurrence_array(string):

# 알파벳 갯수만큼 배열을 생성
alphabet_occurrence_array = [0] * 26

for char in string:

    # 알파벳이 아니면 continue 처리
    if not char.isalpha():
        continue

    # a의 아스키 코드 값을 빼서 arr_index를 구함
    arr_index = ord(char) - ord('a')

    # 인덱스에 해당하는 값을 1 만큼 증가
    alphabet_occurrence_array[arr_index] += 1

    # 최대값인 것들 중 맨 처음 값(키값)을 취하고 아스키 코드 값을 더한다.
max_index = [k for k, v in enumerate(alphabet_occurrence_array) if v == max(alphabet_occurrence_array)][0] + ord('a')

    # 아스키 코드를 문자로 변환
return chr(max_index)

print(find_alphabet_occurrence_array(s))

 

 

# 최빈값을 모두 찾기

s = "hello my name is dingcodingco"

def find_alphabet_occurrence_array(string):
    alphabet_occurrence_array = [0] * 26

    for char in string:
        if not char.isalpha():
            continue
        arr_index = ord(char) - ord('a')
        alphabet_occurrence_array[arr_index] += 1

    # 최빈값을 모두 구하여 딕셔너리에 담는다.
    max_list = {chr(k + ord('a')) : v for k, v in enumerate(alphabet_occurrence_array) if v == max(alphabet_occurrence_array)}

    # 딕셔너리에 담긴 키(v)와 v에 해당하는 값을 찾는다.
    for k, v in enumerate(max_list):
        print(f'{v} : {max_list[v]}')

find_alphabet_occurrence_array(s)

 

 

출처 : 38군데 합격 비법, 2024 코딩테스트 필수 알고리즘

# 알고리즘과 친해지기

# 1. 최대값 찾기
array = [3,5,6,1,10,4]
max = 0
def find_max_num(array):
    for num in array:
        for compare_number in array:
            if num < compare_number:
                max = compare_number
    return max
        
print(f'최대값은 {find_max_num(array)}입니다.') # formatted string, 변수는 {}로 출력

# 위 알고리즘은 시간복잡도가 O(n^2)

def find_max_num2(array):
    max = array[0]
    for num in array:
        if num > max:
            max = num
    return max

print(f'최대값은 {find_max_num2(array)}입니다.')

# 위 알고리즘은 시간복잡도가 O(n)

# 알고리즘 문제풀이의 목표 중 하나는
# 같은 문제라도 시간복잡도가 더 작은 알고리즘을 찾아야한다.

 

출처 : 38군데 합격 비법, 2024 코딩테스트 필수 알고리즘

[이론] Loss Function의 정의

  • 손실함수 의 정의 : NN 모델이 예측한 값 Y^과 원래 정답 Y간의 오차
  • 대표적으로 Mean Square Error Loss가 있다.
    • MSE : L(Y, Y^) = 1/N * sum(Y^ - Y)^2
  • 정답값 Y와 Y^의 차이가 크다 -> 부정확한 예측 -> 손실함수의 값 L(Y, Y^)가 크다.
  • 정답값 Y와 Y^의 차이가 작다 -> 정확한 예측 -> 손실함수의 값 L(Y, Y^)가 작다.
  • 즉, 손실 함수의 값이 최소화되도록 모델의 weight를 최적화하면 모델의 정확도가 높아진다!

[이론] Task의 종류

  • Regression Task (회귀)

    • 어떤 연속적인 값을 예측하는 Task
      • 예시: 주가의 가격을 예측
  • Classfication Task (분류)

    • "discreate", "categorical" 클래스 라벨을 예측하는 task
      • 예시: 책의 장르를 예측하는 task 등
  • Regression Task

    • Input (x1, x2, x3) -> Output (y)
      • X E R^3 y^ E [a,b] (= [] 대괄호는, 각각의 값들이 a이상 b이하에 있는다라는 뜻)
  • Classfication Task

    • Input (x1, x2, x3) -> Output (y)
      • X E R^3 y^ E {0,1, ..., C - 1} (= 0, 1, ..., C - 1 중에서 하나의 값) / label값
  • Regression Task의 접근방법

    • Sigmoid 함수? 기계학습과 신경망에서 널리 사용되는 활성화 함수

      • f(x) = 1 / (1 + e^(-x))

        • 모든 입력값을 0과 1 사이로 변환
        • S자 형태의 곡선을 형성
        • 연속적이고 미분 가능한 함수
        • 확률 표현에 적합한 0~1 사이의 출력값
      • 활용

        • 이진 분류 문제의 출력층
        • 신경망의 은닉층 활성화 함수
        • 확률 기반 모델링
      • 구현예시

        • import numpy as np
          
          def sigmoid(x):
              return 1 / (1 + np.exp(-x))
      • 참고사항

        • 최근 딥러닝에서는 vanishing gradient 문제로 인해 ReLU(Rectified Linear Unit) 함수를 더 선호하는 추세입니다.
    • Input (x1, x2, x3) -> NN -> NN Output(= o^는 sigmoid 함수) : o^ -> (Rescaling) -> final output : y^

      • X E R^3 o^ E [0,1] y^ E [a,b] (=a와 b사이의 값)
        • Linear Rescaling: y^ = (b - a) * o^ + a (o^에 0을 대입하면 y^ = a, o^에 1을 대입하면 y^ = b)
  • Classfication Task의 접근방법

    • Input (x1, x2, x3) -> NN -> NN Output(= Logit, C차원의 벡터) : o^0, ... , o^i, ... , o^C-1 -> (Arg max) -> final output : y^
      • (= 0번째 Class에 대한 Logit, i번째 Class에 대한 Logit, C-1번째 Class에 대한 Logit --> 총 C개이므로, C차원의 Vector)
      • X E R^3 o^ E R^C y^ E {0,1, ..., C - 1}
        • class : 분류
          • 예: 고양이, 개, 원숭이 등..
        • Arg max : 어떤 벡터나 리스트에서 가장 큰 값을 가지는 index를 출력하는 함수.
          • 예: o^i(= i번째 Logit)이 가장 큰 값이면, 모델은 Arg max를 통해 i번째 class로 예측한 셈
        • Softmax Function : y^ = softmax(o^)
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch로 구현해보는 Neural Network

  • PyTorch 모델의 기본 뼈대

    • init 함수

      • NN을 구성하고 있는 layer들을 명시하고 initialize한다.
    • forward 함수

      • 입력에 대한 forward pass을 정의한다.

        class NeuralNetwork(nn.Module):
        def __init__(self): # Neural Network을 구성하는 layer들을 initialize하는 부분
            super(NeuralNetwork, self).__init__()                
            self.fc_layers = nn.Sequential( nn.Linear(784, 784 // 4)
                                          , nn.ReLU()
                                          , nn.Linear(784 // 4, 784 // 16)
                                          , nn.ReLU()
                                          , nn.Linear(784 // 16, 10)
                                          , nn.Sigmoid(), )
        
        def forward(self, x): # Neural Network의 forward pass을 정의하는 부분 # x은 input tensor
            x = torch.flatten(x, start_dim=1)
            x = self.fc_layers(x)
            return x
    • torchsummary을 사용해서 모델의 summary 뽑기

Deep Learning, Neural Network 개념 요약

  • Deep Learning이란 무엇이고 어디에서 기원하는가?
  • 어떤 문제를 풀려고 하는 것인가?
  • Neural Network의 기본 구성은 어떻고, 어떻게 학습시키는가?
  • Deep Learning
    • (NN의 출력값) Y^ = NN(X)가 (실제값) Y = f(X)에 최대한 잘 근사하도록 학습하는 것.
  • 기본적인 NN의 구성
    • Input Layer + (한 개 이상의) Hidden Layer + Output Layer
  • 각 Layer의 Neuron의 구성
    • 가중치 weight w와 활성 함수 activation fucntion으로 구성된다.
  • NN이 학습되는 과정 = weight값이 최적화되는 과정
    • Gradient Descent (경사 하강)을 통한 Loss fucntion (손실 함수)값을 최소화하도록, weight값을 최적화하고 점진적으로 모델의 예측 정확도를 높인다.
  • 각 뉴론의 구성은 Weight, Activation Function으로 구성
  • sigma(i=1~3) xi * wji : 이전 Layer의 출력값 xi은 가중치 wji에 곱해져서 합해진다. (weight multiplication --> Aggregation)
  • sigma : 합해진 값들은 activation function sigma을 통과하여 해당 뉴런의 최종 출력값 hj을 구한다.
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch 기초 - Transforms

  • Transforms

    • Torchvision에서는 Computer Vision에서 사용되는 다양한 모델, 데이터셋들을 제공
    • 여기서 torchvision의 transforms 모듈은 이미지 전처리에 관련된 유용한 기능들을 제공
    • 예를 들어,
      • ToTensor : image를 tensor로 변환하고 0~1 사이 값으로 normalize
      • Data augmentation (데이터 증강)
        • Gaussian Blur
        • Random Affine, 등
  • PreProcessing(전처리)

    • Deep Learning Pipeline(process)

      • Raw Input -> Deep Learning Pipeline -> Cat! (Output)
    • MLOps에서의 pipeline의미는 조금 다름

    • 여기서는 raw input에 대해서 output으로 mapping하는 일련의 과정을 의미한다.

    • CV case.

      • 전처리 -> 딥러닝모델 -> 후처리

      • [전처리]

        • 이미지를 H' W'로 resize한다.
        • 왜냐하면 NN의 input으로 mini-batch를 구성하는 데이터들은 동일한 dimension (shape)을 가져야 한다.
        • 그래야 mini-batch을 Matrix 혹은 Tensor로 표현할 수 있다!
        • resized 된 이미지를 numpy 배열로 변환
        • 0~1사이 값으로 normalize 한다
          • Torchvision의 Transforms은 CV와 관련된 전처리 함수, 기능들을 포함!
      • [딥러닝 모델]

        • NN Model은 전처리 값을 입력받아서 또 다른 Tensor값을 출력한다.

          model(img)
          tensor([0.9900, 0.100])
          # 고양이일 확률 예측 0.999
          # 강아지일 확률 예측 0.100
      • [후처리]

        • Cat!
        • 비록 해당 예제에서는 간단하지만 더 복잡한 전처리의 task도 많이 있다.
        • e.g. Object Detection, Segmentation, NLP ...
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch 기초 - Dataset과 DataLoader

  • Dataset과 Data Loader
    • Dataset과 Data Loader은 PyTorch에서 제공하는 추상 클래스
    • Dataset (torch.utils.data.Dataset)
      • Mini-batch를 구성할 각 data sample을 하나씩 불러오는 기능을 수행한다.
    • Dataloader (torch.utils.data.DataLoader)
      • Dataset에서 불러온 각 data sample들을 모아서 mini-batch로 구성하는 기능을 수행한다.
    • 그리고 Data Loader를 통해서 Data sample들을 병렬적으로 불러오고, 데이터 셔플 등의 작업을 간단하게 수행할 수 있다.
  • Dataset의 뼈대대
    • init function
    • len function
    • getitem function
    • 예:
from torch.utils.data import Dataset
class CustomDataset(Dataset):
    def __init__(self):
        # 데이터셋의 전처리를 수행하는 부분
    def __len__(self):
        # 데이터셋의 길이 (즉, 총 샘플의 갯수를 명시하는 부분)
    def __getitem__(self, item):
        # 데이터셋에서 특정 1개의 샘플을 가져오는 부분
        # 참고로 item은 index
  • Data Loader의 Input:
    • dataset
    • batch_size: mini-batch의 크기
    • shuffle (binary): 무작위 순서로 데이터를 샘플링 할 것인지
    • num_workers: 데이터 로딩에 사룡할 subprocess 개수 (병렬 처리)
    • pin_memory (binary): GPU memory에 pin 할 것인지
    • drop_last (binary): 마지막 mini-batch을 drop할 것인지
  • 참고로
    • num_workers 수가 많을수록 데이터 로딩이 더 빠르지만, 그만큼 CPU core 갯수도 충분해야한다. (CPU core 갯수보다 num_workers가 더 많으면 오히려 느려지는 경우 발생)
    • pin_memory=True로 했을 시, GPU (cuda) memory를 미리 할당, 확보시켜서 조금 더 빠르게 데이터를 GPU에 올릴 수 있다.
  • 다음 내용을 Jupyter Notebook에서 살펴보자:
    • CIFAR10 (torchvision.datasets.CIFAR10)을 활용
    • torch.utils.Dataset으로 Custom Dataset 구현
    • torch.utils.DataLoader 활용
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch 기초 - Tensor

  • PyTorch의 Tensor
    • Tensor (torch.Tensor)
      • Numpy의 배열 (array)와 행렬 (matrix)와 매우 유사한 자료구조
      • PyTorch에서 scalar, vector, matrix, tensor등을 표현하는데 사용
      • 예:
        • Scalar : 1
          • 1
        • Vector : (2)
          • [1]
            [2]
        • Matrix : (2, 3)
          • [[1 3 5]]
            [[2 4 6]]
        • Tensor : (2, 3, 2)
          • [[[1 2] [3 4] [5 6]]]
            [[[7 8] [9 10] [11 12]]]
      • GPU나 TPU와 같은 연산 가속을 위한 특수한 하드웨어에서 실행할 수 있다.
      • Backward pass에서 계산된 Gradient (.grad)을 저장한다.
      • 기본적으로 torch.Tensor에 어떤 operation (더하기, 곱셈 등)을 취하면 해당 operation이 Computational Graph에 기록된다.
        • 해당 Tensor와 다른 배열들과 Parameter 간의 경사를 구하는 것.
        • Auto Differentation
          • Backward Propagation의 핵심개념이자 작동원리
          • 모두 Reverse Differentiation을 활용해서 Gradient Descent에 필요한 Gradient을 계산하는 것임
          • 즉, w = (w0, w1, ... ,wN)인 어떤 임의의 합성함수 L(w)에 대해서 우리는 dL/dwi을 구할 수 있는 것임.
# Import related library
import numpy as np
import torch

# Initializing a tensor
# 초기화 방법 1: 지정된 값으로 Tensor 초기화
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)

print(x_data)
print(x_data.dtype)

# 초기화 방법 2: 랜덤한 값으로 Tensor 초기화
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")

# 초기화 방법 3: Numpy 배열로부터 Tensor 초기화
data = [[1, 2],[3, 4]]
np_array = np.array(data)
x_np = torch.from_numpy(np_array)

print(x_np)
print(x_np.dtype)

# Tensor 데이터의 형식 지정
# Tensor의 데이터 형식은 어떤 것들이 있을까요?
# 1. 정수 int (integer) \
#     1-1. torch.int8, torch.int16, torch.int32, torch.int64 (torch.long) \
#     1-2. torch.uint8: unsigned integer로 양의 정수 0 ~ 255 숫자만 포함, 주로 이미지 데이터를 다룰 때 사용.
# 2. float \
#     2-1. torch.float16, torch.float32, torch.float64
# 3. boolean: torch.bool
# 4. etc.

# torch.float32 형식으로 초기화
data = [[1,2], [3,4]]
x_data = torch.tensor(data, dtype=torch.float32)
print(x_data)
print(x_data.dtype)

# torch.uint8 형식으로 초기화
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data, dtype=torch.uint8)
print(x_data)
print(x_data.dtype)

# 다른 dtype으로 변환
x_data = x_data.to(torch.float16)
print(x_data.dtype)

# 다른 Device로 Tensor 옮기기

# 1. GPU가 사용가능한지 확인하기
# 2. 다른 Device로 Tensor 옮기기
# 3. 어떤 Device상에 Tensor가 있는지 확인하기

# GPU가 사용가능한지 확인하기
print(torch.cuda.is_available())

# GPU로 Tensor 옮기기
# We move our tensor to the GPU if available
if torch.cuda.is_available():
    tensor = tensor.to("cuda")

# CPU로 Tensor 옮기기
x_data = x_data.cpu()
# x_data = x_data.to("cpu")

# 어떤 Device상에 Tensor가 있는지 확인하기
print(x_data.device)

# Tensor을 활용한 연산
# 1. Indexing and slicing
# 2. Concatenation
# 3. Arithmetric
# 4. Inplace-operation

# Indexing
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0 # 모든 행에대한 index 1에 해당하는 값을 0으로 바꿈
print(tensor)

# Concatenation
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)

# Arithmetric
y1 = tensor @ tensor.T # 행렬의 곱
y2 = tensor.matmul(tensor.T) # Matrix Multiple
print(y1)
print(y2)

# Element-wise 곱셈
z1 = tensor * tensor
z2 = tensor.mul(tensor)
print(z1)
print(z2)

# Inplace operation
print(f"{tensor} \n")
tensor.add_(5) # 각 원소에 5씩 더해주고 override(=Inplace) 해줌
print(tensor)

Deep Learning 실무 기초 개념

  • Training, Validation, Test dataset

    • Training (학습/훈련) 데이터셋
      • 모델을 학습시키는 용도
      • 딥러닝 모델의 경우 학습 데이터셋에 대해서 Gradient Descent하여 Loss가 최소화되도록 모델의 weight를 최적화함
    • Validation (검증) 데이터셋
      • 모델의 성능 평가와 Hyperparameter Tuning에 사용
        • Hyperparameter?
          • 모델 구조와 학습 방식에 영향을 주는 파라미터, 모델의 최종 성능에도 영향을 줌
        • Hyperparameter Tuning?
          • 가장 최적의 Hyperparameter 조합을 찾는 것.
          • Validation 성능이 가장 높은 조합 찾기
      • 학습 데이터셋에 대한 "Overfitting" 될 수 있기에 Validation 데이터셋으로 성능 평가
        • Overfitting(과적합)이란?
          • Unseen data에 대해서 모델의 예측값이 일반화되지 않는 경우
          • 뉴럴넷 모델이 학습 데이터에 있는 noise에 대해서도 학습하여, 일반화 성능이 저하되는 현상
          • Epochs(반복 학습)이 늘어날 수록 성능이 마냥 좋이지지 않는다. 어느 기점부터 Valid Loss가 증가하는 현상이 발생하는데 이를 과적합이라고 함
            • 예: 데이터 자체의 노이즈를 고려하지 않고 모델의 Degree를 마냥 높이면 실제 True f(x)와의 오차가 심하게 발생함
    • Test (시험) 데이터셋
      • 검증 단계에서 선택한 최적의 모델의 최종 성능을 평가하는데 사용
      • Hyperparameter Tuning을 과도하게 적용하는 경우, Validation dataset에 대해서 unintentional overfitting이 발생할 수 있다.
  • Overfitting

  • K-fold Cross Validation: 데이터셋이 너무 작아서 Validation dataset을 확보할 수 없을 때 사용

    1. 데이터 분할: 원본 데이터셋을 K 개의 서로 겹치지 않는 부분 집합으로 나눈다. (일반적으로 K=5 혹은 10 사용)

    2. 반복 학습 및 검증

      • 하나의 Fold를 검증 데이터로 사용

      • K-1 개의 폴드를 훈련 데이터로 사용하여 모델 학습

      • i) K = 6

      • Validation Training Training Training Training Training
        (Fold 1) Fold 2 Fold 3 Fold 4 Fold 5 Fold 6
      • ii)

        Training Validation Training Training Training Training
        Fold 1 (Fold 2) Fold 3 Fold 4 Fold 5 Fold 6
      • iii)

        Training Training Validation Training Training Training
        Fold 1 Fold 2 (Fold 3) Fold 4 Fold 5 Fold 6
      • iv)

        Training Training Training Training Training Validation
        Fold 1 Fold 2 Fold 3 Fold 4 Fold 5 (Fold 6)
  1. 성능 측정
    • 각 반복마다 모델은 검증용 폴드에 대한 성능 평가
    • 모든 K 번의 평가 완료 후에 평균 성능 계산
  2. 최종 성능 평가 혹은 Hyperparameter Tuning
    • Fold들에 대한 평균 성능을 최종 성능 지표로 사용
    • 혹은 Hyperparameter Tuning에 사용할 수도 있음
  3. 장점
    • 데이터를 효과적으로 활용하여 모델의 성능을 평가
    • 과적합 문제를 예방하고 모델의 일반화 성능을 더 신뢰성 있게 추정
    • 검증 데이터의 선택에 따라 모델의 평가 결과가 크게 변하지 않는다.
  • Hyperparameter Tuning
  • Loss와 Evaluation Metric의 차이
    • Loss Function
      • 예측한 값과 실제 타깃 값 사이의 차이
      • 학습 단계에서 Loss를 최소화하는 방향으로 모델의 Weight를 조정
      • 미분 가능해야 함 (Gradient Descent를 사용하기 위해)
      • Cross Entropy Loss, Mean Squared Loss 등
      • 결론: 모델 학습 단계에서 모델의 가중치를 조정하기 위한 목적으로 예측 오차를 측정
    • Evaluation Metric
      • 학습된 모델의 성능을 평가하는데 사용되는 지표
      • 손실 함수와 달리 평가 지표는 더 직관적이다.
      • 정확도(Accuracy), 정밀도(Precision), 재현율(Recall), F1 Score 등
      • 결론: 학습된 모델의 성능을 평가하고 보고하기 위해 사용
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

+ Recent posts