資源來源於:莫煩TensorFlow
實驗的環境:
- macOs Catalina 10.15
- Python 3.6.9
- TensorFlow 1.9.0
- Numpy 1.17.4
- Tensorboard 1.9.0
文章目錄
5.1 Classification 分類學習
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# number 1 to 10 data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
def add_layer(inputs, in_size, out_size, activation_function=None):
# 隨機生成權重矩陣, in_size 行, out_size 列
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
# 偏差, 1行, out_size列 全設爲0.1
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
# 預測出來的值, 還沒有用激活函數
Wx_plus_b = tf.matmul(inputs, Weights) + biases
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b)
return outputs
def compute_accuracy(v_xs, v_ys):
global prediction
y_pre = sess.run(prediction, feed_dict={xs: v_xs})
# 判斷預測值和真實值是否一樣
correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1))
# 求平均得到正確率
# eg: 3個true, 7個false, 準確率爲3/3+7=0.3
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys})
return result
# define placeholder for inputs to network
xs = tf.placeholder(tf.float32, [None, 784]) # 28*28
ys = tf.placeholder(tf.float32, [None, 10])
# add output layer
prediction = add_layer(xs, 784, 10, activation_function=tf.nn.softmax)
# the error between prediction and real data
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), reduction_indices=[1])) # loss
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.Session()
# important step
sess.run(tf.global_variables_initializer())
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys})
if i % 50 == 0:
print(compute_accuracy(mnist.test.images, mnist.test.labels))
Extracting MNIST_data/train-images-idx3-ubyte.gz
Please use tf.one_hot on tensors.
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
0.1533
0.6452
0.7388
0.7877
0.8144
0.8245
0.8404
0.8452
0.8487
0.853
0.8556
0.8601
0.8669
0.8697
0.8681
0.8717
0.8733
0.8735
0.8777
0.8783
5.2 過擬合(overfitting)
所謂過擬合(over-fitting)其實就是所建的機器學習模型或者是深度學習模型在訓練樣本中表現得過於優越,導致在驗證數據集以及測試數據集中表現不佳。打個比喻就是當我需要建立好一個模型之後,比如是識別一隻狗狗的模型,我需要對這個模型進行訓練。恰好,我訓練樣本中的所有訓練圖片都是二哈,那麼經過多次迭代訓練之後,模型訓練好了,並且在訓練集中表現得很好。基本上二哈身上的所有特點都涵括進去,那麼問題來了!假如我的測試樣本是一隻金毛呢?將一隻金毛的測試樣本放進這個識別狗狗的模型中,很有可能模型最後輸出的結果就是金毛不是一條狗(因爲這個模型基本上是按照二哈的特徵去打造的)。所以這樣就造成了模型過擬合,雖然在訓練集上表現得很好,但是在測試集中表現得恰好相反,在性能的角度上講就是協方差過大(variance is large),同樣在測試集上的損失函數(cost function)會表現得很大。
解決過擬合的方法:
- 增加數據量, 大部分過擬合產生的原因是因爲數據量太少了
- 運用正則化. L1, l2 regularization
- dropout regularization
5.3 Dropout 解決overfitting
from __future__ import print_function
import tensorflow as tf
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
# load data
digits = load_digits()
X = digits.data
y = digits.target
y = LabelBinarizer().fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.3)
def add_layer(inputs, in_size, out_size, layer_name, activation_function=None, ):
# add one more layer and return the output of this layer
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, )
Wx_plus_b = tf.matmul(inputs, Weights) + biases
# here to dropout
Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b, )
tf.summary.histogram(layer_name + '/outputs', outputs)
return outputs
# define placeholder for inputs to network
# 保持多少不被dropout
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32, [None, 64]) # 8x8
ys = tf.placeholder(tf.float32, [None, 10])
# add output layer
l1 = add_layer(xs, 64, 50, 'l1', activation_function=tf.nn.tanh)
prediction = add_layer(l1, 50, 10, 'l2', activation_function=tf.nn.softmax)
# the loss between prediction and real data
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1])) # loss
tf.summary.scalar('loss', cross_entropy)
train_step = tf.train.GradientDescentOptimizer(0.6).minimize(cross_entropy)
sess = tf.Session()
merged = tf.summary.merge_all()
# summary writer goes in here
train_writer = tf.summary.FileWriter("logs/train", sess.graph)
test_writer = tf.summary.FileWriter("logs/test", sess.graph)
init = tf.global_variables_initializer()
sess.run(init)
for i in range(500):
# here to determine the keeping probability
sess.run(train_step, feed_dict={xs: X_train, ys: y_train, keep_prob: 0.5})
if i % 50 == 0:
# record loss
train_result = sess.run(merged, feed_dict={xs: X_train, ys: y_train, keep_prob: 1})
test_result = sess.run(merged, feed_dict={xs: X_test, ys: y_test, keep_prob: 1})
train_writer.add_summary(train_result, i)
test_writer.add_summary(test_result, i)
運行代碼後, 打開Terminal,在項目文件目錄下,輸入:
tensorboard --logdir='logs'
然後打開給定的網站即可看到可視loss圖
keep_prob: 1
keep_prob: 0.5
5.4 什麼是卷積神經網絡CNN(Convolutional Neural Network)
卷積和神經網絡
我們來具體說說卷積神經網絡是如何運作的吧, 舉一個識別圖片的例子, 我們知道神經網絡是由一連串的神經層組成,每一層神經層裏面有存在有很多的神經元. 這些神經元就是神經網絡識別事物的關鍵. 每一種神經網絡都會有輸入輸出值, 當輸入值是圖片的時候, 實際上輸入神經網絡的並不是那些色彩繽紛的圖案,而是一堆堆的數字. 就比如說這個. 當神經網絡需要處理這麼多輸入信息的時候, 也就是卷積神經網絡就可以發揮它的優勢的時候了. 那什麼是卷積神經網絡呢?
我們先把卷積神經網絡這個詞拆開來看. “卷積” 和 “神經網絡”. 卷積也就是說神經網絡不再是對每個像素的輸入信息做處理了,而是圖片上每一小塊像素區域進行處理, 這種做法加強了圖片信息的連續性. 使得神經網絡能看到圖形, 而非一個點. 這種做法同時也加深了神經網絡對圖片的理解. 具體來說, 卷積神經網絡有一個批量過濾器, 持續不斷的在圖片上滾動收集圖片裏的信息,每一次收集的時候都只是收集一小塊像素區域, 然後把收集來的信息進行整理, 這時候整理出來的信息有了一些實際上的呈現, 比如這時的神經網絡能看到一些邊緣的圖片信息, 然後在以同樣的步驟, 用類似的批量過濾器掃過產生的這些邊緣信息, 神經網絡從這些邊緣信息裏面總結出更高層的信息結構,比如說總結的邊緣能夠畫出眼睛,鼻子等等. 再經過一次過濾, 臉部的信息也從這些眼睛鼻子的信息中被總結出來. 最後我們再把這些信息套入幾層普通的全連接神經層進行分類, 這樣就能得到輸入的圖片能被分爲哪一類的結果了.
我們截取一段 google 介紹卷積神經網絡的視頻, 具體說說圖片是如何被卷積的. 下面是一張貓的圖片, 圖片有長, 寬, 高 三個參數. 對! 圖片是有高度的! 這裏的高指的是計算機用於產生顏色使用的信息. 如果是黑白照片的話, 高的單位就只有1, 如果是彩色照片, 就可能有紅綠藍三種顏色的信息, 這時的高度爲3. 我們以彩色照片爲例子. 過濾器就是影像中不斷移動的東西, 他不斷在圖片收集小批小批的像素塊, 收集完所有信息後, 輸出的值, 我們可以理解成是一個高度更高,長和寬更小的”圖片”. 這個圖片裏就能包含一些邊緣信息. 然後以同樣的步驟再進行多次卷積, 將圖片的長寬再壓縮, 高度再增加, 就有了對輸入圖片更深的理解. 將壓縮,增高的信息嵌套在普通的分類神經層上,我們就能對這種圖片進行分類了.
池化
研究發現, 在每一次卷積的時候, 神經層可能會無意地丟失一些信息. 這時, 池化 (pooling) 就可以很好地解決這一問題. 而且池化是一個篩選過濾的過程, 能將 layer 中有用的信息篩選出來, 給下一個層分析. 同時也減輕了神經網絡的計算負擔具體細節參考. 也就是說在卷集的時候, 我們不壓縮長寬, 儘量地保留更多信息, 壓縮的工作就交給池化了,這樣的一項附加工作能夠很有效的提高準確性. 有了這些技術,我們就可以搭建一個屬於我們自己的卷積神經網絡啦.
流行的 CNN 結構
比較流行的一種搭建結構是這樣, 從下到上的順序, 首先是輸入的圖片(image), 經過一層卷積層 (convolution), 然後在用池化(pooling)方式處理卷積的信息, 這裏使用的是 max pooling 的方式. 然後在經過一次同樣的處理, 把得到的第二次處理的信息傳入兩層全連接的神經層 (fully connected),這也是一般的兩層神經網絡層,最後在接上一個分類器(classifier)進行分類預測. 這僅僅是對卷積神經網絡在圖片處理上一次簡單的介紹.
5.5 CNN1
卷積神經網絡包含輸入層、隱藏層和輸出層,隱藏層又包含卷積層和pooling層,圖像輸入到卷積神經網絡後通過卷積來不斷的提取特徵,每提取一個特徵就會增加一個feature map,所以會看到視頻教程中的立方體不斷的增加厚度,那麼爲什麼厚度增加了但是卻越來越瘦了呢,哈哈這就是pooling層的作用嘍,pooling層也就是下采樣,通常採用的是最大值pooling和平均值pooling,因爲參數太多嘍,所以通過pooling來稀疏參數,使我們的網絡不至於太複雜。
5.6 CNN2
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets('MNIST_data',one_hot=True)
def compute_accuracy(v_xs, v_ys):
pass
def weight_variable(shape):
# stddev(standard deviation)
initail = tf.truncted_normal(shape,stddev=0.1)
return tf.Variable(initail)
def bias_variable(shape):
initial=tf.constant(0.1,shape=shape)
return tf.Variable(initial)
def conv2d(x,W):
# stride[1, x_movement, y_movement, 1]
# Must have strides[0] = strides[4] = 1
return tf.nn.conv2d(x,W,strides=[1,1,1,1], padding='SAME')
def max_poo_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
5.7 CNN3
from __future__ import print_function
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# number 1 to 10 data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
def compute_accuracy(v_xs, v_ys):
global prediction
y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1})
correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1})
return result
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
# stride [1, x_movement, y_movement, 1]
# Must have strides[0] = strides[3] = 1
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
# stride [1, x_movement, y_movement, 1]
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# define placeholder for inputs to network
xs = tf.placeholder(tf.float32, [None, 784])/255. # 28x28
ys = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)
x_image = tf.reshape(xs, [-1, 28, 28, 1])
# print(x_image.shape) # [n_samples, 28,28,1]
## conv1 layer ##
W_conv1 = weight_variable([5,5, 1,32]) # patch 5x5, in size 1, out size 32
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # output size 28x28x32
h_pool1 = max_pool_2x2(h_conv1) # output size 14x14x32
## conv2 layer ##
W_conv2 = weight_variable([5,5, 32, 64]) # patch 5x5, in size 32, out size 64
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) # output size 14x14x64
h_pool2 = max_pool_2x2(h_conv2) # output size 7x7x64
## fc1 layer ##
W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
# [n_samples, 7, 7, 64] ->> [n_samples, 7*7*64]
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
## fc2 layer ##
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
# the error between prediction and real data
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1])) # loss
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
sess = tf.Session()
# important step
# tf.initialize_all_variables() no long valid from
# 2017-03-02 if using tensorflow >= 0.12
if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
init = tf.initialize_all_variables()
else:
init = tf.global_variables_initializer()
sess.run(init)
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
if i % 50 == 0:
print(compute_accuracy(
mnist.test.images[:1000], mnist.test.labels[:1000]))
5.8 saver
目前不知道幹啥用
from __future__ import print_function
import tensorflow as tf
import numpy as np
# Save to file
# remember to define the same dtype and shape when restore
# W = tf.Variable([[1, 2, 3],[3, 4, 5]], dtype=tf.float32, name='weights')
# b = tf.Variable([[1, 2, 3]], dtype=tf.float32, name='biases')
# tf.initialize_all_variables() no long valid from
# 2017-03-02 if using tensorflow >= 0.12
# if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
# init = tf.initialize_all_variables()
# else:
# init = tf.global_variables_initializer()
#
# saver = tf.train.Saver()
#
# with tf.Session() as sess:
# sess.run(init)
# save_path = saver.save(sess, "5/my_net/save_net.ckpt")
# print("Save to path: ", save_path)
################################################
# restore variables
# redefine the same shape and same type for your variables
W = tf.Variable(np.arange(6).reshape((2, 3)), dtype=tf.float32, name="weights")
b = tf.Variable(np.arange(3).reshape((1, 3)), dtype=tf.float32, name="biases")
# not need init step
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, "5/my_net/save_net.ckpt")
print("weights:", sess.run(W))
print("biases:", sess.run(b))