본문 바로가기

필기정리

[DeepLearning] NN(Neural Net) 강의 필기

320x100

 

torch.NeuralNet 패러미터 설명

 
클래스로 구현해서 계속 사용합니다.
 
torch.nn.Module : 
class NeuralNet(torch.nn.Module):  torch.nn.Module : 부모 클래스 / NeuralNet: 자식 클래스
         # 생성자 __int__       
         # 신경망의 구조와 동작을 (부여)정의하는 생성자를 모델 클래스(NeuralNet)에 정의함
         # __init__() : python에서 객체가 갖는 속성값을 초기화하는 역할
         # 초기화 (initialization) : 할당된 자리에 값을 채워줌 / 어떤 값을 대입해줌
         # 정의 (definition) : 변수등의 자리를 만들어 줌
         # __init__ : 객체가 생성되면 자동으로 호출됨         
    def __init__(self, input_size, hidden_size): # 입력층과 은닉층의 사이즈를 초기화 시 결정
         # 이미 정의된 nn.Module을 활용해서 모델을 구성하기로 함        
         super(NeuralNet, self).__init__() 
         # 생성자를 super를 통해 직접 실행해서 부모클래스의 생성자를 작동시킴         
         # super() 함수를 부를 시 nn.Module(부모 클래스)의 속성들을 가지고 초기화         
         # 객체를 만들 때, input_size, hidden_size 입력         
         # input_size : 입력층 차원, hidden_size : 은닉층 차원 
         
         # self는 생성될 객체 그 자체를 의미         
         self.input_size = input_size # self        
         #  input_size 속성이 생김 : __init__ 전달받은 input_size가 부여
         
         self.hidden_size = hidden_size # self → input_size 속성이 생김          
         #  : __init__ 전달받은 hidden_size가 부여         
         # 인공 신경망 연산 정의 (층을 이동할 때 어떠한 계산이 일어날 지)         
         # nn.Linear - 일직선으로 연결, 행렬곱(weight)과 bias를 포함하는 연산         
         # 입력층 → 입력을 받아서 은닉층으로 넘겨줄 것
         
         self.linear_1 = torch.nn.Linear(self.input_size, self.hidden_size)         
         # 들어올 크기 → 나갈 크기
         
         self.relu = torch.nn.ReLU() # 활성화 함수         
         # linear_1 층을 통해서 가중치 계산 → reLU 함수 필터링 
         # (0보다 작으면 0이 출력, 그보다 크면 그대로 출력)
         
         # 은닉층 출력         
         self.linear_2 = torch.nn.Linear(self.hidden_size, 1) # 확률값
         
         # 이진분류 → linear_1의 결과물을 받아서 1개의 출력을 몰아줌 (0,1)
         self.sigmoid = torch.nn.Sigmoid() # 활성화 함수
         
         # linear_1, relu 는 함수처럼 쓰인다
	# forward propagation 가중치를 통해서 입력받은 값들을 변환하는 과정   
    def forward(self, input_tensor): # 학습에 쓰일 텐서 (데이터)
    
    	# init() 함수에서 정의된 동작들을 차례로 실행    
# linear1 : 입력 데이터 (input_tensor)에 [input_size, hidden_size] 크기의 가중치를 행렬 곱
       	# 편향을 더해서 [1, hidden_size] 의 텐서를 반환    
    	linear1 = self.linear_1(input_tensor)    
    	relu = self.relu(linear1) # [1, hidden_size]
    
    	# linear2 : [1, 1] 모양으로 변환    
    	linear2 = self.linear_2(relu)    
    	output = self.sigmoid(linear2)
    
    	return output

 

 

🧨 과적합 사례(검증셋이 없음)

for epoch in range(epochs):

    # 학습 모드로 전환

    model.train()

    # 한번 반복해주는 에포크마다 새로운 경사값을 계산할 것이므로

    # zero_grad() 함수를 호출해서 경사값(기울기)을 0으로 설정.

    # zero_graad를 사용하지 않으면 gradient가 vanishing되거나 exploding해지는 문제가 발생함.

    optimizer.zero_grad()

    # 학습 데이터를 입력해서 결과값을 개선

    train_output = model(x_train) # x_train을 넣었을 때의 결과물

    # nn.module → 알아서 forward propagtion을 호출함

    # 결과값의 차원과 레이블의 차원을 같게 만들고 오차를 계산

    train_loss = criterion(train_output.squeeze(), y_train) 

    # x_train → 모델을 통해 나온 예측값 vs 실제 정답값 비교

    
    # 100 epoch 마다 학습이 잘 되었는지 확인함

    if epoch % 100 ==0:

       print(f"train_ loss at {epoch} : {train_loss.item()}")

    
    # cost function을 weight로 미분해서 오차가 최소가 되는 방향을 구하고

    # 그 방향으로 모델을 learning rate만큼 이동시킴 (back propagation)

    train_loss.backward()

    optimizer.step() # optimizer.step() 함수를 호출할 때마다 가중치를 학습률만큼 갱신

 

 

잠깐 정리, ReLU 함수를 Hidden Layer에서 많이 사용하는 이유는?

ReLU 함수

 

   1 ) Relu는 기울기 소실 문제가 발생하지 않습니다.

 

주) ReLU 함수의 다양한 응용 형태

ReLU함수는 양수는 그대로, 음수는 모두 0으로 반환하는데, 그로인해 특정 양수값에 수렴하지 않아요.

ReLU 함수 이후로 응용한 여러가지 함수들 중에서도,

Linear, Non Linear한 형태를 모두 표현하고, gradient vanishing을 걱정하지 않아도 됩니다.

그렇기에 가장 합리적입니다.

 

2 ) 기존 활성화 함수에 비해 속도가 빠릅니다.

 

ReLU 함수의 공식은 아주아주 단순한 형태이다 보니, Gradient boosting 시

다른 Activation Fuction에 비해 train속도가 꽤 빠른편입니다.

 

그 전에는 활성화 함수가 부드러워야 weight update가 잘 된다고 하여, sigmoid 함수나

하이퍼볼릭 tangent 함수를 사용했었지만, 기울기가 스무스한 부분에 닿아가는 순간

업데이트 속도가 매우 느려지게 됩니다.

ReLU는 기울기가 0 이상에서 일정하므로, 그에 비해 업데이트 속도가 빠릅니다.

 

 


 

학습 후 평가모드로 바꾸기 + 테스트 데이터인 x_test와 y_test를 통해 오차를 구합니다.

 

model.eval() # evaluation
test_loss = criterion(torch.squeeze(model(x_test)), y_test)
print(f'학습 후 loss : {test_loss.item()}')
학습 후 loss : 0.027976524084806442
# 모델을 저장 → deep learning에서 모델을 저장 → 레이어 마다 weight를 저장
# model.state_dict() : model 내의 weight들을 dictionary 형태로 표현
# {연산 이름 : weight tensor와 bias tensor}와 같이 표현된 데이터

model.state_dict()

 

구간별로 구분해서 설명했습니다.

 

 

layer가 두 층이었기 때문에 가중치들도 많은 편은 아닙니다.

위에서부터 Input과 가깝기 때문에 얕은 layer, 아래는 input과 멀기 때문에

깊은 layer라고 표현했습니다.

 

그후 딥러닝 모델의 성능 비교는 loss function을 사용할 수 있습니다.

MSE, RMSE 등이 존재합니다.

728x90