教你使用keras在kaggle數字識別大賽中拿到前百名

1、寫在前面

    最近一直在研究深度學習,每一種深度學習算法都讓我感受打開了新世界的大門。git

    沒想到第一次在kaggle上隨便參加了個簡單比賽就取得了前5%的成績,雖然只是一個簡單的比賽,可是這個結果也讓初學者的我很是開心。github

   

   目前個人模型的識別率是99.771%,爬到52名以後就往上爬不動了。若是有大佬有能提升識別率,甚至識別率達到100%的方法,或者對這篇文章有任何意見建議,歡迎和我交流。算法

個人微博是@阿扣是誰哇  歡迎來找我玩OVObash

2、模型選擇

   在此咱們選擇最簡單的神經網絡模型MLP網絡


   爲何選擇MLP呢?有以下幾個緣由:app


   一、由於up主如今很窮,用的電腦仍是13年的macbook,仍是隻有集顯的那種,卷積神經網絡up主也測試過,可是訓練起來電腦有點吃力,因此就放棄了╮(╯▽╰)╭。機器學習

   二、kaggle中提供的訓練數據和傳統的mnist數據維度徹底同樣,都是長寬爲28像素的黑白圖像,單張圖只有784維,即便不進行池化卷積等操做,須要訓練的參數也只有不到20萬個。函數

   三、若是簡單的神經網絡能解決問題,就不要用複雜的模型了(固然複雜的模型也要能理解而且能coding),畢竟如今顯卡那麼貴.......算了扯遠了.....學習



3、代碼詳解


該項目完整代碼:在這裏測試

(https://github.com/hikariming/Digit_Recognizer_99.771-/blob/master/digit_kaggle.py)


一、引入各類包

這一步就不細說啦,大概就是引入各類包,最主要的仍是引入keras還有numpy

# -*- coding: utf-8 -*-
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.optimizers import SGD
import numpy as np
import csv
複製代碼

二、引入訓練數據


定義一個打開訓練集的函數,訓練數據從kaggle上下載下來便可,下載下來的數據的shape爲(42000,784),即有42000個訓練數據。

def LoadTraincsvfile():
    tmp=np.loadtxt('/Users/itwork/Desktop/train_set/big-mnist/train.csv',dtype=np.str,delimiter=',')
    x_data=tmp[1:,1:].astype(np.float)
    y_data=tmp[1:,0].astype(np.float)
    return x_data,y_data
#打開從kaggle上下載下來的訓練數據
x_data,y_data=LoadTraincsvfile()

複製代碼

三、擴充訓練數據


爲了達到更高的識別率,咱們須要更多的訓練數據,我的感受常規的經過圖像變形的方法對手寫數字沒啥卵用(畢竟手寫的數字通過變形、翻轉以後就不像數字了,並且訓練數據像素比較低),因此我放棄了這種擴充數據集的方法。

在這裏,我直接把標準的mnist數據集也引入進訓練集中,mnist裏面有60000萬個28x28的手寫數字圖像。



path = './mnist.npz'
f = np.load(path)
x_train1, y_train1 = f['x_train'], f['y_train']
x_test1, y_test1 = f['x_test'], f['y_test']
f.close()
x_train1 = x_train1.reshape(60000, 784).astype('float32')複製代碼



把kaggle上的手寫訓練數據和mnist手寫數據結合一下,就有102000條訓練數據了,這樣訓練數據就擴充了2倍多。

x_train=np.concatenate((x_data[0:42000,:],x_train1),axis=0)
y_train=np.concatenate((y_data[0:42000],y_train1),axis=0)複製代碼


四、構建測試集(可忽略)、數據標準化


在這裏的測試集其實沒啥子用,爲了提升準確度我把全部kaggle給的訓練數據全都當作訓練集了,這裏的測試集和訓練集是重合的。


數據標準化很是簡單,直接把單個像素點除個255就好

#構件測試集
x_test=x_data[41000:,:]
y_test=y_data[41000:]
print (x_train.shape)
print (y_train.shape)

#數據標準化
x_train /= 255
x_test /= 255複製代碼

五、創建網絡開始訓練+調參


正片開始了,創建好粗略的MLP模型的以後,慢慢的調參。


我主要調整了損失函數(改變損失函數以後,識別率忽然飆升,我也沒搞懂爲啥會這樣- -),學習率,每層的神經元的個數

在沒有調參和修改損失函數前,這個模型的識別率大概在97%左右,通過調參識別率就上升到了99.7%了,損失函數的值已經降到了10的-5仍是-7次方了,能夠說很是誇張。

在這裏我沒有用dropout,up主不是很喜歡用dropout,由於總以爲它會形成網絡內隨機性和風險增長,下降識別率

此處代碼不詳細說,參考keras官方文檔便可。

model = Sequential()

model.add(Dense(200, activation='relu', input_dim=784))
model.add(Dense(120, activation='relu'))
model.add(Dense(10, activation='softmax'))
#使用adam加速方法,beta的值是adam創始人論文的推薦值,所以就不調了
adam = keras.optimizers.Adam(lr=0.0005, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(loss='binary_crossentropy',
              optimizer=adam,
              metrics=['accuracy'])

model.fit(x_train, y_train,
          epochs=50,
          batch_size=256)
score = model.evaluate(x_test, y_test, batch_size=4096)
print(model.metrics_names)
print(score)
複製代碼


六、對未知數據進行預測,將結果上傳到kaggle

每個kaggle上的比賽,對上傳的結果文件格式都有必定的要求,格式要求在相應競賽的附件裏面有,本身下載下來參考便可。



根據Digit_Recognizer比賽的要求,咱們對測試集進行預測,並將預測結果輸出成csv文件:


#預測部分
is_predict=1
if(is_predict):
    #將測試數據標準化
    tmp = np.loadtxt('/Users/itwork/Desktop/train_set/big-mnist/test.csv', dtype=np.str, delimiter=',')
    x_predict = tmp[1:, :].astype(np.float)
    x_predict /= 255
    #進行預測
    classes = model.predict_classes(x_predict)
   
    #輸出結果
    resultlist = []
    imgid = 1
    for i in classes:
        res_data = {'ImageId': imgid, 'Label': i}
        resultlist.append(res_data)
        imgid = imgid + 1

    headers = ['ImageId', 'Label']
    with open('result.csv', 'w', newline='') as f:
        # 標頭在這裏傳入,做爲第一行數據
        writer = csv.DictWriter(f, headers)
        writer.writeheader()
        for row in resultlist:
            writer.writerow(row)

複製代碼

4、後記

一、比賽方面

   數字識別雖然是最簡單的機器學習分類問題之一,可是能玩到這麼高的識別率,對於萌新如個人人來講仍是挺開心的。

   損失函數的構建公式對預測結果影響仍是挺大的,但願本身能多多理解損失函數的內涵吧。

   kaggle上有很多人已經達到了100%的識別率了,真心佩服,真心想知道他們是怎麼實現的。

二、最後的嘮叨

   計算機視覺這方面的內容因爲我電腦機能的緣由就暫時無法學了QAQ,建議各位想學深度學習的孩子仍是砸鍋賣鐵弄臺好電腦。

    kaggle上的大部分計算機視覺的題目,光是將訓練集就直接能夠把個人筆記本電腦內存塞滿,電腦崩潰╮(╯▽╰),即便解決了內存問題。若是顯卡很差的話,即便你用遷移學習,訓練一趟也仍是要花幾個小時,簡直無法玩。


接下來我會研究LSTM這些RNN的相關技術,參加一下kaggle上面的文本識別比賽,有興趣的朋友歡迎組個隊呀~若是你不嫌棄我電腦卡技術菜的話2333

相關文章
相關標籤/搜索