갈루아의 반서재

서포터 벡터 머신과 이미지 인식 (4) - 서포트 벡터 머신 훈련 (2)


서포트 벡터 머신 훈련


논의를 확장시켜 이제 안경을 쓴 사람과 그렇지 않은 사람으로 얼굴을 분류해보자. 먼저 해야할 것은 안경을 쓴 사람의 이미지의 범위를 정의하는 것이다. 다음 리스트는 안경을 쓴 사람의 색인이다.

1
2
3
4
5
6
7
8
>>> # the index ranges of images of people with glasses
>>> glasses = [
   (1019), (3032), (3738), (5059), (6364),
   (6969), (120121), (124129), (130139), (160161),
   (164169), (180182), (185185), (189189), (190192),
   (194194), (196199), (260269), (270279), (300309),
   (330339), (358359), (360369)
]
cs


print_faces 함수를 사용해 리스트의 정확성 여부를 확인해볼 수 있다.

1
print_faces(faces.images, faces.target, 400)
cs


안경쓴 이미지의 좌측 하단 색인번호와 일치함을 알 수 있다.


안경을 쓰지 않은 얼굴 = 0, 안경을 쓴 얼굴 = 1 로 정의하는 새로운 목적 배열을 반환하는 함수를 만들자.

1
2
3
4
5
6
7
8
9
def create_target(segments):
    # 0 으로 새로운 목적 범주만큼 초기화한다.
    y = np.zeros(faces.target.shape[0])
    # 특정 부분에 1을 넣는다.
    for (start, end) in segments:
        y[start:end + 1= 1
    return y
 
target_glasses = create_target(glasses)
cs


다시 훈련 데이터와 테스트 데이터로 분할하자.

1
2
X_train, X_test, y_train, y_test = train_test_split(faces.data, target_glasses, 
                                                    test_size=0.25, random_state=0)
cs


새로운 SVC 분류기를 만들고 훈련시킨다.

1
svc_2 = SVC(kernel='linear')
cs


교차검증 성능을 확인한다. 테스트 데이터로 평가하면 0.970의 정확도를 얻는다.

1
2
3
4
5
evaluate_cross_validation(svc_2, X_train, y_train, 5)
 
1.          0.95        0.98333333  0.98333333  0.93333333]
Mean score: 0.970 (+/-0.012)
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
train_and_evaluate(svc_2, X_train, X_test, y_train, y_test)
 
Accuracy on training set:
1.0
Accuracy on testing set:
0.99
Classification Report:
             precision    recall  f1-score   support
 
        0.0       1.00      0.99      0.99        67
        1.0       0.97      1.00      0.99        33
 
avg / total       0.99      0.99      0.99       100
 
Confusion Matrix:
[[66  1]
 [ 0 33]]
cs


안경을 쓰거나 쓰지 않은 사람의 모든 이미지를 구별해보자. 같은 사람의 모든 이미지인 30부터 39까지의 이미지를 구별하고, 그외의 나머지 이미지로 훈련한다. 그리고 준비한 10개의 이미지로 평가한다.

1
2
3
4
5
>>> X_test = faces.data[30:40]
>>> y_test = target_glasses[30:40]
>>> print y_test.shape[0]
 
10
cs


1
2
3
4
5
6
7
>>> select = np.ones(target_glasses.shape[0])
>>> select[30:40= 0
>>> X_train = faces.data[select == 1]
>>> y_train = target_glasses[select == 1]
>>> print y_train.shape[0]
 
390
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> svc_3 = SVC(kernel='linear')
>>> train_and_evaluate(svc_3, X_train, X_test, y_train, y_test)
 
Accuracy on training set:
1.0
Accuracy on testing set:
0.9
Classification Report:
             precision    recall  f1-score   support
 
        0.0       0.83      1.00      0.91         5
        1.0       1.00      0.80      0.89         5
 
avg / total       0.92      0.90      0.90        10
 
Confusion Matrix:
[[5 0]
 [1 4]]
cs


10개의 이미지에서 하나의 잘못된 예측이 있었다. 이 예측을 확인해보자.

1
2
3
y_pred = svc_3.predict(X_test)
eval_faces = [np.reshape(a, (6464)) for a in X_test]
print_faces(eval_faces, y_pred, 10)
cs

위의 8번 이미지는 안경을 쓰고 있지만, 쓰고 있지 않은 것으로 분류했다.

이상 선형 SVM 모델을 사용해 얼굴 분류기를 만들었다. 결과가 좋지 못하다면 알고리즘의 하이퍼파라메터를 변경하기 시작한다. SVM의 특별한 경우, 다른 커널 함수를 사용할 수 있다. 선형으로 결과가 좋지 않다면 다항이나 RBF 커널로 변경할 수 있다. C와 감마 매개변수 또한 결과에 영향을 미친다.