반응형

 

 

이번 수업에서는 알고리즘이 실제로 어떻게 작동하는지 볼 것이다.

What is Classification?


Classification 태스크는 input을 넣으면 어떤 물체인지의 category를 예측한다.

사람에게는 쉽지만, 기계에게는 굉장히 어려운 일이다.

 

 

Problem : Semantic Gap


이미지는 예를 들어 800(w) x 600(h) x 3(RGB)개의 0부터 255의 값으로 이루어진 픽셀로 이루어져 있다.

 

이 이미지 정보는 semantic label을 제공하는 것 -> 하지만, 하나하나의 픽셀로 고양이 시맨틱 이미지를 인식하기는 매우 어렵다.

Challenge : 카메라의 각도가 달라짐 /  빛이 어두워지거나 / 고양이가 다른 포즈를 하거나 / 다른 물체에 숨겨져 있으면 더 어려워진다.

모든 상황을 고려하여 이미지를 분류하여야 하므로 기계에게는 매우 어려운 일이다.

 

 

여러가지 시도들 


1) 모든 엣지와 코너를 찾아서 그린다.

-> not worked, 다루기 힘들고 고양이가 아닌 다른 물체는 인식 못한다.

 

 

 

2) Data-driven approach

- 이미지와 카테고리를 가진 데이터를 수집한다.

- 분류기를 학습하기 위해 머신러닝을 이용한다.

- 새로운 이미지에 분류기를 평가한다.

train & predict 두 과정으로 나뉜다.

-> 데이터 드리븐 방식이 딥러닝보다는 좀 더 일반적이고, 간단한 분류기를 사용할 수 있다는 점에서 좋다.

 

 

 

 

2) - a) First classifier : Nearest classifier


Nearest classifier : 학습된 데이터에서 가장 비슷한 이미지를 찾아 예측하는 알고리즘

성능이 아주 좋지는 않다.

 

CIFAR10 으로 테스트 해볼 것이다. 10 classes, 50000 training images, 10000 testing images

테스트 예시)

 

 

비슷한 이미지인지 아닌지는 어떤 기준으로 계산할까?

Distance Function 1 : L1 distance


 

 

 

학습 시에는 x와 y를 지정해주기만 하면 된다.

예측 시에는 모든 학습 이미지를 살펴 보면서 테스트 이미지와 가장 L1 or L2 distance가 작은 학습 이미지를 찾아서 

그 학습 이미지의 레이블을 반환한다.

Q. how fast are training and prediction?

A. train : O(1), predict : O(N)

-> this is bad, 학습이 느리고 예측 과정은 빨라야 실제로 사용할 수 있기 때문에

 

결과는 어떻게 보일까?

-> 초록색 안에 노란색이 들어가 있거나

-> 초록색 영역이 파란색 영역에 침입한 것은 노이즈임

 

 

 

2) - b) Second classifier : K - Nearest classifier


K - Nearest classifier : top K 중에 가장 많은 투표를 받은 레이블로 선택하는 알고리즘

* X.shape = (500, 3072)

* self.X_train.shape = (5000, 3072)

# Test your implementation:
dists = classifier.compute_distances_two_loops(X_test)
print(dists.shape)
def compute_distances_two_loops(self, X):
    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))

    for i in range(num_test):
        for j in range(num_train):
            #####################################################################
            # TODO:                                                             #
            # Compute the l2 distance between the ith test point and the jth    #
            # training point, and store the result in dists[i, j]. You should   #
            # not use a loop over dimension, nor use np.linalg.norm().          #
            #####################################################################
            # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

            dists[i][j] = math.sqrt(sum((X[i] - self.X_train[j]) ** 2))

            # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    return dists
def compute_distances_one_loop(self, X):

    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))
    for i in range(num_test):
        #######################################################################
        # TODO:                                                               #
        # Compute the l2 distance between the ith test point and all training #
        # points, and store the result in dists[i, :].                        #
        # Do not use np.linalg.norm().                                        #
        #######################################################################
        # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

        sum_matrix = (self.X_train - X[i]) ** 2
        dists[i, :] = np.sqrt(sum_matrix.sum(axis=1)).T

        # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
    return dists
def compute_distances_no_loops(self, X):

    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))
    #########################################################################
    # TODO:                                                                 #
    # Compute the l2 distance between all test points and all training      #
    # points without using any explicit loops, and store the result in      #
    # dists.                                                                #
    #                                                                       #
    # You should implement this function using only basic array operations; #
    # in particular you should not use functions from scipy,                #
    # nor use np.linalg.norm().                                             #
    #                                                                       #
    # HINT: Try to formulate the l2 distance using matrix multiplication    #
    #       and two broadcast sums.                                         #
    #########################################################################
    # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    sx = np.sum(X**2, axis=1, keepdims=True)
    sy = np.sum(self.X_train**2, axis=1, keepdims=True)
    dists = np.sqrt(-2 * X.dot(self.X_train.T) + sx + sy.T)

    # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
    return dists

 

 

 

 

Distance Function 2 : L2 distance (=유클리디안 거리)


 

L1 distance는 좌표계에 따르고,

L2 distance는 좌표계에 상관없는 숫자가 되기 때문데 좀 더 매끄러운 라인을 그리는 것을 알 수 있다.

distance function을 변경함으로써 원하는 방식으로 데이터들간의 차이를 정의할 수 있다.

어떤 타입의 데이터든 일반적으로 적용할 수 있기 때문에 처음에 다가가기에 적합한 개념이다.

 

 

Hyperparameter


모델에 의해 계산되는 값이 아니라, 사람이 직접 설정해줘야 하는 파라미터

ex) K, distance function

 

 

How to set hyperparameter?


Idea #1) 가장 좋은 성능을 가져다주는 하이퍼파라미터 선택 -> Bad Idea

Idea #2) split into train and test data, test 데이터에서 성능이 좋은 하이퍼파라미터 선택 -> Bad Idea -> 새로운 데이터는 어떤게 올지 모르기 때문에

Idea #3) train, val, test 데이터로 나누기 -> Good Idea -> 새로운 데이터에도 적용될 수 있어서

* training set에는 Label을 알려주고 학습하는 거지만, validation set은 label 없고 예측하는 것임

 

 

 

Idae #4) cross-validation -> small dataset일 때 많이씀, deep learning x

num_folds = 5
k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]

X_train_folds = []
y_train_folds = []
################################################################################
# TODO:                                                                        #
# Split up the training data into folds. After splitting, X_train_folds and    #
# y_train_folds should each be lists of length num_folds, where                #
# y_train_folds[i] is the label vector for the points in X_train_folds[i].     #
# Hint: Look up the numpy array_split function.                                #
################################################################################
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

X_train_folds = np.array_split(X_train, num_folds)
y_train_folds = np.array_split(y_train, num_folds)

X_train_cv = np.concatenate([X_train_folds[0], X_train_folds[1]])

# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

# A dictionary holding the accuracies for different values of k that we find
# when running cross-validation. After running cross-validation,
# k_to_accuracies[k] should be a list of length num_folds giving the different
# accuracy values that we found when using that value of k.
k_to_accuracies = {}


################################################################################
# TODO:                                                                        #
# Perform k-fold cross validation to find the best value of k. For each        #
# possible value of k, run the k-nearest-neighbor algorithm num_folds times,   #
# where in each case you use all but one of the folds as training data and the #
# last fold as a validation set. Store the accuracies for all fold and all     #
# values of k in the k_to_accuracies dictionary.                               #
################################################################################
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

num_valid = len(X_train) / num_folds
for kSelected in k_choices:
    accuracies = []
    for validIdx in range(num_folds):
        X_train_cv = []
        y_train_cv = []
        for idx in range(num_folds):
            if idx == validIdx:
                X_valid_cv = X_train_folds[idx]
                y_valid_cv = y_train_folds[idx]
            else:
                if len(X_train_cv) == 0:
                    X_train_cv = X_train_folds[idx]
                else:
                    X_train_cv = np.concatenate([X_train_cv, X_train_folds[idx]])
                
                if len(y_train_cv) == 0:
                    y_train_cv = y_train_folds[idx]
                else:
                    y_train_cv = np.concatenate([y_train_cv, y_train_folds[idx]])

        classifier.train(X_train_cv, y_train_cv)
        dists_valid = classifier.compute_distances_no_loops(X_valid_cv)

        y_valid_pred = classifier.predict_labels(dists_valid, k=kSelected)
        num_correct = np.sum(y_valid_pred == y_valid_cv)
        accuracy = float(num_correct) / num_valid
        accuracies.append(accuracy)

    k_to_accuracies[kSelected] = accuracies

# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

# Print out the computed accuracies
for k in sorted(k_to_accuracies):
    for accuracy in k_to_accuracies[k]:
        print('k = %d, accuracy = %f' % (k, accuracy))

 

- K-nearest classifier on images는 사용되지 않는다.

1) test time 너무 오래걸림

2) distance metrics는 이미지 데이터에 적합하지 않음

3) dimensionality 문제 

 

 

 

 

Linear Classification : score function f(x, W) = Wx + b


deep learning은 레고 같은 것이고, linear classification은 가장 기본 뼈대 블럭같은 것이다.

 

 

3) Paramatic Approach


input(x), W(weight)

K-nearest는 테스트할 때 전체 이미지를 사용하지만,

Paramatic approach에서는 input 이미지를 요약하여 W라는 파라미터에 저장하고 요약본을 사용하여 테스트한다.

 

 

함수 f는 어떻게 설정할 것인가? : Linear classifier


f(x, W) = Wx

10 x 1 = (10 x 3072) x (3072 x 1)

W 사이즈의 의미는 10 categories와 3072 input pixels가 있다는 것이다.

3027라는 픽셀의 수는 width * height * 3(RGB)이다.

 

ex) w의 width는 카테고리 수, height 인풋의 픽셀 수이다.

 

 

linear classifier의 한계


1) 카테고리당 하나의 template만 인식한다는 것

 

 

2) 선형으로 표현하기에는 한계가 있다는 것

 

 

 

 

다음 수업 내용


W를 찾는 데 어떤 알고리즘을 사용할 것인가?

- loss function

- optimization

- Convnets

 

 

Q. 궁금한 점 & 더 알아볼 점


- dimensionality 문제란?

- 카테고리당 하나의 template만 인식한다는 것이 어떤 의미인지?

반응형

+ Recent posts