비트교육센터/AI

[비트교육센터][AI] AI 5일차 과적합, K겹 교차 검증

달의요정루나 2023. 8. 5. 17:46

1. 모델 성능 검증(feat.과적합)

과적합: 기계학습에서 학습 데이터를 과하게 학습하는 것을 뜻한다.

sonar3.csv
0.08MB

- 광물데이터를 작업하는 경로로 가지고 온다.

1. csv 파일 로드하기

import pandas as pd

df = pd.read_csv('data/sonar3.csv',header=None)
df.head()

--> 결과

2. 데이터프레임 정보 나타내기

df.info

--> 결과

<bound method DataFrame.info of          0       1       2       3       4       5       6       7       8   \
0    0.0200  0.0371  0.0428  0.0207  0.0954  0.0986  0.1539  0.1601  0.3109   
1    0.0453  0.0523  0.0843  0.0689  0.1183  0.2583  0.2156  0.3481  0.3337   
2    0.0262  0.0582  0.1099  0.1083  0.0974  0.2280  0.2431  0.3771  0.5598   
3    0.0100  0.0171  0.0623  0.0205  0.0205  0.0368  0.1098  0.1276  0.0598   
4    0.0762  0.0666  0.0481  0.0394  0.0590  0.0649  0.1209  0.2467  0.3564   
..      ...     ...     ...     ...     ...     ...     ...     ...     ...   
203  0.0187  0.0346  0.0168  0.0177  0.0393  0.1630  0.2028  0.1694  0.2328   
204  0.0323  0.0101  0.0298  0.0564  0.0760  0.0958  0.0990  0.1018  0.1030   
205  0.0522  0.0437  0.0180  0.0292  0.0351  0.1171  0.1257  0.1178  0.1258   
206  0.0303  0.0353  0.0490  0.0608  0.0167  0.1354  0.1465  0.1123  0.1945   
207  0.0260  0.0363  0.0136  0.0272  0.0214  0.0338  0.0655  0.1400  0.1843   

         9   ...      51      52      53      54      55      56      57  \
0    0.2111  ...  0.0027  0.0065  0.0159  0.0072  0.0167  0.0180  0.0084   
1    0.2872  ...  0.0084  0.0089  0.0048  0.0094  0.0191  0.0140  0.0049   
2    0.6194  ...  0.0232  0.0166  0.0095  0.0180  0.0244  0.0316  0.0164   
3    0.1264  ...  0.0121  0.0036  0.0150  0.0085  0.0073  0.0050  0.0044   
4    0.4459  ...  0.0031  0.0054  0.0105  0.0110  0.0015  0.0072  0.0048   
..      ...  ...     ...     ...     ...     ...     ...     ...     ...   
203  0.2684  ...  0.0116  0.0098  0.0199  0.0033  0.0101  0.0065  0.0115   
204  0.2154  ...  0.0061  0.0093  0.0135  0.0063  0.0063  0.0034  0.0032   
205  0.2529  ...  0.0160  0.0029  0.0051  0.0062  0.0089  0.0140  0.0138   
206  0.2354  ...  0.0086  0.0046  0.0126  0.0036  0.0035  0.0034  0.0079   
207  0.2354  ...  0.0146  0.0129  0.0047  0.0039  0.0061  0.0040  0.0036   

         58      59  60  
0    0.0090  0.0032   0  
1    0.0052  0.0044   0  
2    0.0095  0.0078   0  
3    0.0040  0.0117   0  
4    0.0107  0.0094   0  
..      ...     ...  ..  
203  0.0193  0.0157   1  
204  0.0062  0.0067   1  
205  0.0077  0.0031   1  
206  0.0036  0.0048   1  
207  0.0061  0.0115   1  

[208 rows x 61 columns]>

3. 칼럼별 데이터의 수 출력

df[60].value_counts()
#칼럼 60의 값별로 데이터 수를 출력해준다.

--> 결과

1    111
0     97
Name: 60, dtype: int64

4. 입력과 타겟데이터 선언, 딥러닝 모델 정의

X=df.iloc[:,:-1]
y=df.iloc[:,-1]
from tensorflow.keras import models, layers
#models와 layers 모듈 임포트

model=models.Sequential()
#순차적레이어로 딥러닝 모델 생성

model.add(layers.Dense(24,input_dim=60, activation='relu'))
#입력값 60개, 은닉층 출력값24개, 활성화 함수는 relu를 사용한다.

model.add(layers.Dense(10,activation='relu'))
#입력값 24개, 은닉층 출력값10개, 활성화 함수는 relu를 사용한다.

model.add(layers.Dense(1,activation='sigmoid'))
#입력값 60개, 출력값1개, 활성화 함수는 sigmoid를 사용한다.

model.summary()

#Dense: 입력값과 출력값을 연결해주는 역할을 한다.

--> 결과

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 24)                1464      
                                                                 
 dense_1 (Dense)             (None, 10)                250       
                                                                 
 dense_2 (Dense)             (None, 1)                 11        
                                                                 
=================================================================
Total params: 1,725
Trainable params: 1,725
Non-trainable params: 0
_________________________________________________________________

5. 모델학습(feat. 과적합)

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
h=model.fit(X,y,epochs=200, batch_size=10)
#100퍼가 나온다.

- 200번 반복결과 정확도가 100%가 나온다.

- 이를 과적합이라고 한다. 과적합이란 모델이 학습 데이터셋 안에서는 일정 수준 이상의 예측 정확도를 보이지만, 새로운 데이터를 적용시 잘 맞지 않는 것을 의미한다.

- 데이터를 제대로 학습을 못하면 초록색 그래프처럼 분류를 제대로 못하게 된다.

--> 결과

Epoch 1/200
21/21 [==============================] - 1s 2ms/step - loss: 0.7371 - accuracy: 0.4663
Epoch 2/200
21/21 [==============================] - 0s 1ms/step - loss: 0.6918 - accuracy: 0.5673
Epoch 3/200
21/21 [==============================] - 0s 1ms/step - loss: 0.6746 - accuracy: 0.6010
Epoch 4/200
21/21 [==============================] - 0s 1ms/step - loss: 0.6578 - accuracy: 0.6731
Epoch 5/200
21/21 [==============================] - 0s 1ms/step - loss: 0.6474 - accuracy: 0.7019
Epoch 6/200
21/21 [==============================] - 0s 1ms/step - loss: 0.6349 - accuracy: 0.7260
Epoch 7/200

...

Epoch 194/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0203 - accuracy: 1.0000
Epoch 195/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0205 - accuracy: 1.0000
Epoch 196/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0193 - accuracy: 1.0000
Epoch 197/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0173 - accuracy: 1.0000
Epoch 198/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0164 - accuracy: 1.0000
Epoch 199/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0168 - accuracy: 1.0000
Epoch 200/200
21/21 [==============================] - 0s 1ms/step - loss: 0.0174 - accuracy: 1.0000

6. 훈련용과 테스트 데이터 분리하기

작업환경에서 scikit-learn패키지를 설치한다.

#과적합: 데이터 가공화가 잘 되어있지 않다.
#아웃라이어: 이상치 데이터
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, shuffle=True)
# 훈련데이터: 신경망이 학습에 이용하는 데이터
# 테스트데이터: 학습결과의 검증에 사용하는 데이터
# train_test_split: 데이터를 훈련용과 테스트용으로 쉽게 분리하기 위해 사용,
# 테스트 데이터는 훈련을 마친 모델의 정확도를 평가하는 용도로 사용한다.(과적합 판별에 쓰임)
# 학습에 사용하지 않는 데이터를 분류하기 위해서 사용

- 과적합을 방지하기 위해 학습하는 데이터셋과 테스트셋을 완전히 구분해 학습과 동시에 테스트를 병행했다.

model=models.Sequential()
model.add(layers.Dense(24,input_dim=60, activation='relu'))
model.add(layers.Dense(10,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))
#모델 설정하기

- 모델: 입력데이터를 가지고 원하는 출력을 예측하기 위한 구조이다.

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
h=model.fit(X_train,y_train,epochs=200, batch_size=10)
#훈련데이터 X_train, y_train으로 모델을 학습한다.

--> 결과

Epoch 1/200
15/15 [==============================] - 1s 2ms/step - loss: 0.7042 - accuracy: 0.4759
Epoch 2/200
15/15 [==============================] - 0s 1ms/step - loss: 0.6901 - accuracy: 0.5586
Epoch 3/200
15/15 [==============================] - 0s 1ms/step - loss: 0.6838 - accuracy: 0.6069
Epoch 4/200
15/15 [==============================] - 0s 1ms/step - loss: 0.6795 - accuracy: 0.6000
Epoch 5/200
15/15 [==============================] - 0s 1ms/step - loss: 0.6743 - accuracy: 0.6414
Epoch 6/200
15/15 [==============================] - 0s 3ms/step - loss: 0.6672 - accuracy: 0.6690
Epoch 7/200
15/15 [==============================] - 0s 1ms/step - loss: 0.6598 - accuracy: 0.6483

...

Epoch 194/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0197 - accuracy: 1.0000
Epoch 195/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0198 - accuracy: 1.0000
Epoch 196/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0180 - accuracy: 1.0000
Epoch 197/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0187 - accuracy: 1.0000
Epoch 198/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0214 - accuracy: 1.0000
Epoch 199/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0187 - accuracy: 1.0000
Epoch 200/200
15/15 [==============================] - 0s 1ms/step - loss: 0.0171 - accuracy: 1.0000

7. 정확도 구하기

score=model.evaluate(X_test, y_test)
print('Test Accuracy: %.4f'%(score[1]))
#테스트셋으로 학습된 모델을 평가한다.

--> 결과

2/2 [==============================] - 0s 2ms/step - loss: 0.6518 - accuracy: 0.7937
Test Accuracy: 0.7937

- 훈련데이터로는 100%가 나왔지만 테스트셋으로 한 결과 79.3%가 나왔다.

8. 모델 저장

model.save('model/mineral.hdf5')
#저장할 위치와 모델이름을 지정한다.

--> 결과

9. 모델 삭제

del model
model

--> 결과

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[14], line 1
----> 1 model

NameError: name 'model' is not defined

10. 정확도 구하기(모델 재활용)

model=models.load_model('model/mineral.hdf5')
# 레이어, 가중치 정보등이 들어있다.
score=model.evaluate(X_test, y_test)
print('Test Accuracy: %.4f'%(score[1]))
#저장한 모델을 가지고와 정확도를 계산할수 있다.

--> 결과

2/2 [==============================] - 0s 2ms/step - loss: 0.6518 - accuracy: 0.7937
Test Accuracy: 0.7937

2. 모델 성능 검증(파이토치 이용)

1. 데이터 확인과 예측 실행

import torch 
#파이토치 라이브러리

import numpy as np
#numpy라이브러리(수치연산)

import torch.nn as nn 
#파이토치에서 딥러닝 모델 정의하는데 필요한 모듈제공

import torch.optim as optim 
#파이토치에서 최적화 알고리즘 제공

from torch.utils.data import DataLoader, TensorDataset 
#데이터를 로드하고 학습에 사용하기 위한 클래스

import pandas as pd 
#pandas 라이브러리(데이터 분석, 조작)

from sklearn.model_selection import train_test_split 
#scikit-learn 라이브러리 제공, 훈련과 테스트 세트 분할시 사용
device = ('cuda' if torch.cuda.is_available() else 'cpu')
#cpu인지 gpu인지 조사
df = pd.read_csv('data/sonar3.csv',header=None)
#csv파일을 로드한다.
X=df.iloc[:,:-1]
y=df.iloc[:,-1]
#입력데이터와 타겟변수를 선언한다.
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, shuffle=True)
#훈련데이터와 학습데이터를 분류한다.
def df_to_tensor(df):
    return torch.from_numpy(df.values).float().to(device)
    #from_numpy: 데이터프레임(df) 내 데이터를 넘파이 배열로 변환한다.
    #float: 넘파이 배열을 파이토치의 float데이터 타입으로 변환한다.
    #to(device): 지정한 디바이스(cpu혹은 gpu)로 이동한다.
X_train=df_to_tensor(X_train)
X_test=df_to_tensor(X_test)
y_train=df_to_tensor(y_train)
y_test=df_to_tensor(y_test)
#훈련,학습 데이터들을 df_to_tensor함수로 파이토치의 텐서로 변환하고 디바이스로 이동해
#모델에 입력하게 한다. 이제 데이터를 사용해 모델을 학습하고 평가할 수 있다.
#인공신경망 Mineral를 생성한다.
class Mineral(nn.Module):
    def __init__(self):
        super(Mineral, self).__init__()
        self.hidden_linear1 = nn.Linear(60,24)
        self.hidden_activation1 = nn.ReLU()
        self.hidden_linear2 = nn.Linear(24,10)
        self.hidden_activation2 = nn.ReLU()
        self.output_linear = nn.Linear(10,1)
        self.output_activation = nn.Sigmoid()
   
    def forward(self, x):
        x = self.hidden_linear1(x)
        x = self.hidden_activation1(x)
        x = self.hidden_linear2(x)
        x = self.hidden_activation2(x)
        x = self.output_linear(x)
        x = self.output_activation(x)

        return x
model=Mineral().to(device)
model
#Mineral클래스를 인스턴스화해 model에 할당하고
#모델이 지정한 디바이스로 옮긴다.

--> 결과

Mineral(
  (hidden_linear1): Linear(in_features=60, out_features=24, bias=True)
  (hidden_activation1): ReLU()
  (hidden_linear2): Linear(in_features=24, out_features=10, bias=True)
  (hidden_activation2): ReLU()
  (output_linear): Linear(in_features=10, out_features=1, bias=True)
  (output_activation): Sigmoid()
)

2. 파리미터 개수 구하기

def count_parameters(model):
    total_param = 0
    for name, param in model.named_parameters():
        if param.requires_grad:
            num_param = np.prod(param.size())
            if param.dim() > 1:
                print(name, ':', ' x '.join(str(x) for x in list(param.size())[::-1]), '=', num_param)
            else:
                print(name, ':', num_param)
                print('-' * 40)
            total_param += num_param
    print('total:', total_param)
count_parameters(model)

--> 결과

hidden_linear1.weight : 60 x 24 = 1440
hidden_linear1.bias : 24
----------------------------------------
hidden_linear2.weight : 24 x 10 = 240
hidden_linear2.bias : 10
----------------------------------------
output_linear.weight : 10 x 1 = 10
output_linear.bias : 1
----------------------------------------
total: 1725

3. 손실값 구하기

batch_size=10 
#한 번의 반복마다 사용할 미니배치 크기 설정

ds = TensorDataset(X_train,y_train)
#훈련 데이터를 TensorDataset형태로 만든다.

dataloader = DataLoader(ds, batch_size=batch_size)
#훈련 데이터셋을 미니배치로 나누고(batch_size=10) 로드한다.

optimizer = optim.Adam(model.parameters())
#Adam 옵티마이저를 정의한다.

loss_fn=nn.BCELoss()
#이진분류를 위한 이진 교차 엔트로피 손실함수를 정의한다.

n_epochs = 100 #전체데이터셋을 몇번 반복해 학습할지 설정한다.

for epoch in range(n_epochs): #반복횟수 관련 for문 선언
    for data, label in dataloader: #훈련 데이터셋 관련 for문 선언()
        out = model(data.type(torch.FloatTensor).to(device))
        #forward propagation
        #모델을 사용해 입력데이터에 대한 예측값을 계산한다.
        
        loss = loss_fn(out, label.type(torch.FloatTensor).unsqueeze(1).to(device))
        #calculate loss 
        #예측값과 실제 타겟 값을 사용해 손실을 계산한다.
        
        optimizer.zero_grad() 
        #옵티마이저에 연결된 모든 파라미터의 그라디언트를 0으로 초기화시킨다.
        
        loss.backward() #개별 파라미터 기울기 계산
        optimizer.step() #개별 파라미터 갱신
        
    print("Epoch: %d, Loss: %.4f"%(epoch, float(loss)))
    #에포크와 손실을 출력한다.
    
torch.save(model.state_dict(),'model/mineral.pth')
#학습이 끝난 모델의 파라미터를 mineral.pth파일로 저장한다.

--> 결과

Epoch: 0, Loss: 0.6825
Epoch: 1, Loss: 0.6847
Epoch: 2, Loss: 0.6866
Epoch: 3, Loss: 0.6861
Epoch: 4, Loss: 0.6843
Epoch: 5, Loss: 0.6814

...

Epoch: 94, Loss: 0.0775
Epoch: 95, Loss: 0.0815
Epoch: 96, Loss: 0.0739
Epoch: 97, Loss: 0.0744
Epoch: 98, Loss: 0.0712
Epoch: 99, Loss: 0.0704

4. 정확도 구하기

model.load_state_dict(torch.load('model/mineral.pth',map_location=device))
#mineral.pth파일을 불러와 학습된 모델의 파리미터를 불러 현재 디자이스에 맞게 조정한다.

test_ds = TensorDataset(X_test, y_test)
#테스트 데이터를 TensorDataset형태로 만든다.

test_loader=DataLoader(test_ds,batch_size=batch_size)
#test_ds을 풀러와 batch_size만큼 데이터를 로드한다.

correct = 0 #정확히 예측할 개수이다. 지금은 0으로 초기화한 것이다.

with torch.no_grad():#모델 평가과정에서 그라디언트는 계산할 필요없어 no_grad()를 선언했다.
    for data, label in test_loader: 
    	#테스트 데이터 관련 루프를 선언한다.(data: 입력데이터, label: 실제타겟값)
        
        pred = model(data.to(device))
        #모델을 사용해 입력 데이터에 대한 예측값 계산
        
        result = pred.squeeze(1).ge(torch.tensor(0.5).to(device)) #1차원으로 바뀜
        #타겟이 0,1이라서 0,1이 되어야 실질적인 비교가 가능, 0.5보다 이상이면1 아니면 0
        
        correct += result.long().eq(label.to(device)).sum().item()
        #예측수를 계산한다. 예측결과와 실제 레이블을 비교해 올바르게 예측한 개수를 더한다.
        
print('Accuracy: %.4f'%(correct / len(test_loader.dataset)))
#정확도를 출력한다.

--> 결과

Accuracy: 0.6825

3. k겹 교차 검증 

- K겹 교차 검증

1) 데이터셋을 여러 개로 나누어 하나씩 테스트셋으로 사용하고 나머지를 모두 합해 학습셋으로 사용하는 방법이다.

2) 데이터 셋을 여러개로 나누었을때 나누어진 셋을 전부다 사용하지 못하는 단점을 보완한 것이다.

3) 이렇게 하면 가지고 있는 데이터의 100%를 학습셋으로 사용할 수 있고 동시에 테스트셋으로도 사용할 수 있다.

1. csv파일 로드, 입력 목표선수 선언, 딥러닝 모델 생성

from tensorflow.keras import models, layers
from sklearn.model_selection import KFold
import pandas as pd

df = pd.read_csv('data/sonar3.csv',header=None)
#csv 파일을 로드한다.
X=df.iloc[:,:-1]
y=df.iloc[:,-1]
#입력변수와 목표변수를 만든다.
k=5
#파일을 몇개로 나눌지 넣는다.

kfold = KFold(n_splits=k, shuffle=True)
#KFold함수를 불러와 분할 전에 샘플이 치우치지 않도록 섞는다.

acc_score=[]
#정확도가 채워질 빈 리스트를 준비한다.

def model_fn():
    model=models.Sequential()
    model.add(layers.Dense(24,input_dim=60, activation='relu'))
    model.add(layers.Dense(10,activation='relu'))
    model.add(layers.Dense(1,activation='sigmoid'))
    return model
#딥러닝 모델을 선언한다.
for train_index, test_index in kfold.split(X):
	#Kfold 교차검증 위해 데이터 셋을 
    X_train, X_test = X.iloc[train_index, :], X.iloc[test_index,:]
    #행의 train_index번째를 출력하고 열은 전부 출력한다.
    #인덱스로 훈련, 검증 데이터를 생성한다.
    
    y_train, y_test = y.iloc[train_index], y.iloc[test_index]
    #train_index번째 값들을 출력한다.
    #마찬가지로 인덕스로 훈련, 검증데이터를 생성한다.
    
    model=model_fn()
    #모델 함수를 호출해 새로운 모델을 생성한다.
    
    model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
    #모델 컴파일 단계에서 손실함수, 옵티마이저, 평가지표를 설정한다.
    
    h=model.fit(X_train,y_train,epochs=100, batch_size=10,verbose=0)
    #훈련 데이터로 모델을 학습시킨다.
    #verbose=0: 계산은 하지만 출력은 X
    
    accuracy = model.evaluate(X_test,y_test)[1]
    #검증 데이터를 사용해 모델의 성능을 평가해 정확도를 계산한다.
    
    acc_score.append(accuracy)
    #각 폴드에서 계산된 정확도를 리스트에 추가한다.

avg_acc_score = sum(acc_score)/k #K번 폴드에서 계산된 정확도를 리스트에 추가한다.
print('정확도: ',acc_score)
print('정확도 평균:',avg_acc_score)

--> 결과

2/2 [==============================] - 0s 2ms/step - loss: 0.5441 - accuracy: 0.7857
2/2 [==============================] - 0s 0s/step - loss: 0.6377 - accuracy: 0.8095
2/2 [==============================] - 0s 2ms/step - loss: 0.2608 - accuracy: 0.8810
2/2 [==============================] - 0s 13ms/step - loss: 0.6155 - accuracy: 0.7073
WARNING:tensorflow:5 out of the last 9 calls to <function Model.make_test_function.<locals>.test_function at 0x00000270549F1700> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
2/2 [==============================] - 0s 10ms/step - loss: 0.3397 - accuracy: 0.9512
정확도:  [0.7857142686843872, 0.8095238208770752, 0.8809523582458496, 0.707317054271698, 0.9512194991111755]
정확도 평균: 0.8269454002380371

- 텐서플로 함수가 for문에 포함될 경우 WARNING 메시지가 나올수 있지만 문제는 없다.

4.  모델 성능 향상시키기

wine.csv
0.34MB

 

- wine.csv파일을 작업하는 경로에 추가해준다.

1) UCI 사이트로 들어간다.

https://archive.ics.uci.edu/

 

UCI Machine Learning Repository

Welcome to the UC Irvine Machine Learning Repository We currently maintain 624 datasets as a service to the machine learning community. Here, you can donate and find datasets used by millions of people all around the world!

archive.ics.uci.edu

2) Wine으로 들어간다. 이곳에서 wine데이터 features를 알 수 있다.

(여담으로 이 사이트는 딥러닝을 할수 있는 자료들이 많다)

1. 모듈임포트, csv파일 가져오기

from tensorflow.keras import models, layers #tensorflow패키지에서 keras모듈의 models,layers클래스
from sklearn.model_selection import train_test_split
import pandas as pd
df = pd.read_csv('data/wine.csv',header=None)
df.head()

--> 결과

2. 기본 정보 출력하기

df.info()

--> 결과

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6497 entries, 0 to 6496
Data columns (total 13 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   0       6497 non-null   float64
 1   1       6497 non-null   float64
 2   2       6497 non-null   float64
 3   3       6497 non-null   float64
 4   4       6497 non-null   float64
 5   5       6497 non-null   float64
 6   6       6497 non-null   float64
 7   7       6497 non-null   float64
 8   8       6497 non-null   float64
 9   9       6497 non-null   float64
 10  10      6497 non-null   float64
 11  11      6497 non-null   int64  
 12  12      6497 non-null   int64  
dtypes: float64(11), int64(2)
memory usage: 660.0 KB

3. 입력과 타겟변수 선언, 훈련과 테스트 데이터 나누기

X=df.iloc[:,:-1]
y=df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, shuffle=True)
model=models.Sequential()
model.add(layers.Dense(30,input_dim=12, activation='relu'))
model.add(layers.Dense(12, activation='relu'))
model.add(layers.Dense(8, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

--> 결과

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 30)                390       
                                                                 
 dense_1 (Dense)             (None, 12)                372       
                                                                 
 dense_2 (Dense)             (None, 8)                 104       
                                                                 
 dense_3 (Dense)             (None, 1)                 9         
                                                                 
=================================================================
Total params: 875
Trainable params: 875
Non-trainable params: 0
_________________________________________________________________

4. 모델 컴파일, 모델 실행

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
h=model.fit(X_train,y_train,epochs=50, batch_size=200,validation_split=0.25)

--> 결과

Epoch 1/50
20/20 [==============================] - 1s 14ms/step - loss: 0.0657 - accuracy: 0.9813 - val_loss: 0.0626 - val_accuracy: 0.9815
Epoch 2/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0628 - accuracy: 0.9808 - val_loss: 0.0622 - val_accuracy: 0.9823
Epoch 3/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0612 - accuracy: 0.9823 - val_loss: 0.0625 - val_accuracy: 0.9823
Epoch 4/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0609 - accuracy: 0.9836 - val_loss: 0.0623 - val_accuracy: 0.9823
Epoch 5/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0602 - accuracy: 0.9820 - val_loss: 0.0643 - val_accuracy: 0.9808

...

Epoch 46/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0516 - accuracy: 0.9856 - val_loss: 0.0595 - val_accuracy: 0.9838
Epoch 47/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0518 - accuracy: 0.9838 - val_loss: 0.0595 - val_accuracy: 0.9823
Epoch 48/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0519 - accuracy: 0.9849 - val_loss: 0.0618 - val_accuracy: 0.9838
Epoch 49/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0532 - accuracy: 0.9856 - val_loss: 0.0626 - val_accuracy: 0.9808
Epoch 50/50
20/20 [==============================] - 0s 3ms/step - loss: 0.0529 - accuracy: 0.9846 - val_loss: 0.0602 - val_accuracy: 0.9823

5. 테스트 결과 출력

score=model.evaluate(X_test, y_test)
print('Test Accuracy:%.4f'%(score[1]))

--> 결과

41/41 [==============================] - 0s 1ms/step - loss: 0.1269 - accuracy: 0.9546
Test Accuracy:0.9546

5.  모델업데이트 하기

1. 모듈 임포트하기

from tensorflow.keras import models, layers
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import ModelCheckpoint
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

2. csv 로드, 입력과 타겟 변수나누기,

df = pd.read_csv('data/wine.csv',header=None)
X=df.iloc[:,:-1]
y=df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, shuffle=True)

3. 딥러닝 모델 생성

model=models.Sequential()
model.add(layers.Dense(30,input_dim=12, activation='relu'))
model.add(layers.Dense(12, activation='relu'))
model.add(layers.Dense(8, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

4. 모델 컴파일

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

5. 모델 저장조건 설정

modelpath = "model/"+"{epoch:02d}-{val_accuracy:.4f}.hdf5"
#가중치 파일이 저장될 경로와 파일이름을 지정한다.
#{epoch:02d}:2자리형식으로 에포크 번호를 입력한다.
#{val_accuracy:.4f}: 소수점 4자리까지 검증데이터 정확도를 입력한다.

checkpoint = ModelCheckpoint(filepath=modelpath,verbose=1)
#ModelCheckPoint를 선언해 학습중인 모델을 저장한다.
#verbose=1을 선언해 진행되는 현황을 모니터한다.

h=model.fit(X_train,y_train,epochs=50, batch_size=200,validation_split=0.25,
           verbose=0,callbacks=[checkpoint])
#모델을 실행한다.

--> 결과

Epoch 1: saving model to model\01-0.7908.hdf5

Epoch 2: saving model to model\02-0.8846.hdf5

Epoch 3: saving model to model\03-0.9023.hdf5

Epoch 4: saving model to model\04-0.9277.hdf5

Epoch 5: saving model to model\05-0.9315.hdf5

...

Epoch 46: saving model to model\46-0.9646.hdf5

Epoch 47: saving model to model\47-0.9715.hdf5

Epoch 48: saving model to model\48-0.9715.hdf5

Epoch 49: saving model to model\49-0.9746.hdf5

Epoch 50: saving model to model\50-0.9746.hdf5

--> model 폴더에 생성된 파일

6.  그래프로 과적합 확인하기

1. 모듈임포트, csv로드, 딥러닝 모델만들기

from tensorflow.keras import models, layers
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import ModelCheckpoint
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv('data/wine.csv',header=None)
X=df.iloc[:,:-1]
y=df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, shuffle=True)

model=models.Sequential()
model.add(layers.Dense(30,input_dim=12, activation='relu'))
model.add(layers.Dense(12, activation='relu'))
model.add(layers.Dense(8, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

2. 학습하기(에포크 수를 2000으로 늘렸다.)

h=model.fit(X_train,y_train,epochs=2000, batch_size=200,validation_split=0.25,verbose=0)
#인위적으로 많이 주어서 과대적합 관찰

 

hist_df=pd.DataFrame(h.history)
#model.fit()을 실행할 때마다 결과를 history에 저장한다.
hist_df.head()

--> 결과

3. 히스토리값 정보

hist_df.info()

--> 결과

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2000 entries, 0 to 1999
Data columns (total 4 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   loss          2000 non-null   float64
 1   accuracy      2000 non-null   float64
 2   val_loss      2000 non-null   float64
 3   val_accuracy  2000 non-null   float64
dtypes: float64(4)
memory usage: 62.6 KB

4. 타입 출력

print(type(h.history))

--> 결과

<class 'dict'>

5. 히스토리 데이터의 키값 조회

print(h.history.keys())

--> 결과

dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])

6. 그래프 표현

import os
os.environ["KMP_DUPLICATE_LIB_OK"]="1"

# y_vloss에 테스트셋(여기서는 검증셋)의 오차를 저장합니다.
y_vloss = hist_df['val_loss']

# y_loss에 학습셋의 오차를 저장합니다.
y_loss = hist_df['loss']

# x 값을 지정하고 테스트셋(검증셋)의 오차를 빨간색으로, 학습셋의 오차를 파란색으로 표시합니다.
x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, "o", c="red", markersize=2, label='Testset_loss')
plt.plot(x_len, y_loss, "o", c="blue", markersize=2, label='Trainset_loss')

plt.legend(loc='upper right')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

--> 결과

- 학습을 오래 진행할 수록 학습셋의 오차(파란색)는 줄어들지만 검증셋의 오차(빨간색)는 다시 커진다.

- 이는 과도한 학습으로 과적합이 발생했기 때문이다.

- 이는 과도한 학습으로 과적합이 발생했다는 것을 알 수 있다.

- 검증셋 오차가 커지기 직전까지 학습한 모델이 최적의 횟수로 학습한 모델이다.

 

7.  학습 자동중단

- 학습이 진행되어도 테스트셋 오차가 줄어들지 않으면 학습을 자동으로 멈추게 한다.

1. 딥러닝 모델 만들기

from tensorflow.keras import models, layers
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv('data/wine.csv',header=None)
X=df.iloc[:,:-1]
y=df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, shuffle=True)

model=models.Sequential()
model.add(layers.Dense(30,input_dim=12, activation='relu'))
model.add(layers.Dense(12, activation='relu'))
model.add(layers.Dense(8, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

2. early_stopping

early_stopping = EarlyStopping(monitor='val_loss',patience=20)
#EarlyStopping: 학습이 진행되어도 테스트셋 오차가 줄지 않으면 학습을 자동으로 멈추는 함수
#학습이 언제 자동 중단될지 설정한다.
#연속 20번이상 안좋아시지면 학습을 멈추게함.

modelpath = "model/wine-best.hdf5"
#최적화 모델이 저장될 폴더와 모델이름을 지정한다.

checkpoint = ModelCheckpoint(filepath=modelpath,verbose=0,monitor='val_loss',
                             save_best_only=True)
#최적화 모델을 업데이트하고 저장한다. 단, 좋아실때만(loss가 줄어들때) 저장

h=model.fit(X_train,y_train,epochs=2000, batch_size=200,validation_split=0.25,
           verbose=1,callbacks=[checkpoint,early_stopping])
#모델을 실행한다.

--> 결과

Epoch 1/2000
20/20 [==============================] - 1s 13ms/step - loss: 0.4851 - accuracy: 0.8247 - val_loss: 0.2952 - val_accuracy: 0.9146
Epoch 2/2000
20/20 [==============================] - 0s 5ms/step - loss: 0.2556 - accuracy: 0.9281 - val_loss: 0.2492 - val_accuracy: 0.9169
Epoch 3/2000
20/20 [==============================] - 0s 6ms/step - loss: 0.2281 - accuracy: 0.9338 - val_loss: 0.2389 - val_accuracy: 0.9162
Epoch 4/2000
20/20 [==============================] - 0s 5ms/step - loss: 0.2189 - accuracy: 0.9335 - val_loss: 0.2336 - val_accuracy: 0.9185
Epoch 5/2000
20/20 [==============================] - 0s 5ms/step - loss: 0.2106 - accuracy: 0.9348 - val_loss: 0.2238 - val_accuracy: 0.9192

...

Epoch 203/2000
20/20 [==============================] - 0s 3ms/step - loss: 0.0421 - accuracy: 0.9887 - val_loss: 0.0482 - val_accuracy: 0.9838
Epoch 204/2000
20/20 [==============================] - 0s 3ms/step - loss: 0.0443 - accuracy: 0.9864 - val_loss: 0.0514 - val_accuracy: 0.9854
Epoch 205/2000
20/20 [==============================] - 0s 3ms/step - loss: 0.0497 - accuracy: 0.9864 - val_loss: 0.0494 - val_accuracy: 0.9862
Epoch 206/2000
20/20 [==============================] - 0s 3ms/step - loss: 0.0483 - accuracy: 0.9859 - val_loss: 0.0491 - val_accuracy: 0.9838
Epoch 207/2000
20/20 [==============================] - 0s 4ms/step - loss: 0.0432 - accuracy: 0.9864 - val_loss: 0.0496 - val_accuracy: 0.9823

3. 정확도 출력

score=model.evaluate(X_test,y_test)
print('Test Accuracy:%.4f'%(score[1]))

--> 결과

41/41 [==============================] - 0s 1ms/step - loss: 0.0565 - accuracy: 0.9815
Test Accuracy:0.9815

- 초반에 와인데이터를 분석할때 95.46%였던 것을 감안하면 모델성능이 대폭 향상된 것을 볼 수 있다.