ADHD: 신경다양성의 진화적 재해석 - 인지 메커니즘의 숨겨진 잠재력

 

목차:

제1장: 서론 1.1 연구 배경

  • ADHD에 대한 기존 패러다임의 한계
  • 신경다양성 관점의 학술적 중요성
  • 연구의 목적과 가설

1.2 연구의 학제간 접근

  • 진화심리학
  • 인지신경과학
  • 사회문화적 관점

제2장: 이론적 프레임워크 2.1 진화심리학적 관점

  • 원시 사회에서 ADHD 특성의 생존 이점
  • 사냥, 위험 감지, 빠른 대응력 메커니즘
  • 현대 사회에서의 적응적 가치

2.2 신경생물학적 기반

  • 뇌 구조와 기능의 특수성
  • 신경전달물질 변이
  • 인지처리 메커니즘의 독특성

2.3 인지유연성 이론

  • 다중 작업 처리 능력
  • 창의적 문제해결 접근
  • 비선형적 사고 패턴

제3장: 연구 방법론 3.1 연구 설계

  • 혼합 방법론 접근
  • longitudinal 연구 방법
  • 다차원적 데이터 수집

3.2 연구 대상

  • 다양한 연령대와 배경의 ADHD 집단
  • 대조군 선정 기준
  • 윤리적 고려사항

3.3 측정 도구

  • 신경심리학적 평가
  • 기능적 MRI
  • 심층 인터뷰
  • 자기보고식 설문

제4장: 연구 결과 4.1 진화적 적응성 분석

  • 직업군별 ADHD 특성 강점
  • 위기상황에서의 대응력
  • 혁신적 문제해결 능력

4.2 인지적 특성 발견

  • 주의분산과 초점 전환 메커니즘
  • 감각 과부하 대처 전략
  • 정서조절의 역동성

4.3 사회문화적 함의

  • 다양성에 대한 인식 변화
  • 교육 및 직업 환경의 재설계
  • 개인화된 지원 모델

제5장: 논의 5.1 연구 결과 해석

  • 기존 의료모델에 대한 비판적 시각
  • ADHD의 재정의
  • 신경다양성 패러다임 제안

5.2 실천적 제언

  • 교육시스템 개선
  • 직장 내 포용 전략
  • 개인 맞춤형 지원 메커니즘

5.3 한계점과 future research

제6장: 결론

  • 패러다임 전환의 필요성
  • ADHD를 결함이 아닌 다른 형태의 인지적 강점으로 재인식
  • 사회적 포용과 이해의 중요성

부록:

  • 심층 인터뷰 전문
  • 뇌 스캔 이미지
  • 통계 데이터
  • 인포그래픽 자료

글쓴이 : 이종화

작성일자 : 2025-02-22

'끄적끄적' 카테고리의 다른 글

종합적, 비판적 사고에 관한 고찰  (0) 2025.02.02

시간 복잡도

  • 시간 복잡도란?
    • 반에 있는 사람들이 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)

+ Recent posts