Logistic 회귀 로 MNIST 핸드폰 문자 분류 식별

간단 한 소개
이 절 에서 우 리 는 Theano 를 사용 하여 가장 기본 적 인 분류 기: Logistic 회귀 (Logistic Regression) 에 사용 합 니 다.모든 코드 는 제 CSDN 다운로드 에서 무료 로 다운로드 할 수 있 습 니 다.http://download.csdn.net/detail/ws_20100/9222263。 다음은 모형 부터 시작 하 겠 습 니 다.
모형.
논리 회 귀 는 확률, 선형 분류 기다.그것 의 매개 변 수 는 가중치 행렬 W 와 편향 벡터 b 를 포함한다.분류 기 는 입력 벡터 를 일련의 초 평면 에 투사 하고 모든 초 평면 은 하나의 유형 에 대응 합 니 다.입력 벡터 와 초 평면 거 리 는 입력 이 대응 하 는 분류 에 속 할 확률 을 반영 한다.수학 에서 입력 벡터 x 는 분류 i (확률 변수 Y 의 값) 에 속 할 확률 입 니 다.
P(Y=i|x,W,b)=softmaxi(Wx+b)=eWix+bi∑jeWix+bi
모델 의 예측 치
ypred 는 확률 이 가장 높 은 분류 로 정의 합 니 다.
ypred=argmaxiP(Y=i|x,W,b)
Theano 에서 모델 구축 에 관 한 코드 는 다음 과 같 습 니 다.
# initialize with 0 the weights W as a matrix of shape (n_in, n_out)
self.W = theano.shared(
    value=numpy.zeros(
        (n_in, n_out),
        dtype=theano.config.floatX
    ),
    name='W',
    borrow=True
)
# initialize the biases b as a vector of n_out 0s
self.b = theano.shared(
    value=numpy.zeros(
        (n_out,),
        dtype=theano.config.floatX
    ),
    name='b',
    borrow=True
)

# symbolic expression for computing the matrix of class-membership
# probabilities
# Where:
# W is a matrix where column-k represent the separation hyperplane for
# class-k
# x is a matrix where row-j represents input training sample-j
# b is a vector where element-k represent the free parameter of
# hyperplane-k
self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)

# symbolic description of how to compute prediction as class whose
# probability is maximal
self.y_pred = T.argmax(self.p_y_given_x, axis=1)

모델 의 매개 변 수 는 훈련 할 때 항상 회귀 상 태 를 유지 해 야 하기 때문에 우 리 는 W 와 b 를 가중치 로 공유 합 니 다.그것들 은 기호 와 내용 에 모두 공유 가 존재 한다.그리고 우 리 는 점 적 (dot) 과 softmax 회귀 연산 을 사용 하여 벡터 값 P (Y | x, W, b) 를 계산한다.결과 p_y_given_x 는 벡터 형식의 기호 변수 이다.실제 모델 의 예측 치 를 얻 기 위해 우 리 는 T.argmax 연산 자 를 사용 합 니 다. 이것 은 색인 값 을 되 돌려 줍 니 다. p_y_given_x 의 어느 위치 에서 가장 큰 값 (예 를 들 어 가장 큰 확률 을 가 진 분류) 을 대표 합 니 다.현재 우리 가 정의 하 는 모델 은 아무것도 할 수 없다. 모든 매개 변수 가 초기 상태 에 있 기 때문에 최 적 화 된 매개 변 수 를 어떻게 배 우 는 지 소개 할 것 이다.
정의 손실 함수
훈련 은 모델 매개 변 수 를 최적화 시 키 고 손실 함 수 를 최소 화 하 는 데 관련된다.여러 종류의 분류 문제 에서 자 연 스 러 운 생각 은 마이너스 대 수 를 손실 함수 로 사용 하 는 것 같다.이것 은 매개 변수 에서θ 의 모델 에서 데이터 세트 D 를 최대 화 하 는 것 과 비슷 합 니 다.우 리 는 L 과 L 손실 을 정의 하 는 것 부터 시작 합 니 다.
L(θ={W,b},D)=∑i=0|D|log(P(Y=y(i)|x(i),W,b))
ℓ(θ={W,b},D)=−L(θ={W,b},D)
최적화 이론 에서 임 의 비 선형 함 수 를 최소 화 하 는 가장 간단 한 방법 은 경사도 하강 법 (gradient descent) 이다.
여기 서 사용 하 는 것 은 소량의 확률 경도 방법 (mini - batches Stochastic Gradient Descent, MSGD) 입 니 다.Theano 코드 에서 손실 에 대한 정 의 는 다음 과 같 습 니 다.
# y.shape[0] is (symbolically) the number of rows in y, i.e.,
# number of examples (call it n) in the minibatch
# T.arange(y.shape[0]) is a symbolic vector which will contain
# [0,1,2,... n-1] T.log(self.p_y_given_x) is a matrix of
# Log-Probabilities (call it LP) with one row per example and
# one column per class LP[T.arange(y.shape[0]),y] is a vector
# v containing [LP[0,y[0]], LP[1,y[1]], LP[2,y[2]], ...,
# LP[n-1,y[n-1]]] and T.mean(LP[T.arange(y.shape[0]),y]) is
# the mean (across minibatch examples) of the elements in v,
# i.e., the mean log-likelihood across the minibatch.
return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])

비록 형식 상 손실 함 수 는 데이터 집합 에 있 는 모든 오차 항목 과 형식 으로 정의 된다.그러나 코드 에 서 는 평균 함수 (T.mean) 를 사용 합 니 다. 이 는 학습 율 이 데이터 일괄 의 크기 에 의존 하지 않 기 때 문 입 니 다.
회귀 클래스 만 들 기
우 리 는 이제 논리 회귀 의 모든 특징 을 포괄 하 는 LogisticRegression 종 류 를 정의 해 야 한다.아래 의 코드 는 여러 가지 측면 을 포함 하고 있 으 며, 주석 이 매우 명확 합 니 다.
class LogisticRegression(object):
    """Multi-class Logistic Regression Class The logistic regression is fully described by a weight matrix :math:`W` and bias vector :math:`b`. Classification is done by projecting data points onto a set of hyperplanes, the distance to which is used to determine a class membership probability. """

    def __init__(self, input, n_in, n_out):
        """ Initialize the parameters of the logistic regression :type input: theano.tensor.TensorType :param input: symbolic variable that describes the input of the architecture (one minibatch) :type n_in: int :param n_in: number of input units, the dimension of the space in which the datapoints lie :type n_out: int :param n_out: number of output units, the dimension of the space in which the labels lie """
        # start-snippet-1
        # initialize with 0 the weights W as a matrix of shape (n_in, n_out)
        self.W = theano.shared(
            value=numpy.zeros(
                (n_in, n_out),
                dtype=theano.config.floatX
            ),
            name='W',
            borrow=True
        )
        # initialize the biases b as a vector of n_out 0s
        self.b = theano.shared(
            value=numpy.zeros(
                (n_out,),
                dtype=theano.config.floatX
            ),
            name='b',
            borrow=True
        )

        # symbolic expression for computing the matrix of class-membership
        # probabilities
        # Where:
        # W is a matrix where column-k represent the separation hyperplane for
        # class-k
        # x is a matrix where row-j represents input training sample-j
        # b is a vector where element-k represent the free parameter of
        # hyperplane-k
        self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)

        # symbolic description of how to compute prediction as class whose
        # probability is maximal
        self.y_pred = T.argmax(self.p_y_given_x, axis=1)
        # end-snippet-1

        # parameters of the model
        self.params = [self.W, self.b]

        # keep track of model input
        self.input = input

    def negative_log_likelihood(self, y):
        """Return the mean of the negative log-likelihood of the prediction of this model under a given target distribution. .. math:: \frac{1}{|\mathcal{D}|} \mathcal{L} (\theta=\{W,b\}, \mathcal{D}) = \frac{1}{|\mathcal{D}|} \sum_{i=0}^{|\mathcal{D}|} \log(P(Y=y^{(i)}|x^{(i)}, W,b)) \\ \ell (\theta=\{W,b\}, \mathcal{D}) :type y: theano.tensor.TensorType :param y: corresponds to a vector that gives for each example the correct label Note: we use the mean instead of the sum so that the learning rate is less dependent on the batch size """
        # start-snippet-2
        # y.shape[0] is (symbolically) the number of rows in y, i.e.,
        # number of examples (call it n) in the minibatch
        # T.arange(y.shape[0]) is a symbolic vector which will contain
        # [0,1,2,... n-1] T.log(self.p_y_given_x) is a matrix of
        # Log-Probabilities (call it LP) with one row per example and
        # one column per class LP[T.arange(y.shape[0]),y] is a vector
        # v containing [LP[0,y[0]], LP[1,y[1]], LP[2,y[2]], ...,
        # LP[n-1,y[n-1]]] and T.mean(LP[T.arange(y.shape[0]),y]) is
        # the mean (across minibatch examples) of the elements in v,
        # i.e., the mean log-likelihood across the minibatch.
        return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
        # end-snippet-2

    def errors(self, y):
        """Return a float representing the number of errors in the minibatch over the total number of examples of the minibatch ; zero one loss over the size of the minibatch :type y: theano.tensor.TensorType :param y: corresponds to a vector that gives for each example the correct label """

        # check if y has same dimension of y_pred
        if y.ndim != self.y_pred.ndim:
            raise TypeError(
                'y should have the same shape as self.y_pred',
                ('y', y.type, 'y_pred', self.y_pred.type)
            )
        # check if y is of the correct datatype
        if y.dtype.startswith('int'):
            # the T.neq operator returns a vector of 0s and 1s, where 1
            # represents a mistake in prediction
            return T.mean(T.neq(self.y_pred, y))
        else:
            raise NotImplementedError()

그렇다면 어떻게 하나의 LogisticRegression 류 를 예화 합 니까? 다음 과 같은 코드 를 볼 수 있 습 니 다.
# generate symbolic variables for input (x and y represent a
# minibatch)
x = T.matrix('x')  # data, presented as rasterized images
y = T.ivector('y')  # labels, presented as 1D vector of [int] labels

# construct the logistic regression class
# Each MNIST image has size 28*28
classifier = LogisticRegression(input=x, n_in=28 * 28, n_out=10)

위의 코드 에서 먼저 입력 변수 x 와 대응 하 는 분류 y 의 기호 변 수 를 정의 했다.주의해 야 할 것 은 xyLogisticRegression 대상 이외 의 것 으로 정의 된다 는 것 이다.이 클래스 는 __init__ 함수 의 매개 변수 로 값 을 입력 해 야 하기 때문에 이 인 스 턴 스 를 연결 하여 깊이 있 는 네트워크 를 구성 하려 면 이 설정 이 매우 유용 합 니 다.한 층 의 출력 은 다음 층 의 입력 으로 쓸 수 있다.(여 기 는 다 층 네트워크 를 구축 하지 않 았 지만 코드 는 다 층 네트워크 에서 다시 사용 할 수 있 습 니 다) 마지막 으로 저 희 는 (부호 화) cost 변 수 를 정의 하여 최소 화하 고 인 스 턴 스 방법 classifier.negative_log_likelihood 을 사용 합 니 다.
# the cost we minimize during training is the negative log likelihood of
# the model in symbolic format
cost = classifier.negative_log_likelihood(y)

주의 정의 cost 에 포 함 된 기호 입력 x 이 있 습 니 다. classifier 의 기호 변 수 는 초기 화 할 때 x 에 정의 되 기 때 문 입 니 다.
학습 모형
대부분의 프로 그래 밍 언어 (C / C + +, Matlab, Python) 에서 MSGD 를 실현 합 니 다. 손실 함수 가 매개 변수 에 대한 경사도 표현 식 을 사용 할 수 있 습 니 다.복잡 한 모델 에서 엄격 한 표현 식 형식 을 가지 고 있 습 니 다.θ ,특히 수치 안정성 을 고려 해 야 하 는 상황 에서Theano 를 사용 하면 이런 일 은 대량으로 간소화 된다.그것 은 자동 구 도 를 완성 하고 해당 하 는 수학 변 화 를 응용 하여 수치 안정성 을 높 일 수 있다.Theano 에서 ∂ ℓ / ∂ W 와 ∂ ℓ / ∂ b 를 얻 을 수 있 습 니 다. 아래 코드 만 있 으 면 됩 니 다:
g_W = T.grad(cost=cost, wrt=classifier.W)
g_b = T.grad(cost=cost, wrt=classifier.b)
g_Wg_b 는 기호 변수 로 계산 할 수 있다.함수 train_model 는 경사도 하강 을 완성 할 수 있 습 니 다. 정 의 는 다음 과 같 습 니 다.
# specify how to update the parameters of the model as a list of
# (variable, update expression) pairs.
updates = [(classifier.W, classifier.W - learning_rate * g_W),
           (classifier.b, classifier.b - learning_rate * g_b)]

# compiling a Theano function `train_model` that returns the cost, but in
# the same time updates the parameter of the model based on the rules
# defined in `updates`
train_model = theano.function(
    inputs=[index],
    outputs=cost,
    updates=updates,
    givens={
        x: train_set_x[index * batch_size: (index + 1) * batch_size],
        y: train_set_y[index * batch_size: (index + 1) * batch_size]
    }
)
updates 은 일련의 이원 조 이다.각 이원 그룹 에서 첫 번 째 요 소 는 업데이트 되 어야 할 기호 변수 이 고 두 번 째 요 소 는 새로운 수 치 를 계산 하 는 기호 함수 입 니 다.비슷 하 게 givens 는 사전 입 니 다. 그 중에서 키 워드 는 기호 변수 이 고 그 중의 값 은 그들의 교환 을 지정 합 니 다.함수 train_model 의 정 의 는 다음 과 같다.
  • 입력 은 소량 데이터 의 색인 index 이 고 데이터 의 크기 (이것 은 입력 이 아니 라 고정 값 이기 때 문) 를 포함 하여 x 와 해당 하 는 태그 y 를 정의 합 니 다.
  • 반환 값 은 index 에 대응 하 는 x 와 y 가 계산 한 대가 / 손실 값 이다.
  • 각 함수 호출 에 대해 먼저 index 에 따라 훈련 집중 xy 의 값 을 교체 합 니 다.그 다음 에 이 데이터 그룹 에 대응 하 는 세대 가 치 를 평가 하고 응용 updates 업데이트 할 것 이다.

  • 매번 호출 train_model(index) 할 때마다 데이터 그룹 을 계산 하여 그 세대 의 가 치 를 되 돌려 주 고 MSGD 의 한 걸음 을 완성 합 니 다.전체 학습 알고리즘 은 모든 데이터 세트 를 반복 적 으로 옮 겨 다 니 며 한 번 에 한 무더기 의 데이터 안의 모든 견본 만 고려 한 다음 에 train_model 함 수 를 반복 적 으로 호출 합 니 다.
    테스트 모델
    테스트 모델 을 테스트 할 때 우 리 는 잘못된 분류의 견본 개 수 를 중시한다.따라서 LogisticRegression 류 는 모든 데이터 그룹 에서 잘못된 분 류 된 견본 의 개 수 를 줄 이려 는 추가 적 인 사례 방법 이 있다.코드 는 다음 과 같 습 니 다:
    def errors(self, y):
        """Return a float representing the number of errors in the minibatch over the total number of examples of the minibatch ; zero one loss over the size of the minibatch :type y: theano.tensor.TensorType :param y: corresponds to a vector that gives for each example the correct label """
    
        # check if y has same dimension of y_pred
        if y.ndim != self.y_pred.ndim:
            raise TypeError(
                'y should have the same shape as self.y_pred',
                ('y', y.type, 'y_pred', self.y_pred.type)
            )
        # check if y is of the correct datatype
        if y.dtype.startswith('int'):
            # the T.neq operator returns a vector of 0s and 1s, where 1
            # represents a mistake in prediction
            return T.mean(T.neq(self.y_pred, y))
        else:
            raise NotImplementedError()

    그 다음 에 우 리 는 함수 test_model 와 함수 validate_model 를 만 들 었 습 니 다. 우 리 는 이 함수 들 을 호출 하여 잘못된 분류의 값 을 되 돌 릴 수 있 습 니 다.validate_model 교체 탈퇴 의 관건 임 을 보 게 될 것 이다.이 함수 들 의 입력 매개 변 수 는 데이터 패 킷 의 색인 번호 이 고 함수 가 이 색인 번호 에 대응 하 는 데이터 패 킷 에서 잘못 분 류 된 개 수 를 계산 합 니 다.두 함수 의 유일한 차 이 는 test_model 테스트 집합 을 대상 으로 하고 validate_model 검증 집합 을 대상 으로 하 는 것 이다.
    # compiling a Theano function that computes the mistakes that are made by
    # the model on a minibatch
    test_model = theano.function(
        inputs=[index],
        outputs=classifier.errors(y),
        givens={
            x: test_set_x[index * batch_size: (index + 1) * batch_size],
            y: test_set_y[index * batch_size: (index + 1) * batch_size]
        }
    )
    
    validate_model = theano.function(
        inputs=[index],
        outputs=classifier.errors(y),
        givens={
            x: valid_set_x[index * batch_size: (index + 1) * batch_size],
            y: valid_set_y[index * batch_size: (index + 1) * batch_size]
        }
    )

    종합 코드
    마지막 코드 는 다음 과 같 습 니 다. [다운로드 주소:http://download.csdn.net/detail/ws_20100/9222263] 사용 자 는 다음 명령 을 입력 하고 SGD 논리 회귀 로 MNIST 문 자 를 분류 할 수 있 습 니 다.
    python code/logistic_sgd.py

    출력 은 다음 과 같은 형식 이 어야 합 니 다:
    ...
    epoch 72, minibatch 83/83, validation error 7.510417 %
         epoch 72, minibatch 83/83, test error of best model 7.510417 %
    epoch 73, minibatch 83/83, validation error 7.500000 %
         epoch 73, minibatch 83/83, test error of best model 7.489583 %
    Optimization complete with best validation score of 7.500000 %,with test performance 7.489583 %
    The code run for 74 epochs, with 1.936983 epochs/sec

    Intel 쿠 예 쌍 핵 CPU E8400 @ 3.00 Ghz 의 호스트 에서 약 1.936 epochs / sec 로 75 epochs 를 거 친 후 테스트 오 차 는 7.489% 이다.GPU 에 서 는 약 10.0 epochs / sec 입 니 다.
    이미 훈련 된 모델 을 사용 하여 예측 하 다.
    훈련 이 최저 오차 에 이 르 렀 을 때 우 리 는 모델 을 다시 불 러 와 서 새로운 데이터 의 라벨 을 예측 할 수 있 습 니 다. predict 함수 가 이러한 조작 을 완 성 했 습 니 다.
    def predict():
        """ An example of how to load a trained model and use it to predict labels. """
    
        # load the saved model
        classifier = cPickle.load(open('best_model.pkl'))
    
        # compile a predictor function
        predict_model = theano.function(
            inputs=[classifier.input],
            outputs=classifier.y_pred)
    
        # We can test it on some examples from test test
        dataset='mnist.pkl.gz'
        datasets = load_data(dataset)
        test_set_x, test_set_y = datasets[2]
        test_set_x = test_set_x.get_value()
    
        predicted_values = predict_model(test_set_x[:10])
        print ("Predicted values for the first 10 examples in test set:")
        print predicted_values

    참고 자료
    Theano 딥 러 닝 자료:http://deeplearning.net/tutorial/logreg.html
    [각주] [1] 더 작은 데이터 세트 나 더 간단 한 모델 에 대해 복잡 한 하강 알고리즘 이 더욱 효과 적일 수 있 습 니 다.logistic_cg. py 코드 는 Scipy 의 공 압 경사도 방법 (conjugate gradient solver) 을 어떻게 사용 하여 논리 회귀 임 무 를 완성 하 는 지 논술 하 였 다.logistic_cg. py 코드 는 제 CSDN 다운로드 에서 무료 로 다운로드 할 수 있 습 니 다.http://download.csdn.net/detail/ws_20100/9223959

    좋은 웹페이지 즐겨찾기