모델형태가 y^=∑i=1nβixi+β0+ϵ 이라고 가정하자. 그 계수값 β0,β1,β2,...,βn 을 구한뒤, 해당 모델로 종속변수를 예측하는 일련의 방법론을 선형회귀라고 부른다
모델형태를 벡터폼으로 정의할 수도 있다. y^=Xβ+b+ϵ 이때
- β=[β1,β2,⋯,βn] and b=β0
- X∈Rm×n 는 design matrix라 불린다. 이 행렬은 jth 의 행이 jth 의 데이터포인트이다.
- 이때 β=[β0,β1,⋯,βn] 으로 표현할수도 있으며 이런 경우 상수항 정보를 β 에 넣음으로써 항이 하나 줄어들게 작성할 수 있다. 이경우 X(i)=[1xi1xi2⋯xin] 이 된다. 아래서부턴 이 표현식을 활용한다
최적화된 회귀계수 찾기
- 논리
- L(β) 를 최소화하는 β^ 가 최적화된 β 값이다
- 순서
- L(β)=∣Y−Xβ∣2=⟨Y−Xβ,Y−Xβ⟩=(Y−Xβ)T(Y−Xβ)=(YT−βTXT)(Y−Xβ)=YTY−YTXβ−βTXTY+βTXTXβ
- =YTY−2βTXTY+βTXTXβ
- (∂x∂Ax=A, ∂x∂xAx=2Ax (A가 대칭행렬일 경우)을 활용함)
- 미분을 이용하여 RSS를 최소화하는 계수값을 찾자
- ∂β∂(L(β))=−2(XTY)T+2βT(XTX)=−2YTX+2XTXβ=0
- XTXβ=YTX
- β=(XTX)−1(YTX) : 추정된 β값
3. Minibatch Stochastic Gradient
위와 같이 β=(XtX)−1(YTX) 가 계산이 되는, 즉 (XTX) 의 역행렬이 존재하는 상태라면 해석적으로 해를 구할수 있다
- 이는 rank(T∗T))=rank(T)) 로, 즉 각 데이터포인터의 집합이 모두 선형독립인 정보일때 이렇게 해석적으로 계산가능한 것이다
반대로, 해석적으로 최적화된 β 값을 구할수 없더라도, 반복 계산을 통하여 근사하는 값을 찾을 수 있다. 이 방법이 gradent descent이다
Gradient descent
반복적인 계산으로 Loss function L(β) 값을 줄이는 파라미터 β 를 찾아가는 방법이다.
종류
- Batch gradient descent
- loss function을 계산할 때 전체 훈련데이터셋을 활용하는 방법이다
- stochastic gradient descent
- loss function을 계산할 때 무작위로 선택된 하나의 데이터포인트만 활용하는 방법이다
- 계산에 참가하는 데이터포인트가 적기 때문에 계산이 빠르지만 어떤 데이터포인트가 뽑힐지 모른다는 점에서 불안정성이 올라간다
- minibatch gradient descent
- loss function을 계산할 때 (주로 2의 n승) 특정 갯수의 데이터포인트를 뽑아 활용하는 방법이다
- 계산
- β←β−∣B∣η∂β∂L(β)
- β←β−∣B∣η∂β∂i∈Bt∑21(βTx(i)−y(i))2
- β←β−∣B∣η∂β∂(21∣Xβ−Y∣2)
- β←β−∣B∣η(−2YTX+2XTXβ)
- β←β−∣B∣2η(XTXβ−YTX)
4. 노이즈 계산
가정
- ϵ∼N(0,σ2)로 가정하자
- y=βTx+ϵ
그렇다면 독립변수값이 x f로 주어져있을때 관측값이 y 이라면
- P(y∣x)=2πσ21⋅exp[−2σ21(y−βTx)2]
최대우도추정의 원칙에 따라 P(y∣X)=∏i=1nP(y(i)∣x(i))
5.모델 설계
Utilities
우리가 만들고자 하는 수학적 모델들을 python 의 class 형태로 정의하자
이때 필요한 함수를 미리 정의하여 둔다
"""
어떤 함수의 정의식 위에 @add_to_class(클래스)를 적는다면
해당 클래스의 메소드로 해당 함수가 추가되게 된다
"""defadd_to_class(Class):#@savedefwrapper(obj):setattr(Class, obj.__name__, obj)return wrapper
"""
__init__함수: 특정 클래스가 클래스 내부에서 활용될 값을
미리 저장해놓을 수 있게 해주는 함수. 이 값을 attribute라고 부른다
"""
Model 구조
모듈
- 현재 클래스를 파이토치의 neural network의 기본 클래스가 되는 nn.Module의 서브클래스로 정할 수 있다. 이를 활용하면 neural network를 활용하는 유용한 feature를 제공한다
함수
- __init__
- 학습될 파라미터를 저장한다
- training_step
- 손실함수 계산에 활용될 training 데이터 배치 크기를 정한다
- configure_optimizers
- 손실함수 계산에 활용된 옵티마이저 종류를 반환한다
- validation_step
- 손실함수 계산에 활용될 validation 데이터 배치 크기를 정한다
- loss
- 손실함수 식을 정의하는 공간.
"""
Module 클래스에 속성을 nn.Module과 dl2.HyperParameters의 속성을
상속시킨다
super().__init__(): 부모 클래스인 nn.Module과
dl2.Hyperparameters를 호출한다
"""classModule(nn.Module, d2l.HyperParameters):def__init__(self,plot_train_per_epoch=2,
plot_valid_per_epoch=1)->None:super().__init__()
self.save_hyperparameters()
self.board= ProgressBoard()#NotImplementedError:실행 시나리오중 구현되지 않음을 나타내는 것defloss(self,y_hat,y):raise NotImplementedError
"""
hasattr:argument로 넘겨준 object에 name의 속성이 존재하면
True 아니면 False를 반환한다
assert: 이 조건이 참일때 코드를 보장한다. 이 조건이 거짓일때
보장하지 않은 동작이기에 AssertionError를 발생시켜라
assert[조건][오류메시지] 순으로 작성됨
"""deffoward(self,X):asserthasattr(self,'net'),'Neural network is defined'return self.net(X)# self.net속성이 없을시에 대해 오류를 제시하는 모습: 컴퓨터가 잘못 이해(self.net이 없다면 먼저 앞에서 종료되니까)defplot(self,key,value,train):""" plot a point in animation"""asserthasattr(self,'trainer'),'Trainer is not inited'
self.board.xlabel='epoch'if train:
x = self.trainer.train_batch_idx / \
self.trainer.num_train_batches
n = self.trainer.num_train_batches / \
self.plot_train_per_epoch
else:
x=self.trainer.epoch +1
n=self.trainer.num_val_batches /\
self.plot_valid_per_epoch
self.board.draw(x,value.to(d2l.cpu()).detach().numpy(),'train_'if train else'val_'+key , every_n=int(n))"""
*batch[:-1]는 왼쪽 끝부터 오른쪽 끝 하나전까지의 부분배열을,
batch[-1]는 오른쪽 원소값을 지정한다
"""deftraining_step(self,batch):# *arg는 가변인자임을 의미한다
l=self.loss(self(*batch[:-1]),batch[-1])
self.plot('loss',l,train=True)return l
defvalidation_step(self,batch):#
l= self.loss(self(*batch[:-1]),batch[-1])
self.plot('loss',l,train=False)defconfigure_optimizers(self):raise NotImplementedError
데이터
함수
- train_dataloader
- 저장된 training 데이터를 반환한다
- val_dataloader
- 저장된 validation 데이터를 반환한다
- get_dataloader
변수에 대한 도함수값 저장
- x= torch.tensor(value,requires_grad=True)
- requires_grad=True 조건 설정을 통하여 해당 변수의 도함수값을 저장한다
수식 정의
- y=f(x)
- y.backward()
수식의 도함수값 호출
- x.grad : y 에 대한 x 의 편미분값임
선형회귀 모델 Scratch
함수
- __init__
- 파라미터 β 의 가중치를 평균0, 표준편차 0.01의 가우시안 분포 bias를 0으로 초기값을 정한다
- forward
- Xβ 행렬곱을 계산하여준다
- loss
- 손실함수를 정의한다
- 클래스 SGD
- step : param -= self.lr * param *grad 로 값을 계산해준다
- fit_epoch
1. loss 값을 계산한다
2. 한번의 학습이 완료될 때마다 requires_grad=False로 텐서에 저장된 미분값을 0으로 초기화한다