Deep Learning Tutorial (翻譯) 之使用邏輯迴歸分類手寫數字MNIST

林堯彬發表於2020-04-04

英文原文請參考http://www.deeplearning.net/tutorial/logreg.html

模型

這裡,我們將使用Theano實現最基本的分類器:邏輯迴歸,以及學習數學表示式如何對映成Theano圖。

邏輯迴歸是一個基於概率的線性分類器,W和b為引數。通過投射輸入向量到一組超平面,每個對應一個類,輸入到一個平面的距離反應它屬於對應類的概率。

那麼輸入向量x為i類的概率,數值表示如下:

 

預測類別為概率最大的類,及:

用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
        )
        self.b = theano.shared(
            value=numpy.zeros(
                (n_out),
                dtype=theano.config.floatX
            ),
            name='b',
            borrow=True
        )
        self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
        self.y_pred = T.argmax(self.p_y_given_x, axis=-1)

模型的引數在訓練中維持一個持久的狀態,我們將W,b設為共享變數,也是Theano符號變數。

目前定義的模型還沒有做任何有用的事情,接下來將介紹如何學習最優引數。

定義損失函式(Loss Function)

對於多類迴歸,常見的是使用negative log-likelihood作為損失。

在引數θ下,最大化資料集D的似然函式,讓我們先定義似然函式和損失:

這裡使用隨機梯度下降的方法求最小值。

建立邏輯迴歸類

程式碼請參考源網址:http://www.deeplearning.net/tutorial/logreg.html

def negative_log_likelihood(self, y):
        '''
        :type y: theano.tensor.TensorType
        :param y: correct label
        :return:
        Note: 我們使用mean而不是sum是為了學習率更少地依賴於batch size
        p_y_given_x是vector型別
        '''
        # y.shape返回y的行數和列數,則y.shape[0]返回y的行數,即樣本的總個數,因為一行是一個樣本。
        # T.arange(n),則是產生一組包含[0,1,...,n-1]的向量。
        # T.log(x),則是對x求對數。記為LP
        # LP[T.arange(y.shape[0]),y]是一組向量,其元素是[ LP[0,y[0]], LP[1,y[1]],
        # LP[2,y[2]], ...,LP[n-1,y[n-1]] ]
        # T.mean(x),則是求向量x中元素的均值。
        return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
    def errors(self, y):
        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))
        if y.dtype.startwith('int'):
            # T.neq(y1, y2)是計算y1與y2對應元素是否相同,如果相同便是0,否則是1。
            # 舉例:如果y1=[1,2,3,4,5,6,7,8,9,0] y2=[1,1,3,3,5,6,7,8,9,0]
            # 則,err = T.neq(y1,y2) = [0,1,0,1,0,0,0,0,0,0],其中有3個1,即3個元素不同
            # T.mean()的作用就是求均值。那麼T.mean(err) = (0+1+0+1+0+0+0+0+0+0)/10 = 0.3,即誤差率為30%
            return T.mean(T.neq(self.y_pred, y))
        else:
            raise NotImplementedError()

訓練模型

若要在大多數的程式語言中實現梯度下降演算法,需要手動的推匯出梯度表示式,這是一個非常麻煩的推導,而且最終結果也很複雜,特別是考慮到數值穩定性的問題的時候。 

然而,在Theano這個工具中,這個變得異常簡單。因為它已經把求梯度這種運算給封裝好了,不需要手動推導公式,只需要按照格式傳入資料即可。

 

g_W = T.grad(cost=cost, wrt=classifier.W)
g_b = T.grad(cost=cost, wrt=classifier.b)

updates = [(classifier.W, classifier.W - learning_rate * g_W),
               (classifier.b, classifier.b - learning_rate * g_b)]
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]
        }
    )

每一次呼叫train_model(index),都會計算並返回輸入樣本塊的cost,然後執行一次MSGD,並更新Wb。整個學習演算法的一次迭代這樣迴圈呼叫train_model (總樣本數/樣本塊數)次。假設總樣本60000個,一個樣本塊600個,那麼一次迭代就需要呼叫100次train_model。而模型的訓練又需要進行多次迭代,直到達到迭代次數或者誤差率達到要求。

測試模型

驗證模型和測試模型的不同之處在於計算所用的資料不一樣,驗證模型用的是驗證資料集。

 As you will see shortly, validate_model is key to our early-stopping implementation .

test_model = thenao.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]
    }
)  

完整程式碼

略(請參考官方教程)

參考目錄

1.深度學習(DL)與卷積神經網路(CNN)學習筆記隨筆-03-基於Python的LeNet之LR

2.官方教程

轉載於:https://www.cnblogs.com/liwei33/p/5578056.html

相關文章