1. 程式人生 > >Kaggle學習之路(二) —— Digit Recognizer之問題分析

Kaggle學習之路(二) —— Digit Recognizer之問題分析

Digit Recognizer是數字手寫體識別。
Kirill Kliavin基於TensorFlow 框架與深度學習演算法,給出了準確率高達0.99的解決方法,值得我們學習。
  • 閱讀本篇的先決條件:需要有一定python基礎,一些線性代數的理論基礎,尤其是對於矩陣的處理。(矩陣的乘法,轉置等)
本篇主要說明Digit Recognizer的分析,程式碼我已經寫了詳細的註釋,如果你感興趣,請移步:
https://github.com/Skyamz/Data_Recognizer

1. 明確我們的目標

讓機器判斷人類的手寫體數字是幾,並且輸出出來。

2. 熟悉kaggle給的資料集

  • train.csv是訓練集,這些資料用來建立一個模型。數字以圖片的形式儲存在電腦中,我們將這個數字圖片分成784個畫素(pixel),儲存在一個向量裡面。訓練集的一行就表示一個向量,也就是一個數字。784列對應的就是784個畫素。第一行label表明這一行是數字幾。我們的資料有42000行,即有42000個手寫的數字圖片。第十行的數字‘8‘長這個樣子:
    這裡寫圖片描述


    這裡寫圖片描述

        這個矩陣原理類似於我們去檢查眼睛的時候,醫生看我們是不是色盲時,用的那張卡片。這中間的每一個數字對應圖片上的一個小塊。
  • test.csv是測試集,這些資料用來檢測我們的模型。我們的模型最後就是要輸出測試集中的這28000張圖片都是數字幾。然後輸出一個檔案儲存結果,輸出檔案長這樣子:
    這裡寫圖片描述

3. 資料的處理

    由於我們使用的kaggle資料集都是比較乾淨的,都是已經儲存到784列裡的(有784個畫素),所以不用進行圖片的放大縮小等處理。

3.1 減少影象的儲存。

    經過統計,最大的pixel為255,要用2^7空間來儲存。一共42000*784個畫素,佔的空間會很多,而且處理的時間會很慢。所以我們給images矩陣都乘以1.0/255.0來進行處理,把畫素值控制在0-1之間。畫素值越接近於1,就越黑,越接近於0越白。

images = np.multiply(images, 1.0 / 255.0)

    影象畫素在0-255之間為灰度影象,我們訓練集中的影象已經是灰度影象了。我們之所以不對映二值影象影象,而是除以1.0/255.0,是因為轉化成二值影象資訊損失太大,只有0,1兩個數字,會造成判斷的錯誤。

3.2 對train.csv第一列的label進行one-hot編碼

  • one-hot編碼是什麼?

        我們現在有0-9這十個數字,我們建立十個一維矩陣。每個矩陣表示一個數字。如下所示:

    0 => [1 0 0 0 0 0 0 0 0 0]
    1 => [0 1 0 0 0 0 0 0 0 0]
    2 => [0 0 1 0 0 0 0 0 0 0]
    3 => [0 0 0 1 0 0 0 0 0 0]
    4 => [0 0 0 0 1 0 0 0 0 0]

    9 => [0 0 0 0 0 0 0 0 0 1]

    實現的程式碼如下
    def dense_to_one_hot(labels_dense, num_classes):
        num_labels = labels_dense.shape[0]
        index_offset = np.arange(num_labels) * num_classes
        labels_one_hot = np.zeros((num_labels, num_classes))
        labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
        return labels_one_hot
    labels = dense_to_one_hot(labels_flat, labels_count)

    再來舉一個更直觀的例子:現在有一個訂單,有三個feature:

    date=[“20170720”, “20170721”]
    fee=[“1000-2000”, “2000-3000”, “3000-4000”]
    person=[“Zhao”, “Qian”, “Sun”, “Li”]

    那麼我們對上面三個feature的編碼為:

    date=[01,10]
    fee=[001,010,100]
    person=[0001,0010,0100,1000]

        可以看出,編碼位數取決於一個feature的種類數。哪一位生效,哪一位就對應為1。如果一個訂單為[“20170721”, “2000-3000”, “Qian”]的話,它的one-hot編碼就為[00,10 000,010,000 0000,0010,0000,0000],可以簡寫為[0,1 0,1,0 0,1,0,0]

  • 為什麼要用one-hot編碼?

    one-hot編碼可以使類別獨立出來,能夠很好地處理離散型資料。我們這裡要用到one-hot編碼是因為後面要建立一個softmax層來給類別分配概率,這些概率是獨立同分布的。所以要求輸入的標籤也應該是獨立的,因此我們要對標籤(0-9)進行one-hot編碼。進而計算交叉熵。

3.3 劃分訓練集和驗證集

    我們將train.csv再劃分為兩部分,一部分用來構建模型,另一部分來驗證模型的準確率。我們這裡取的驗證validation_images是images的前VALIDATION_SIZE行,即取VALIDATION_SIZE個圖片。取的訓練集為images的VALIDATION_SIZE後面的所有行,即42000-VALIDATION_SIZE個圖片。此處我們的VALIDATION_SIZE設定為2000。取了整個train.csv的5%的大小,是後期調參調出來的,開始一般取10%-25%,慢慢降低比例。

    validation_images = images[:VALIDATION_SIZE]
    validation_labels = labels[:VALIDATION_SIZE]
    train_images = images[VALIDATION_SIZE:]
    train_labels = labels[VALIDATION_SIZE:
                                     memoryjdch編輯於2017.7.14