336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

세 번째 프로젝트 순서 

 

1. 식물 병충해 자료 파일분류

2. CNN 모델링

3. 이미지화

4. CNN, AlexNet, VGG-16 모델 평가

 


프로젝트 발표 준비 전 모델 평가 및 성능 테스트? 단계

 

참고로 그린라이트로 정하게 된 배경에는.. 예전에 마녀사냥에서 자주 사용했던 그린라이트, 불빛이 들어온다는 느낌에서 약간의 언어유희를 사용했다. 식물이 아픈지 안 아픈지 제대로 정의해준다(right)와 밝혀준다(light)의 조합이랄까..

 

 

 

 

이미지 인식 모델에서 자주 사용 되는 모델 AlexNet, VGG-16, GoogleNet(2012~2014), ResNet, InceptionV3 (2014 이후) 매년  ImageNet Large Scale Visual Recognition Challenge( ILSVRV ) 대회에서 성능 비교를 한다. 요즘은 점차 정확도에 차이가 줄어서 0.01% 차이로도 순위가 갈린다고 수업시간에 들었다.

 

 

 

 

 

AlexNet

2012AlexNet 은 이전의 모든 경쟁자를 압도할 정도로, 상위 5개 오류를 26%에서 15.3%로 줄였다고 한다. 총 8개의 layer로 구성 됐고, 5개는 convolutional layer로 구성이 됐다.  11x11, 5x5, 3x3, 컨볼루션, 최대 풀링, 드롭아웃, 데이터 증대, ReLU 활성화 등으로 구성이 됐다. 

 

입력 크기 256x256x3

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
def Alexnet_model():
    inputs = Input(shape=(64643))
 
    conv1 = Conv2D(filters=48, kernel_size=(1010), strides=1, padding="valid", activation='relu')(inputs)
    pool1 = MaxPooling2D(pool_size=(33), strides=2, padding="valid")(conv1)
    nor1 = tf.nn.local_response_normalization(pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0, beta=0.75)
 
    conv2 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", groups=2, activation='relu')(nor1)
    pool2 = MaxPooling2D(pool_size=(33), strides=2, padding="valid")(conv2)
    nor2 = tf.nn.local_response_normalization(pool2, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)
 
    conv3 = Conv2D(filters=192, kernel_size=(33), strides=1, padding="same", activation='relu')(nor2)
    conv4 = Conv2D(filters=192, kernel_size=(33), strides=1, padding="same", activation='relu')(conv3)
    conv5 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv4)
    pool3 = MaxPooling2D(pool_size=(33), strides=2, padding="valid")(conv5)
    drop1 = Dropout(0.5)(pool3)
    nor3 = tf.nn.local_response_normalization(drop1, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)
 
    flat = Flatten()(nor3)
    dense1 = Dense(units=2048, activation='relu')(flat)
    dense2 = Dense(units=1024, activation='relu')(dense1)
    logits = Dense(units=20, activation='softmax')(dense2)
 
    return Model(inputs=inputs, outputs=logits)
 
 
model=Alexnet_model()
model.summary()
model.compile(loss='binary_crossentropy', optimizer=otm, metrics=["accuracy"])
cs

 

 

 

 

 

GoogleNet

ILSVRC 2014 대회의 우승자는 Google의 GoogLeNet(Inception V1이라고도 함)이다. 6.67%의 상위 5위 오류율을 달성. 인간 수준의 성과에 매우 가까웠다고 한다. 27개의 pooling layer가 포함된 22개의 layer로 구성된다. 

 

 

 

 

EarlyStopping을 했을 때 이미지 사이즈에 맞게 변형해서 만든 저희 모델들의 결과

 

 

 

 

 

VGG-16

ILSVRC 2014 대회의 준우승은 커뮤니티에서 VGGNet이다. VGGNet은 16개의 컨볼루션 레이어로 구성되며 매우 균일한 아키텍처로 구성됐다. AlexNet과 유사한 3x3 회선만 있지만 필터가 더 많다. 이미지에서 특징을 추출하기 위해 커뮤니티에서 선호되고 있다. 단점은 훈련에 많은 시간이 걸리고, 네트워크 아키텍처 가중치가 크다.

 

이미지 크기 244x244

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
def vgg_16():
    inputs = Input(shape=(64643))
    conv1_1 = Conv2D(filters=32, kernel_size=(33), strides=1, padding="same", activation='relu')(inputs)
    conv1_2 = Conv2D(filters=32, kernel_size=(33), strides=1, padding="same", activation='relu')(conv1_1)
    pool1 = MaxPooling2D(pool_size=(22), strides=2, padding="valid")(conv1_2)
    nor1 = BatchNormalization()(pool1)
 
    conv2_1 = Conv2D(filters=64, kernel_size=(33), strides=1, padding="same", activation='relu')(nor1)
    conv2_2 = Conv2D(filters=64, kernel_size=(33), strides=1, padding="same", activation='relu')(conv2_1)
    pool2 = MaxPooling2D(pool_size=(22), strides=2, padding="valid")(conv2_2) # 16
    nor2 = BatchNormalization()(pool2)
 
    conv3_1 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(nor2)
    conv3_2 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv3_1)
    conv3_3 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv3_2)
    pool3 = MaxPooling2D(pool_size=(22), strides=2, padding="valid")(conv3_3)
    nor3 = BatchNormalization()(pool3)
 
    # 4 layers
    conv4_1 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(nor3)
    conv4_2 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv4_1)
    conv4_3 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv4_2)
    pool4 = MaxPooling2D(pool_size=(22), strides=2, padding="valid")(conv4_3) # 4
    nor4 = BatchNormalization()(pool4)
 
    # 5 layers
    conv5_1 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(nor4)
    conv5_2 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv5_1)
    conv5_3 = Conv2D(filters=128, kernel_size=(33), strides=1, padding="same", activation='relu')(conv5_2)
    pool5 = MaxPooling2D(pool_size=(22), strides=2, padding="valid")(conv5_3)
    nor5 = BatchNormalization()(pool5)
    drop5 = Dropout(0.5)(nor5)
 
    flatten1 = Flatten()(drop5)
    dense1 = Dense(units=2048, activation=tf.nn.relu)(flatten1)
    dense2 = Dense(units=1024, activation=tf.nn.relu)(dense1)
 
    logits = Dense(units=20, activation='softmax')(dense2)
    return Model(inputs=inputs, outputs=logits)
 
model=vgg_16()
model.compile(loss='categorical_crossentropy', optimizer=otm, metrics=["accuracy"])
model.summary()
cs

 

 

 

모델 성능 평가

외부 데이터를 수집하려고 직접 찾아보면서 고생을 하다가, 관련 자료를 깃허브에 친절하게 올려주신 분이 있어서 감사히 썼습니다.

 

https://github.com/spMohanty/PlantVillage-Dataset/tree/master/raw/color

 

GitHub - spMohanty/PlantVillage-Dataset: Dataset of diseased plant leaf images and corresponding labels

Dataset of diseased plant leaf images and corresponding labels - GitHub - spMohanty/PlantVillage-Dataset: Dataset of diseased plant leaf images and corresponding labels

github.com

 

 

 

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
##########################
# 테스트 데이터 50개 랜덤으로 평가
##########################
 
 
########################################
#class name으로 변경
from os import rename, listdir
 
path2 = "./tests"  #TEST_DATA => tests로 수정함
 
list3 = list(str(i) for i in range(20))
dict3 = dict(zip(combined_labels,list3))
 
for fname in os.listdir(path2):
    newname = dict3.get(fname)
    try:
        if newname not in os.listdir(path2) :    
            os.rename(os.path.join(path2, fname), os.path.join(path2,newname))
    except:
        counter = True
 
if counter :        
    print("이미 변경 완료")
else :
    print("class name으로 변경완료")
 
 
########################################
### 필수 아님 #####
 
#labeled_name으로 되돌리고 싶을 때
list3 = list(str(i) for i in range(20))
dict3 = dict(zip(list3, combined_labels))
 
for fname in os.listdir(path2):
    newname = dict3.get(fname)
    try :
        if newname not in os.listdir(path2) :    
            os.rename(os.path.join(path2, fname), os.path.join(path2,newname))
    except:
        counter = True
 
if counter :        
    print("이미 변경 완료")
else :
    print("labeled name으로 변경완료")
 
 
########################################
import os, re, glob
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import img_to_array
import random
 
# class에 따른 본래 label
t_list = list(str(i) for i in range(20))
t_dict = dict(zip(t_list, combined_labels))
 
 
 
########################################
#테스트 데이터 list
tests ='./tests'
tests_list = os.listdir(tests)
 
model = load_model('model1.h5')     # 자신의 model load
 
def convert_image_to_array(image_dir):
    try:
        image = cv2.imread(image_dir)
        if image is not None :
            image = cv2.resize(image, dsize=(64,64))
            return img_to_array(image)
        else :
            return np.array([])
    except Exception as e:
        print(f"Error : {e}")
        return None
 
def predict_disease(image_path, num):
    global count
    image_array = convert_image_to_array(image_path)
    np_image = np.array(image_array, dtype=np.float32) / 225.0
    np_image = np.expand_dims(np_image,0)
    result = model.predict_classes(np_image)
    c = result.astype(str)[0]
    if c == num : 
        count += 1
    return count
 
for i in range(20):
    num = str(i)
    tests_file = os.listdir(f'tests/{num}')
    count = 0
    max = len(tests_file)
    
    for j in range(50):
        ran_num = random.randint(0,max) # 임의의 숫자 추출
        tests_path =  f'tests/{num}/' + os.listdir(f'./tests/{num}')[ran_num]
        predict_disease(tests_path, num)
 
    print(f'###### 테스트 데이터 {t_dict.get(num)} 의 정확도 입니다 #######' )
    print('accuracy: {:0.5f}'.format(count/50))
 
print('테스트 완료')
cs

 

###### 테스트 데이터 Corn_(maize)_Common_rust_ 의 정확도 입니다 #######
accuracy: 1.00000
###### 테스트 데이터 Corn_(maize)_healthy 의 정확도 입니다 #######
accuracy: 1.00000
###### 테스트 데이터 Grape_Black_rot 의 정확도 입니다 #######
accuracy: 0.96000
###### 테스트 데이터 Grape_Esca_(Black_Measles) 의 정확도 입니다 #######
accuracy: 0.94000
###### 테스트 데이터 Grape_Leaf_blight_(lsariopsis_Leaf_Spot) 의 정확도 입니다 #######
accuracy: 0.98000
###### 테스트 데이터 Orange_Haunglongbing_(Citrus_greening) 의 정확도 입니다 #######
accuracy: 0.98000
###### 테스트 데이터 Pepper,_bell_Bacterial_spot 의 정확도 입니다 #######
accuracy: 0.94000
###### 테스트 데이터 Pepper,_bell_healthy 의 정확도 입니다 #######
accuracy: 0.98000
###### 테스트 데이터 Potato_Early_blight 의 정확도 입니다 #######
accuracy: 1.00000
###### 테스트 데이터 Potato_Late_blight 의 정확도 입니다 #######
accuracy: 0.98000
###### 테스트 데이터 Soybean_healthy 의 정확도 입니다 #######
accuracy: 0.96000
###### 테스트 데이터 Squash_Powdery_mildew 의 정확도 입니다 #######
accuracy: 0.94000
###### 테스트 데이터 Tomato_Bacterial_spot 의 정확도 입니다 #######
accuracy: 0.90000
###### 테스트 데이터 Tomato_Early_blight 의 정확도 입니다 #######
accuracy: 0.90000
###### 테스트 데이터 Tomato_Late_blight 의 정확도 입니다 #######
accuracy: 0.84000
###### 테스트 데이터 Tomato_Septoria_leaf_spot 의 정확도 입니다 #######
accuracy: 0.96000
###### 테스트 데이터 Tomato_Spider_mites_Two-spotted_spider_mite 의 정확도 입니다 #######
accuracy: 0.96000
###### 테스트 데이터 Tomato_Target_Spot 의 정확도 입니다 #######
accuracy: 0.96000
###### 테스트 데이터 Tomato_Tomato_Yellow_Leaf_Curl_Virus 의 정확도 입니다 #######
accuracy: 0.98000
###### 테스트 데이터 Tomato_healthy 의 정확도 입니다 #######
accuracy: 0.98000
테스트 완료
----------------------------------------------------------------------------------------------------
테스트 정확도 :  0.957

 

 

 

 

 

 

이건 팀원이 정확도와 loss 값 그래프를 보고 그린 그래프

수고하셨습니다

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

세 번째 프로젝트 순서

1. 식물 병충해 자료 파일분류
2. CNN 모델링
3. 이미지화
4. CNN, AlexNet, VGG-16 모델 평가


예전에 네이버 블로그를 하듯이 글을 자유롭게 쓰고 싶은데, 혹시나 틀릴까 하는 마음에 쉽게 글이 작성이 되지 않는다. 너무나 쉽게 생각을 한 것이 아닌가 싶기도 하지만.. 그래도 팀프로젝트 5개 + 현재하고 있는 파이널 프로젝트 관련된 글을 작성하려고 한다.

이번에는 실패했던 시각화에 대한 내용이라 너무 관심 있게 보지는 말아주셨으면 한다. (부끄러우니까)

CNN 모델링을 했을 때 정확도가 90퍼센트 이상이 나왔지만 이를 어떻게 하면 더 개선시킬 수 있을까에 대한 고민을 많이 했다. 그러다가 생각한 것이 학습에 필요한 데이터는 전체 사진이 아닌 식물의 사진만 중요하지 않을까? 그래서 배경을 제외하고 학습을 해보기로 했다.

-배경과 식물 분리하는 mask
-sharpen 값을 줘서 병충해가 있는 데이터는 조금 더 부각이 되게


여러 예제들을 찾아보다가 이거다! 하는 예제가 있어서 처음에 단순히 따라하는 식으로 해봤다! 이건 그냥 너무 쉽게 되겠는 걸?






결과는 참담했다.



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
#배경과 분리하기 위해서 hsv 값 조정
def create_mask_for_plant(image):
    image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
 
    sensitivity = 30
    lower_hsv = np.array([60 - sensitivity, 10050])
    upper_hsv = np.array([60 + sensitivity, 255255])
 
    mask = cv2.inRange(image_hsv, lower_hsv, upper_hsv)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    
    return mask
 
#비트연산 and 모든 색이 같을 때만 색 표현
def segment_plant(image):
    mask = create_mask_for_plant(image)
    output = cv2.bitwise_and(image, image, mask = mask)
    return output
 
#샤픈, 특징을 조금더 부각시키게
def sharpen_image(image):
    image_blurred = cv2.GaussianBlur(image, (00), 3)
    image_sharp = cv2.addWeighted(image, 1.5, image_blurred, -0.50)
    return image_sharp
cs

sensitivity를 어떻게 하느냐에 따라서 결과값이 많이 차이가 났다. 위의 경우가 1을 뒀을 때고, 아래의 경우가 30일 때 실행을 했는데 단점이 배경 없이 잎만 찍은 데이터의 경우 분간이 제대로 되지가 않았다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
%matplotlib inline
import os
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import cv2
import numpy as np
from glob import glob
import seaborn as sns
 
image = cv2.imread('8_9_2.jpg')
 
image_mask = create_mask_for_plant(image)
image_segmented = segment_plant(image)
image_sharpen = sharpen_image(image_segmented)
 
fig, axs = plt.subplots(14, figsize=(2020))
axs[0].imshow(image)
axs[1].imshow(image_mask)
axs[2].imshow(image_segmented)
axs[3].imshow(image_sharpen)
cs

그래도 이전보다는 배경과 잎의 경계가 뚜렷하게 나눠지는 것을 확인할 수 있었다. 그런데도 문제가 되는 부분은 잎을 나눈데 있어서 hsv 값을 비슷하게 판단해서인지? 식물의 잎도 같이 사라지는 마술을 보여줬다. 병충해가 있어서 저렇게 빵꾸가 뚤렸다고 생각하면 좋겠지만, 병충해가 있는 부분은 중간 아래부분이다.

라이트룸이나 사진 편집을 할 때, 어떤 식으로 특정 색만 색깔을 남길까 생각을 해봤을 때.. hsv 전체 색 공간이 아닌 말 그대로 특정색만 추출하면 되는데 왜 이생각을 못 했을까 하고 무릎을 탁 쳤다. 그래서 초록색을 가장 잘 나타낼 수 있는 값들을 조절해봤다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np 
import cv2 
img_color = cv2.imread('4_7_5.jpg'
 
img_hsv = cv2.cvtColor(img_color, cv2.COLOR_BGR2HSV) # cvtColor 함수를 이용하여 hsv 색공간으로 변환 
lower_green = (03030)
upper_green = (80255255
img_mask = cv2.inRange(img_hsv, lower_green, upper_green) #hsv 색공간 전체가 아닌 지정한 범위 내의 
img_result = cv2.bitwise_and(img_color, img_color, mask = img_mask) # 바이너리 이미지를 마스크로 사용하여 원본이미지에서 범위값에 해당하는 부분을 획득 
 
 
fig, axs = plt.subplots(13, figsize=(2020))
axs[0].imshow(img_color) 
axs[1].imshow(img_mask) 
axs[2].imshow(img_result) 
cs

이정도면 나름 선방한 결과였다. 하지만 이 이미지들을 다 다시 저장시키고, 식물마다 톤이 다르고, 사진 찍은 곳 조명이 달라서 lower_green과 upper_green을 일일이 다 조정해야 한다는 치명적인 단점이 있어서 실패를 했다.

그래도 어떤 식으로 사진과 배경을 분리하고, 샤픈을 줘서 CNN이 사진의 특징을 학습할 때 조금 더 도움을 줄 수 있지 않을까 하는 생각이 든다.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

세 번째 프로젝트 순서 

 

1. 식물 병충해 자료 파일분류

2. CNN 모델링

3. 이미지화

4. CNN, AlexNet, VGG-16 모델 평가




쉼호흡부터 한 번 후~ 하~ 파이썬 팀프로젝트 당시에도 내용이 어려웠는데, 지금 다시 봐도 내용이 어렵다. 그래도 블로그로 글을 쓰면서 다시 정리한다는 생각으로 일단 간단하게 정리를 해봤다. 

 

 

인공지능 : 인간의 지능을 기계로 구현한 것

머신러닝 : 인간이 개발한 알고리즘을 컴퓨터 언어를 통해 기계에게 학습. 데이터로부터 스스로 학습을 통해 데이터를 가장 잘 표현하는 규칙, 패턴을 찾는 것(함수로 정의하는 과정 - x와 y관계)

딥러닝 : 인간의 뇌 신경망을 모방한 인공 신경망, 분류 예측 등의 머신러닝 수행  (입력층과 출력층 사이에 여러 층을 거쳐서 학습)

 

지도학습 : 입력 데이터(feature, 독립변수)와 출력데이터(class, target, 종속변수)를 이용해서 학습 – 분류, 회귀

비지도학습 : 입력 데이터를(feature)를 이용한 학습 – 군집

강화 학습 : 학습 결과에 대한 보상이 주는 방식으로 학습

 

train data : 모델 구축시 사용되는 데이터 (학습)

test data  : 구축된 모델 검증하는데 사용 (검증)

 

케라스(keras) ㅡ 저차원의 딥러닝 라이브러리를 래핑한 고차원의 라이브러리

sequential – 딥러닝의 구조를 한 층 한층 순차적으로 층을 쌓은 신경망 모델

dense – 신경망 모델에 포함된 완전 연결층 (각 층이 각각 어떤특성을 가질지 옵션을 설정)

activation – 다음 층으로 어떻게 값을 넘길지 결정하는 부분(relu, sigmoid, softmax 등)

loss – 한 번 신경망이 실행될 때마다 오차 값을 추적하는 함수 (mse, rmse 등)

optimizer – 오차를 어떻게 줄여 나갈지 정하는 함수 (adam, 경사하강법, 확률적 경사하강법)

input_shape – 입력 데이터의 형태

epoch - 주어진 데이터를 신경망 모델에서 한 번 훈련하는 단위

 

 

 

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
from keras.models import Sequential
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.layers import Dropout, Activation, Dense
from keras.layers import Flatten, MaxPooling2D
from keras.layers import Conv2D
from keras.models import load_model
from keras.optimizers import Adam
from tensorflow.keras.layers import BatchNormalization
import os
import numpy as np
 
# dataset 불러오기
if not os.path.exists("./model/"):
    os.mkdir('./model/')
X_train, X_test, Y_train, Y_test = np.load('./data/img_data.npy', allow_pickle=True)
 
# 기본 설정
categories = list(str(i) for i in range(20))
EPOCHS = 30
BS = 32
INIT_LR = 1e-3
n_classes = len(categories)
 
 
# CNN 모델
model = Sequential()
model.add(Conv2D(32, (33), padding="same", input_shape=X_train.shape[1:], activation='relu'))
model.add(MaxPooling2D(pool_size=(22)))
model.add(Dropout(0.2))
 
model.add(Conv2D(64, (33), padding="same", activation='relu'))
model.add(MaxPooling2D(pool_size=(22)))
model.add(Dropout(0.2))
 
model.add(Conv2D(64, (33), padding="same", activation='relu'))
model.add(MaxPooling2D(pool_size=(22)))
model.add(Dropout(0.25))
 
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
 
model.add(Dense(n_classes, activation='softmax'))
 
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
 
 
# 모델 요약
print(model.summary())
 
# 모델 학습
# opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
# model.compile(loss="binary_crossentropy", optimizer=opt,metrics=["accuracy"])
# print("트레이닝 ")
 
#EarlyStopping
model_dir = './model'
model_filepath = "model/se_cnn.h5"
if os.path.exists(model_filepath):
    model.load_weights(model_filepath)
else:
    model_path = model_dir + '/multi_img_classification.model'
    checkpoint = ModelCheckpoint(filepath=model_path, monitor='val_loss', verbose=1, save_best_only=True)
    early_stopping = EarlyStopping(monitor='val_loss', patience=6)
 
    model.fit(
        X_train,
        Y_train,
        batch_size=BS,
        validation_data=(X_test, Y_test),
        steps_per_epoch=len(X_train) // BS,
        epochs=EPOCHS, verbose=1,
        callbacks=[checkpoint, early_stopping]
    )
    model.save_weights(model_filepath)
 
cs

지속적으로 층을 바꿔가면서 모델링을 진행했다. 솔직히 어떤 부분에서 무엇을 바꿔야 하는지 이해는 쉽지 않았다. 같은 모델을 돌린다고 해도 train, test 데이터가 바뀌어서 학습이 진행되기 때문에, 데이터 중에 인간도 판별하기 힘든 데이터가 많이 섞여 있으면 정확도가 계속 떨어졌다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#모델 시각화
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)

#모델 정확도
plt.rc('font',family='Malgun Gothic')
plt.plot(epochs, acc, 'b', label='Training accurarcy')
plt.plot(epochs, val_acc, 'r', label='Testing accurarcy')
plt.title('학습과 훈련 정확도')
plt.legend()
plt.figure()
 
#모델 손실
plt.plot(epochs, loss, 'b', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Testing loss')
plt.title('학습과 훈련 손실')
plt.legend()
plt.show()
cs

신기한 부분은 모델을 돌리게 되면 정확도가 90%가 넘는게 쉽지 않은데... 데이터 자체가 양질의 데이터고 분류가 잘 돼서 더 잘 학습이 되는 것으로 보인다. 다음에는 시각화와 어떻게 하면 정확도를 높일 수 있을지에 대한 고민이 담긴 글이다. 실패는 했지만 그래도 어떻게 하면 계선을 할 수 있을까 많은 고민을 했다.

+ Recent posts