卷積神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)多個(gè)數(shù)字識(shí)別

數(shù)據(jù)集:MNIST
框架:Keras
顯卡:NVIDIA GEFORCE 750M
參考:Keras中文文檔

這是優(yōu)達(dá)學(xué)城的深度學(xué)習(xí)項(xiàng)目,數(shù)據(jù)集和需求都很簡(jiǎn)單,關(guān)鍵是為了熟悉框架的使用以及項(xiàng)目搭建的套路险耀,只要用很簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)就能實(shí)現(xiàn)臭猜,準(zhǔn)確率輕輕松松就能上90%松捉。

需求描述

隨機(jī)從MNIST數(shù)據(jù)集中選擇5個(gè)或5個(gè)以下的數(shù)字,拼成一張圖片飘千,如下圖所示。搭建一個(gè)模型栈雳,識(shí)別圖片中的數(shù)字护奈,空白字符的類型為0。


imgs and labels

項(xiàng)目實(shí)戰(zhàn)

載入數(shù)據(jù)集

keras有

from keras.datasets import mnist

(X_raw, y_raw), (X_raw_test, y_raw_test) = mnist.load_data()

n_train, n_test = X_raw.shape[0], X_raw_test.shape[0]
查看數(shù)據(jù)集
import matplotlib.pyplot as plt
import random

%matplotlib inline
%config InlineBackend.figure_format = 'retina'

for i in range(15):
    plt.subplot(3, 5, i+1)
    index = random.randint(0, n_train-1)
    plt.title(str(y_raw[index]))
    plt.imshow(X_raw[index], cmap='gray')
    plt.axis('off')
dataset
合成數(shù)據(jù)

載入數(shù)據(jù)集的時(shí)候?qū)?shù)據(jù)集分成了訓(xùn)練集X_raw和測(cè)試集X_test哥纫,這里需要從X_raw中隨機(jī)選取數(shù)字霉旗,然后拼成新的圖片,并將20%設(shè)為驗(yàn)證集蛀骇,防止模型過擬合厌秒。
注意:數(shù)字的長(zhǎng)度不一定為5,不到5的以空白填充松靡,最終圖片高28長(zhǎng)28x5=140

  • 為什么將數(shù)據(jù)分成訓(xùn)練集简僧、驗(yàn)證集和測(cè)試集
    訓(xùn)練集是用來訓(xùn)練模型的雕欺;驗(yàn)證集是用來對(duì)訓(xùn)練的模型進(jìn)行進(jìn)一步調(diào)參優(yōu)化岛马,如果使用測(cè)試集驗(yàn)證棉姐,網(wǎng)絡(luò)就會(huì)記住測(cè)試集,容易使模型過擬合啦逆;測(cè)試集用來測(cè)試模型表現(xiàn)伞矩。

難點(diǎn):
原圖是28x28,拼成28x140夏志,原來一行有28乃坤,現(xiàn)在一行有140,是每行做的append沟蔑,用list.append效率會(huì)很低湿诊,用矩陣轉(zhuǎn)置就會(huì)很快。

import numpy as np
from sklearn.model_selection import train_test_split

n_class, n_len, width, height = 11, 5, 28, 28

def generate_dataset(X, y):
    X_len = X.shape[0] # 原數(shù)據(jù)集有幾個(gè)瘦材,新數(shù)據(jù)集還要有幾個(gè)
    # 新數(shù)據(jù)集的shape為(X_len, 28, 28*5, 1)厅须,X_len是X的個(gè)數(shù),原數(shù)據(jù)集是28x28食棕,取5個(gè)數(shù)字(包含空白)拼接朗和,則為28x140, 1是顏色通道,灰度圖簿晓,所以是1
    X_gen = np.zeros((X_len, height, width*n_len, 1), dtype=np.uint8)
    # 新數(shù)據(jù)集對(duì)應(yīng)的label眶拉,最終的shape為(5,  X_len,11)
    y_gen = [np.zeros((X_len, n_class), dtype=np.uint8) for i in range(n_len)]
    
    for i in range(X_len):
        # 隨機(jī)確定數(shù)字長(zhǎng)度
        rand_len = random.randint(1, 5)
        lis = list()
        # 設(shè)置每個(gè)數(shù)字
        for j in range(0, rand_len):
            # 隨機(jī)找一個(gè)數(shù)
            index = random.randint(0, X_len - 1)
            # 將對(duì)應(yīng)的y置1, y是經(jīng)過onehot編碼的憔儿,所以y的第三維是11忆植,0~9為10個(gè)數(shù)字,10為空白皿曲,哪個(gè)索引為1就是數(shù)字幾
            y_gen[j][i][y[index]] = 1
            lis.append(X[index].T)
        # 其余位取空白    
        for m in range(rand_len, 5):
            # 將對(duì)應(yīng)的y置1
            y_gen[m][i][10] = 1
            lis.append(np.zeros((28, 28),dtype=np.uint8))
        lis = np.array(lis).reshape(140,28).T
     
        X_gen[i] = lis.reshape(28,140,1)
        
    return X_gen, y_gen
X_raw_train, X_raw_valid, y_raw_train, y_raw_valid = train_test_split(X_raw, y_raw, test_size=0.2, random_state=50)

X_train, y_train = generate_dataset(X_raw_train, y_raw_train)
X_valid, y_valid = generate_dataset(X_raw_valid, y_raw_valid)
X_test, y_test = generate_dataset(X_raw_test, y_raw_test)
顯示合成的圖片
# 顯示生成的圖片
for i in range(15):
    plt.subplot(5, 3, i+1)
    index = random.randint(0, n_test-1)
    title = ''
    for j in range(n_len):
        title += str(np.argmax(y_test[j][index])) + ','
    
    plt.title(title)
    plt.imshow(X_test[index][:,:,0], cmap='gray')
    plt.axis('off')
合成的圖片
CNN搭建

使用了keras的函數(shù)式模型唱逢,很方便,可以參考官方文檔屋休。
由于數(shù)據(jù)集比較簡(jiǎn)答坞古,所以隨便一個(gè)網(wǎng)絡(luò)結(jié)構(gòu)都能有不錯(cuò)的表現(xiàn),我用的是兩層卷機(jī)模型劫樟,卷積層痪枫、最大池化層、卷積層叠艳、最大池化層奶陈,然后兩個(gè)全連接層。

from keras.models import Model
from keras.layers import *
import tensorflow as tf

# This returns a tensor
inputs = Input(shape=(28, 140, 1))

conv_11 = Conv2D(filters= 32, kernel_size=(5,5), padding='Same', activation='relu')(inputs)
max_pool_11 = MaxPool2D(pool_size=(2,2))(conv_11)
conv_12 = Conv2D(filters= 10, kernel_size=(3,3), padding='Same', activation='relu')(max_pool_11)
max_pool_12 = MaxPool2D(pool_size=(2,2), strides=(2,2))(conv_12)
flatten11 = Flatten()(max_pool_12)
hidden11 = Dense(15, activation='relu')(flatten11)
prediction1 = Dense(11, activation='softmax')(hidden11)

hidden21 = Dense(15, activation='relu')(flatten11)
prediction2 = Dense(11, activation='softmax')(hidden21)

hidden31 = Dense(15, activation='relu')(flatten11)
prediction3 = Dense(11, activation='softmax')(hidden31)

hidden41 = Dense(15, activation='relu')(flatten11)
prediction4 = Dense(11, activation='softmax')(hidden41)

hidden51 = Dense(15, activation='relu')(flatten11)
prediction5 = Dense(11, activation='softmax')(hidden51)

model = Model(inputs=inputs, outputs=[prediction1,prediction2,prediction3,prediction4,prediction5])

model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

可視化網(wǎng)絡(luò)

依賴 pydot-ng 和 graphviz附较,若出現(xiàn)錯(cuò)誤吃粒,用命令行輸入pip install pydot-ng & brew install graphviz
windows需要安裝一下graphviz,配置一下環(huán)境

from keras.utils.vis_utils import plot_model, model_to_dot
from IPython.display import Image, SVG

SVG(model_to_dot(model).create(prog='dot', format='svg'))
網(wǎng)絡(luò)可視化
訓(xùn)練模型

訓(xùn)練20代拒课,如果驗(yàn)證集上的準(zhǔn)確率連續(xù)兩次沒有提高徐勃,就減小學(xué)習(xí)率事示。顯卡不是很好,但依然很快僻肖,大概20分鐘左右就學(xué)好了肖爵。

from keras.callbacks import ReduceLROnPlateau

learnrate_reduce_1 = ReduceLROnPlateau(monitor='val_dense_2_acc', patience=2, verbose=1,factor=0.8, min_lr=0.00001)
learnrate_reduce_2 = ReduceLROnPlateau(monitor='val_dense_4_acc', patience=2, verbose=1,factor=0.8, min_lr=0.00001)
learnrate_reduce_3 = ReduceLROnPlateau(monitor='val_dense_6_acc', patience=2, verbose=1,factor=0.8, min_lr=0.00001)
learnrate_reduce_4 = ReduceLROnPlateau(monitor='val_dense_8_acc', patience=2, verbose=1,factor=0.8, min_lr=0.00001)
learnrate_reduce_5 = ReduceLROnPlateau(monitor='val_dense_10_acc', patience=2, verbose=1,factor=0.8, min_lr=0.00001)

model.fit(X_train, y_train, epochs=20, batch_size=128,
          validation_data=(X_valid, y_valid), 
         callbacks=[learnrate_reduce_1,learnrate_reduce_2,learnrate_reduce_3,learnrate_reduce_4,learnrate_reduce_5])
計(jì)算模型準(zhǔn)確率

5個(gè)數(shù)字全部識(shí)別正確為正確,錯(cuò)一個(gè)即為錯(cuò)臀脏∪翱埃可以用循環(huán)一一比對(duì),我這里用了些概率論知識(shí)揉稚,因?yàn)槎际仟?dú)立事件秒啦,所以5個(gè)數(shù)字的準(zhǔn)確率乘起來就是模型準(zhǔn)確率。

def evaluate(model):
    # TODO: 按照錯(cuò)一個(gè)就算錯(cuò)的規(guī)則計(jì)算準(zhǔn)確率.
    result = model.evaluate(np.array(X_test).reshape(len(X_test),28,140,1), [y_test[0], y_test[1], y_test[2], y_test[3], y_test[4]], batch_size=32)
    return result[6] * result[7] * result[8] * result[9] * result[10]

evaluate(model)

最后可以得到0.9476的正確率窃植。

預(yù)測(cè)值可視化
def get_result(result):
    # 將 one_hot 編碼解碼
    resultstr = ''
    for i in range(n_len):
        resultstr += str(np.argmax(result[i])) + ','
    return resultstr

index = random.randint(0, n_test-1)
y_pred = model.predict(X_test[index].reshape(1,28,140,1))

plt.title('real: %s\npred:%s'%(get_result([y_test[x][index] for x in range(n_len)]), get_result(y_pred)))
plt.imshow(X_test[index,:,:,0], cmap='gray')
plt.axis('off')
預(yù)測(cè)結(jié)果可視化
保存模型
model.save('model.h5')

以上內(nèi)容來自822實(shí)驗(yàn)室神經(jīng)網(wǎng)絡(luò)知識(shí)分享
我們的822帝蒿,我們的青春
歡迎所有熱愛知識(shí)熱愛生活的朋友和822思享實(shí)驗(yàn)室一起成長(zhǎng),吃喝玩樂巷怜,享受知識(shí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暴氏,一起剝皮案震驚了整個(gè)濱河市延塑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌答渔,老刑警劉巖关带,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沼撕,居然都是意外死亡宋雏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門务豺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磨总,“玉大人,你說我怎么就攤上這事笼沥◎窖啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵奔浅,是天一觀的道長(zhǎng)馆纳。 經(jīng)常有香客問我,道長(zhǎng)汹桦,這世上最難降的妖魔是什么鲁驶? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮舞骆,結(jié)果婚禮上钥弯,老公的妹妹穿的比我還像新娘径荔。我一直安慰自己,他們只是感情好寿羞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布猖凛。 她就那樣靜靜地躺著,像睡著了一般绪穆。 火紅的嫁衣襯著肌膚如雪辨泳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天玖院,我揣著相機(jī)與錄音菠红,去河邊找鬼。 笑死难菌,一個(gè)胖子當(dāng)著我的面吹牛试溯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播郊酒,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼遇绞,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了燎窘?” 一聲冷哼從身側(cè)響起摹闽,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎褐健,沒想到半個(gè)月后付鹿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚜迅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年舵匾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谁不。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坐梯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拍谐,到底是詐尸還是另有隱情烛缔,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布轩拨,位于F島的核電站践瓷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏亡蓉。R本人自食惡果不足惜晕翠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淋肾,春花似錦硫麻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碌尔,卻和暖如春浇辜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唾戚。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工柳洋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叹坦。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓熊镣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親募书。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绪囱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容