深度學習入門——tensorflow和keras的基本使用

一、TensorFlow入門——實現MNIST

項目地址:https://github.com/audier/my_deep_project/tree/master/basic_deep_model
該項目是爲了整理常用深度學習框架使用細節,以及整理建模思路。因爲之前做一些模型並沒有結構化,使用一個比較整體的思路去做,所以做完收穫也寥寥。希望通過在一個框架之下去做一個項目,養成好的習慣,並鞏固基礎。

1. 項目背景

項目背景是爲了規範自己建模方法,熟悉深度框架,使用開源數據集mnist進行0-9的手寫數字識別。
其實項目目標就是將類似下圖的圖片識別爲具體數字。
mnist

2. 項目數據

項目數據採用開源數據集MNIST,MNIST是一個計算機視覺數據集,它包含70000張手寫數字的灰度圖片,其中每一張圖片包含 28 X 28 個像素點。可以用一個數字數組來表示這張圖片:

數據集被分成兩部分:60000 行的訓練數據集(mnist.train)和10000行的測試數據集(mnist.test)。

3. 數據處理

由於該數據已經是處理過的形式,這裏我們不過多介紹,僅僅介紹一下該數據常用的讀取方法。通過tf讀取數據我們就可以直接獲取能夠被用來訓練的張量。
注意
one_hot參數代表lable的表達形式是否是one_hot形式,這裏使用one_hot對標籤編碼:
reshape決定了圖片數據的維度,若爲False數據維度爲( ,28,28,1),若爲True則爲( ,784);

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("mnist/", one_hot = True, reshape = False)
print('train image shape:', mnist.train.images.shape, 'trian label shape:', mnist.train.labels.shape)
print('val image shape:', mnist.validation.images.shape)
print('test image shape:', mnist.test.images.shape)

數據結構:

train image shape: (55000, 28, 28, 1) 	trian label shape: (55000, 10)
val image shape: (5000, 28, 28, 1)
test image shape: (10000, 28, 28, 1)

數據處理部分我們不用過多處理,按照給定的訓練集、驗證集、測試集進行數據劃分即可。

4. 模型選擇與建模

1)模型選擇DNN

第一個模型選擇使用DNN結構,使用到了TensorFlow的深度框架進行建模。我們在建模過程中用到的TensorFlow模塊包括如下,都是非常常見的模塊,不理解含義的可以提前瞭解:

  • tf.nn.dropout
  • tf.nn.relu
  • tf.matmul
  • tf.variable
  • tf.placeholder
  • tf.random_normal
  • tf.reduce_mean
  • tf.nn.softmax_cross_entropy_with_logits
  • tf.train.AdamOptimizer().minimizer()
  • tf.global_variables_initializer()
  • tf.Session()
  • tf.equal
  • tf.argmax
  • tf.cast
  • tf.train.exponential_decay

2)模型輸入及參數

定義佔位符和權值變量、常用參數,這裏定義了隱藏層的節點數以及學習率等參數:

input_size = 784
hidden1_size = 512
hidden2_size = 256
output_size = 10
learning_rate = 0.005
batch_size = 100
batch_nums = mnist.train.labels.shape[0] // batch_size

x = tf.placeholder(tf.float32, [None, 784])
keepprob = tf.placeholder(tf.float32)
y_ = tf.placeholder(tf.float32, [None, 10])

w1 = tf.Variable(tf.random_normal([input_size, hidden1_size]))
b1 = tf.Variable(tf.random_normal([hidden1_size]))
w2 = tf.Variable(tf.random_normal([hidden1_size, hidden2_size]))
b2 = tf.Variable(tf.random_normal([hidden2_size]))
w_out = tf.Variable(tf.random_normal([hidden2_size, output_size]))
b_out = tf.Variable(tf.random_normal([output_size]))

w = [w1, w2, w_out]
b = [b1, b2, b_out]

3)模型結構

首先,定義全連接層,其中激活函數採用relu,使用了dropout避免過擬合:

def dense(x, w, b, keepprob):
	return tf.nn.dropout(tf.nn.relu(tf.matmul(x, w) + b), keepprob)

利用全連接層搭建輸入到輸出的網絡結構:

def DNNModel(images, w, b, keepprob):
	dense1 = dense(images, w[0], b[0], keepprob, name='dense1')
	dense2 = dense(dense1, w[1], b[1], keepprob, name='dense2')
	output = tf.matmul(dense2, w[2]) + b[2]
	return output

4)損失函數和優化器

定義訓練參數所需的損失函數和優化算法,這裏我們用的是交叉熵和Adam優化算法:

logits = DNNModel(x, w, b, keepprob)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_))
opt = tf.train.AdamOptimizer(learning_rate).minimize(loss)

5)模型訓練並保存

開始會話進行訓練並保存模型:

saver = tf.train.Saver()
with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	for i in range(batch_nums):
		xs, ys = mnist.train.next_batch(batch_size)
		sess.run(opt, {x: xs, y_: ys, keepprob: 0.75})
	saver.save(sess, './checkpoint/tfdnn.ckpt')

5. 評估準則與效果

分類評估準則直接按照識別準確率作爲評估準則,將輸出結果與標籤比較得出準確率,定義識別率:

predict = tf.equal(tf.argmax(logits, 1), tf.argmax(y_, 1))
acc = tf.reduce_mean(tf.cast(predict, tf.float32))

利用識別率評估模型,注意這裏不是訓練模型,因此keepprob設置爲1:

valloss, accuracy = sess.run([loss, acc], {x: mnist.validation.images, y_: mnist.validation.labels, keepprob: 1.})

可以得到驗證集的結果如下:

54 th batch val loss: 56.47905 , accuracy: 0.893

6. 模型優化與提升

模型優化方法有如下幾種:

  1. 防止過擬合,這個在模型中已經使用正則化和dropout來防止過擬合。
  2. 學習率處理: 指數衰減法tf.train.exponential_decay,它實現瞭如下代碼功能:
decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)

示例:

global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(0.01, global_step, 50, 0.96, staircase=True)
opt = tf.train.AdamOptimizer(learning_rate).minimize(loss, global_step=global_step)
  1. 滑動平均模型:tf.train.ExponentialMovingAverage
  2. BN層…

本項目只使用了學習率的處理以及dropout進行優化。

7. 不同模型實現結果對比

1)RNN

  1. 如果我們利用rnn來對mnist進行分類,在此之前需要了解rnn相關的模塊:
  • tf.contrib.rnn.LSTMCell
  • tf.contrib.rnn.DropoutWrapper
  • tf.contrib.rnn.MultiRNNCell
  • tf.contrib.rnn.MultiRNNCell().zero_state
  • tf.variable_scope
  • tf.get_variable_scope().reuse_variables()
  1. 在此處給出一個基於RNN進行MNIST圖像識別的例子:
    利用rnn建模和dnn主要區別只在於模型的網絡結構上,網絡結構如下:
  • 定義網絡結構:
def rnn(x, batch_size, keepprob):
	hidden_size = 28
	rnn_layers = 2
	rnn_cell = tf.contrib.rnn.LSTMCell(28)
	rnn_drop = tf.contrib.rnn.DropoutWrapper(rnn_cell, output_keep_prob=keepprob)
	multi_cell = tf.contrib.rnn.MultiRNNCell([rnn_drop] * 2)
	state = multi_cell.zero_state(batch_size, tf.float32)
	with tf.variable_scope('RNN'):
		for i in range(28):
			if i > 0: tf.get_variable_scope().reuse_variables()
			output, state = multi_cell(x[:, i, :], state)
	w = tf.Variable(tf.random_normal([28, 10]))
	b = tf.Variable(tf.random_normal([10]))
	output = tf.matmul(output, w) + b
	return output

2)CNN

和rnn一樣,cnn和dnn區別也是隻在網絡結構上有區別。

  1. 首先了解cnn相關的模塊,需要注意各模塊傳入的參數:
  • tf.nn.conv2d
  • tf.nn.max_pool
    這裏只用了卷積層和池化層,其他模塊在前面都用過了。
  1. 定義網絡結構:
def cnn_net(x, keepprob):
	w1 = tf.Variable(tf.random_normal([5, 5, 1, 64]))
	b1 = tf.Variable(tf.random_normal([64]))
	w2 = tf.Variable(tf.random_normal([5, 5, 64, 32]))
	b2 = tf.Variable(tf.random_normal([32]))
	w3 = tf.Variable(tf.random_normal([7*7*32, 10]))
	b3 = tf.Variable(tf.random_normal([10]))
	hidden1 = pool(conv2d(x, w1, b1))
	hidden1 = tf.nn.dropout(hidden1, keepprob)
	hidden2 = pool(conv2d(hidden1, w2, b2))
	hidden2 = tf.reshape(hidden2, [-1, 7*7*32])
	hidden2 = tf.nn.dropout(hidden2, keepprob)
	output = tf.matmul(hidden2, w3) + b3
	return output

二、Keras入門——實現 MNIST

項目地址:https://github.com/audier/my_deep_project/tree/master/basic_deep_model
利用keras建模會減少一定的代碼量,少定義很多東西,這裏簡單介紹一下。

1. DNN

用keras搭建DNN模型需要熟悉下面幾個模塊:
可以通過keras的手冊進行查看:https://keras-cn.readthedocs.io/en/latest/

from keras.models import Model
from keras.layers import Input, Dense, Dropout
from keras import regularizers
from keras.optimizers import Adam

模型選擇與建模

# =============定義網絡結構==============
inputs = Input(shape=(784,))
h1 = Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01))(inputs)
h1 = Dropout(0.2)(h1)
h2 = Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01))(h1)
h2 = Dropout(0.2)(h2)
h3 = Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01))(h2)
h3 = Dropout(0.2)(h3)
outputs = Dense(10, activation='softmax', kernel_regularizer=regularizers.l2(0.01))(h3)
model = Model(input=inputs, output=outputs)

損失函數和優化器

# ============訓練所需損失函數==========
opt = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

# ================開始訓練==============
model.fit(x=xs, y=ys, validation_split=0.1, epochs=4)

model.save('k_dnn.h5')

2. RNN

同上,直接給出模型搭建:

from keras.layers import LSTM
# =============定義網絡結構==============
inputs = Input(shape=(28, 28))
h1 = LSTM(64, activation='relu', return_sequences=True, dropout=0.2)(inputs)
h2 = LSTM(64, activation='relu', dropout=0.2)(h1)
outputs = Dense(10, activation='softmax', kernel_regularizer=regularizers.l2(0.01))(h2)
model = Model(input=inputs, output=outputs)

# ============訓練所需損失函數==========
opt = Adam(lr=0.003, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

# ================開始訓練==============
model.fit(x=xs, y=ys, validation_split=0.1, epochs=1)

3. CNN

同上,直接給出模型搭建:

from keras.layers import Conv2D, MaxPooling2D, Reshape
# =============定義網絡結構==============
inputs = Input(shape=(28, 28, 1))
h1 = Conv2D(64, 3, padding='same', activation='relu')(inputs)
h1 = MaxPooling2D()(h1)
h2 = Conv2D(32, 3, padding='same', activation='relu')(h1)
h2 = MaxPooling2D()(h2)
h3 = Conv2D(16, 3, padding='same', activation='relu')(h2)
h3 = Reshape((16 * 7 * 7,))(h3)
outputs = Dense(10, activation='softmax', kernel_regularizer=regularizers.l2(0.01))(h3)
model = Model(input=inputs, output=outputs)

# ============訓練所需損失函數==========
opt = Adam(lr=0.003, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

# ================開始訓練==============
model.fit(x=xs, y=ys, validation_split=0.1, epochs=1)

4. 評價模型

keras能夠簡單的讀取模型,並對模型進行評價:

#=============讀取模型=============
model = load_model('k_dnn.h5')

#=============評估模型=============
evl = model.evaluate(x=xs, y=ys)
evl_name = model.metrics_names
for i in range(len(evl)):
	print(evl_name[i], ':\t',evl[i])

結果:

loss :	 0.127047069221735
acc :	 0.978
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章