1. 程式人生 > >深度學習原理與TensorFlow實踐1:以分類問題入門Tensorflow

深度學習原理與TensorFlow實踐1:以分類問題入門Tensorflow

一、問題描述

Titanic問題(具體問題可檢視Kaggle平臺)

根據已有資料預測每位乘客是否倖存。共包含12個欄位(或特徵)。

二、看做分類問題處理解決方案

1. 資料讀入及預處理(pandas、scikit-learn)

 *pandas可以讀入各種型別的資料,讀入的資料為DataFrame型別的物件。

首先需要選擇要選取的特徵維資料,如果有大量的特徵維,需要只留下某幾個重要的特徵。常用方法有:

(1)根據閾值過濾掉方差小的變數

(2)通過計算變數與標籤的相關係數,留下相關性高的特徵

(3)根據決策樹或隨機森林,選擇重要程度高的特徵

(4)利用PCA等,對資料進行變換,選擇區分度最高的特徵組合。

import pandas as pd
data = pd.read_csv('train.csv')
data.info() # 類似資料庫中檢視資料概況的操作,從info的顯示情況看,能夠看到資料的缺失值情況。
# 資料的準備、預處理
# 對於原先是數值型的內容,先不做處理,對於原先是物件型(字元型)的內容,進行數值的轉換。
# (1)Sex 將male轉換為0,female轉換為1
data['Sex'] = data['Sex'].apply(lambda s: 1 if s == 'male' else 0)
# (2)Age 缺失部分賦值為0
data = data.fillna(0)
# 實際上,缺失部分的補充要視情況而定,可以有四種情況
"""
(1)丟棄整行資料——樣本資料量足夠
(2)丟棄整列資料——缺失非常嚴重
(3)填充預設值(相當於將全部缺失值作為一類處理)
(4)填充平均值(弱化缺失值的影響)
"""
dataset_X = data[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare' ]]
dataset_X = dataset_X.as_matrix()
# 樣本的y需要轉換為one-hot表示
data['Deceased'] = data['Survived'].apply(lambda s : int (not s))
dataset_Y = data[['Deceased', 'Survived']]
dataset_Y = dataset_Y.as_matrix()
# 隨機打亂資料並按比例拆分,防止過擬合
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(dataset_X, dataset_Y, test_size = 0.2, random_state = 42) # random_state如果選擇相同的值,模型會得到一樣的結果。(是一個隨機的種子數)



2. 構建計算圖及訓練迭代過程

* 用作示例,使用最簡單的邏輯迴歸演算法進行分類。邏輯迴歸之前的博文中有講過,是wx+b的形式,之後進行一個softmax操作(其實就是一個標準化、歸一化的操作) W、b是要學習的引數。

# 用佔位符首先定義好x,y的形狀、儲存資料型別,None表示資料量可變
# 在佔位符中,可以加入name標籤,方便視覺化
# 在定義輸入x的形狀時,第一個維度一般是mini-batch維,從第二維才開始特徵維
x = tf.placeholder(tf.float32, shape = [None, 6])
y = tf.placeholder(tf.float32, shape = [None, 2])

# 使用變數定義引數
W = tf.Variable(tf.random_normal([6,2]), name = 'weights') # 剛開始隨機生成一組向量
b = tf.Variable(tf.zeros([2]), name = 'bias') # 預定義時b設為0

# 前向傳播計算圖
y_pred = tf.nn.softmax(tf.matmul(input, W) + bias)

# 優化目標 —— 此處選用交叉熵
cross_entropy = - tf.reduce_sum(y * tf.log(y_pred + 1e-10), reduction_indices = 1)# reduction _indices表示維度,為1表示最終的結果是一個1維的向量。 同時y_pred加入了一個小的誤差,當非常接近0或1時,避免因為輸出非法,無法計算梯度。
cost = tf.reduce_mean(cross_entropy) # 求所有樣本交叉熵的平均值
"""
誤差處理其實有三種辦法
(1)上例中,問題y_pred會超過1
(2)當y_pred接近0,就賦值為極小誤差值。y_pred始終控制在[10^-10, 1](使用clip函式)
(3)當出現nan值,就將cost設定為0,不改變y_pred
"""

# 優化演算法(此處使用梯度下降演算法)不同優化演算法在不同問題上有不同的收斂態度,在面向不同的任務需要多嘗試選擇。演算法最大的引數為學習率,不同學習率也有影響。
train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost)


# 訓練迭代過程(採用session,它能管理上下文各種資源)
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    # 迴圈迭代,迭代10次
    for epoch in range(10):
        total_loss = 0
        for i in range(len(X_train)):
            feed = {X : [X_train[i]], y_true : [y_train[i]]}
            _, loss = sess.run([train_op, cost], feed_dict = feed) # train_op是運算元(操作),cost是tensor,要返回值
            total_loss += loss
        print('Epoch: %04d, total loss = %.9f' % (epoch + 1, total_loss))
    print 'Training complete!'
    # 預測
    pred = sesss.run(y_pred, feed_dict = {X: X_val})
    correct = np.equal(np.argmax(pred, 1), np.argmax(y_val, 1))
    accuracy = np.mean(correct.astype(np.float32))
    print("Accuracy on validation set:%.9f" % accuracy)





3. 儲存和載入模型引數(tf.train.Saver和checkpoint機制)

v1 = tf.Variable(tf.zeros([200]))
saver = tf.train.Saver()  # 若不指定變數列表,saver只會預設處理宣告之前的變數。即v1會被處理,而v2不會。選擇性載入非常有用,可以只加載部分引數資料,例如如果要將圖片分類模型應用於一個不同領域,那麼只需要載入卷積層部分引數,在此基礎上重新訓練全連線層即可。
v2 = tf.Variable(tf.ones([100]))

with tf.Session() as sess1:
    # 模型定義、訓練

    # 變數儲存

save_path = saver.save(sess1, "model.ckpt")
"""
saver.save的儲存會生成四個檔案,
(1).ckpt檔案 真實儲存變數及其取值
(2).ckpt.meta 描述檔案
(3).ckpt.index 村粗變數在checkpoint檔案中的位置縮影
(4)checkpoint,儲存最新存檔的檔案路徑
"""
with tf.Session as sess2:
    # 載入變數
    saver.restore(sess2,"model.ckpt")
    # 預測

# 除這樣一次性儲存模型外,為方便監控迭代情況,可以在迭代中儲存
with tf.Session() as sess:
    for step in range(max_step):
        #執行計算
        saver.save(sess, 'my-mode.ckpt', global_step = step)

"""
為防止上述情況造成的由於迭代次數過多,造成儲存空間耗盡,有幾種解決方式
(1)max_to_keep引數,只保留最後幾個版本
(2)keep_checkpoint_every_n_hours引數,每n個小時儲存一個版本
"""

# 載入checkpoint:
# (1)利用字首,直接載入
# (2)載入最新版本
ckpt = tf.train.get_checkpoint_state(ckpt_dir)
if ckpt and ckpt.model_checkpoint_path:
    saver.restore(sess, ckpt.model_checkpoint_path)

4. 預測

testdata = pd.read_csv('data/test.csv')
testdata = testdata.fillna(0)
testdata['Sex'] = testdata['Sex'].apply(lambda s: 1 if s == 'male')
X_test = testdata[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]
with tf.Session() as sess:
    saver.restore(sess, 'model.ckpt')
    predictions = np.argmax(sess.run(y_pred, feed_dict = {X: X_test}))
    submission = pd.DataFrame({"PassengerId": testdata["PassengerId"], "Survived": p    redictions})
    submission.to_csv(titanic-submission.csv", index = false)