Study

2023-05-08. 딥러닝, 신경망, 신경망 데이터 표현, 텐서

86400 2023. 5. 9. 00:16

 

 

1. 딥러닝

: 딥러닝이란 신경망을 공부하는 것

- 이미테이션 게임: 1940년대 후반에 튜링의 B타입 기계 형식으로 처음 형태를 갖추었고, 인간의 학습 과정을 연구하는 신경 과학자와 인지 신경학자들의 신경가소성에 대한 초기 연구에 의존

- 제프리 힌튼

- CPU, GPU

- 딥러닝의 발전: ILSVRC _ 2010, 28% 오류에서 2017, 2.25% 줄이게 되는 계기

(AlexNet, 제프리 힌튼 신경망 생성, 8개의 칩을 만들어 연결시킴 - 이게 딥러닝이라고 일컬음, 이후 레이어 숫자가 늘어나면서 오류가 급격히 감소하게 됨) 

 

1.1. Framework

  • TensorFlow: C++, 직관적인 API,
  • Keras: 쉬운 API, 탠서플로우 연계, CPU, GPU에서 실행 가능(쿠다)
  • maxnet
  • PyTorch: 페이스북, C/CUDA 백앤드로 사용 등등(자료 참고 다시 작성)
  • Caffe
  • MS Congitive Toolkit
  • ONNX (중간 파일 역할)
  • etc

 

1.2. 신경망(Neural Network)

  • 입력(inputs) - 가중치(weight) - 활성함수 (Activation Function)
  • 활성함수: ReLU, 시그모이드 함수(S자형 시그모이드 곡선, 로지스틱), 쌍곡탄젠트 함수 등이 대표적인 활성함수
  • 시그모이드: 여러 종류의 시그모이드 함수는 인공 뉴런의 활성화 함수로 사용되었다. 통계학에서도 로지스틱 분포, 정규 분포, 스튜던트 t 분포 등의 누적 분포 함수로 시그모이드 곡선이 자주 등장한다. 시그모이드 함수는 가역 함수로, 그 역은 로짓 함수다.

시그모이드
ReLU https://ko.wikipedia.org/wiki/ReLU

 

  • 뉴런의 개수가 많은 것(input layer, 큰 문제 해결, 정보량 많음) > hidden layer(레이어가 많다는 것, 깊은 문제 해결) > Output layer
  • 대다수 Dense Layer로 처리

 

1.3. 신경망의 활용

  1. 회귀
  2. 분류

 

2. 신경망 기초

  • 1차함수 (직선)
import math
import numpy as np
import matplotlib.pyplot as plt

# 일차함수의 표현
def linear_function(x):
  a = 0.5
  b = 2

  return a*x + b

print(linear_function(50))

# 범위 지정 -5에서 5까지, 0.5씩 증가
x = np.arange(-5, 5, 0.5)
y = linear_function(x)

# 시각화 - 딥러닝은 어디 지점에서 어떤 것이 있는지 눈으로 확인 하기
plt.plot(x, y)

# 예쁘게 꾸미기, x라벨, y라벨, 이름 지정
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('linear_function')

 

  • 2차함수 (곡선): 곡선 활용을 하여 오류가 가장 작은 값을 찾기 쉬워짐 왜냐하면 오류가 작아졌다가 늘어나기 때문입니다, 최솟값 즉 최적값을 구하기 위해 곡선으로 표현합니다. 그래프의 어떤 한 점을 찍었을 때 그 값이 내려가는지 올라가는지 확인하는 것은 이전 값과 앞에 있는 값을 알고서 확인할 수 있습니다, 이 앞 값과 뒷 값을 줄이면서 확인하게 되고 이게 미분이라고 합니다. 여기서 기울기의 중요성이 대두되는데 이 기울기는 문제를 찾아가는 방법이기도 합니다. 어떤 한 지점에서 다른 점으로 넘어갔을 때 최솟값(최적값)을 지나갔는가 지나가지 않았는가 확인하면서 계속 알아가게 되고, 이 기울기의 방향에 따라 잘라서 볼 수 있습니다.
# 2차함수의 표현
def quadratic_funtion(x):
  a = 1
  b = -1
  c = -2

# 곱하기 나중에 확인 안되는군
  return a*x**2 + b*x + c

print(quadratic_funtion(20))

# 2차 시각화
x = np.arange(-5, 5, 0.5)
y = quadratic_funtion(x)

plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('quadratic_function')

 

  • 3차함수 (이미지): 인간의 눈으로 확인할 수 있는 최대 차원
  • Image(3차원) / Color Image Datasets(4차원, 여러 장의 이미지) / 동영상(5차원)
# 3차 함수의 표현
def cubic_funciton(x):
  a = 4
  b = 0
  c = -1
  d = -38

  return a*x**3 + b*x**2 + c*x + d

x = np.arange(-5, 5, 0.5)
y = cubic_funtion(x)

plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('cubic_function')

 

  • 4차함수 (이미지들의 조합, 좁은 의미의 영상)
  • 5차함수 (넓은 의미의 영상)
  • 지수/로그 함수
  • 미분/편미분

 

2.1. 신경망 데이터 표현

  • 신경망 데이터의 분류: DNN, CNN, RNN
  • 텐서(Tensor) - 데이터> 데이터를 흘려 보내면서 가중치(w) 접목 시킴> 가장 좋은 가중치가 세팅될 때까지 계속 돌려봄> 최적의 가중치가 모델(Model)
  • 데이터 각 차원별로 변환(1차원이나 2차원, 3차원 텐서를 흘러보내게 됐을 때 이미지(CNN)와 시계열데이터(증권사에서 사용, RNN) 등, 4차원 텐서를 흘려보냈을 경우 영상 등)> 가중치 파악> 가장 최적의 가중치 모델 파악
  • 요즘에는 필요한 요소들을 통해 동작시키면 됨
  • 시계열 데이터: 가격, 시간, 지표(금리, 환율, 실적, 카더라(?)) 등 / 이 신경망을 나타내는 건 좀 다름

 

2.2. 텐서의 표현

# 스칼라: 요소 하나가 들어간 배열, 모양 없는 데이터, 0차원
x = np.array(3)
print(x)

# 모양 확인
print(x.shape)

# 차원 확인
print(x.ndim)



# 1차원 텐서: 한 줄 배열, 열 없이 1차원
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
c = a+b # 같은 차원의 연산

# 텐서의 특징(브로드캐스팅): 서로 차원이 달라도 연산이 가능, 빈 자리를 채워줌
d = ax # 1차원과 0차원 사이의 연산

print(d) # 1차원 텐서 사이의 연산 (같은 자리끼리의 연산)
print(d.shape)
print(d.ndim)


x = np.array([1, 2, 0])
y = np.array([0, 2, 1])
z = np.dot(x, y)

print(z)
print(z.shape)
print(np.ndim(z))

# 벡터의 곱, 요약할 때 사용 이 부분 연결 끊겨서 다시 확인******************
# 두 1차원 백터가 있을 때 각각의 성분끼리의 곱을 모두 더함



# 2차원 텐서: 정확하게 그리면 큰 사각형 안에 작은 사각형 6개가 2줄, 3칸으로 존재
matrix = np.array([[10, 20, 30], [40, 50, 60]])

print(matrix)
print(matrix.shape)
print(np.ndim(matrix))

a = np.array([[10, 20], [30, 40]])
b = np.array([[100, 100], [100, 100]])

print(a * b)

# 전치 행렬
a = np.array([[10, 20, 30], [40, 50, 60]])

print(a)
print(a.shape)
print(np.ndim(matrix))

# 전치 행렬의 저장
# T: 전치행렬

a_ = a.T

print(a_)
print(a_.shape)
print(np.ndim(a))



# 3차원 텐서
- 나중에 이미지 처리, 비전 쪽이기 때문에 많이 볼 것, 익숙해져야 할 필요 있음

x = np.array([[[1, 2, 3, 5],
               [1, 3, 5, 5],
               [3, 2, 1, 6]],
              [[1, 1, 1, 1],
               [2, 2, 2, 2],
               [3, 3, 3, 3]],
              [[4, 4, 4, 4],
               [5, 5, 5, 5],
               [6, 6, 6 ,6]]])

print(x)
print(x.shape)
print(np.ndim(x))

 

  • 0차원(스칼라): 요소가 하나 있는 것, 방향 x,1차원 텐서(배열), 2차원(행렬이라고 하지만 대다수 2차원 텐서라고 표현), 3차원
  • 브로드캐스팅: 같은 차원이 아니더라도 빈 자리를 채워서 연산
  • 숫자로 된 배열 - 넘파이(nd.array)로 표현합니다 / 참고로 파이토치는 다른 포맷으로 이뤄져 있음
  • 전치행렬: column과 row를 바꿉니다 (세로의 2차원 텐서가 가로의 2차원 텐서로 표현, 엑셀의 피벗테이블과 유사합니다)

 

2.3. 논리회로 게이트

# 논리 게이트



# AND
def AND(a, b):
  input = np.array([a, b])

  # 가중치 - 세팅하고 값이 마음에 안 들면 다시 가중치 재조정 반복> GPU 한도 내에서 스스로 찾아봄
  weights = np.array([0.4, 0.4])

  # b
  bias = -0.6

  # 수식으로 값 넣기(각 배열을 곱해서 합에 bias 더함)
  value = np.sum(input * weights) + bias

  # if 문으로 논리구조 만듦 (0, 1로 리턴)
  if value <= 0:
    return 0
  else:
    return 1



# NAND
def NAND(a, b):
  input = np.array([a, b])
  weights = np.array([0.4, 0.4])
  bias = -0.6

  value = np.sum(input * weights) + bias

  if value <= 0:
    return 1
  else:
    return 0

# function 호출
print(AND(0, 0))
print(AND(0, 1))
print(AND(1, 0))
print(AND(1, 1))

print('-------------')
print(NAND(0, 0))
print(NAND(0, 1))
print(NAND(1, 0))
print(NAND(1, 1))

# 시각화
x1 = np.arange(-2, 2, 0.01)
x2 = np.arange(-2, 2, 0.01)
bias = -0.6

y = (-0.4 * x1 - bias) / 0.4

# 수직선, 수평선
plt.axvline(x=0)
plt.axhline(y=0)

plt.plot(x1, y, 'r--')
# 안쪽은 0, 바깥쪽은 1, (1, 1)만 바깥쪽으로 표현되고 있음

# 점찍기 (좌표, 컬러(color), 마커, 사이즈)
plt.scatter(0,0,color='orange', marker='o',s=150)
plt.scatter(0,1,color='orange', marker='o',s=150)
plt.scatter(1,0,color='orange', marker='o',s=150)
plt.scatter(1,1,color='black', marker='^',s=150)

# 그래프 범위 제약, x, y limit, grid 표현
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.grid()



# OR 
def OR(a, b):
  input = np.array([a, b])
  weights = np.array([0.4, 0.4])
  bias = -0.3

  value = np.sum(input * weights) + bias

  if value <= 0:
    return 1
  else:
    return 0

# NOR
def NOR(a, b):
  input = np.array([a, b])
  weights = np.array([0.4, 0.4])
  bias = -0.3

  value = np.sum(input * weights) + bias

  if value <= 0:
    return 0
  else:
    return 1

print(OR(0, 0))
print(OR(1, 0))
print(OR(0, 1))
print(OR(1, 1))

print('-------------------')
print(NOR(0, 0))
print(NOR(1, 0))
print(NOR(0, 1))
print(NOR(1, 1))



# XOR
def XOR(x1, x2):
  s1 = NAND(x1, x2)
  s2 = OR(x1, x2)
  y = AND(s1, s2)

  return y

print(XOR(0,0))
print(XOR(0,1))
print(XOR(1,0))
print(XOR(1,1))

 

2.4. 퍼셉트론

퍼셉트론(perceptron)은 인공신경망의 한 종류로서, 1957년에 코넬 항공 연구소(Cornell Aeronautical Lab)의 프랑크 로젠블라트 (Frank Rosenblatt)에 의해 고안되었다. 이것은 가장 간단한 형태의 피드포워드(Feedforward) 네트워크, 선형분류기로도 볼 수 있다.