퐈니썬's LIfe - 잘 실패하자 RSS 태그 관리 글쓰기 방명록
2021-07-06 22:12:01
728x90
반응형

01. Confusion Matrix?

Confusion Matrix라고 해서 굉장히 어렵게 느꼈는데, 생각보다 간단하였습니다.

한국말로 "분류결과표"라고 합니다.

즉, 참값(타겟의 원래 클래스)와 예측값(모형이 예측한 클래스)가 일치하는지를 갯수로 수치화 한 결과 표입니다.

정답 클래스는 행(row)로, 예측 클래스는 열(column)로 표현합니다. 

 

02. 실습을 통해 Confusion Matrix 보기 (코드포함)

이전에, 포스트한 CIFAR-10 학습을 기반으로 해당 모델의 Confusion Matrix를 추출 해보았습니다. 

 

https://panython.tistory.com/12

 

[AI Study] ImageDataGenerator 사용하여 CIFAR-10 분류하기

01. CIFAR-10 이미지 분류해 보기 01. ImageDataGenerator 사용해 보기 keras에서는 이미지데이터 학습을 쉽게하도록 하기위해 다양한 패키지를 제공한다. 그 중 하나가 ImageDataGenerator 클래스이다. ImageData..

panython.tistory.com

 

이전에 학습하였던 모델을 사용하였습니다. 

 

이전 학습 모델을 불러와 테스트 데이터 예측하기

model = load_model('./saved_models/cifar10_cnn_model_epoch40.h5')
images = test_set
label, fns, images2 = load_rand_img(images,32)
predictions = model.predict(images2/255)

예측한 데이터와 정답 텍스트로 확인 하기

#정답보기
for i in range(32):
    pred_label = labels[np.argmax(predictions[i])]
    fn = fns[i]
    la = labels[label[i]]
    print(i, '번째', '파일', fn, '참값', la, '예측값', pred_label)
>>>0 번째 파일 ./CIFAR-10-images-master/test/truck/0959.jpg 참값 truck 예측값 truck
>>>1 번째 파일 ./CIFAR-10-images-master/test/truck/0830.jpg 참값 truck 예측값 truck
>>>2 번째 파일 ./CIFAR-10-images-master/test/bird/0134.jpg 참값 bird 예측값 bird
>>>3 번째 파일 ./CIFAR-10-images-master/test/horse/0935.jpg 참값 horse 예측값 horse
>>>4 번째 파일 ./CIFAR-10-images-master/test/horse/0147.jpg 참값 horse 예측값 horse
>>>5 번째 파일 ./CIFAR-10-images-master/test/dog/0239.jpg 참값 dog 예측값 dog
>>>6 번째 파일 ./CIFAR-10-images-master/test/frog/0285.jpg 참값 frog 예측값 frog
>>>7 번째 파일 ./CIFAR-10-images-master/test/truck/0876.jpg 참값 truck 예측값 truck
>>>8 번째 파일 ./CIFAR-10-images-master/test/deer/0236.jpg 참값 deer 예측값 frog

 

위의 방법이 있다는 수준으로 전달 드린 것입니다. 결국 참값과 예측값을 비교하는 것이죠!! 

 

이번에는 그림으로 시각화 해보시죠!

 

예측한 데이터와 정답 이미지로 확인 하기

#이미지 데이터를 랜덤하게 n개 추출하여 라벨, 파일이름, 이미지 배열 추출 함수 
def load_rand_img(imagesset, randint):
    images = imagesset.filepaths
    labels = imagesset.labels
    rand_imgs = []
    label = []
    for i in range(randint):
        rand_num = random.randrange(0,len(images))
        rand_imgs.append(images[rand_num])
        label.append(labels[rand_num])
    load_imgs = load_img(rand_imgs)
    return label, rand_imgs, load_imgs
    
# 예측 결과를 figure로 확인하는 함수 
def plot_predict(figsize, num, classes, label, images, predictions):
    fig = plt.figure(figsize=(figsize[0], figsize[1]))
    for i in range(num):
        plt.subplot(figsize[0], figsize[1], i + 1)
        plt.grid(False)
        plt.xticks([])
        plt.yticks([])
        fn = plt.imread(images[i])
        plt.imshow(fn)
        la = classes[label[i]]
        pred_label = classes[np.argmax(predictions[i])]
        if pred_label == la:
            color = 'green'
        else:
            color = 'red'
        plt.xlabel("{}({}, i={})".format(pred_label, la, i), color=color)
    plt.show()
    
# 메인 실행 
labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
label, fns, images2 = load_rand_img(images, 10000)
predictions = model.predict(images2/255)
plot_predict((4,8),32, labels, label, fns, predictions)

xlabel의 형식은 "예측값(참값)" 으로 설정하였습니다.

이번 시행에서 32개 중에 7개 오답을 보였으니, 약 22%의 오답률, 즉 78% 정답률을 보여주었지만, 해당 코드는 실행할 때마다 다시 랜덤추출하기 때문에 한눈에 모델을 평가하기는 어렵습니다!! 

 

그래서!! 모델의 성능을 한눈에 보기위해 "Confusion Matrix"를 적용해보았습니다!!

 

예측한 데이터와 정답을 "Confusion Matrix"로 확인 하기

Confusion Matrix에 대해 잠깐 본다면 참값(타겟의 원래 클래스)와 예측값(모형이 예측한 클래스)가 일치하는지를 갯수로 수치화 한 결과 표라고 보시면 되겠네요!

정답 클래스는 행(row)로, 예측 클래스는 열(column)로 표현하기때문에, Confusion Matrix는 모델이 잘 작동되는지 확인할 수 있는 좋은 방법입니다. 

예를 들면 아래의 표와 같다. (출처 : datascienceschool.net)

 

# confusion matrix 사용을 위한 라이브러리
from sklearn.metrics import confusion_matrix

# confusion matrix 그리는 함수 
def plot_confusion_matrix(con_mat, labels, title='Confusion Matrix', cmap=plt.cm.get_cmap('Blues'), normalize=False):
    plt.imshow(con_mat, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    marks = np.arange(len(labels))
    nlabels = []
    for k in range(len(con_mat)):
        n = sum(con_mat[k])
        nlabel = '{0}(n={1})'.format(labels[k],n)
        nlabels.append(nlabel)
    plt.xticks(marks, labels)
    plt.yticks(marks, nlabels)

    thresh = con_mat.max() / 2.
    if normalize:
        for i, j in itertools.product(range(con_mat.shape[0]), range(con_mat.shape[1])):
            plt.text(j, i, '{0}%'.format(con_mat[i, j] * 100 / n), horizontalalignment="center", color="white" if con_mat[i, j] > thresh else "black")
    else:
        for i, j in itertools.product(range(con_mat.shape[0]), range(con_mat.shape[1])):
            plt.text(j, i, con_mat[i, j], horizontalalignment="center", color="white" if con_mat[i, j] > thresh else "black")
    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

# 예측값과 참값 
pred_labels = np.argmax(predictions, axis=1)
true_labels = test_set.labels

#메인 실행 
confusion_matrix = confusion_matrix(true_labels, pred_labels)
plot_confusion_matrix(confusion_matrix, labels=labels, normalize=True)

 

 

 

짜잔! 이렇게 대각을 보시면 진한 파란색일 수록 많이 맞췄다는 겁니다. 

Xlabel은 예측값, Ylabel은 참값이기 때문에 각 라벨에서 몇개를 예측한지 볼 수 있으며 어떤 라벨은 어떤라벨에서 헷갈릴 수 있는지도 파악이됩니다!!

예를 들면, 예측값 dog이라고 예측을 했지만 사실상 cat이라고 예측한 비율도 꽤 높습니다. 이것을 미루어 볼때, 해당모델은 다른 라벨에 비해 dog과 cat을 분류하는데는 조금 좋지 못한 성능을 보이구나! 와 같이 확인 할 수 있습니다. 

 

728x90
반응형