使用tensorflow構建卷積神經網路(CNN)

Convolutional Neural Networks (卷積神經網路)

術語羅列

  • Convolutional layer 卷積層
  • pooling layer 池化層
  • Fully connected 全連接層

推薦閱讀:卷積神經網路工作原理直觀的解釋?

以下圖片均來自於互聯網,侵刪。

簡介

1962年受Hubel和Wiesel對貓視覺皮層電生理研究啟發,Kunihiko Fukishima(福島邦彥)最先提出了卷積神經網路(CNN),近年來卷積神經網路發展迅速,在語音識別、人臉識別、通用物體識別、運動分析。tensorflow為手寫字元推薦的演算法就是卷積神經網路,模型識別率高達99.6%

卷積神經網路原理

  • 神經網路
  • 含有隱含層的神經網路
  • 卷積神經網路
  • 使用python代碼實現卷積神經網路

1.神經網路

神經網路過程圖

具體過程就是。神經信號x乘上權重向量w,經過輸入函數(Net input function)求和後,由激活函數(Activation function)輸出。監督學習過程中,輸出結果將會對比數據集樣本結果(label),使用損失函數(cost function)計算損失,並且經過優化器迭代後更新權重。

2.含有隱含層的神經網路

神經網路隱含層

注意:Layer L1 為輸入層,L2為隱含層,L3為輸出層,h(x)為假設函數

這種神經網路叫做反向傳播(Back Propagation)神經網路,簡稱BP網路,一般使用sigmoid(s型)激活函數。

3.卷積神經網路

卷積神經網路包含了一個由卷積層和子採樣層構成的特徵抽取器。

卷積層通常包含若干個特徵平面(featureMap),每一個特徵平面由一些矩形排列的神經元組成,同一特徵平面的神經元共享權值,這個共享權值就是卷積核。卷積核一般以隨機小數矩陣的形式初始化,在網路的訓練過程中卷積核將學習得到合理的權值。

子採樣也叫做池化(pooling),通常有均值採樣(mean poooling)和 最大值採樣(max pooling)兩種形式。

卷積神經網路分為了三部分,第一部分為輸入層,第二部分由若干個卷積層和池化層 組成,第三部分為一個全連接的多層感知分類器構成。

卷積神經網路

Convolutional layer :卷積層

Pooling layer :池化層

Fully connected layer: 全連接層

卷積層工作原理

卷積層工作原理

卷積層的作用就是把數據通過weight變成特徵向量。

池化層工作原理

池化層的作用就是把數據用最大值或者平均值代替。達到降低數據量的目的。

4. Python 代碼實現(使用TensorFlow)

代碼片段

  1. tensorflow 的卷積層

tf.nn.conv2d(input,#輸入的應該是一個四維圖像數據[batch,in_height,in_width,in_channels] filter, #卷積核的四維數據[height,width,in_channels,out_channels] trides, padding, use_cudnn_on_gpu=None, data_format=None,#表示輸入的格式默認為NHWC name=None)

2. tensorflow 的池化層

tf.nn.max_pool(value,#輸入的是一個四維數據[batch,height,width,channels] ksize,# 池化窗口大小[1,height,width,1] strides, padding, data_format=NHWC, name=None)

環境安裝

1.安裝tensorflow

pip install tensorflow 或者 pip install tensorflow-gpu

2. 安裝PIL

推薦使用whl進行安裝 :Pillow的地址

3. 安裝科學計算庫numpy

pip install numpy

這一步,我們引入了所需的庫,並且聲明了一個changeImage的轉換方法

import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("/tmp/data/", one_hot=True)from PIL import Imageimport base64import reimport numpy as npimport time# 創建一個changeImage方法將base64圖片轉化為模型可用的數據集,方便伺服器之間傳輸def changeImage(dataUrl): dataUrl = re.sub(^data:image/.+;base64,,,dataUrl) image_s = base64.b64decode(dataUrl) fileName =test.jpg file= open(fileName,wb) file.write(image_s) file.close() img = Image.open(./test.jpg).convert(L) if img.size[0] != 28 or img.size[1] != 28: img = img.resize((28, 28)) arr = [] for i in range(28): for j in range(28): pixel = 1.0 - float(img.getpixel((j, i)))/255.0 arr.append(pixel) image_data = np.array(arr).reshape((1,784)) return image_data

這一步,我們聲明了一些神經網路的參數

learning_rate = 0.001 #學習率 batch_size = 128 #批大小num_steps = 500 #使用的樣本數量display_step = 50 #顯示間隔num_input = 784 #image shape:28*28num_classes = 10 # MNIST total classes (0-9 digits)dropout = 0.75 #用於隨機丟棄,防止過擬X = tf.placeholder(tf.float32, [None, num_input])Y = tf.placeholder(tf.float32, [None, num_classes])keep_prob = tf.placeholder(tf.float32)

創建我們的模型

def conv2d(x, W, b, strides=1): # Conv2D wrapper, with bias and relu activation x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding=SAME) x = tf.nn.bias_add(x, b) return tf.nn.relu(x)def maxpool2d(x, k=2): # MaxPool2D wrapper return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding=SAME)#創建模型def conv_net(x, weights, biases, dropout): x = tf.reshape(x, shape=[-1, 28, 28, 1]) # Convolution Layer conv1 = conv2d(x, weights[wc1], biases[bc1]) # Max Pooling (down-sampling) conv1 = maxpool2d(conv1, k=2) # Convolution Layer conv2 = conv2d(conv1, weights[wc2], biases[bc2]) # Max Pooling (down-sampling) conv2 = maxpool2d(conv2, k=2) # Fully connected layer # Reshape conv2 output to fit fully connected layer input fc1 = tf.reshape(conv2, [-1, weights[wd1].get_shape().as_list()[0]]) fc1 = tf.add(tf.matmul(fc1, weights[wd1]), biases[bd1]) fc1 = tf.nn.relu(fc1) # Apply Dropout fc1 = tf.nn.dropout(fc1, dropout) # Output, class prediction out = tf.add(tf.matmul(fc1, weights[out]), biases[out]) return out

設置我們的權重和偏移,損失函數,梯度下降,初始化參數,初始化模型保存

# 設置權重和偏移weights = { # 5x5 conv, 1 input, 32 outputs wc1: tf.Variable(tf.random_normal([5, 5, 1, 32])), # 5x5 conv, 32 inputs, 64 outputs wc2: tf.Variable(tf.random_normal([5, 5, 32, 64])), # fully connected, 7*7*64 inputs, 1024 outputs wd1: tf.Variable(tf.random_normal([7*7*64, 1024])), # 1024 inputs, 10 outputs (class prediction) out: tf.Variable(tf.random_normal([1024, num_classes]))}biases = { bc1: tf.Variable(tf.random_normal([32])), bc2: tf.Variable(tf.random_normal([64])), bd1: tf.Variable(tf.random_normal([1024])), out: tf.Variable(tf.random_normal([num_classes]))}# Construct modellogits = conv_net(X, weights, biases, keep_prob)prediction = tf.nn.softmax(logits)pred = tf.argmax(prediction, 1)# Define loss and optimizerloss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits=logits, labels=Y))optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)train_op = optimizer.minimize(loss_op)# Evaluate modelcorrect_pred = tf.equal(pred, tf.argmax(Y, 1))accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))init = tf.global_variables_initializer()saver = tf.train.Saver(tf.trainable_variables())

聲明我們的訓練函數,保存模型

def train(): sess.run(init) for step in range(1,num_steps+1): batch_x, batch_y = mnist.train.next_batch(batch_size) # Run optimization op (backprop) sess.run(train_op, feed_dict={X: batch_x, Y: batch_y, keep_prob: dropout}) if step % display_step == 0 or step == 1: # Calculate batch loss and accuracy loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x, Y: batch_y, keep_prob: 1.0}) print("Step " + str(step) + ", Minibatch Loss={:.4f}".format(loss) + ", Training Accuracy={:.3f}".format(acc)) print(sess.run(accuracy, feed_dict={X: mnist.test.images[:500], Y: mnist.test.labels[:500], keep_prob: 1.0})) save_path = saver.save(sess,"../tmp/model.ckpt") print("save success in:"+save_path)

訓練和識別一張圖片

with tf.Session() as sess: train() # 訓練完成之後就可以使用模型通過圖片直接預測手寫字母了 # saver.restore(sess, "../tmp/model.ckpt") # arr1 = changeImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAACvUlEQVRIS+1WPUiyURg9LhYhEUImStqgU2Au4WJE0GCp4NAQBZqQhSCUCSq52B85GDg4OjSUNCX2Q6M4uClESK4SIQT9OBQRQX48FxTD6r19RnzDd8FF7/uce84957yKarVaDb+4RP8Bf1rtf1vScrmM3d1d9PT0oFqtMvJisRhdXV3o7e3F7OysoCDcDMPhME5OTlAoFDA6OopsNsuG9/X1QaPR4O3tDYuLi3A4HF+CcgEeHBwgGo3i5eUFZrMZcrn8HcPX11ckEgkGnMlk2gfc3t7G9fU1JiYmYLFYWgbe3d1hfHwc3d3dDeafoQoyPD8/x8rKCrurqakpzM/Pt8wiqa1WK4aGhkD7v1qCgGQOl8uFi4sLPD8/Q6fTYW9vjxmnvshITqcTS0tLiMVi7QHWnyYWwWAQdF8ymQzHx8cNUJVKBa1WC6/X+6HkzScQZNi8mdiaTCbc3t6iv7+fRWRnZwdnZ2cYHh5GMpn8uVjUJxHoyMgIisUiJBIJHh8fGauNjQ3o9fqfByRTbG1tIZVKNXJ4enrKBUYPcEtKzNbW1ljOnp6eUKlUoFarWfaOjo4EmdU3cAHu7+/D4/Ews1CNUdOQQebm5vDw8IB4PA6j0cgFKghIQMTq8vISMzMzTM6BgQE2fHl5Gfl8nh1menq6fcD19XXmQrL8wsIC+zQvMsrh4SECgUD7gPRmINlKpRKoSz9yIEVEJBIhFAq1LymVNd0dlfXm5maLXHQgisfg4CA7UHPz/FW1UahXV1dZoNPpdMuMsbEx9p3BYEAkEuG6P8FYKBQKKJVK+Hy+d3dE7szlcujs7GQVVzcRD+qXLqUiJqb39/csa5RFu93O3hxUb/SbzWbjwWnsEYyF2+1uhL2jowNSqZSF3e/3c7fLt8ubmN7c3ODq6gqTk5Nc/10+oy3I8Ft6cWz+dcA/8zN3vADs60gAAAAASUVORK5CYII=") # print(sess.run(pred,feed_dict={X:arr1,keep_prob: 1.0})) # 如果訓練成功,那麼你輸出的應該這張base64圖片的數字[8]

上傳一張結果圖


推薦閱讀:

TAG:機器學習 | 卷積神經網路CNN | AI技術 |