정보이론
정보량의 정의
- 예시
- 전기신호로 동전 5번 던지는 시행을 한다 하자. 이때 던진 결과가 어떤지 묻기위해 몇번의 질문을 해야 하는가? 결과의 경우의 수는 몇개가 있는가?
- 총 5번 질문하면된다
- 동전 한번 던지는 경우당 2회로 하여 25 개의 경우의 수가 존재한다
- 이를 통해 질문갯수=log2(가능한 결과의 수) 라는 공식이 성립한다
- Hartely의 정보량 정의
- 정답을 구분해내기 위해 필요한 질문의 개수
- H=nlog2s :
- n : 문자열의 갯수
- s : 각 선택에서 가능한 결과의 수
- 하나의 문자열 구분해내기 위한 질문의 수는 sn 이기 때문이다
엔트로피의 정의
- 예시
- 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.5
- B,C인 경우 필요한 질문수는 3, B일 확률,C일 확률 각각 P(B)=P(C)=0.125
- D일 경우 필요한 질문수는 2, D일 확률 P(D)=0.25
- 즉 평균 질문수는 1⋅0.5+3⋅(0.125⋅2)+2⋅0.25=0.5+0.75+0.5=1.75
- 똑같은 경우의수 A,B,C,D를 갖고 있더라도, 해당 결과가 선택될 확률이 다르면, 평균 질문수는 바뀌게 된다. 이 예제에선 기계 Y가 기계 X보다 더 적은 질문을 해서 알아낼 수 있는 정보, 즉 더 적은 정보량을 갖고 있다고 해석한다
- 필요한 질문의 수는 최적 전략하에선 log2p(xi)1 라고 볼 수 있다.
- Shannon의 엔트로피 정의
- H=i∑p(xi)⋅log2p(xi)1=−i∑p(xi)⋅log2p(xi)
- 엔트로피는 최적 전략하에서 결과를 확인하는데 필요한 질문의 갯수 기댓값이다
- 엔트로피는 모든 사건이 동등한 확률로 발생할 떄 가장 큰 값을 갖는다.
크로스 엔트로피 정의
-
예
- 앞선 예제에선 기계 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 질문 다음 A 인가를 물어 질문 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)=i∑pilog2qi1=−i∑pilog2qi
- 여기서 log2qi1 는 기계 Q의 최적전략을 활용하였을 때 필요한 질문의 갯수이다
- 만약 여기서 p=[0.5,0.125,0.125,0.25] 이고 q=[0.25,0.25,0.25,0.25] 라 하자. 이런 상황에서 qi 를 학습시키고 있다면 qi→pi 가 될수록 cross-entropy값을 작아지게 된다
-
증명 : 미완
- Jensen's Inequality와 관련이 있다는 내용이 있음 -> 후에 증명해보도록 하자
KL-Divergence의 정의
- Kullback-Leibler 발산이란 뜻으로, 여기서 Divergence란 벡터장의 발산이 아닌 (확률분포의 )차이를 의미한다. 따라서 relative entropy라고 불리기도 한다
- 정의
- DKL(P∣∣Q)=x∑P(x)log(Q(x)P(x))
- =E[logP(x)]−E[logQ(x)]
- =HP(Q)−H(P)
- 즉 실제분포 P와 추측된 분포 Q 사이 크로스 엔트로피와 엔트로피의 차로 해석할 수 있다
Ref.
- . logab=logcalogcb
- proof
- logab=x
- ax=b
- logcax=logcb
- xlogca=logcb
- x=logcalogcb=logab
- ∂x∂(log2x)=∂x∂(log21⋅logx)=x1⋅log21
Softmax Regression
- 회귀문제는 분류문제와 명확하게 구분되는것은 아니다.
- 회귀 문제는 자연수 순서매기기로 클래스를 구분지을 수 없다. 이를 해결하기 위해 다음과 같은 방법을 활용한다
- 원-핫 인코딩: 각 카테고리의 수만큼의 차원을 갖는 벡터가 있다 하자. 이 벡터는 어떤 데이터포인트가 jth 카테고리에 속한다면 이에 대응되는 벡터는jth 의 위치만 1이고 나머지 값은 0이라 정의한다
- 몇가지 조건을 추가한다면 분류문제는 단순 vector-valued 회귀문제로 다룰수 있게 된다. 각 output oj 에 대하여
- i∑oi=1 결과값들의 합이 1이 되어야한다
- oj 는 음수이거나 1를 초과하는 값이여선 안된다
- Softmax 함수를 활용하면 이 문제를 해결할 수 있다
- y^=softmax(o) , where y^i=j∑exp(oj)exp(oi)
- softmax함수는 이 argument들 사이의 크기 순서까지 보존한다.
Log-likelihood
- 소프트맥스 함수는 각 각 클래스에 대한 조건부 확률을 계산할 수 있다.
- P(y∣x)=∏i=1nP(y(i)∣x(i))
- Cross-Entropy
- 두 확률 분포가 얼마나 유사한지를 측정하는 함수이다
- Hp(q)=i=1∑nq(xi)log(p(xi))
- q 는 실제이며, 알지못하고 있는 분포이다
- Cross-Entropy는 분류문제에서 loss-function으로 활용된다
Softmax와 Cross-Entropy
- softmax 함수와 이에 대응되는 크로스 엔트로피는 일반적으로 활용된다.
- L(y,y^)=−j=1∑qyjlogk=1∑qexp(ok)exp(oj)
- =j=1∑qyj[log(k=1∑qexp(ok))]−j=1∑qyjoj
- =log(k=1∑qexp(ok))−j=1∑qyjoj
- ∂oj∂L(y,y^)=k=1∑qexp(ok)exp(oj)−yk=softmax(o)j−yj=0
- 즉 Cross-Entropy를 최소화하는 softmax값은 실제 관측값과 같다.
예시 : 이미지 분류
이미지 분류 데이터셋
데이터셋1. MNIST 손글씨 숫자 데이터셋
-
28×28 개의 픽셀로 구성된 60000개의 이미지이다
데이터셋2. 패션 MNIST
-
10개의 카테고리로 구성되어, 32×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)
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)
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 메소드
@d2l.add_to_class(Classifier)
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):
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)
- 현재 활용되는 optimizer, 파라미터값, 학습률을 반환한다
@d2l.add_to_class(d2l.Module)
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
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 값을 계산한다
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)