Liz's Blog

Python學習筆記#22:深度學習之Tensorflow實作篇

| Comments

終於把這個課程完成了,由於Tensorflow變動很快,很多程式碼改變的很快,所以反而花很多時間在安裝環境、修改程式碼等,但往往學到最多也是遇到問題,找到解決方法時。所以之後,就是要找資料集來練習囉!

Udemy
課程名稱:Python for Data Science and Machine Learning Bootcamp
講師:Jose Portilla

Artificial neural networks可參考Wiki上文章,看完可以得到比較完整概論的知識。深度學習是一門很精深的學問,講師推薦可以再去閱讀MIT Deep LearningTensorflow是由Google Brain Team發展深度學習及人工智慧研究時發展出來,目前開放原始碼給大眾使用。

1.Tensorflow安裝(依照Tensorflow上不同安裝系統的安裝步驟進行)
我自己是macOS Sierra + Python 3.6 + Anaconda,以下紀錄我自己遇到的問題及解決方法。
(1)終端機:conda create -n tensorflow python=3.6.2
--在創造一個名叫tensorflow的conda環境

(2)終端機:source activate tensorflow
--活化tensorflow環境

(3)終端機:pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.4.0-py3-none-any.whl
--製造一個指令在conda環境中安裝tensorflow

(4)確認是否安裝成功,在tensorflow環境下終端機輸入:python
接著輸入以下指令,若回傳Hello, TensorFlow!,則代表成功:

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

(5)以上步驟都確認成功後,我在該環境下,輸入:jupyter notebook,想要用notebook跑tensorflow,卻不能載入tensorflow,爬了很久的文,找到這篇,才知道在tensorflow下是沒有我之前安裝的jupyter和ipython,相對的其他之前裝過的套件,像是SciKit Learn、Seaborn、Matplotlib都沒有,所以要自己再裝一次。

#進入到tensorflow環境中
source activate tensorflow

#查詢ipython在哪,應該會看到類似/Users/username/anaconda/bin/ipython
which ipython

#查詢jupyter在哪,應該會看到類似/Users/username/anaconda/bin/jupyter
which jupyter

#查詢python在哪,應該會看到類似/User/username//anaconda/envs/tensorflow/bin/python
which python

#查詢tensorflow下是沒有ipython & jupyter
ls /User/username/anaconda/envs/tensorflow/bin/

#因此在該環境下先安裝ipython & jupyter
conda install ipython
pip install jupyter

#結束後再查詢一次tensorflow就可以看到ipyhton & jupyter囉
ls /User/username/anaconda/envs/tensorflow/bin/

(6)進入jupyter notebook,載入tensorflow,可能會得到一個警告訊息(如下),似乎大家最近有在回報這樣問題,但好像還沒看到解決辦法,但我自己跑是暫時忽略還是可以動。
RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6 return f(args, *kwds)

2.Tensorflow基礎篇
(1)Simple Constant

#載入tensorflow套件
import tensorflow as tf

#建立一個簡單常數(TF會儲存為tensor object)
hello = tf.constant('Hello World')

#回傳object的型態
type(hello)                                 #tensorflow.python.framework.ops.Tensor

x = tf.constant(100)
x                                           #<tf.Tensor 'Const_2:0' shape=() dtype=int32>    
type(x)                                     #tensorflow.python.framework.ops.Tensor

(2)建立tensorflow的session(跑tensorflow運算),包含運算環境及被評估的tensor obeject

sess = tf.Session()
sess.run(hello)                             #b'Hello World'
sess.run(x)                                 #100
type(sess.run(x))                           #numpy.int32
type(sess.run(hello))                       #bytes

(3)Operations(運算):可在一個session組合好幾個tensorflow運算

x = tf.constant(2)
y = tf.constant(3)
with tf.Session() as sess:
    print('Operation with Constants')
    print('Addition: ',sess.run(x+y))
    print('Subtraction: ',sess.run(x-y))
    print('Multiplication: ',sess.run(x*y))
    print('Division: ',sess.run(x/y))
    
#由於手上不一定隨時就會有常數,可能會等到特定運算循環後才來建立常數。因此可以先使用tf.placeholder,之後再來修改
x = tf.placeholder(tf.int32)
y = tf.placeholder(tf.int32)

#先來建立基本運算
add = tf.add(x,y)
sub = tf.subtract(x,y)
mul = tf.multiply(x,y)

#設定不同變數
d = {x:20,y:30}

with tf.Session() as sess:
    print('Operation with Placeholder')
    print('addition',sess.run(add,feed_dict=d))
    print('Subtration',sess.run(sub,feed_dict=d))
    print('Multiplication',sess.run(mul,feed_dict=d))

(4)載入numpy來載入陣列,進行更複雜的運算

import numpy as np

#最好數字設定成小數點,因為int64會出現錯誤訊息
a = np.array([[5.0,5.0]])
b = np.array([[2.0],[2.0]])
a                                               #array([[ 5.,  5.]])

#a是一個1X2的陣列
a.shape                                         #(1, 2)

#b是一個2X1的陣列
b.shape                                         #(2, 1)

#設定tensorflow的constant
mat1 = tf.constant(a)
mat2 = tf.constant(b)

#矩陣乘法運算
matrix_multi = tf.matmul(mat1,mat2)

#跑session來呈現運算結果
with tf.Session() as sess:
    result = sess.run(matrix_multi)
    print(result)                               #[[ 20.]]

3.MNIST Multi-Layer Perceptron
(1)載入資料集

#載入tensorflow
import tensorflow as tf

#先載入資料集,利用Multi Layer Perceptron試著分類手寫數字
#資料集中的黑白圖片大小為28*28像素(784像素),特徵為像素值,數值可能白色(0)或其他數值
#目的為預測手寫數字的結果
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

(2)資料格式

#回傳object資料型態
type(mnist)

type(mnist.train.images)

#mnist.train.images是一個55000X784的陣列
mnist.train.images.shape

mnist.train.images[2]

#雖然是28*28像素的圖,但目前是展開成784個特徵,每個特徵有特定的像素值
mnist.train.images[2].shape

#將784改成28*28的陣列
sample = mnist.train.images[2].reshape(28,28)

(3)視覺化資料

#載入視覺化資料的套件
import matplotlib.pyplot as plt
%matplotlib inline

#載入圖形結果
plt.imshow(sample)

(4)參數設定對新資料集會是大的挑戰,但因為該資料集非常有名,所以已經有一些合理的參數可供設定

#learning_rate:多快調整cost function
learning_rate = 0.001

#training_epochs:多少訓練循環
training_epochs = 15

#batch_size:訓練資料的批次大小
batch_size = 100

(5)設定Neural Network的參數(取決於資料而設定)

#共0-9數字,有10個類別
n_classes = 10

#訓練組
n_sample =mnist.train.num_examples

#784個輸入值(28*28)
n_input = 784

#第一層特徵數
n_hidden_1 = 256

#第二層特徵樹
n_hidden_2 = 256

(6)MultiLayer Model
接受到輸入資料後,會送到第一層,接著會有權重產生,之後會送到節點來活化功能,並且可能伴隨著bias,這個練習中使用的是RELU(類似一種整流器,會輸出x或0)。接著再進入到下一層,重複相同過程直到輸出層。越多層會花費越多時間,但也有可能得到更精確的訓練資料。

一旦資料進入到輸出層,就必須要評估它。這邊使用loss function(或稱cost function)來評估距離想要的結果要多遠。在這個練習中為得到多少類別是正確的。

接著藉由調整weight來來最小化cost(或稱降低錯誤),在這個練習使用Adam Optimizer。也就是前面提到的learning rate參數,值越低,越有機會得到正確率高的訓練結果,但伴隨著時間也可能拉長,並且在一個時機點後,怎麼降低學習率也沒用。

#建立模型中所需的參數
def multilayer_perceptron(x, weights, biases):
    '''
    x : Place Holder for Data Input
    weights: Dictionary of weights
    biases: Dicitionary of biases
    '''
    
    #第一層(使用RELU活化)
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
    layer_1 = tf.nn.relu(layer_1)
    
    #第二層(使用RELU活化)
    layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
    layer_2 = tf.nn.relu(layer_2)
    
    #輸出層(使用線性活化)
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer
    
#使用tf.Variable來設定weights & biases,比起constant,variable是可修改的tensor,並且存在於Tensorflow互動運算的圖形中
#利用random_normal()來建立weights & biases的隨機值
weights = {
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}

biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_classes]))
}

#TensorFlow圖形輸入
x = tf.placeholder('float',[None,n_input])
y = tf.placeholder('float',[None,n_classes])

#建立模型
pred = multilayer_perceptron(x, weights, biases)

#利用tensorflow內建功能來設定loss(或稱cost)和optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

#使用next_batch()可回傳(X,y)。X代表資料陣列,y代表二元陣列中的類別
t = mnist.train.next_batch(1)
t[1]
Xsamp,ysamp = t

#轉成28*28陣列後輸出圖像結果
plt.imshow(Xsamp.reshape(28,28))
print(ysamp)

(7)跑session,有兩個循環,外層循環為跑epochs,內層循環則跑為每個epoch跑批次

#執行session
sess = tf.InteractiveSession()

#初始化前面用tf.Variable設定的變數
init = tf.global_variables_initializer()
sess.run(init)

#訓練epochs(盡可能停止前進行最多次循環,也可以在達到cost/loss上限則停止)
for epoch in range(training_epochs):

    #以cost=0為起始點
    avg_cost = 0.0

    #將所有批次數量轉成整數
    total_batch = int(n_sample/batch_size)

    #設定整個批次循環
    for i in range(total_batch):

        #取得訓練資料和標籤的批次
        batch_x, batch_y = mnist.train.next_batch(batch_size)

        #設定最佳化及loss的feed_dict
        #回傳tuple(c是cost)
        _, c = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y})

        #計算平均loss
        avg_cost += c / total_batch

    print("Epoch: {} cost={:.4f}".format(epoch+1,avg_cost))

print("Model has completed {} Epochs of Training".format(training_epochs))

(8)使用tensorflow內建的函式來評估模型

#tf.equal()要確認prediction == y_test
#在這個練習裡,我們已經知道預測的array是在0-9的位置,只有一個位置為1
#y在這裡還是等於一開始設定空的placeholder
correct_predictions = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
print(correct_predictions[0])

#為了取得預測的數字,所以使用tf.cast()來將布林值轉成float數字
correct_predictions = tf.cast(correct_predictions, 'float')
print(correct_predictions[0])

#利用tf.reduce_mean()來取得整個tensor元素的平均值
accuracy = tf.reduce_mean(correct_predictions)

#這時候accuracy還是Tensor Object
type(accuracy)

#呼叫測試的labels
mnist.test.labels[0]

#呼叫測試的圖片
mnist.test.images[0]

#eval()可以直接在session評估tensor,不用直接呼叫tf.sess
accuracy.eval({x:mnist.test.images,y:mnist.test.labels})

4.ContribLearn
前面用的是Multi-Layer Perceptron來跑,過程很繁複,但有人開發出ContribLearn,可以用類似SciKit Learn的介面來做,缺點是可供客製化的地方有限。

(1)載入有名的鳶尾花資料集

from sklearn.datasets import load_iris
import tensorflow as tf

iris = load_iris()
X = iris['data']
y = iris['target']
y.dtype

(2)將資料分成訓練組及測試組

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

(3)載入contrib.learn介面

import tensorflow.contrib.learn as learn

#使用DNNClassifier(Deep Neural Network)來做模型
feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(X_train)
 
classifier = tf.contrib.learn.DNNClassifier(
      feature_columns=feature_columns, hidden_units=[10, 20, 10], n_classes=3)

(4)載入metrics評估模型好壞

from sklearn import metrics

#建立模型
classifier.fit(X_train, y_train, steps=200)

#依照模型預測結果
predictions = list(classifier.predict(X_test, as_iterable=True))

#評估模型好壞
score = metrics.accuracy_score(y_test, predictions)
print('Accuracy: {0:f}'.format(score))

from sklearn.metrics import classification_report,confusion_matrix
print(classification_report(y_test,predictions))

Comments

comments powered by Disqus