페이지

2022년 8월 6일 토요일

STEP2 변수를 낳는 함수

 앞 단계에서 Variable클래스를 상자로 사용할 수 있게 했습니다. 하지만 지금 이대로는 그냥 상자일뿐입니다. 우리에겐 단순한 상자를 마법의 상자로 바꾸는 장치가 필요한데, 그 열쇠는 바로 '함수'입니다. 이번 단계에서는 함수에 대해 생각해보겠습니다.


1.3 [보충] 넘파이의 다차원 배열

 마지막으로 넘파이 다차원 배열에 관해 간단히 보충학셌습니다. 다차원 배열은 숫자 등의 원소가 일정하게 모여 있는 데이터 구조입니다. 다차원 배열에서 원소의 순서에는 방향이 있고, 이 방향을 차원(dimension) 혹은 축(axis)이라고 합니다. [그림 1-2]는 다차원 배령의 예입니다.

[그림 1-2]에는 외쪽부터 0차원 배열, 1차원 배열, 2차원 배열이 나오는데, 차례대로 스칼라(scalar), 벡터(vector), 행열(matrix)이라고 합니다. 스칼라는 단순히 하나의 수를 나타냅니다. 벡터는 하나의 축을 따라 숫자가 들어서 있고, 행렬은 축이 2개입니다.

다차원 배열을 텐서(tensor)라고도 합니다. [그림1-2]는 외쪽부터 0차원 텐서, 1차원 텐서, 2차원 텐서가 되겠죠.

넘파이의 ndarray 인스턴스에는 ndim이라는 인스턴스 변수가 있습니다. ndim은 'number of dimensions'의 약자로, 다차원 배열의 '차원수'를 뜻합니다

import numpy as np
x = np.array(1)
x.ndim
0

x = np.array([1,2,3])
x.ndim
1

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

벡터를 다룰 때는 '차원'이라는 말에 주의해야 합니다. 예를 들어 np.array([1,2,3])은 벡터인
데, 세개의 요소가 일렬로 늘어서 있기 때문에 '3차원 벡터'라고도 합니다. 이때 '벡터의 차원'
은 벡터의 원소수를 말합니다. 한편 '3차원 배열'은 (원소가 아닌) 축이 3개라는 뜻입니다.

이상과 같이 ndarray인스턴스를 사용하면 스칼라, 벡터, 행렬, 심지어 더 높은 차원의 텐서를
만들 수 있습니다.




1.2 Variable 클래스 구현

 변수는 영어로 variable입니다. 그래서 DeZero에서 사용하는 변수라는 개념을 Variable이라는 이름의 클래스로 구현하겠습니다. 덧붙여서, 파이썬에서는 클래스 이름의 첫 글자를 보통 대문자로 합니다. 파이썬이 권항하는 코딩 규칙은  PEP8을 참고하세요.

이제 Variable 클래스가 상자가 되도록 구현해보죠. 다음은 이 기능을 최소한의 코드로 작성해본 모습니다.

class Variable:
  def __init__(selfdata):
    self.data = data
보는 바와 같이 초기화 함수 __init__에 주어진 인수를 인스턴스 변수 data에 대입했습니다.
아주 간단한 코드지만, 이제 Variable클래스를 상자로 사용할 수 있습니다. 실제 데이터가
Variable의 data에 보관되기 때문이죠, 다음 예를 보면 더 명확해질 것입니다.
import numpy as np
data = np.array(1.0)
x = Variable(data)
print(x.data)

1.0
이 예에서 상자에 데이터는 '넘파이의 다차원 배열'을 사용했습니다. 이때 x는 Variable
인스턴스이며, 실제 데이터는 x안에 담겨 있습니다. 즉, x는 데이터 자체가 아니라 데이터를
담은 상자가 됩니다.

머신 러닝 시스템은 기본 데이터 구조로 '다차원 배열'을 사용합니다. 그래서 DeZero의
Variable 클래스는 넘파이의 다차원 배열만 취급합니다. 넘파이의 다차원 배열 클래스는
numpyu.ndarray이며 np.ndarray로 줄여 쓰곤 합니다. 넘파이 배열은 앞의 코드에서 볼 수
있듯 np.array함수를 이용해 생성할 수 있습니다. 이 책에서는 앞으로numpy.ndarray인스터스
를 단순히 ndarray 인스턴스라고 부르겠습니다.
이어서 앞 코드에 x에 새로운 데이터를 대입해 보겠습니다.

x.data = np.array(2.0)
print(x.data)
2.0

보는 바와 같이 x.data = ... 형태로 쓰면 새로운 데이터가 대입됩니다. 이제 Variable클래스
를 상자로 사용할 수 있게 되었습니다.

1.1 변수란

 본론으로 들어가서, 변수란 무엇일까요? 프로그래밍 입문서를 펼쳐보면 변수는 대락 [그림 1-1]과 같은 이미지로 설명합니다. [그림 1-1]과 같이 상자에 데이터를 넣는 그림을 보여주며 이 '상자'가 바로 변수라고 설명합니다. 변수를 상자에 비유한 설명은 변수의 성질을 (제법) 잘 보여줍니다. 정리하면 다음과 같습니다

1) 상자와 데이터는 별개다.

2) 상자에는 데이터가 들어간다(대입 혹은 할당한다).

3) 상자 속을 들여다보면 데이터를 알 수 있다(참조한다).


STEP 1 상자로서의 변수

 첫 번째 단계에서는 DeZero의 구성 요소인 '변수'를 만듭니다. 변수는 DeZero에서 가장 중요한 개념입니다. 이번 단계에서는 변수가 어떤 기능을 하는지 이해하고, 그 기능에 맞게 코드로 구현합니다.



제1고지 미분 자동 계산

 미분은 다양한 과학 기술 분야에 사용됩니다. 특히 립러닝을 포한한 머신러닝의 여러 분야에서 중추적인 역할을 합니다. 딥러닝 프레임워크는 말하자면 미분을 계산하기 위한 도구입니다. 그래서 이 책의 주제도 자연스럽게 '미분'과 이어집니다. 즉, 컴퓨터를 사용하여 미분을 계산하는 일이 주요 주제입니다.

지금부터 시작되는 제1고지는 총 10간계로 구성됩니다. 이 고지에서는 미분을 자동으로 계산하는 틀을 만듭니다. '미분을 자동으로 계산한다'라는 말은 미분을 (사람이 아니라)컴퓨터가 계산한다는 뜻입니다. 정확히 말하면, 어떤 계산(함수)을 코드로 구현하면 그 계산의 미분을 컴퓨터가 자동으로 계산해주는 시스템을 가리킵니다.

이번 고지에서는 미분을 자동으로 계산하기 위해 '변수'와 '함수'를 표현하는 두 클래스 Variable과 Function을 만듭니다. 놀랍게도 이 두 클래스만으로 미분 자동 계산의 기반이 완성됩니다. 제1고지가 끝날 무렵에는 간단한 계산(함수)의 미분은 자동으로 계산할 수 있게 됩니다. 그럼 DeZero의 첫 번째 단계로 발을 내디뎌보죠.

2022년 8월 3일 수요일

5.3.1 특성 추출

 특성 추출은 사전에 학습된 네트워크의 표현을 사용하여 새로운 샘플에서 흥미로운 특성을 ㅂ뽀아내는 것입니다. 이런 특성을 사용하여 새로운 분류기를 처음부터 훈련합니다.

앞서 보았듯이 컨브넷은 이미지 분류를 위해 두 부분으로 구성됩니다. 먼저 연속된 합성곱과 풀링 층으로 시작해서 완전 연결 분류기로 끝납니다. 첫 번째 부분을 모델의 합성곱 기반 층(convolutional base)이라고 부르겠습니다. 컨브넷의 경우 특성 추출은 사전에 훈련된 네트워크의 합성곱 기반층을 선택하여 새로운 데이터를 통과시키고, 그 출력으로 새로운 분류기를 훈련합니다.


왜 합성곱 층만 재사용할까요? 완전 연결 분류기도 재사용할 수 있을까요? 일반적으로 권장히지 않습니다. 합성곱 층에 의해 삭습된 표현이 더 일반적이어서 재사용이 가능하기 때문입니다. 컨브넷의 특성 맵은 사진에 대한 일반적인 콘셉트의 존재 여부를 기록한 맵입니다. 주어진 컴퓨터 비전 문제에 상관없이 유용하게 사용할 수 있습니다. 하지만 뷴류기에서 학습한 표현은 모델이 훈련된 클래스 집합에 특화되어 있습니다. 분류기는 전체 사진에 어떤 클래스가 존재할 확률에 관한 정보만 담고 있습니다. 더군다나 완전 연결 층에서 찾은 표현은 더 이상 입력 이미지에 있는 객체의 위치 정보를 가지고 있지 않습니다. 완전 연결 층들은 공간 개념을 제거하지만 합성곱의 특성맵은 객체 위치를 고려합니다. 객체 위치가 중요한 문제라면 완전 연결 층에서 만든 특성은 크게 쓸모가 없습니다.
특성 합성곱 층에서 추출한 표현의 일반성(그리고 재사용성) 수준은 모델에 있는 층의 깊이에 달려 있습니다. 모델의 하위 층은(에지, 색깔, 질감 등) 지역적이고 매우 일반적인 특성 맵을 추출합니다. 모델의 하위 층은(에지, 색깔, 질감 등) 지역적이고 매우 일반적인 특성 맵을 추출합니다. 반면에 상위 층은('강아지 눈'이나 '고양이 귀'처럼) 좀 더 추상적인 개념을 추출합니다. 새로운 데이터셋이 원본 모델이 훈련한 데이터셋과 많이 다르다면 전체 합성곱 기반 층을 사용하는 것보다는 모델의 하위 층 몇 개만 특성 추출에 사용하는 것이 좋습니다.

ImageNet의 클래스 집합에는 여러 종류의 강아지와 고양이를 포함하고 있습니다. 이런 경우 원본 모델의 완전 연결 층에 있는 정보를 재사용하는 것이 도움이 될 것 같습니다. 하지만 새로운 문제의 클래스가 원본 모델의 클래스 집합과 겹치지 않는 좀 더 일반적인 경우를 다루기 위해서 여기서는 완전 연결 층을 사용하지 않겠습니다. ImageNet 데이터셋에 훈련된 VGG16네트워크의 합성곱 기반 층을 사용하여 강아지와 고양이 이미지에서 유요한 특성을 추출해 보겠습니다. 그런 다음 이 특성으로 강아지 vs. 고양이 분류기를 훈련합니다.
VGG16모델은 케라스에 패키지로 포함되어 있습니다. keras.applications 모듈에서 임포트할 수 있습니다. keras.application 모듈에서 사용 가능한 이미지 분류 모델은 다음과 같습니다.
(모두 ImageNet 데이터셋에서 훈련되었습니다).
1) Xception
2) Inception V3
3) REsNet50
4) VGG16
5) VGG19
6) MobileNet

VGG16모델을 만들어 보죠.

from keras.applications.vgg16 import VGG16

conv_base = VGG16(weights='imagenet',
                  include_top=False,
                  input_shape=(1501503))

VGG16함수에 3개의 매개변수를 전달합니다.
1) weights는 모델을 초기화할 가중치 체크포인트(checkpoint)를 지정합니다.
2) include_top은