基于tensorflow2.0利用CNN与线性回归两种方法实现手写数字识别
CNN實現手寫數字識別
導入模塊和數據集
import os import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers, optimizers, datasets os.environ['TF_CPP_MIN_LOG_LEVEL']='2'(x_train,y_train),(x_test,y_test)=datasets.mnist.load_data()##直接從keras庫中下載mnist數據集數據集預處理
#由于導入的數據集的shape為(60000,28,28),因為利用CNN需要先進行卷積和池化操作,所以需要保持圖片的維度,經過處理之后,shape就變成了(60000,28,28,1),也就是60000張圖片,每一張圖片28(寬)*28(高)*1(單色) x_train4D = x_train.reshape(x_train.shape[0],28,28,1).astype('float32') x_test4D = x_test.reshape(x_test.shape[0],28,28,1).astype('float32') #像素標準化 x_train,x_test = x_train4D/255.0,x_test4D/255.0模型搭建
model = tf.keras.models.Sequential([tf.keras.layers.Conv2D(filters=16,kernel_size=(5,5),padding='same',input_shape=(28,28,1),activation='relu'),tf.keras.layers.MaxPool2D(pool_size=(2,2)),tf.keras.layers.Conv2D(filters=36,kernel_size=(5,5),padding='same',activation='relu'),tf.keras.layers.MaxPool2D(pool_size=(2,2)),tf.keras.layers.Dropout(0.25),tf.keras.layers.Flatten(),tf.keras.layers.Dense(128,activation='relu'),tf.keras.layers.Dropout(0.5),tf.keras.layers.Dense(10,activation='softmax') ])CNN模型為兩個卷積和池化層以及全連接層輸出的小型網絡。加入了Dropout層防止過擬合,提高模型的泛化能力。
模型訓練
我們所選取的loss函數為sparse_categorical_crossentropy函數,優化器選用的為adam,使用accuracy作為評判標準。對于訓練集,我們分出80%作為訓練集,20%作為測試集。一共訓練20次,批訓練尺寸為300.
“verbose=2”:顯示訓練過程。
訓練結果如圖所示:
訓練集的訓練效果準確率高達99.2%,訓練效果不錯。
用搭建好的模型對測試集進行實驗
model.evaluate(x_test,y_test,batch_size=200,verbose=2)結果如下圖所示:
沒有出現過擬合的情況,正確率達到了99.3%。
線性回歸實現手寫數字識別
雖然標題為線性回歸實現手寫數字識別,但是也不知是用了線性回歸,網絡模型使用的是全連接層,沒有CNN中的卷積和池化層,沒有Dropout層。在更新參數的時候,用到的是線性回歸方法。
導入模塊和數據集
import os import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers, optimizers, datasetsos.environ['TF_CPP_MIN_LOG_LEVEL']='2'(x,y),(x_val,y_val)=datasets.mnist.load_data()這一部分與CNN大同小異
訓練集數據預處理
#訓練集數據預處理 x=tf.convert_to_tensor(x,dtype=tf.float32)/255. y=tf.convert_to_tensor(y,dtype=tf.int32)##由于一開始讀入的時候是numpy格式的,需要將其展開成tensor格式。 y=tf.one_hot(y,depth=10)##個人理解是,將每張圖片的標簽,弄成一個10維的向量。如果這個標簽為1的話,那么在1那個位置就是1,其余地方為0 train_dataset = tf.data.Dataset.from_tensor_slices((x, y))#將圖片單張取出來 train_dataset = train_dataset.batch(200)##批處理的尺度為200數據預處理這一塊,與CNN不同,因為我們這種方法,不需要用到卷積層和池化層,所以我們不需要保證每張圖片都是(28 * 28),而是將其展成(1 * 784).
測試集數據預處理
x_test = tf.convert_to_tensor(x_val,dtype=tf.float32)/255. y_test = tf.convert_to_tensor(y_val,dtype=tf.int32) test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test)) test_db = test_db.batch(200)測試集和訓練集的數據預處理,差別在于沒有tf.one_hot的過程,因為測試集的圖片維度后來需要用到,就不能隨意處理。
模型搭建
model = keras.Sequential([layers.Dense(512,activation='relu'),##全連接層,784-512-256-10layers.Dense(256,activation='relu'),layers.Dense(10) ]) optimizer = optimizers.SGD(learning_rate=0.001)##學習率,也可以理解為步長模型為簡單的3層全連接層,激活函數為relu函數。
參數調整
def train_epoch(epoch):for step,(x,y) in enumerate(train_dataset):##循環300次with tf.GradientTape() as tape:#[b,28,28]=>[b,784]將圖片打平x=tf.reshape(x,(-1,28*28))out=model(x)##[b,784]=>[b,10]loss=tf.reduce_sum(tf.square(out-y))/x.shape[0]##out和y的歐氏距離平方和再除以n作為loss##需要更新w1,w2,w3,b1,b2,b3,用這個函數直接返回的是loss對于wi的偏導,loss對于bi的偏導grads=tape.gradient(loss,model.trainable_variables)##更新參數optimizer.apply_gradients(zip(grads,model.trainable_variables))if step % 100 == 0:print(epoch,step,'loss:',loss.numpy())利用訓練集調整的參數,對測試集進行測試
def test():total_correct = 0total_num = 0for step,(x_test,y_test) in enumerate(test_db):x_test=tf.reshape(x_test,(-1,28*28))##調整圖片的維度out = model(x_test)#利用訓練好的模型對輸入進行處理probability = tf.nn.softmax(out,axis=1)#softmax函數處理為該圖片為某一類別的概率prediction = tf.argmax(input=probability,axis=1)#argmax函數挑選出最大的那個數的索引。這里我說的不是很清楚,大家可以百度一下argmax函數的功能prediction = tf.cast(x=prediction,dtype=tf.int32)#轉換為int類型correct = tf.equal(x=prediction,y=y_test)#將預測與真正的結果作比較,返回有多少個位置相匹配correct = tf.cast(x=correct,dtype=tf.int32)#轉換成int類型correct = tf.reduce_sum(input_tensor = correct)#求和total_correct+=int (correct)total_num+=x_test.shape[0]acc=total_correct / total_numprint("測試集正確率:",acc)訓練過程
def train():#一共100次epochfor epoch in range(100):train_epoch(epoch)test()結果如下圖所示:
經過100次epoch之后,正確率維持在94.8%左右。可以看一下當做了30次epoch的時候,結果如下圖所示:
epoch次數多了,正確率確實高了,但是提升的速度越來越小。
綜合對比:CNN實現手寫數字識別比線性回歸實現手寫數字識別,正確率高很多。
總結
以上是生活随笔為你收集整理的基于tensorflow2.0利用CNN与线性回归两种方法实现手写数字识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序开发:学习笔记[2]——WXM
- 下一篇: tensorflow2.0中的Broad