본문 바로가기

AI

1207 - 아달린 SGD

728x90

딥러닝 기초 - Adaptive Linear Stochastic Gradient Descent


확률적 경사 하강법은 경사 하강법보다 가중치가 더 자주 업데이트되기 때문에 수렴 속도가 훨씬 빠름.

 - 훈련 샘플 순서를 무작위하게 주입 

 - 에포크마다 훈련 데이터셋을 섞음 ; 

class AdalineSGD(object):
    """
    ADAptive Linear Neuron 분류기
    
    매개변수
    -------------
    learning_rate : float
      학습률 (0.0과 1사이)
    n_iter : int
      훈련 데이터셋 반복 횟수
    shuffle : bool (default: True)
      True로 설정하면 같은 반복이 되지 않도록 에포크마다 훈련 데이터를 섞음.
    random_state : int
      가중치 무작위 초기화를 위한 난수 생성기 시드
    
    속성
    -----------
    w_ : 1d-array
      학습된 가중치
    cost_ : list
      모든 훈련 샘플에 대해 에포크마다 누적된 평균 비용 함수의 제곱합    
    
    """
    
    def __init__(self, learning_rate = 0.01, n_iter = 10,
                 shuffle = True, random_state = None):
        self.learning_rate = learning_rate
        self.n_iter = n_iter
        self.w_initialized = False
        self.shuffle = shuffle
        self.random_state = random_state
        
    def fit(self, X, y):
        """
        훈련 데이터 학습
        
        매개변수
        -----------
        X : {array-like}, shape = [n_samples, n_features]
          n_samples개의 샘플과 n_features개의 특성으로 이루어진 훈련 데이터
        y : array-like, shape = [n_samples]
          타깃 벡터
          
        반환값
        -----------
        self : object
        
        """
        
        self._initialize_weights(X.shape[1]) # 가중치 초기화
        self.cost_ = [] # 비용함수 초기화
        for i in range(self.n_iter):
            if self.shuffle:
                X, y = self._shuffle(X, y) # 에포크마다 훈련 데이터셋 셔플
            cost = []
            for xi, target in zip(X, y):
                cost.append(self._update_weights(xi, target)) # 훈련 샘플에 대해 가중치 업데이트
            avg_cost = sum(cost)/len(y) # 알고리즘이 수렴하는지 확인하기 위해 매 에포크마다 평균 비용 계산
            self.cost_.append(avg_cost)
        return self
    
    def partial_fit(self, X, y):
        """
        가중치를 초기화하지 않고 훈련 데이터를 학습
        """
        
        if not self.w_initialized:
            self._initialize_weights(X.shape[1])
        if y.ravel().shape[0] > 1:
            for xi, target in zip(X, y):
                self._update_weights(xi, target)
        else:
            self._update_weights(X, y)
        return self
    
    def _shuffle(self, X, y):
        """
        훈련 데이터를 섞음
        """
        r = self.rgen.permutation(len(y))
        return X[r], y[r]
    
    def _initialize_weights(self, m):
        """
        랜덤한 작은 수로 가중치를 초기화
        """
        self.rgen = np.random.RandomState(self.random_state)
        self.w_ = self.rgen.normal(loc = 0.0, scale = 0.01, size = 1 + m)
        self.w_initialized = True
        
    def _update_weights(self, xi, target):
        """
        아달린 학습 규칙을 적용하여 가중치를 업데이트
        """
        output = self.activation(self.net_input(xi))
        error = (target - output)
        self.w_[1:] += self.learning_rate * xi.dot(error)
        self.w_[0] += self.learning_rate * error
        cost = 0.5 * error**2
        return cost
    
    def net_input(self, X):
        """
        최종 입력 계산
        """
        return np.dot(X, self.w_[1:])+self.w_[0]
    
    def activation(self, X):
        """
        선형 활성화 계산
        """
        return X
    
    def predict(self, X):
        """
        단위 계단 함수를 사용하여 클래스 레이블을 반환
        """
        return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)

 

학습 및 결과 확인

ada = AdalineSGD(n_iter = 15, learning_rate = 0.01, random_state=1)
ada.fit(X_std, y)
plot_decision_regions(X_std, y, classifier=ada)
plt.title('Adaline = Stochastic Gradient Descent')
plt.xlabel('sepal length [standardized]')
plt.ylabel('petal length [standardized]')
plt.legend(loc='upper left')
plt.show()

plt.plot(range(1, len(ada.cost_)+1), ada.cost_, marker = 'o')
plt.xlabel('Epochs')
plt.ylabel('Average Cost')
plt.tight_layout()
plt.show()

 

에포크마다 적절하고 빠르게 비용이 감소함을 알 수 있다

'AI' 카테고리의 다른 글

1208 - 서포트백터머신  (0) 2021.12.08
1207 - 로지스틱회귀  (0) 2021.12.07
1202 - 아달린  (0) 2021.12.02
1201 - 퍼셉트론  (0) 2021.12.01
Kaggle 준비 해보기(1)  (0) 2021.08.16