열심히 코딩 하숭!
1. 딥러닝에 꼭 필요한 파이썬의 개념 | 파이토치 딥러닝 프로그래밍 본문
차근차근 실습하며 배우는 파이토치 딥러닝 프로그래밍 | 위키북스
3월달부터 개발 동아리에 들어가게 되었다! 현재까지 동아리 부원들과 함께 딥러닝 스터디를 진행하고 있다
스터디에서 " 차근차근 실습하며 배우는 파이토치 딥러닝 프로그래밍" 교재를 활용하여 공부하고 있기 때문에
이에 대해 정리한 개념을 티스토리에 남기려고 한다~🙉
0. 기본적인 동작 구조
⇒ 딥러닝 기본 구조: 실제값과 예측값의 차이인 오차를 최소로 만들기 위해 손실 함수를 최소화하는 모델 파라미터를 경사 하강법을 토대로 수정해나간다
⇒ 파이토치: 위에서 말한 동작 구조를 다음과 같은 함수를 사용해 구현한다
💡 함수명이 새로워서 그런지, 딥러닝을 처음 공부하는 것이 아닌데 생소하게 느껴짐
어느정도 공부한 후에 해당 그림을 다시 살펴보는 것으로 하자
1. 딥러닝에 꼭 필요한 파이썬의 개념
1.2 컨테이너 타입 변수에 주의
1) 컨테이너 타입
- 실제 데이터에 액세스하기 위해 인덱스를 거쳐야하는 데이터 (→ list, numpy array)
2) 문제점
- numpy의 array: 변수 설정 시 포인터가 사용되므로, 값 변경 시 두 변수의 array값이 함께 변경되는 것처럼 보일 수 있다
- torch의 Tensor: 텐서를 array로 변환하여 저장하였을 때, tensor값이 바뀌면 array값도 같이 변경된다
import numpy as np
x = np.array([1,2,3])
y = x
x[1] = 0 # 값 변경
print(x)
print(y)
# 결과 #
[1 0 3]
[1 0 3]
import torch
x1 = torch.ones(5)
x2 = x1.data.numpy()
x1[1] = -2 # 값 변경
print(x1)
print(x2)
# 결과 #
tensor([1., -2., 1., 1., 1.]
[1. -2. 1. 1. 1.]
3) 해결 방법
- x2가 x1을 참조하지 않으려면 copy()함수를 사용하면 된다
x1 = torch.ones(5)
x2 = x1.data.numpy().copy()
4) 궁금증
- tensor끼리도 포인터를 통해 값이 저장되나?
- 맞음!
1.3 ‘합성함수’를 파이썬으로 구현하기
1) 합성함수
- 어떤 함수의 출력이 다른 함수의 입력이 되는 과정 f( g(x) )
1.4 ‘미분’과 파이썬의 ‘수치 미분’ 구현하기
1) 함수의 함수
- 함수를 인수로 받아서 함수를 반환하는 것
2) 수치 미분
- h에 매우 작은 값을 넣어 수치 계산을 통해 근사치를 구한다
↔ 해석적 미분은 우리가 아는 미분 공식이라고 생각하면 된다
3) 코드를 통해 확인
- fdiff(f) 함수 | sigmoid 함수에 적용
def fdiff(f):
def diff(x):
h = 1e-6
return (f(x+h)-f(x-h)) / (2*h)
return diff
# f의 미분함수인 diff를 얻는다
diff = fdiff(f)
# x라는 특정 점에서의 미분값(기울기)을 계산한다
y_dash = diff(x)
print(y_dash)
def g(x):
return 1 / (1+np.exp(-x))
diff = fdiff(g)
y_dash = diff(x)
print(y_dash)
- 근사값을 활용하여 fdiff함수를 작성하니, 복잡한 합성함수의 미분값을 간편하게 구할 수 있다
4) 딥러닝에서
- 딥러닝의 학습 알고리즘은 ‘손실’이라고 하는 방대한 파라미터를 가진 복잡한 합성 함수의 미분계산을 수행하고, 그 결과를 이용해서 최적의 파라미터 값을 구하는 구조다
- 때문에 파이토치는 수치미분을 사용한 미분계산을 간단히 처리하는 구조를 내장하고 있다
1.5 커스텀 클래스 정의하기
- 파이토치로 머신러닝 또는 딥러닝 모델을 구축할 경우, 커스텀 클래스의 정의가 필요하다
1) 클래스 기본 형태
import matplotlib.pyplot as plt
import matplotlib.patches as patches
class Point:
def __init__(self, x, y): # 생성자
self.x = x
self.y = y
def draw(self): # 클래스의 함수
plt.plot(self.x, self.y, marker='o', markersize=10, c='k')
p1 = Point(2, 3)
print(p1.x, p1.y)
p1.draw()
- self의 개념
- Class 타입의 어떤 객체가 method를 호출하면, Python은 그 객체를 self 매개변수를 통해 메서드에 전달한다
- 이를 통해 메서드 내에서는 self를 사용하여 해당 인스턴스의 다른 속성이나 메서드에 접근할 수 있다
- 실제로 함수를 호출할 때는 self인수는 지정하지 않는다 (python이 자동으로 처리해준다!)
2) 클래스 상속 기본
class Circle1(Point): # Point라는 클래스를 상속받음
def __init__(self, x, y, r):
super().__init__(x,y) # x, y는 부모 클래스의 __init__함수를 호출하여 설정한다
self.r = r
c1_1 = Circle1(1, 0, 2)
c1_1.draw() # <= 부모 클래스의 draw 함수가 출력된다
3) 오버라이드
class Circle2(Point):
def __init__(self, x, y, r):
super().__init__(x,y)
self.r = r
def draw(self): # 부모 클래스에 있던 함수를 오버라이딩하여 재정의한다
c = patches.Circle(xy=(self.x,self.y), radius = self.r, fc='b', ec='k')
ax.add_patch(c)
c2_1 = Circle2(1, 0, 2)
c2_1.draw()
- Circle2 클래스에서 정의한 draw() 함수가 실행된다
- 오버라이드: 부모 클래스와 같은 이름의 함수를 자식 클래스에서 역할을 달리 정의하는 것
4) 오버라이드 - 부모 클래스의 함수를 불러오기
class Circle3(Point):
def __init__(self, x, y, r):
super().__init__(x,y)
self.r = r
def draw(self): # 부모 클래스에 있던 함수를 오버라이딩하여 재정의한다
super().draw() # 부모 클래스의 함수를 불러온다
c = patches.Circle(xy=(self.x,self.y), radius = self.r, fc='b', ec='k')
ax.add_patch(c)
c3_1 = Circle2(1, 0, 2)
c3_1.draw()
- super().함수()를 사용하여 부모 클래스의 함수를 불러온다
1.6 인스턴스를 함수로 사용하는 방법
1) call - 객체를 함수처럼 호출
class H:
def __call__(self, x):
return 2*x**2 + 2
x = np.arange(-2, 2.1, 0.25)
h = H()
y = h(x)
- 클래스로 생성한 인스턴스를 함수로 사용할 수 있다
- pytorch 라이브러리 내부의 다양한 부분에서 이 방법을 사용하고 있다. 알아두기!
💡 나중에 pytorch 코드 리뷰할 때 헷갈리지 않도록 잘 숙지하기!
'프로그래밍 책 > 파이토치 딥러닝 프로그래밍' 카테고리의 다른 글
9. CNN을 활용한 이미지 인식 | 파이토치 딥러닝 프로그래밍 (1) | 2024.04.21 |
---|---|
8. MNIST를 활용한 숫자 인식 | 파이토치 딥러닝 프로그래밍 (1) | 2024.04.21 |
4. 예측 함수 정의하기 | 파이토치 딥러닝 프로그래밍 (1) | 2024.04.17 |
3. 처음 시작하는 머신러닝 | 파이토치 딥러닝 프로그래밍 (0) | 2024.04.17 |
2. 파이토치의 기본 기능 | 파이토치 딥러닝 프로그래밍 (0) | 2024.04.16 |