18 深度學習案例——基於卷積神經網絡的手寫體識別

#!/usr/bin/env python
# coding: utf-8

19.2 深度學習的概念及關鍵技術

1、神經網絡模型

·生物神經元
·軸突(輸出)終端爲其他神經元的樹突(輸入)
·人工神經網絡

2、深度學習之卷積神經網絡

·深度學習結構:含有多隱層的神經網絡。
·池化:子採樣,可看作一種特殊的卷積過程。
·激活函數:sigmoid、tanh、relu
    ·sigmoid:把一個實數壓縮至0~1(分類的概率)
    ·relu:對於隨機梯度下降的收斂有巨大的加速作用。
    但脆弱,易造成不可逆轉的死亡。
·卷積神經網絡的網絡結構
    若干卷積層(配合relu) + 池化層 + 全連接層(分類器的作用)

19.3 Python深度學習庫——Keras

1、Keras的安裝

import numpy,scipy


# In[ ]:


import tensorflow as tf


# In[ ]:


import keras

2、Keras的網絡層

(包括:常用層、卷積層、池化層、局部連接層、遞歸層、嵌入層、高級激活層、規範層、噪聲層、包裝層,自己編寫的層)
·二維卷積層
·Dense層(全連接層)

3、用Keras構建神經網絡

步驟:
    1、選擇模型
    2、構建網絡層
    3、編譯
    4、訓練
    5、預測

19.4 程序設計的思路

數據集的描述:
   ·訓練與測試數據:28*28像素
   ·訓練數據集:測試數據集 = 60000 : 10000
   ·輸出層:十個神經元


網絡結構:
    ·輸入層:原始訓練圖像
    ·第一卷積層:6個5*5的卷積核,步長爲1
    ·第一池化層:2*2的卷積核,步長爲2的最大池化
    ·第一卷積層:12個5*5的卷積核,步長爲1
    ·第一池化層:2*2的卷積核,步長爲2的最大池化
    ·輸出層:十維向量,激活函數爲sigmoid


代碼流程簡述:
    (1)獲取訓練數據 和 測試數據
    (2)訓練網絡的超參數的定義(學習率,每次迭代中訓練的樣本數目,迭代次數)
    (3)構建網絡層級結構
    (4)編譯模型
    (5)訓練模型
    (6)網絡模型評估

19.5 源代碼

1、MNIST數據集

·一個計算機視覺數據集(7包含0000張手寫數字的灰度圖片)28*28像素點

2、手寫體識別案例體現

# 讀取MNIST數據集
import numpy as np


# In[ ]:


# 數據加載基類,派生出 圖片加載器 和 標籤加載器
class Loader(object):
    def __init__(self, path, count):
        self.path = path
        self.count = count
        
    def get_file_count(self):
        print(self.path)
        f = open(self.path, 'rb')
        content = f.read()
        f.close()
        return content


# In[ ]:


# 圖像數據加載器
class ImageLoader(Loader):
    
    # 內部函數,從文件字節數組中獲取第index個圖像數據
    def get_picture(self, content, index):
        start = index * 28 * 28 +16
        picture = []
        for i in range(28):
            picture.append([])
            for j in range(28):
                byte1 = content[start + i*28 + j]
                picture[i].append(byte1)
        return picture
    
    # 將圖像數據轉化成長度爲784行向量形式
    def get_one_sample(self, picture):
        sample = []
        for i in range(28):
            for j in range(28):
                sample.append(picture[i][j])
        return sample
    
    # 加載數據文件,獲得全部樣本的輸入向量,onerow表示是否將每張圖片轉化爲行向量,to2表示是否轉化爲0,1矩陣
    def load(self, onerow = False):
        content = self.get_file_content()
        data_set = []
        for index in range(self.count):
            onepic = self.get_picture(content, index)
            if onerow: 
                onepic = self.get_one_sample(onepic)
            data_set.append(onepic)
        return data_set
    
 


# In[ ]:


# 標籤數據加載器
class LabelLoader(Loader):
    
    # 加載數據文件,獲得全部樣本的標籤向量
    def load(self):
        content = self.get_file_content()
        labels = []
        for index in range(self.count):
            onelabel = content[index + 8]
            onelabelvec = self.norm(onelabel)
            labels.append(onelabelvec)
        return labels
    
    # 內部函數,one-hot編碼,用於將一個值轉換爲10維標籤向量
    def norm(self, label):
        label_vec = []
        label_value = label
        for i in range(10):
            if i == label_value:
                label_vec.append(1)
            else:
                label_vec.append(0)
        return label_vec
    
    # 獲得訓練數據集,onerow表示是否將每張圖片轉化爲行向量
    def get_training_data_set(num, onerow = False):
        image_loader = ImageLoader('train-images.idx3-ubyte', num)
        label_loader = LabelLoader('train-labels.idx1-ubyte', num)
        return image_loader(onerow), label_loader.load()
    
    # 獲得測試數據集, onerow表示是否將每張圖片轉化爲行向量
    def get_test_data_set(num, onerow = False):
        image_loader = ImageLoader('t10k-images.idx3-ubyte', num)
        label_loader = LabelLoader('t10k-labels.idx1-ubyte', num)
        return image_loader.load(onerow), label_loader.load()
    
    # 將個長度爲784的行向量打印成圖形的樣式
    def printimg(onepic): 
        onepic = onepic.reshape(28, 28)
        for i in range(28):
            for j in range(28):
                if onepic[i, j] == 0:
                    print(' ', end = '')
                else:
                    print('* ', end = '')
            print('')


# In[ ]:


# 訓練及測試數據集

import numpy as np
np.random.seed(1337)
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
import MNIST


# In[ ]:


# 全局變量
batch_size = 128                        # 批處理樣本數量
nb_classes = 10                         # 分類數目
epochs = 600                            # 迭代次數
img_rows, img_cols = 28, 28             # 輸入圖片樣本的寬、高
nb_filters = 32                         # 卷積核的個數
pool_size = (2, 2)                      # 池化層的大小
kernel_size = (5, 5)                    # 卷積核的大小
input_shape = (img_rows, img_cols, 1)   # 輸入圖片的維度


# In[ ]:


X_train, Y_train = MNIST.get_test_data_set(6000, False)
X_test, Y_test = MNIST.get_test_data_set(1000, False)

X_train = np.array(X_train).astype(bool).astype(float) / 255 # 數據歸一化
X_train = X_train[:,:,:,np.newaxis]                          #  添加一個通道,代表圖片通道
Y_train = np.array(Y_train)

X_test = np.array(X_test).astype(bool).astype(float) / 255 # 數據歸一化
X_test = X_test[:,:,:,np.newaxis]                          #  添加一個通道,代表圖片通道
Y_test = np.array(Y_test)

print('樣本數據集的維度:', X_train.shape, Y_train.shape)
print('測試數據集的維度:', X_test.shape, Y_test.shape)


# In[ ]:


# 構建模型
model = Sequential()
model.add(Conv2D(6, kernel_size, input_shape=input_shape, strides=1))

model.add(AveragePooling2D(pool_size=pool_size, strides=2))

model.add(Conv2D(12, kernel_size, strides=1))

model.add(AveragePooling2D(pool_size=pool_size, strides=2))

model.add(Flatten())                                         # 拉成一維度矩陣

model.add(Dense(nb_classes))

model.add(Activation('sigmoid'))


# In[ ]:


# 編譯模型
model.compile(loss = 'categorical_crossentropy', optimizer='adadelta', metrics= ['accuracy'])


# In[ ]:


# 訓練模型(420最爲精確!!)
model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, Y_test))


# In[ ]:


# 評估模型
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Trst accuracy:', score[1])


# In[ ]:


# 保存模型!!!
model.save('cnn_model.h5')

3、預測自己手寫圖像

# In[2]:


from keras.models import load_model
import numpy as np
import cv2


# In[ ]:


model = load_model('cnn_model.h5')
image = cv2.imread('1.png', 0)
img = cv2.imread('1.png', 0)
img = np.reshape(img, (1,28,28,1)).astype(bool).astype('float32')

my_proba = model.predict_proba(img)
my_predict = model.predict_classes(img)
print('識別爲:')
print(my_proba * 10**10)
print(my_predict * 10**10)
cv2.imshow('Image1', image)
cv2.waitKey(0)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章