딥러닝 이론: 2.분류

milkbuttercheese·2023년 2월 1일
0

Dive_into_Deeplearning

목록 보기
2/7
post-custom-banner

정보이론

정보량의 정의

  • 예시
    - 전기신호로 동전 5번 던지는 시행을 한다 하자. 이때 던진 결과가 어떤지 묻기위해 몇번의 질문을 해야 하는가? 결과의 경우의 수는 몇개가 있는가?
    - 총 5번 질문하면된다
    - 동전 한번 던지는 경우당 2회로 하여 252 ^{5} 개의 경우의 수가 존재한다
    - 이를 통해 질문갯수=log2\log_{2}{}(가능한 결과의 수) 라는 공식이 성립한다
  • Hartely의 정보량 정의
    - 정답을 구분해내기 위해 필요한 질문의 개수
    - H=nlog2sH=n \log_{2}{s} :
    - nn : 문자열의 갯수
    - ss : 각 선택에서 가능한 결과의 수
    - 하나의 문자열 구분해내기 위한 질문의 수는 sns ^{n} 이기 때문이다

엔트로피의 정의

  • 예시
    - A,B,C,D를 각각 0.25확률로 출력하는 기계 P와 A,B,C,D를 각각 0.5,0.125,0.125,0.25로 출력하는 기계 Q가 있다하자
    - 각 기계 가 출력하는 문자를 구분하기 위해 필요한 최소 질문 갯수를 구하자
  • 기계 P의 경우는
    1. 출력이 A,B 중에 있나, C,D중에 있냐고 묻는다
    2. A,B중이라고 한 경우 A인지 묻고, C,D중이라 한경우 C인지 묻는다
  • 기계 Q의 경우는
    1. 출력이 A중에 있나, B,C,D중에 있냐고 묻는다
    2. A인 경우 확정, B,C,D인 경우 B,C중에 있나 D중에 있나 묻는다
    3. D인 경우 확정 B,C인 경우 B인가 묻는다
  • 이때 각 기계에 대하여 정답을 구하기 위해 필요한 평균 질문 갯수를 구하자
    - 기계 P의 경우 2개이다
    - 기계 Q의 경우
    - A일 경우 필요한 질문수는 1, A일 확률은 P(A)=0.5P(A)=0.5
    - B,C인 경우 필요한 질문수는 3, B일 확률,C일 확률 각각 P(B)=P(C)=0.125P(B)=P(C)=0.125
    - D일 경우 필요한 질문수는 2, D일 확률 P(D)=0.25P(D)=0.25
    - 즉 평균 질문수는 10.5+3(0.1252)+20.25=0.5+0.75+0.5=1.751 \cdot0.5 +3 \cdot(0.125 \cdot2)+2 \cdot 0.25=0.5+0.75+0.5=1.75
  • 똑같은 경우의수 A,B,C,D를 갖고 있더라도, 해당 결과가 선택될 확률이 다르면, 평균 질문수는 바뀌게 된다. 이 예제에선 기계 Y가 기계 X보다 더 적은 질문을 해서 알아낼 수 있는 정보, 즉 더 적은 정보량을 갖고 있다고 해석한다
    - 필요한 질문의 수는 최적 전략하에선 log21p(xi)\log_{2}{\displaystyle\frac{1}{p(x _{i})}} 라고 볼 수 있다.
  • Shannon의 엔트로피 정의
    - H=ip(xi)log21p(xi)=ip(xi)log2p(xi)H=\displaystyle\sum_{i}^{}{p(x _{i})}\cdot \log_{2}{\displaystyle\frac{1}{p(x _{i})}}=-\displaystyle\sum_{i}^{}{p(x _{i})\cdot \log_{2}{p(x _{i})}}
    - 엔트로피는 최적 전략하에서 결과를 확인하는데 필요한 질문의 갯수 기댓값이다
    - 엔트로피는 모든 사건이 동등한 확률로 발생할 떄 가장 큰 값을 갖는다.

크로스 엔트로피 정의


  • - 앞선 예제에선 기계 P는
    1. 출력이 A,B 중에 있나, C,D중에 있냐고 묻는다
    2. A,B중이라고 한 경우 A인지 묻고, C,D중이라 한경우 C인지 묻는다
    - 로 2번의 질문으로 이루어 졌었고
    - 기계 Q의 경우는
    1. 출력이 A중에 있나, B,C,D중에 있냐고 묻는다
    2. A인 경우 확정, B,C,D인 경우 B,C중에 있나 D중에 있나 묻는다
    3. D인 경우 확정 B,C인 경우 B인가 묻는다
    - 이 질문은 각 확률분포에 대해 최소로 질문하기 위한 최적 전략이였는데, 만약 기계 Q에 대하여 기계 P에 사용된 전략을 활용한다면 어떻게 되는지 계산해볼 수 있다.
    - A일 경우 A,B 질문 다음 AA 인가를 물어 질문 2개.
    - B일 경우 A,B 질문 다음 A인가를 물어 질문 2개
    - C일 경우 C,D 질문 다음 C인지 물어 질문 2개
    - D일경우 C,D 질문 다음 D인지 물어 질문 2개
    - 즉 2*(0.5+0.125+0.125+0.25)=2 필요한 평균 질문수가 2개가 된다

  • 크로스 엔트로피란 특정 전략하에 결과를 확인하는데 필요한 질문의 갯수 기댓값이다
    - 엔트로피가 최적 전략하에 결과를 확인하는데 필요한 질문의 갯수이므로, 항상 크로스 엔트로피보다 작은값을 가진다

  • 정의
    - Hp(q)=ipilog21qi=ipilog2qiH _{p}(q)=\displaystyle\sum_{i}^{}{p _{i}\log_{2}{\displaystyle\frac{1}{q _{i}}}}=-\displaystyle\sum_{i}^{}{p _{i}\log_{2}{q _{i}}}
    - 여기서 log21qi\log_{2}{\displaystyle\frac{1}{q _{i}}} 는 기계 Q의 최적전략을 활용하였을 때 필요한 질문의 갯수이다
    - 만약 여기서 p=[0.5,0.125,0.125,0.25]p=[0.5,0.125,0.125,0.25] 이고 q=[0.25,0.25,0.25,0.25]q=[0.25,0.25,0.25,0.25] 라 하자. 이런 상황에서 qiq _{i} 를 학습시키고 있다면 qipiq _{i} \to p _{i} 가 될수록 cross-entropy값을 작아지게 된다

  • 증명 : 미완
    - Jensen's Inequality와 관련이 있다는 내용이 있음 -> 후에 증명해보도록 하자

KL-Divergence의 정의

  • Kullback-Leibler 발산이란 뜻으로, 여기서 Divergence란 벡터장의 발산이 아닌 (확률분포의 )차이를 의미한다. 따라서 relative entropy라고 불리기도 한다
  • 정의
    - DKL(PQ)=xP(x)log(P(x)Q(x))D _{KL}(P||Q)=\displaystyle\sum_{x }^{}{P(x)\log_{}{(\displaystyle\frac{P(x)}{Q(x)})}}
    - =E[logP(x)]E[logQ(x)]=\mathbb{E}[\log_{}{P(x)}]-\mathbb{E}[\log_{}{Q(x)}]
    - =HP(Q)H(P)=H _{P}(Q)-H(P)
    - 즉 실제분포 PP와 추측된 분포 QQ 사이 크로스 엔트로피와 엔트로피의 차로 해석할 수 있다

Ref.

  • . logab=logcblogca\log_{a}{b}=\displaystyle\frac{\log_{c}{b}}{\log_{c}{a}}
  • proof
    - logab=x\log_{a }{b}=x
    - ax=ba ^{x}=b
    - logcax=logcb\log_{c}{a ^{x}}=\log_{c}{b}
    - xlogca=logcbx \log_{c}{a}=\log_{c}{b}
    - x=logcblogca=logabx=\displaystyle\frac{\log_{c}{b}}{\log_{c}{a}}=\log_{a}{b}
  • (log2x)x=x(1log2logx)=1x1log2\cfrac{\partial {(\log_{2}{x}})}{\partial {x}}=\cfrac{\partial {}}{\partial {x}}(\displaystyle\frac{1}{\log_{}{2}}\cdot \log_{}{x})=\displaystyle\frac{1}{x}\cdot \displaystyle\frac{1}{\log_{}{2}}

Softmax Regression

  • 회귀문제는 분류문제와 명확하게 구분되는것은 아니다.
  • 회귀 문제는 자연수 순서매기기로 클래스를 구분지을 수 없다. 이를 해결하기 위해 다음과 같은 방법을 활용한다
    - 원-핫 인코딩: 각 카테고리의 수만큼의 차원을 갖는 벡터가 있다 하자. 이 벡터는 어떤 데이터포인트가 jthj ^{th} 카테고리에 속한다면 이에 대응되는 벡터는jthj ^{th} 의 위치만 1이고 나머지 값은 0이라 정의한다
  • 몇가지 조건을 추가한다면 분류문제는 단순 vector-valued 회귀문제로 다룰수 있게 된다. 각 output ojo _{j} 에 대하여
    - ioi=1\displaystyle\sum_{i}^{}{o _{i}}=1 결과값들의 합이 1이 되어야한다
    - ojo _{j} 는 음수이거나 1를 초과하는 값이여선 안된다
  • Softmax 함수를 활용하면 이 문제를 해결할 수 있다
    - y^=softmax(o)\hat{y}=softmax(\boldsymbol{o}) , where y^i=exp(oi)jexp(oj)\hat{y}_{i}=\displaystyle\frac{exp(o _{i})}{\displaystyle\sum_{j}^{}{exp(o _{j})}}
    - softmax함수는 이 argument들 사이의 크기 순서까지 보존한다.

Log-likelihood

  • 소프트맥스 함수는 각 각 클래스에 대한 조건부 확률을 계산할 수 있다.
    - P(yx)=i=1nP(y(i)x(i))\boldsymbol{P}(\boldsymbol{y}|\boldsymbol{x})=\prod_{i=1}^{n}{P(\boldsymbol{y}^{(i)}|\boldsymbol{x}^{(i)})}
  • Cross-Entropy
    - 두 확률 분포가 얼마나 유사한지를 측정하는 함수이다
    - Hp(q)=i=1nq(xi)log(p(xi))H _{p}(q)=\displaystyle\sum_{i=1}^{n}{q(x _{i})log(p(x _{i}))}
    - qq 는 실제이며, 알지못하고 있는 분포이다
    - Cross-Entropy는 분류문제에서 loss-function으로 활용된다

Softmax와 Cross-Entropy

  • softmax 함수와 이에 대응되는 크로스 엔트로피는 일반적으로 활용된다.
  • L(y,y^)=j=1qyjlogexp(oj)k=1qexp(ok)L(\boldsymbol{y},\hat{\boldsymbol{y}})=-\displaystyle\sum_{j=1}^{q}{y _{j}\log_{}{\displaystyle\frac{exp(o _{j})}{\displaystyle\sum_{k=1}^{q}{exp(o _{k})}}}}
    - =j=1qyj[log(k=1qexp(ok))]j=1qyjoj=\displaystyle\sum_{j=1}^{q}{y _{j}[log(\displaystyle\sum_{k=1}^{q}{exp(o _{k})})]-\displaystyle\sum_{j=1}^{q}{y _{j}o _{j}}}
    - =log(k=1qexp(ok))j=1qyjoj={log(\displaystyle\sum_{k=1}^{q}{exp(o _{k})})-\displaystyle\sum_{j=1}^{q}{y _{j}o _{j}}}
  • ojL(y,y^)=exp(oj)k=1qexp(ok)yk=softmax(o)jyj=0\cfrac{\partial {}}{\partial {o _{j}}}L(\boldsymbol{y},\hat{\boldsymbol{y}})=\displaystyle\frac{exp(o _{j})}{\displaystyle\sum_{k=1}^{q}{exp(o _{k})}}-y _{k}=softmax(\boldsymbol{o})_{j}-y _{j}=0
  • 즉 Cross-Entropy를 최소화하는 softmax값은 실제 관측값과 같다.

예시 : 이미지 분류

이미지 분류 데이터셋

데이터셋1. MNIST 손글씨 숫자 데이터셋

  • 28×2828 \times 28 개의 픽셀로 구성된 60000개의 이미지이다

    데이터셋2. 패션 MNIST

  • 10개의 카테고리로 구성되어, 32×3232 \times 32 개의 픽셀로 구성된 6000개의 이미지다

  • 각 카테고리당 100개가 테스트 데이터셋으로 할당되어 있다

FashionMNIST 클래스

  • 함수 종류
    - transform.Compose
    - transforms.Resize : 이미지의 픽셀 크기를 재조정할 수 있다
    - transform.ToTensor() : 이미지를 Pytorch tensor타입으로 변형한다
    - transforms.RandomHorizontalFlip : 이미지를 좌우 반전할 수 있다
    - torchvision.datasets
    - MNIST,Fashion-MNIST외의 다양한 데이터셋을 불러올 수 있다
    - root : 이미지가 다운로드된 Root directory 위치를 지정한다
    - train : 훈련 데이터셋인지, 테스트 데이터셋인지 분류한다
    - transform : PIL 이미지를 transformed된 버전으로 반환한다
    - download : True 라면 데이터셋을 인터넷으로부터 다운하여 Root directory에 넣는다. 이미 다운로드 되었다면 다시 다운로드하지 않음.
class FashionMNIST(d2l.DataModule):
    def __init__(self, batch_size=64,resize=(28,28)):
        super().__init__()
        self.save_hyperparameters()
        trans= transforms.Compose([transforms.Resize(resize),
                                    transforms.ToTensor])
        self.train= torchvision.datasets.FashionMNIST(
            root=self.root, train=True , transform = trans,download=True)
        self.val= torchvision.datasets.FashionMNIST(
            root=self.root, train=False, transform=trans, download=True)


data= FashionMNIST(resize=(32,32))
print(len(data.train) , len(data.val))

DataLoader 메소드

  • 파이토치에torch.utils.data.DataLoader 로 지원한다
  • 우리가 실제 학습할 때 이용할 수 있게끔 만들어놓은 클래스로 데이터를 저장한후, 불러올때 데이터를 배치형태로 쪼갠다.
  • 함수들
    - dataset : 불러올 데이터를 지정한다
    - batch_size : 한 배치당 할당될 데이터포인트수를 지정한다
    - shuffle : True 로 지정할 시 한 에포크가 끝날 때마다 데이터를 섞는다
    - sampler : 데이터셋으로부터 데이터포인트를 뽑을 알고리즘(원문:strategy)을 지정한다
    - num_workers : 데이터를 불러올때 얼마나 많은 subprocess를 사용할지 지정한다
@d2l.add_to_class(FashionMNIST)  #@save
def get_dataloader(self, train):
    data = self.train if train else self.val
    return torch.utils.data.DataLoader(data, self.batch_size, shuffle=train,
                                       num_workers=self.num_workers)

Visualize 메소드

@d2l.add_to_class(FashionMNIST)  #@save
def visualize(self, batch, nrows=1, ncols=8, labels=[]):
    X, y = batch
    if not labels:
        labels = self.text_labels(y)
    d2l.show_images(X.squeeze(1), nrows, ncols, titles=labels)
batch = next(iter(data.val_dataloader()))
data.visualize(batch)

accuracy 메소드

  • accuracy를 계산한다
@d2l.add_to_class(Classifier)  #@save
def accuracy(self, Y_hat, Y, averaged=True):
    """Compute the number of correct predictions."""
    Y_hat = Y_hat.reshape((-1, Y_hat.shape[-1]))
    preds = Y_hat.argmax(axis=1).type(Y.dtype)
    compare = (preds == Y.reshape(-1)).type(torch.float32)
    return compare.mean() if averaged else compare

Classifier 클래스

  • 기존 정의된 loss, accuracy 메소드를 활용하여 해당 배치에 대한 손실함수와 정확도를 계산한다
class Classifier(d2l.Module):  #@save
    def validation_step(self, batch):
        Y_hat = self(*batch[:-1])
        self.plot('loss', self.loss(Y_hat, batch[-1]), train=False)
        self.plot('acc', self.accuracy(Y_hat, batch[-1]), train=False)

configure_optimizer 메소드

  • 현재 활용되는 optimizer, 파라미터값, 학습률을 반환한다
@d2l.add_to_class(d2l.Module)  #@save
def configure_optimizers(self):
    return torch.optim.SGD(self.parameters(), lr=self.lr)

Softmax-Regression 구현

Softmax 함수

def softmax(X):
    X_exp = torch.exp(X)
    partition = X_exp.sum(1, keepdims=True)
    return X_exp / partition  
    # The broadcasting mechanism is applied here

SoftmaxRegression 클래스

  • __init__ 메소드
    - super().__init__() : d2l.Classifier 클래스로부터 속성을 이어받는다
    - self.save_hyperparameters
    - self.W = torch.normal(0, sigma, size=(num_inputs, num_outputs),requires_grad=True) : 가중치를 평균이 0, 표준편차가 0.01인 가우시안 분포에서 샘플링한 값으로 초기화한다
    - self.b = torch.zeros(num_outputs, requires_grad=True) : 편향을 영벡터로 초기화한다
  • parameter 메소드
    - 함수 입력시 가중치와 편향값을 반환한다
  • forward 메소드
    - 행렬곱 연산하여 y=Xβ+b\boldsymbol{y}=\boldsymbol{X}\boldsymbol{\beta}+\boldsymbol{b} 값을 계산한다

Cross-Entropy Loss 함수 와 loss 함수

def cross_entropy(y_hat, y):
    return - torch.log(y_hat[list(range(len(y_hat))), y]).mean()

cross_entropy(y_hat, y)

@d2l.add_to_class(SoftmaxRegressionScratch)
def loss(self, y_hat, y):
    return cross_entropy(y_hat, y)

학습

data = d2l.FashionMNIST(batch_size=256)
model = SoftmaxRegressionScratch(num_inputs=784, num_outputs=10, lr=0.1)
trainer = d2l.Trainer(max_epochs=10)
trainer.fit(model, data)

예측

"""__iter__ 메소드를 갖는 데이터타입에 대하여, 현재 성분의 다음 위치 성분을
불러내는 함수"""
X, y = next(iter(data.val_dataloader()))
preds = model(X).argmax(axis=1)
preds.shape

wrong = preds.type(y.dtype) != y
X, y, preds = X[wrong], y[wrong], preds[wrong]
labels = [a+'\n'+b for a, b in zip(
    data.text_labels(y), data.text_labels(preds))]
data.visualize([X, y], labels=labels)

profile
안녕하세요!
post-custom-banner

0개의 댓글