과대적합(Overfitting) : 학습 데이터에 대해서는 높은 성능을 보이지만, 새로운 데이터에 대해서는 낮은 성능을 보이는 문제
모델이 학습 데이터에만 너무 적합해져서 일반화하지 못하는 문제
과소적합(Underfitting) : 모델이 데이터에 대한 패턴을 제대로 파악하지 못해 학습 데이터와 테스트 데이터 모두 성능이 낮은 상태, 모델이 너무 간단하거나 학습 데이터가 적어서 발생
규제(Regulation) : 과대적합 문제를 해결하기 위한 방법, 모델의 복잡도를 제한하여 과대 적합을 방지한다. L1, L2 규제가 있다.
교차 검증(Cross Validation)
: 모델의 일반화 성능을 평가하기 위한 방법 중 하나, 데이터를 여러 개의 폴드(fold)로 나누어 각각을 테스트 데이터로 사용하고 나머지 데이터로 모델을 학습하여 성능을 평가한다.
과소적합을 해결하는 법 -> 모델의 복잡도를 높인다 (모델에 변수 추가, 변수의 차수를 늘림, 모델의 파라미터 개수를 늘림)
학습 데이터를 늘린다.
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDClassifier
import numpy as np
import matplotlib.pyplot as plt
cancer = load_breast_cancer()
x = cancer.data
y = cancer.target
x_train_all , x_test, y_train_all, y_test = train_test_split(x,y,stratify =y, test_size=0.2 ,random_state=42)
sgd = SGDClassifier(loss='hinge', random_state=42)
sgd.fit(x_train_all, y_train_all)
x_train, x_val, y_train, y_val = train_test_split(x_train_all, y_train_all, stratify=y_train_all, test_size=0.2, random_state=42)
class SingleLayer:
def __init__(self, learning_rate=0.1, l1=0, l2=0):
self.w = None
self.b = None
self.losses = []
self.val_losses = []
self.w_history = []
self.lr = learning_rate
self.l1 = l1
self.l2 = l2
def forpass(self,x):
z = np.sum(x*self.w) + self.b
return z
def backprop(self, x, err):
w_grad = x * err
b_grad = 1 * err
return w_grad, b_grad
def activation(self, z):
z = np.clip(z, -100, None)
a = 1/(1+np.exp(-z))
return a
def fit(self, x, y, epochs = 100, x_val = None, y_val = None):
self.w = np.ones(x.shape[1])
self.b = 0
self.w_history.append(self.w.copy())
np.random.seed(42)
for i in range(epochs):
loss = 0
indexes = np.random.permutation(np.arange(len(x)))
for i in indexes:
z = self.forpass(x[i])
a = self.activation(z)
err = -(y[i] - a)
w_grad, b_grad = self.backprop(x[i], err)
w_grad += self.l1 * np.sign(self.w) + self.l2 * self.w
self.w -= self.lr * w_grad
self.b -= self.lr * b_grad
self.w_history.append(self.w.copy())
a=np.clip(a,1e-10, 1-1e-10)
loss += -(y[i]*np.log(a)+(1-y[i])*np.log(1-a))
self.losses.append(loss/len(y)+self.reg_loss())
self.update_val_loss(x_val, y_val)
def predict(self, x):
z = [self.forpass(x_i) for x_i in x]
return np.array(z) >= 0
def score(self, x, y):
return np.mean(self.predict(x) == y)
def reg_loss(self):
return self.l1 * np.sum(np.abs(self.w))+ self.l2 / 2* np.sum(self.w**2)
def update_val_loss(self,x_val,y_val):
if x_val is None:
return
val_loss = 0
for i in range(len(x_val)):
z = self.forpass(x_val[i])
a = self.activation(z)
a = np.clip(a,1e-10,1-1e-10)
val_loss += -(y_val[i]*np.log(a)+(1-y_val[i])*np.log(1-a))
self.val_losses.append(val_loss/len(y_val)+self.reg_loss())
layer1 = SingleLayer()
layer1.fit(x_train,y_train)
print(layer1.score(x_val, y_val))
w2 = []
w3 = []
for w in layer1.w_history:
w2.append(w[2])
w3.append(w[3])
# plt.plot(w2,w3)
# plt.plot(w2[-1],w3[-1],'ro')
# plt.plot(w2[-5],w3[-5],'ro')
train_mean = np.mean(x_train, axis = 0)
train_std = np.std(x_train, axis=0)
x_train_scaled = (x_train-train_mean) / train_std
val_mean = np.mean(x_val, axis=0)
val_std = np.std(x_val, axis=0)
x_val_scaled = (x_val - val_mean) / val_std
layer2 = SingleLayer()
layer2.fit(x_train_scaled, y_train)
print(layer2.score(x_val_scaled, y_val))
#과대 적합 , 과소 적합
# layer3 = SingleLayer()
# layer3.fit(x_train_scaled, y_train, x_val = x_val_scaled, y_val = y_val)
# plt.ylim(0, 0.3)
# plt.xlim(0,100)
# plt.plot(layer3.losses)
# plt.plot(layer3.val_losses)
# plt.ylabel('loss')
# plt.xlabel('epoch')
# plt.legend(['train_loss','val_loss'])
# plt.show()
# 규제
# l1_list = [0.0001, 0.001, 0.01]
# for l1 in l1_list:
# lyr = SingleLayer(l1 = l1)
# lyr.fit(x_train_scaled, y_train, x_val = x_val_scaled, y_val=y_val)
# plt.plot(lyr.losses)
# plt.plot(lyr.val_losses)
# plt.title('Learning Curve (l1={})'.format(l1))
# plt.ylabel('loss')
# plt.xlabel('epoch')
# plt.legend(['train_loss','val_loss'])
# plt.ylim(0,0.3)
# plt.xlim(0,100)
# plt.show()
# 교차 검증
validation_scores = []
k = 10
bins = len(x_train_all) // k
for i in range(k):
start = i*bins
end = (i+1)*bins
val_fold = x_train_all[start:end]
val_target = y_train_all[start:end]
train_index = list(range(0,start)) + list(range(end, len(x_train_all)))
train_fold = x_train_all[train_index]
train_target = y_train_all[train_index]
train_mean = np.mean(train_fold, axis=0)
train_std = np.std(train_fold, axis=0)
train_fold_scaled = (train_fold - train_mean) / train_std
val_fold_scaled = (val_fold - train_mean) / train_std
lyr = SingleLayer(l2 = 0.01)
lyr.fit(train_fold_scaled, train_target, epochs = 50)
score = lyr.score(val_fold_scaled, val_target)
validation_scores.append(score)
print(np.mean(validation_scores))
728x90
'CS(Computer Science) > 인공지능' 카테고리의 다른 글
8. 사이킷런 경사하강법 (0) | 2023.03.19 |
---|---|
7. 단일층 신경망 (0) | 2023.03.19 |
6. 로지스틱 회귀 (0) | 2023.03.19 |
5. 뉴런 생성 & 시그모이드 함수 (0) | 2023.03.18 |
4. 경사하강법 (0) | 2023.03.18 |