|
|
1.1. 인공뉴런의 수학적 정의
(1) 입력 값 x와 이에 상응하는 가중치 백터 w의 선형 조합으로 결정함수를 정의함.
(2) 벡터 접곱
: x와 w 값을 곱해 더한 것
1.2. 퍼셉트론 학습규칙
<퍼셉트론 알고리즘>
1. 가중치를 0 또는 랜덤한 작은 값으로 초기화 함.
2. 각 훈련 샘플 x^(i)에서
| 개별가중치와 절편유닛 동시 업데이트 | 업데이트 값(델타) |
2. 파이썬으로 퍼셉트론 학습 알고리즘 구현
2.1. 객체 지향 퍼셉트론 API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | import numpy as np class Perceptron: """퍼셉트론 분류기 매개변수 ------------ eta : float 학습률 (0.0과 1.0 사이) n_iter : int 훈련 데이터셋 반복 횟수 random_state : int 가중치 무작위 초기화를 위한 난수 생성기 시드 속성 ----------- w_ : 1d-array 학습된 가중치 b_ : 스칼라 학습된 절편 유닛 errors_ : list 에포크마다 누적된 분류 오류 """ def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta # 학습률 초기화 self.n_iter = n_iter # 에포크 횟수 초기화 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 """ # 초기 가중치 벡터는 표준편차가 0.01인 정규 분포에서 뽑은 랜덤한 작은 수를 담고 있음 #rgen은 넘파이 난수 생성기로, 사용자가 지정한 랜덤 시드로 이전과 동일한 결과를 재현할 수 있음 rgen = np.random.RandomState(self.random_state) # 벡터 R로 초기화 self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1]) self.b_ = np.float_(0.) # 절편 0으로 초기화 self.errors_ = [] for _ in range(self.n_iter): errors = 0 for xi, target in zip(X, y): update = self.eta * (target - self.predict(xi)) self.w_ += update * xi self.b_ += update errors += int(update != 0.0) self.errors_.append(errors) return self def net_input(self, X): """입력 계산""" return np.dot(X, self.w_) + self.b_ def predict(self, X): """단위 계단 함수를 사용하여 클래스 레이블을 반환합니다""" return np.where(self.net_input(X) >= 0.0, 1, 0) | cs |
2.2. 붓꽃 데이터셋에서 퍼셉트론 훈련
- 붓꽃 데이터셋에서 두 개의 꽃 종류를 사용하여 100개의 클래스 레이블을 추출한다.
- 100개의 훈련 샘플에서 첫 번째 특성 열(꽃받침 길이)와 세 번재 특성 열(꽃잎 길이)을 추출하여 특성 행렬 X에 저장.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import matplotlib.pyplot as plt import numpy as np import pandas as pd # 퍼셉트론 class Perceptron: def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta # 학습률 초기화 self.n_iter = n_iter # 에포크 횟수 초기화 self.random_state = random_state def fit(self, X, y): # 초기 가중치 벡터는 표준편차가 0.01인 정규 분포에서 뽑은 랜덤한 작은 수를 담고 있음 #rgen은 넘파이 난수 생성기로, 사용자가 지정한 랜덤 시드로 이전과 동일한 결과를 재현할 수 있음 rgen = np.random.RandomState(self.random_state) # 벡터 R로 초기화 self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1]) self.b_ = np.float_(0.) # 절편 0으로 초기화 self.errors_ = [] for _ in range(self.n_iter): errors = 0 for xi, target in zip(X, y): update = self.eta * (target - self.predict(xi)) self.w_ += update * xi self.b_ += update errors += int(update != 0.0) self.errors_.append(errors) return self def net_input(self, X): return np.dot(X, self.w_) + self.b_ def predict(self, X): return np.where(self.net_input(X) >= 0.0, 1, 0) df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None, encoding='utf-8') # setosa와 versicolor를 선택합니다 y = df.iloc[0:100, 4].values y = np.where(y == 'Iris-setosa', 0, 1) # 꽃받침 길이와 꽃잎 길이를 추출합니다 X = df.iloc[0:100, [0, 2]].values fig, ax = plt.subplots(1, 2, figsize=(10, 5)) # 첫 번째 그래프 (산점도) ax[0].scatter(X[:50, 0], X[:50, 1], color='red', marker='o', label='Setosa') ax[0].scatter(X[50:100, 0], X[50:100, 1], color='blue', marker='s', label='Versicolor') ax[0].set_title('Scatter Plot') ax[0].set_xlabel('Sepal length [cm]') ax[0].set_ylabel('Petal length [cm]') ax[0].legend(loc='upper left') ppn = Perceptron(eta=0.1, n_iter=10) ppn.fit(X, y) # 두 번째 그래프 (에포크와 업데이트 수) ax[1].plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o') ax[1].set_title('Epochs vs Updates') ax[1].set_xlabel('Epochs') ax[1].set_ylabel('Number of updates') plt.tight_layout() plt.show() | cs |
- 샘플을 잘못 분류할 때마다 퍼셉트론의 가중치의 절편이 업데이트되기 때문에 잘못 분류된 오차의 개수와 업데이트 횟수가 같다.
- 산점도그래프의 각 점들은 훈련 샘플이고, 꽃받침 길이(Sepal length)와 꽃잎 길이(Petal length)로 분류됨.
- 위의 Epochs vs Updates 그래프에서 보면 퍼셉트론은 여섯 번째 에포크 이후에 수렴했고 훈련샘플을 완벽하게 분류했다.
<2차원 데이터셋의 결정 경계 시각화>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib.colors import ListedColormap # 퍼셉트론 class Perceptron: def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta # 학습률 초기화 self.n_iter = n_iter # 에포크 횟수 초기화 self.random_state = random_state def fit(self, X, y): # 초기 가중치 벡터는 표준편차가 0.01인 정규 분포에서 뽑은 랜덤한 작은 수를 담고 있음 #rgen은 넘파이 난수 생성기로, 사용자가 지정한 랜덤 시드로 이전과 동일한 결과를 재현할 수 있음 rgen = np.random.RandomState(self.random_state) # 벡터 R로 초기화 self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1]) self.b_ = np.float_(0.) # 절편 0으로 초기화 self.errors_ = [] for _ in range(self.n_iter): errors = 0 for xi, target in zip(X, y): update = self.eta * (target - self.predict(xi)) self.w_ += update * xi self.b_ += update errors += int(update != 0.0) self.errors_.append(errors) return self def net_input(self, X): return np.dot(X, self.w_) + self.b_ def predict(self, X): return np.where(self.net_input(X) >= 0.0, 1, 0) def plot_decision_regions(X, y, classifier, resolution=0.02): # 마커와 컬러맵을 설정합니다 markers = ('o', 's', '^', 'v', '<') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # plot the decision surface x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) lab = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) lab = lab.reshape(xx1.shape) plt.contourf(xx1, xx2, lab, alpha=0.3, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # 샘플의 산점도를 그립니다 for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=colors[idx], marker=markers[idx], label=f'Class {cl}', edgecolor='black') df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None, encoding='utf-8') # setosa와 versicolor를 선택합니다 y = df.iloc[0:100, 4].values y = np.where(y == 'Iris-setosa', 0, 1) # 꽃받침 길이와 꽃잎 길이를 추출합니다 X = df.iloc[0:100, [0, 2]].values ppn=Perceptron(eta=0.1,n_iter=10) ppn.fit(X,y) # 산점도를 그립니다 plot_decision_regions(X,y,classifier=ppn) plt.xlabel('Sepal length [cm]') plt.ylabel('Petal length [cm]') plt.legend(loc='upper left') # plt.savefig('images/02_06.png', dpi=300) plt.show() | cs |
3. 적응형 선형 뉴런과 학습의 수렴
3.1. 경사 하강법으로 손실 함수 최소화
| 그레이디언트 | 변화와 방향의 크기를 나타내는 값. - 함수가 가장 빠르게 증가하거나 감소하는 방향을 가리키는 벡터 --> 손실함수의 값을 줄이기 위해 가중치를 어떻게 업데이트해야할지 알려주는 중요한 역할을 함. |
| 각 가중치 w_i에 대한 손실함수의 편도함수 | 절편에 대한 손실의 편도 함수 |
3.2. 파이썬으로 아달린 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | import numpy as np class AdalineGD: """적응형 선형 뉴런 분류기 매개변수 ------------ eta : float 학습률 (0.0과 1.0 사이) n_iter : int 훈련 데이터셋 반복 횟수 random_state : int 가중치 무작위 초기화를 위한 난수 생성기 시드 속성 ----------- w_ : 1d-array 학습된 가중치 b_ : 스칼라 학습된 절편 유닛 losses_ : list 각 에포크의 평균 제곱 오차 손실 함수 값 """ def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta self.n_iter = n_iter 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 """ rgen = np.random.RandomState(self.random_state) self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1]) self.b_ = np.float_(0.) self.losses_ = [] for i in range(self.n_iter): net_input = self.net_input(X) # 이 코드의 활성화 함수는 항등 함수(identity function)이기 때문에 # 아무런 효과가 없습니다. # 이 대신 `output = self.net_input(X)`로 바로 쓸 수 있습니다. # 이 활성화 함수는 개념적인 목적을 위해 만들었습니다. # (잠시 후에 보게 될) 로지스틱 회귀의 경우 이 함수를 시그모이드 함수로 # 바꾸어 로지스틱 회귀 분류기를 구현합니다. output = self.activation(net_input) errors = (y - output) #for w_j in range(self.w_.shape[0]): # self.w_[w_j] += self.eta * (2.0 * (X[:, w_j]*errors)).mean() self.w_ += self.eta * 2.0 * X.T.dot(errors) / X.shape[0] self.b_ += self.eta * 2.0 * errors.mean() loss = (errors**2).mean() self.losses_.append(loss) return self def net_input(self, X): """최종 입력 계산""" return np.dot(X, self.w_) + self.b_ def activation(self, X): """선형 활성화 계산""" return X def predict(self, X): """단위 계단 함수를 사용하여 클래스 레이블을 반환합니다""" return np.where(self.activation(self.net_input(X)) >= 0.5, 1, 0) | cs |
---> 0.1과 0.0001의 두개의 학습률로 에포크 횟수 대비 손실 함수의 값을 그래프로 나타내어 아달린 구현이 훈련 데이터에서 얼마나 잘 학습하는지 볼 수 있다.
==> 위 [그림1](좌)처럼 학습률이 너무 크면 전역 최솟값을 지나쳤기 때문에 손실함수를 최소화하지 못하고 MSE는 에포크마다 점점 더 커진다. 반면 [그림1](우)는 손실이 감소하지만 학습률=0.0001은 너무 작기 대문에 알고리즘이 전역 최솟값에 수렴하려면 아주 많은 에포크가 필요함.
3.3. 특성 스케일을 조정하여 경사 하강법 결과 향상
1 2 3 4 | # 특성을 표준 X_std = np.copy(X) X_std[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std() X_std[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std() | cs |
<표준화한 후 다시 아달린 모델을 훈련하고 학습률=0.5 실행>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib.colors import ListedColormap class AdalineGD: def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta self.n_iter = n_iter self.random_state = random_state def fit(self, X, y): rgen = np.random.RandomState(self.random_state) self.w_ = rgen.normal(loc=0.0, scale=0.01, size=X.shape[1]) self.b_ = np.float_(0.) self.losses_ = [] for i in range(self.n_iter): net_input = self.net_input(X) output = self.activation(net_input) errors = (y - output) self.w_ += self.eta * 2.0 * X.T.dot(errors) / X.shape[0] self.b_ += self.eta * 2.0 * errors.mean() loss = (errors**2).mean() self.losses_.append(loss) return self def net_input(self, X): return np.dot(X, self.w_) + self.b_ def activation(self, X): return X def predict(self, X): return np.where(self.activation(self.net_input(X)) >= 0.5, 1, 0) def plot_decision_regions(X, y, classifier, resolution=0.02): # 마커와 컬러맵을 설정합니다 markers = ('o', 's', '^', 'v', '<') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # plot the decision surface x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) lab = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) lab = lab.reshape(xx1.shape) plt.contourf(xx1, xx2, lab, alpha=0.3, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # 샘플의 산점도를 그립니다 for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=colors[idx], marker=markers[idx], label=f'Class {cl}', edgecolor='black') df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None, encoding='utf-8') # setosa와 versicolor를 선택합니다 y = df.iloc[0:100, 4].values y = np.where(y == 'Iris-setosa', 0, 1) # 꽃받침 길이와 꽃잎 길이를 추출합니다 X = df.iloc[0:100, [0, 2]].values X_std=np.copy(X) X_std[:,0]=(X[:,0]-X[:,0].mean())/X[:,0].std() X_std[:,1]=(X[:,1]-X[:,1].mean())/X[:,1].std() ada_gd = AdalineGD(n_iter=20, eta=0.5) ada_gd.fit(X_std, y) fig,ax=plt.subplots(nrows=1,ncols=2,figsize=(10,4)) # 첫 번째 그래프: 결정 경계 시각화 plt.sca(ax[0]) # 첫 번째 subplot을 활성화 plot_decision_regions(X_std, y, classifier=ada_gd) ax[0].set_title('Adaline - Gradient Descent') ax[0].set_xlabel('Sepal length [standardized]') ax[0].set_ylabel('Petal length [standardized]') ax[0].legend(loc='upper left') # 두 번째 그래프: 손실 그래프 ax[1].plot(range(1, len(ada_gd.losses_) + 1), ada_gd.losses_, marker='o') ax[1].set_title('Training Loss') ax[1].set_xlabel('Epochs') ax[1].set_ylabel('Mean Squared Error') # 레이아웃 조정 및 표시 plt.tight_layout() plt.show() | cs |
3.4. 대규모 머신 러닝과 확률적 경사 하강법
<확률적 경사 하강법 구현>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib.colors import ListedColormap class AdalineSGD: """ADAptive LInear NEuron 분류기 Parameters ------------ eta : float 학습률 (0.0과 1.0 사이) n_iter : int 훈련 데이터셋 반복 횟수 shuffle : bool (default: True) True로 설정하면 같은 반복이 되지 않도록 에포크마다 훈련 데이터를 섞습니다 random_state : int 가중치 무작위 초기화를 위한 난수 생성기 시드 Attributes ----------- w_ : 1d-array 학습된 가중치 b_ : 스칼라 학습된 절편 유닛 losses_ : list 각 에포크마다 모든 훈련 샘플에 대해 평균한 평균 제곱 오차 손실 함수 값 """ def __init__(self, eta=0.01, n_iter=10, shuffle=True, random_state=None): self.eta = eta self.n_iter = n_iter self.w_initialized = False self.shuffle = shuffle self.random_state = random_state def fit(self, X, y): """훈련 데이터 학습 Parameters ---------- 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.losses_ = [] for i in range(self.n_iter): if self.shuffle: X, y = self._shuffle(X, y) losses = [] for xi, target in zip(X, y): losses.append(self._update_weights(xi, target)) avg_loss = np.mean(losses) self.losses_.append(avg_loss) 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=m) self.b_ = np.float_(0.) self.w_initialized = True def _update_weights(self, xi, target): """아달린 학습 규칙을 적용하여 가중치를 업데이트합니다""" output = self.activation(self.net_input(xi)) error = (target - output) self.w_ += self.eta * 2.0 * xi * (error) self.b_ += self.eta * 2.0 * error loss = error**2 return loss def net_input(self, X): """입력 계산""" return np.dot(X, self.w_) + self.b_ def activation(self, X): """선형 활성화 계산""" return X def predict(self, X): """단위 계단 함수를 사용하여 클래스 레이블을 반환합니다""" return np.where(self.activation(self.net_input(X)) >= 0.5, 1, 0) def plot_decision_regions(X, y, classifier, resolution=0.02): # 마커와 컬러맵을 설정합니다 markers = ('o', 's', '^', 'v', '<') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # plot the decision surface x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) lab = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) lab = lab.reshape(xx1.shape) plt.contourf(xx1, xx2, lab, alpha=0.3, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # 샘플의 산점도를 그립니다 for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=colors[idx], marker=markers[idx], label=f'Class {cl}', edgecolor='black') df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None, encoding='utf-8') # setosa와 versicolor를 선택합니다 y = df.iloc[0:100, 4].values y = np.where(y == 'Iris-setosa', 0, 1) # 꽃받침 길이와 꽃잎 길이를 추출합니다 X = df.iloc[0:100, [0, 2]].values X_std=np.copy(X) X_std[:,0]=(X[:,0]-X[:,0].mean())/X[:,0].std() X_std[:,1]=(X[:,1]-X[:,1].mean())/X[:,1].std() ada_sgd = AdalineSGD(n_iter=15, eta=0.01, random_state=1) ada_sgd.fit(X_std, y) fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4)) # 첫 번째 그래프: 결정 경계 시각화 plt.sca(ax[0]) # 첫 번째 subplot을 활성화 plot_decision_regions(X_std, y, classifier=ada_sgd) ax[0].set_title('Adaline - Stochastic Gradient Descent') ax[0].set_xlabel('Sepal length [standardized]') ax[0].set_ylabel('Petal length [standardized]') ax[0].legend(loc='upper left') # 두 번째 그래프: 손실 그래프 ax[1].plot(range(1, len(ada_sgd.losses_) + 1), ada_sgd.losses_, marker='o') ax[1].set_title('Training Loss') ax[1].set_xlabel('Epochs') ax[1].set_ylabel('Average Loss') # 레이아웃 조정 및 표시 plt.tight_layout() plt.show() | cs |
| 숫자 시퀀스 | 시퀀스: 일련의 항목들이 일정한 순서대로 배열된 것. - 숫자 시퀀스를 특성 행렬과 클래스 레이블 벡터를 섞는 인덱스로 사용. |
<훈련결과>
- 그림(우)에서 평균 손실히 상당히 바르게 감소함. 15번째 에포크 이후 최종 결정 경계는 배치 경사 하강법과 거의 비슷해 보임.
-------------------------- 추가된 내용--------------------------
1. 퍼셉트론 모델은 뭐와 똑같이 동작하도록 만든건가?
- 퍼셉트론 모델은 인간의 뇌 시스템과 똑같이 동작하도록 만든것이다. 퍼셉트론은 인간의 뇌세포 중 하나인 뉴런의 동작원리를 수식으로 표현한 것.
2. 모델의 구조(입출력 관계식의 형태)를 설명하라.
3. 모델의 구조는 어떻게 유도한 건가?
- 인간의 뇌에 있는 뉴런의 동작 방식을 수학적 수식으로 유도하였다.
4. 모델의 파라미터는 무엇인가?
- 모델이 훈련 과정에서 최적화해야 할 값, 입력 데이터를 기반으로 출력 값을 생성하는 데 필요하다.
5. 모델의 파라미터는 어떻게 구하는가?
- 모델의 훈련과정에서 입력 데이터와 출력 데이터를 비교하면서 모델 파라미터 값을 구한다.
- 훈련 데이터를 기반으로 손실 함수를 최소화하는 방향으로 경사하강법(최적의 알고리즘)을 사용해 반복적으로 업데이트하여 구한다. 초기화된 가중치와 편향 값에서 시작해, 손실 함수의 기울기를 계산한 뒤 이를 역전파를 통해 전달하며, 학습률을 사용해 파라미터를 조정하는 과정을 에포크 동안 반복해 최적의 파라미터 값을 찾는다.
6. 아달라인에서 훈련알고리즘은 기존과 무엇이 다른가?
| 아딜린 | 기존(퍼셉트론) | |
| 훈련알고리즘 차이점 | 가중치 업데이트 할 때 사용되는 함수 : 선형 활성화 함수 - 선형 활성화 함수를 사용하여 출력값을 연속으로 조정할 수 있어 기존 퍼셉트론보다 더 넓은 범위의 문제 해결 가능. - 선형 활성화 함수를 사용하여 손실함수가 미분이 가능해지기 때문에 경사하강법을 통해 손실 함수를 최소화 하는 가중치를 업데이트함. - 아달린 알고리즘은 진짜 클래스 레이블과 선형 활성화 함수의 실수 출력 값을 비교하여 모델의 오차를 계산하고 가중치를 업데이트함. | 가중치 업데이트 할 때 사용되는 함수 : 단위 계단 함수 - 선형 결정 경계를 찾는데 한계가 있음(XOR 문제와 같은 비선형 문제 해결 불가능) - 잘못 분류된 샘플에 대해서만 가중치 업데이트함. - 퍼셉트론은 진짜 클래스 레이블과 예측 클래스 레이블을 비교함. |
7. 좌표평면의 점의 의미를 설명하라.
- 그래프의 좌표평면의 점은 훈련데이터 샘플을 나타낸다. [그림1] 그래프에서 2종류의 100개 붓꽃 훈련 데이터 샘플을 가지고 훈련하였고, 각 훈련 샘플들이 꽃잎 길이(y축), 꽃받침 길이(x축)으로 각 특징에 따라 분류된것을 볼 수 있다.
8. 클래스란 무엇인가?
- 위의 그래프로 예시를 들어 말하자면 100개의 붓꽃 훈련 데이터 샘플을 2종류로 나눌 때 이 2종류가 클래스 이다.
- 클래스는 데이터 샘플이 속할 수 있는 범주나 카테고리이다.
9. 레이블이란 무엇인가?
- 레이블은 데이터 샘플이 속하는 클래스의 이름이다.
- 머신러닝에서는 각 데이터 포인터에 대한 정답 또는 목표 값이며, 그 데이터가 속하는 클래스나 카테고리를 명시한다.
10. 에퍽의 정의는?
- 에포크는 모델을 훈련시키는 과정 중에 전체 훈련 데이터를 한 번 모두 사용한 횟수이다.
- 하나의 에포크는 훈련 데이터셋을 모델에 한번 전달하고, 그에 따라 가중치를 업데이트 하는 과정을 포함한다.
11. 손실함수의 의미를 설명하라.
- 모델이 예측한 값과 실제 값(정답) 사이의 차이를 측정하는 함수이다.
12. 손실함수의 용도는 무엇인가?
- 모델이 잘못 예측한 정도를 수치적으로 표현하고 그 수치를 최소화할 수 있도록 모델를 훈련시키는 것이다.
- 손실함수의 출력값은 오차를 나타내고 이 값이 작을수록 모델의 예측이 실제 값에 가까워진다.
첫댓글 1. 퍼셉트론 모델은 뭐와 똑같이 동작하도록 만든건가?
2. 모델의 구조(입출력 관계식의 형태)를 설명하라.
3. 모델의 구조는 어떻게 유도한 건가?
4. 모델의 파라미터는 무엇인가?
5. 모델의 파라미터는 어떻게 구하는가?
6. 아달라인에서 훈련알고리즘은 기존과 무엇이 다른가?
7. 좌표평면의 점의 의미를 설명하라.
8. 클래스란 무엇인가?
9. 레이블이란 무엇인가?
10. 에퍽의 정의는
11. 손실함수의 의미를 설명하라.
12. 손실함수의 용도는 무엇인가?
추가 작성하였습니다
사람과 모델의 신호처리과정
1. 입력-> 실제사람 -> 출력
2. 입력-> 인공지능모델 -> 출력
입력이 같으면 실제사람과 인공지능모델의 출력이 같도록 하는 모델을 만드는것이 최종목표임
모델의 출력값을 예측값 또는 추론결과라고 부르고 실제사람의 출력값을 실제출력, 정답, 레이블 등이라고 부른다.
실제 사람의 출력과 인공지능 모델의 출력을 같도록(실제로 같게 만드는건 불가능하고 최소화하도록) 모델의 파라미터를 구하는 과정을 훈련이라고 부름
사람의 출력과 모델의 출력의 차이를 수치화한것이 손실함수이고 이함수를 최소화하는 모델 파라미터를 구하는것이 목표
함수를 최소화하는 독립변수를 찾는문제이므로 미분이 필요함