반응형

 

 

W는 Input의 해당 픽셀이 얼마나 특정 클래스에 영향을 미치는 지에 대한 값이다.

W의 사이즈 = (클래스 개수) x (인풋 이미지의 픽셀 개수) 

W를 계산해낸 이 loss function은 score 를 보고 W가 얼마나 양적으로 나쁜지 알려주는 척도이다.

이 강의에서 여러가지 loss function을 소개할 것이다.

가장 적게 나쁜 W를 찾아가는 과정이 "최적화" 과정이다.

 

 

 

 

 

Loss function : multi-label SVM


image classification 에서 많이 쓰는 것 -> multi-label SVM

sj = 틀린 함수값, syi = 맞는 합수값

만약 맞는 클래스의 score가 틀린 클래스의 score보다 월등히 크다면, Loss는 0으로 설정한다.

그렇지 않다면, 맞는 클래스의 score에서 틀린 클래스의 score을 빼는 방식으로 Loss를 계산한다.

Hinge Loss 라고도 부른다. x축은 맞는 클래스의 score이고, y축은 loss이다.

맞는 클래스 score이 높아지면, loss는 감소한다.

loss가 0이 되면 잘 분류한 것으로 보면 된다.

 

from builtins import range
import numpy as np
from random import shuffle
from past.builtins import xrange


def svm_loss_naive(W, X, y, reg):
    """
    Structured SVM loss function, naive implementation (with loops).

    Inputs have dimension D, there are C classes, and we operate on minibatches
    of N examples.

    Inputs:
    - W: A numpy array of shape (D, C) containing weights.
    - X: A numpy array of shape (N, D) containing a minibatch of data.
    - y: A numpy array of shape (N,) containing training labels; y[i] = c means
      that X[i] has label c, where 0 <= c < C.
    - reg: (float) regularization strength

    Returns a tuple of:
    - loss as single float
    - gradient with respect to weights W; an array of same shape as W
    """
    dW = np.zeros(W.shape)  # initialize the gradient as zero

    # compute the loss and the gradient
    num_classes = W.shape[1]
    num_train = X.shape[0]
    loss = 0.0

    for i in xrange(num_train):
        scores = X[i].dot(W)
        correct_class_score = scores[y[i]]
        loss_contributors_count = 0
        for j in xrange(num_classes):
            if j == y[i]:
                continue
            margin = scores[j] - correct_class_score + 1  
            if margin > 0:
                loss += margin
                dW[:, j] += X[i] # [GD] 틀린 애
                loss_contributors_count += 1
        dW[:, y[i]] += (-1) * loss_contributors_count * X[i] # [GD] 맞는 애 

    loss /= num_train
    dW /= num_train

	# [Regularization]
    loss += reg * np.sum(W * W)
    dW += 2 * reg * W  

    #############################################################################
    # TODO:                                                                     #
    # Compute the gradient of the loss function and store it dW.                #
    # Rather that first computing the loss and then computing the derivative,   #
    # it may be simpler to compute the derivative at the same time that the     #
    # loss is being computed. As a result you may need to modify some of the    #
    # code above to compute the gradient.                                       #
    #############################################################################
    # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****


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

    return loss, dW


def svm_loss_vectorized(W, X, y, reg):
    """
    Structured SVM loss function, vectorized implementation.

    Inputs and outputs are the same as svm_loss_naive.
    """
    loss = 0.0
    dW = np.zeros(W.shape)  # initialize the gradient as zero

    #############################################################################
    # TODO:                                                                     #
    # Implement a vectorized version of the structured SVM loss, storing the    #
    # result in loss.                                                           #
    #############################################################################
    # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    num_train = X.shape[0]
    s = X.dot(W)

    correct_score = s[list(range(num_train)), y]
    correct_score = correct_score.reshape(num_train, -1)

    s += 1 - correct_score
    s[list(range(num_train)), y] = 0
    loss = np.sum(np.fmax(s, 0)) / num_train
    loss += reg * np.sum(W * W)

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

    #############################################################################
    # TODO:                                                                     #
    # Implement a vectorized version of the gradient for the structured SVM     #
    # loss, storing the result in dW.                                           #
    #                                                                           #
    # Hint: Instead of computing the gradient from scratch, it may be easier    #
    # to reuse some of the intermediate values that you used to compute the     #
    # loss.                                                                     #
    #############################################################################
    # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    X_mask = np.zeros(s.shape)
    X_mask[s > 0] = 1
    X_mask[np.arange(num_train), y] = -np.sum(X_mask, axis=1)
    dW = X.T.dot(X_mask)
    dW /= num_train
    dW += 2 * reg * W

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

    return loss, dW

 

ex)

Q. 어떻게 +1을 정한거죠?

score의 절대적인 값이 아니라 score들 간의 상대적인 차이가 의미가 있는 것이고,

correct score이 incorrect score보다 상당히 높아야 하기 때문에 +1을 한 것이다.

1이라는 숫자는 미분 계산을 통해 씻겨 나가기 때문에 영향이 거의 없어서 괜찮다.

 

 

loss값은 상대적인 값임.

Q. 만약 car의 score가 조금 바뀐다면, loss 값도 변할까?

A. No, 이미 다른 틀린 score보다 1이상 크기 때문에 score가 조금 바뀌어도 loss에는 영향이 없다.

 

Q. multiclass SVM loss의 최소, 최대값은?

A. 최소 : 0, 최대 : 무한대

 

Q. correct score과 incorrect score의 차이가 거의 없다면 multiclass SVM loss는 어떻게 될까?

A. (class의 개수) - 1

=> 좋은 디버깅 툴임.

 

Q. multiclass SVM loss에서 max를 mean으로 변경하면?

A. 차이가 없다. loss값의 상대적인 차이가 의미가 있는 것이므로 max든 mean으로 하든간에 차이가 없다.

 

Q.multiclass SVM loss에서 제곱을 추가한다면?

A. 차이가 있다. 차이가 큰 값의 차이를 더 키우는 것이기 때문에 다른 의미가 된다.

 

Q. L = 0으로 만드는 W가 있다면, 이 값 하나 뿐일까?

A. 아니다.

 

 

Loss function은 어떤 타입의 에러를 더 고려하느냐를 결정하는 것.

 

 

loss가 0인 W가 두배가 된다고 하더라도 loss는 still 0

 

 

모델과 loss function은 training이아니라 test dataset에서 잘 작동해야한다.

training set에만 너무 fit하지 않고 제너럴한 모델을 만들기 위해서

우리는 regularization이라는 방법을 사용한다.

람다는 하이퍼파라미터인데, 굉장히 중요한 요소이다.

 

 

 Regularization


 

L2 regularization은 w2를 선호할 것이다. norm 이 더 작기 때문에. L2는 값이 골고루 spread 되어 있는 것이 덜 복잡하다고 판단한다.

L1 regularization은 w1를 선호할 것이다. 값은 같지만, L1은 직관적으로 sparse solution(대부분이 0이고 소수만 non-zero인)을 선호하기 때문이다. L1의 complexity 측정 방식은 non-zero값의 개수일 것이다.

 

L2 Loss 는 직관적으로 오차의 제곱을 더하기 때문에 Outlier 에 더 큰 영향을 받는다.

L1 Loss 가 L2 Loss 에 비해 Outlier 에 대하여 더 Robust(덜 민감 혹은 둔감) 하다.

 

L2 Loss 는 모든 데이터에서 score가 고르게 분포할 것을 유도.

 

모델과 태스크에 따라 L1, L2 정규화 방식을 선택할 것!

 

 

 

 

Softmax Classifier(Multinomial Logistic Regression)


SVM에서는 점수에 어떠한 해석을 하지 못했다.

하지만 softmax classifier에서는 점수에 대한 해석을 할 수 있다.

softmax는 0~1의 확률 분포를 뱉어낸다.

 

정답 확률을 모든 확률의 합으로 나눈 것에 -Log를 취한다. (KL divergence)

만약, 정답 확률이 높아서 거의 1에 가깝다면, loss는 정답 확률에 negative log를 취한 것이 될 것이다.

즉, 정답 확률이 높을수록 loss는 감소한다.

 

def softmax_loss_naive(W, X, y, reg):
    """
    Softmax loss function, naive implementation (with loops)

    Inputs have dimension D, there are C classes, and we operate on minibatches
    of N examples.

    Inputs:
    - W: A numpy array of shape (D, C) containing weights.
    - X: A numpy array of shape (N, D) containing a minibatch of data.
    - y: A numpy array of shape (N,) containing training labels; y[i] = c means
      that X[i] has label c, where 0 <= c < C.
    - reg: (float) regularization strength

    Returns a tuple of:
    - loss as single float
    - gradient with respect to weights W; an array of same shape as W
    """
    # Initialize the loss and gradient to zero.
    loss = 0.0
    dW = np.zeros_like(W)

    #############################################################################
    # TODO: Compute the softmax loss and its gradient using explicit loops.     #
    # Store the loss in loss and the gradient in dW. If you are not careful     #
    # here, it is easy to run into numeric instability. Don't forget the        #
    # regularization!                                                           #
    #############################################################################
    # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    num_classes = W.shape[1]
    num_train = X.shape[0]

    for i in xrange(num_train):

        scores = X[i].dot(W)
        scores -= scores.max()
        scores_expsum = np.sum(np.exp(scores))
        cor_ex = np.exp(scores[y[i]])
        loss += - np.log( cor_ex / scores_expsum)

        dW[:, y[i]] += (-1) * (scores_expsum - cor_ex) / scores_expsum * X[i] # [gd] 맞은 애
        for j in xrange(num_classes):
            if j == y[i]:
                continue
            dW[:, j] += np.exp(scores[j]) / scores_expsum * X[i] # [gd] 틀린 애

    loss /= num_train
    dW /= num_train
    
    # [regulation]
    loss += reg * np.sum(W * W)
    dW += 2 * reg * W


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

    return loss, dW

 

Q. softmax의 최소, 최대값은?

A. 최소값 : 0, 최대값 : 무한대(정답 확률이 마이너스 무한대일 때)

 

Q. 모든 s가 거의 0에 가까울 때 loss는?

A. -log(1/C) = logC

=> senity check? => 좋은 디버깅 툴임.

 

correct label의 score과 incorrect label의 score의 값이 매우 차이가 나면,

SVM은 correct score가 조금 바뀌어도 loss 값에 영향이 없지만,

softmax loss값은 바뀐다.

 

loss function은 GT보다 얼마나 다른지 알려주는 지표가 된다. 

loss를 최소화하는 W를 선택한다. -> 딥러닝 학습 과정

 

 

 

 

어떻게 W를 변경하며 최적 값을 찾을까?

optimization function

optimization function #1 random search


bad idea

 

optimization function #2 follow the slope


work well

slope -> derivative of a function 미분값

gradient -> the vector of partial derivative along each dimension

h만큼의 어떤 방향으로든 이동한다고 가정하면 기울기를 반환한다.

 

[ numeric gradient ] 

모든 W값의 값의 미분값을 구한다. -> 매우 시간이 많이 걸림.

 

하지만, 다행히도 이 과정을 할 필요가 없다.

loss가 그 자체로 W의 함수이기 때문에, loss function에 w로 편미분을 하면 된다.

[ analytic gradient ]

 

 

Gradient Descent


W를 랜덤으로 초기화하고

weight를 계속 gradient의 반대 방향으로 업데이트한다.

gradient는 높은 지점을 향해서 가기 때문에, 반대 방향으로 마이너스를 붙여서 업데이트 한다. 

step size = learning rate => 하이퍼 파라미터

빨간색이 loss 최소 지점

 

 

SGD


샘플된 미니배치를 사용함으로써 계산 속도를 빠르게 하는 방법. 

 

 

 

Image Features representation 여러 방식


 

 

 

Image features vs ConvNets


 

 

Q. 궁금한 점 \ 알아볼 점


- penalizing이 무슨 뜻인지?

오버피팅을 막고 일반화한다는 것인가? 아니면 학습한다는 것인가?

- numeric gradient -> analytic gradient?

- 과제에서 dw는 어떻게 구하는 건지??

반응형
반응형

 

 

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

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만 인식한다는 것이 어떤 의미인지?

반응형
반응형

 

Opening


인터넷 세상에 있는 거의 80%의 traffic은 비디오이다. 대다수의 인터넷에 올라와 있는 자료들은 모두 비주얼 데이터이다.

따라서, 이 데이터를 이용하고 이해하는 것은 매우 중요하다. 하지만, 이는 굉장히 어렵다.

유튜브가 굉장히 좋은 통계이다. 사람들이 계속해서 만들어 내고, 구글의 직원이 이를 하나하나씩 관리할 여력이 되지 않는다.

이 때 비주얼 데이터의 내용을 이해하는 기술이 굉장히 중요할 것이다.

컴퓨터 비전은 다양한 분야들에 대한 이해를 바탕으로 이루어져야 한다. (물리학, 생물학 등)

 

 

 

관련된 강의 소개


CS231a : 3d reconstruction, 컴퓨터비전을 위한 센서 등

CS231n : 이미지 분류에 사용할 neural network(딥러닝)

 

 

visual recognition의 역사


현재의 컨볼루션 네트워크까지의 발전된 과정을 아는 것이 중요하다.

 

1) 540백만년 전 갑자기 많은 종류의 동물이 멸종하였다.

동물학자 앤드류 파커가 화석을 바탕으로, 첫 동물의 눈이 발달하였고 갑자기 볼 수 있게 되었다는 것을 발견하였다.

처음으로 볼 수 있게 되면서 삶을 사전 예방하게 되었다.

먹이는 포식자들로부터 탈출하여야 했고, 이는 진화적 군비 전쟁으로 이어졌다.

이것이 시각의 시작이었다.

 

특별히 지적으로 뛰어난 인간의 뇌의 뉴런은 시각 처리와 관련이 되어 있다. 이것이 가장 큰 센서리 시스템이다.

시각 시스템을 통해 움직이고, 일하고, 먹고, 등등을 한다.

따라서 시각 시스템은 지성을 가진 인간에게 중요한 역할을 한다.

 

인간의 기계적인 시각 시스템인 카메라는 어떨까?

2) 가장 처음의 카메라는 르네상스 시대의 Camera Obscura(1545)이다.

카메라가 진화하면서 가장 많이쓰는 센서가 되었다.

 

3) Gubel & Wiesel의 Electronic signal from brain(1950-1960)이다. 고양이의 뇌가 어떻게 반응하는지를 보았다. 

visual processing은 뇌에서 간단한 구조로 시작되고, 뇌가 복잡하게 구조화한다는 것을 알게 되었다.

 

4) Block world(1963) : 첫번째 컴퓨터 비전 이론 -> visual world가 기하학적 모양으로 되어있고, 목적은 인식과 재건이었다.

the summer vision project(1966) -> visual system에 대한 연구 -> 이것으로 시작하여, 가장 중요하고 빠르게 성장하고 있음. 하지만 아직도 해결안됨

 

5) David marr(1970s) -> vision이 뭔지? 어떤 방향으로 computer vision이 가야하는지를 고민하였다.

인풋 이미지 -> Primal Sketch(Edges) -> 2 1/2-D sketch -> 3D model(계층적으로 3D 로 구현)

 

6) Generalized Cylinder(1979)

간단한 블록 세상에서 실제 물체를 인식하려면 어떻게 해야할까? 고민하였다. 하지만, 컴퓨터가 정말 느리고 데이터가 없었다. 

모든 물체는 실린더 모양으로 되어있다고 가정하여 물체의 복잡도를 줄였다.

7) Pictorial Structure(1973)

Lines & Edges -> toys 정도에 그침

 

 

물체 인식이 너무 어려우면, 먼저 object segmentation을 하는게 어떨까?

8) Normalized Cut(1997)

image segmentation의 등장이었다. 픽셀 단위로 물체를 인식하는 개념.

 

9) Face Detection(2001)

machine learning tech -> SVM, boosting, graphical model, etc.

많은 기여를 한 것은 AdaBoosting을 realtime face-detection에서 사용한 것이었다.

컴퓨터 칩이 아직도 많이 느렸지만, 머신러닝 기법으로 리얼타임 얼굴인식을 성공하였다.

 

10) fuji digital camera (2006)

real-time face detector를 가진 카메라를 fuji에서 출시하였다.

 

 

11) feature-based  (1999)

객체 인식을 feature-based로 해보고자 하였다. 전체 물체를 다른 동일 물체로 대입시키고자 하였다.

물체의 각도, 조명 등등 때문에 실현하기 어려운 아이디어였지만,

물체의 부분(feature)을 보자는 시각을 건네 주었다. 

패턴을 맞춰보는 것보다 피쳐를 이용해서 두 개의 물체를 맞춰볼 수 있었다.

 

 

12) Spatial Pyramid Matching(2006)

이미지의 여러 부분에서 feature들을 뽑아서 feature descriptor에 넣고

support vector machine 알고리즘을 돌림

 

 

13) Histogram of Graidents(2005), Deformable Part Model(2009)

사람을 인식하고자 노력하였다.

 

21세기가 되면서 사진의 질이 좋아졌다

인터넷의 성장과 함께 디지털 카메라의 성능이 더더 좋아지고, 컴퓨터 비전을 수행하기에 적합하게 데이터의 질이 높아졌다.

 

14) PASCAL Visual Object Challence라는 데이터셋이 등장

물체 인식의 진전 정도를 측정할 수 있게 해준 벤치마크 데이터가 등장하였다.

데이터셋은 20개의 물체 클래스로 이루어져있다. 

-> 2007년부터 2012년까지 예측 정확도가 꾸준히 올랐다.

 

문제는 너무 train set에 overfitting되었다는 것이다.

visual data는 너무 복잡하였다.

 

15) ImageNet : 22K 카테고리 + 14M 개의 이미지들 

데이터양을 급격하게 늘려서 train set에 오버피팅 되지 않자는 목적에서 22K 카테고리 + 14M 개의 이미지를 가진 ImageNet을 만들었다.

성능을 진전시키기 위해 ImageNet Large Scale Visual Recognition Challenge을 개최하였다.

상위 5개의 클래스가 맞으면 correct로 채점한다.

 

error rate graph

2012년에 error rater가 엄청 급감 했다. -> Convolution Neural Network 등장 !!

 

 

 

우리 수업에서는 Convolution Neural Network 에 딥 다이브해서 알아볼 것이다.

그 중에서도 image classification에 focus 할 것이다.

object detection, image captioning(이미지를 자연어로 설명)도 할 것이다.

 

 

CNN은 물체 인식의 아주 중요한 도구가 되었다.


ImageNet Large Scale Visual Recognition Challenge 우승 모델

2010년) 아직도 계층적이다. 

2012년) AlexNet. 이 때부터 모든 우승자는 Neural Network 였다. 7-8 layer를 가지고 있다.

2014년) 19 layer를 가지고 있다. (VGG)

2015년) 152개의 layer를 가진 ResNet이 개발되었다.

 

사실, CNN은 2012년에 나온게 아니다.

1998년에 나와서 post office에서 digit를 인식하는데 사용되었다.

1998년에 나온 모델이 2012년의 AlexNet과 비슷해 보인다.

take pixels -> classify

 

그렇다면 왜 2012년에 주목받게 되었을까?

1) computation (계산능력)

: 트랜지스터의 개수가 엄청나게 증가

동일한 환경에서 모델의 사이즈만 증가시켜도 성능이 증가하는 경우가 있기 때문이다.

2) data

: labeled 데이터가 많아져서, ex) PASCAL, ImageNet

많고 high-quality인 data가 수집되었기 때문이다.

 

 

더 다양하게 활용되고 있는 사례들.

Image Retrieval




객체 뿐만 아니라 객체간의 관계와 상황, 객체의 특성을 인식할 수 있어야 한다.

 

 

Fei-Fei Lee의 연구


사람들은 잠깐의 영상을 보고 많은 양의 글로 설명할 수 있다.

 

 

수업의 철학


1) thorough and detailed : CNN 구현

2) practical

3) state of the art

4) fun

 

 

Q. 궁금한것, 더알아볼것


- support vector machine 알고리즘이 무엇인지?

- AdaBoost

반응형

+ Recent posts