揭開深度學習的神祕面紗,人工智慧對我們的生活有多重要?

不知不覺,人工智能已經悄然的走進我們的生活。在我們的潛意識裡,還是將人工智能和智能人形機器人聯繫在一起,這是我們對人工智能的固有偏見。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

在2016年的雲棲大會上,馬雲的演講飛速的被翻譯成文字,顯示在現場的大屏幕上;

自動駕駛是汽車產業與人工智能、物聯網、高性能計算等新一代信息技術深度融合的產物,是當前全球汽車與交通出行領域智能化和網聯化發展的主要方向,已成為各國爭搶的戰略制高點;

手機中的語音助手Siri,總能和我們愉快的聊天;iPhone 手機上的照片-相簿-人物中自動對照片中的人臉進行識別和歸類,將包含一個人臉的照片放在同一個相簿裡面;

今日頭條中推薦的新聞總是你感興趣的東西,不同人打開淘寶App出來的界面總不一樣。人工智能已經應用在我們生活的很多領域了。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

到底什麼是人工智能(AI),李開復對AI在人工智能中列舉了AI的五個常見定義:

1、AI就是讓人覺得不可思議的計算機程序;

2、AI就是與人類思考方式相似的計算機程序;

3、 AI就是與人類行為相似的計算機程序;

4、AI就是會學習的計算機程序;

5、AI就是根據對環境的感知,做出合理的行動,並獲得很大收益的計算機程序。

從其五點定義中,我們可以很輕易的得到這個結論:AI就是計算機程序。

當然並不僅僅是這樣,詳細點的概括為,AI是一種為了解決某些問題而人工設計出的計算機程序,這個程序的算法是模仿人類思考問題的方式,並且具有學習能力。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

2016年,AlphaGo 與李世石的圍棋大戰無疑成為人工智能的一道里程碑,也是人工智能的再一次復興。

反觀 AlphaGo 低層算法原理,如下圖2所示,需要收集大量棋手的棋譜,通說深度神經網絡來訓練模型。

人工智能的這一次復興的最大特點是,AI在語音識別、機器視覺、數據挖掘等多個領域走進了業界多個真實的應用場景,與商業模式緊密結合,開始在各個行業發揮出真正的價值。

可以說新時期的人工智能模式為:深度學習+大數據。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

現在我們走進深度學習,是機器學習的一個分支。

深度學習算法可以從數據中學習更加複雜的特徵表達,是最後一步的特徵學習變得更加簡單有效。

就圖像識別而言,深度學習可以一層一層地將簡單的像素特徵逐步轉化成更加複雜的特徵,從而使不同類別的圖像更加可分。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

和傳統機器學習相比,深度學習的特點主要體現在“深度”二字中,主要體現在網絡結構的深度和提取的特徵深度。

本文主要針對的是深度學習在機器視覺上的應用,那麼我們就繞不開一個重要的網絡結構——卷積神經網路。

在早期的圖像識別中,主要是從圖像低層特徵入手,對圖像特徵進行歸納分析,當然,組織特徵也是圖像識別技術最大的難點。

卷積神經網絡,英文全稱為 Convolutional Neural Network,簡稱 CNN,在最開始就是專門用來解決圖像中的物體識別等問題,現在,CNN 的應用已經不僅僅侷限於圖像識別和視頻處理,也被應用於時間序列信號的處理,比如識別音頻信號、文本數據。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

CNN起源於神經科學家對喵星人的大腦的研究,他們將電極插到貓的腦子裡,去觀察視覺皮層的活動,他們的經過研究推斷出,生物視覺是從物體小的部分入手,經過層層的抽象,最後拼起來送入處理中心,減少物體判斷物體的可疑性。

顯然,這個推斷和我們普通的BP神經網絡原理背道而馳,BP 神經網絡認為,大腦的每個神經元都要感知物體的全部像素點,即全像素全連接,並且知識簡單的映射,並沒有對物體進行抽象處理。

然而 CNN 最先證明了BP神經網絡理論的不合理性。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

LeNet 網絡結構

經典的 CNN 的網絡結構如圖3所示,卷積神經網絡主要結構有:卷積層、池化層和全連接層。

在 LeNet 的網絡結構中,對於一個32×32的圖像,首先用6個卷積核對圖像進行卷積得到 6×28×28 的一對數據,然後對數據的每一維做一個池化,得到6×14×14的數據結構,後面再用有16個卷積核的卷積層對數據進行卷積得到16×10×10的數據結構,再用一個池化層對將數據簡化成16×5×5,後面接一個全連接的神經網絡。

圖中所示為我們常用的卷積神經網絡實例,變化比較多的可能是卷積層和池化層的層數,卷積層和池化層的之中可能會連接數次,還可以在所用卷積核的Size上面做文章,也能達到不同的效果。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

CNN運用實例

以 Mnist 數字集為例來構建自己的 CNN 網絡,下文中分別用 Keras 和TensorFlow 對 CNN 網絡進行了實現,實現代碼如下所示。

1)Keras 實現代碼:

 import numpy  from keras.datasets import mnist  from keras.models import Sequential  from keras.layers import Dense  from keras.layers import Dropout  from keras.layers import Flatten  from keras.layers.convolutional import Convolution2D  from keras.layers.convolutional import MaxPooling2D  from keras.utils import np_utils  from keras import backend as K  K.set_image_dim_ordering('th')  seed = 7  numpy.random.seed(seed)

加載數據:

 (X_train,y_train),(X_test,y_test) = mnist.load_data()  X_train = X_train.reshape(X_train.shape[0],1,28,28).astype('float32')  X_test = X_test.reshape(X_test.shape[0],1,28,28).astype('float32')  X_train = X_train/255  X_test = X_test/255  y_train = np_utils.to_categorical(y_train)  y_test = np_utils.to_categorical(y_test)  num_classes = y_test.shape[1]  def baseline_model():

構建模型:

 model = Sequential()  model.add(Convolution2D(30,5,5,border_mode='valid',input_shape=(1,28,28),activation='relu'))  model.add(MaxPooling2D(pool_size=(2,2)))  model.add(Convolution2D(15,3,3,activation='relu'))  model.add(MaxPooling2D(pool_size=(2,2)))  model.add(Dropout(0.2))  model.add(Flatten())  model.add(Dense(128,activation='relu'))  model.add(Dense(50,activation='relu'))  model.add(Dense(num_classes,activation='softmax')) model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])  return model  model = baseline_model()  model.fit(X_train,y_train,validation_data=(X_test,y_test),nb_epoch=10,batch_size=200,verbose=2)  scores = model.evaluate(X_test,y_test,verbose=0)  print("Baseline Error: %.2f%%" % (100-scores[1]*100))

2)TensorFlow 實現

 from tensorflow.examples.tutorials.mnist import input_data  import tensorflow as tf  mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)# 讀取圖片數據集  sess = tf.InteractiveSession()# 創建session
 def weight_variable(shape):  # 正態分佈,標準差為0.1,默認最大為1,最小為-1,均值為0  initial = tf.truncated_normal(shape, stddev=0.1)  return tf.Variable(initial)  def bias_variable(shape):  # 創建一個結構為shape矩陣也可以說是數組shape聲明其行列,初始化所有值為0.1  initial = tf.constant(0.1, shape=shape)  return tf.Variable(initial)  def conv2d(x, W):  # 卷積遍歷各方向步數為1,SAME:邊緣外自動補0,遍歷相乘  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')  def max_pool_2x2(x):  # 池化卷積結果(conv2d)池化層採用kernel大小為2*2,步數也為2,周圍補0,取最大值。數據量縮小了4倍  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

二、定義輸入輸出結構

 # 聲明一個佔位符,None表示輸入圖片的數量不定,28*28圖片分辨率  xs = tf.placeholder(tf.float32, [None, 28*28])  # 類別是0-9總共10個類別,對應輸出分類結果  ys = tf.placeholder(tf.float32, [None, 10])  keep_prob = tf.placeholder(tf.float32)  # x_image又把xs reshape成了28*28*1的形狀,因為是灰色圖片,所以通道是1.作為訓練時的input,-1代表圖片數量不定  x_image = tf.reshape(xs, [-1, 28, 28, 1]) 

三、搭建網絡,定義算法公式,也就是 forward 時的計算

 ## 第一層卷積操作 ##  # 第一二參數值得卷積核尺寸大小,即patch,第三個參數是圖像通道數,第四個參數是卷積核的數目,代表會出現多少個卷積特徵圖像;  W_conv1 = weight_variable([5, 5, 1, 32])  # 對於每一個卷積核都有一個對應的偏置量。  b_conv1 = bias_variable([32])  # 圖片乘以卷積核,並加上偏執量,卷積結果28x28x32  h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # 池化結果14x14x32 卷積結果乘以池化卷積核  h_pool1 = max_pool_2x2(h_conv1)  ## 第二層卷積操作 ##  # 32通道卷積,卷積出64個特徵  w_conv2 = weight_variable([5,5,32,64])  # 64個偏執數據  b_conv2 = bias_variable([64])  # 注意h_pool1是上一層的池化結果,#卷積結果14x14x64  h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2)  # 池化結果7x7x64  h_pool2 = max_pool_2x2(h_conv2)  # 原圖像尺寸28*28,第一輪圖像縮小為14*14,共有32張,第二輪後圖像縮小為7*7,共有64張  ## 第三層全連接操作 ##  # 二維張量,第一個參數7*7*64的patch,也可以認為是隻有一行7*7*64個數據的卷積,第二個參數代表卷積個數共1024個  W_fc1 = weight_variable([7*7*64, 1024])  # 1024個偏執數據  b_fc1 = bias_variable([1024])  # 將第二層卷積池化結果reshape成只有一行7*7*64個數據# [n_samples, 7, 7, 64] ->> [n_samples, 7*7*64]  h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])  # 卷積操作,結果是1*1*1024,單行乘以單列等於1*1矩陣,matmul實現最基本的矩陣相乘,不同於tf.nn.conv2d的遍歷相乘,自動認為是前行向量後列向量  h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)  # dropout操作,減少過擬合,其實就是降低上一層某些輸入的權重scale,甚至置為0,升高某些輸入的權值,甚至置為2,防止評測曲線出現震盪,個人覺得樣本較少時很必要  # 使用佔位符,由dropout自動確定scale,也可以自定義,比如0.5,根據tensorflow文檔可知,程序中真實使用的值為1/0.5=2,也就是某些輸入乘以2,同時某些輸入乘以0  keep_prob = tf.placeholder(tf.float32)  h_fc1_drop = tf.nn.dropout(f_fc1,keep_prob) #對卷積結果執行dropout操作  ## 第四層輸出操作 ##  # 二維張量,1*1024矩陣卷積,共10個卷積,對應我們開始的ys長度為10  W_fc2 = weight_variable([1024, 10])  b_fc2 = bias_variable([10])  # 最後的分類,結果為1*1*10 softmax和sigmoid都是基於logistic分類算法,一個是多分類一個是二分類  y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) 

四、定義 loss(最小誤差概率),選定優化優化loss

 cross_entropy = -tf.reduce_sum(ys * tf.log(y_conv)) # 定義交叉熵為loss函數  train_step = tf.train.DradientDescentOptimizer(0.5).minimize(cross_entropy) # 調用優化器優化,其實就是通過喂數據爭取cross_entropy最小化

五、開始數據訓練以及評測

 correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(ys,1))  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  tf.global_variables_initializer().run()  for i in range(20000):  batch = mnist.train.next_batch(50)  if i%100 == 0:  train_accuracy = accuracy.eval(feed_dict={x:batch[0], ys: batch[1], keep_prob: 1.0})  print("step %d, training accuracy %g"%(i, train_accuracy))  train_step.run(feed_dict={x: batch[0], ys: batch[1], keep_prob: 0.5})  print("test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, ys: mnist.test.labels, keep_prob: 1.0}))

兩種方式實現 CNN 都是比較容易,但是在代碼量上,Keras佔據很大優勢,但是就代碼的靈活程度上,Keras 遠遠不及 TensorFlow。

事實上,Keras 是 TensorFlow 的簡化接口。具體地,Keras簡單易學,對於想把深度學習作為黑箱子使用的人,Keras 非常容易上手,在擴展性上面,Keras 將大部分的內部運算代碼都隱藏了。

我們就自然而然的認為它的功能比較狹窄,但是我們還是可以通過 theano 和 Tensorflow 的語句來擴展功能和 Keras 結合使用。

但是對初學者而言,不建議直接上手Keras,因為這樣會忽略很多細節和低層原理。

以簡單的 CNN 為基礎出現了很多先進的卷積網絡結構,AlexNet、VGGNet、Google Inception Net 以及 ResNet,這四種經典網絡對卷積神經網絡和深度學習有非常大的推動作用。

揭開深度學習的神秘面紗,人工智能對我們的生活有多重要?

ILSVRC 的 top-5 錯誤率在最近幾年取得了重大突破,而主要的突破點就在卷積神經網絡和深度學習,傳統的機器學習算法也難以追上深度學習的步伐了。


分享到:


相關文章: