1. 程式人生 > >使用TensorFlow實現邏輯迴歸(Titanic船員獲救專案實現)

使用TensorFlow實現邏輯迴歸(Titanic船員獲救專案實現)

        Titanic船員獲救問題是kaggle上一個很經典的機器學習練手專案,很適合機器學習入門階段拿來練手以熟悉機器學習相關流程和知識。本篇文章用來記錄本人學習TensorFlow時,用Titanic問題來練習的筆記。

        通常機器學習的常規流程可概括為三部曲:

        1.熟悉原始資料,並對原始資料進行預處理。比如對缺失值的處理、非數值型資料的處理等。

        2.從預處理完的資料中挑選特徵。挑選特徵是機器學習的關鍵,模型訓練的好壞和資料預處理以及特徵挑選有很大關係。 因此發展出了特徵工程這個領域,專門來“對付”特徵挑選。

        3.使用挑選好的特徵來訓練模型,並使用模型來預測測試集資料的結果。

        根據以上流程,我使用TensorFlow分為六步來實現邏輯迴歸來預測Titanic船員獲救資料。

1.資料讀入及預處理

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

#讀取訓練資料
data = pd.read_csv("data/train.csv")
#檢視資料情況
data.info()

#將Sex列資料轉換為1或0
data['Sex'] = data['Sex'].apply(lambda s : 1 if s == 'male' else 0)
#缺失欄位填充為0
data = data.fillna(0)
#選擇以下特徵用於分類
dataset_X = data[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]
dataset_X = dataset_X.as_matrix()

#兩種分類分別是倖存和死亡,‘Survived’欄位是其中一種分類的標籤
#新增加'Deceased'欄位表示第二種分類的標籤,取值為'Survived'取非
data['Deceased'] = data['Survived'].apply(lambda s : int(not s))
dataset_Y = data[['Deceased', 'Survived']]
dataset_Y = dataset_Y.as_matrix()
#在訓練資料中選擇20%資料用來進行測試
X_train, X_val, y_train, y_val = train_test_split(dataset_X, dataset_Y, test_size=0.2, random_state=1)

2.構建計算圖,採用邏輯迴歸進行構建


import tensorflow as tf
#宣告輸入資料佔位符
#shape引數的第一個元素為None,表示可以同時放入任意條記錄,每條記錄都有6個特徵
X = tf.placeholder(tf.float32, shape=[None, 6])
y = tf.placeholder(tf.float32, shape=[None, 2])

#宣告引數變數權重W和bias
W = tf.Variable(tf.random_normal([6, 2]), name='weights')
bias = tf.Variable(tf.zeros([2]), name='bias')

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

#代價函式
cross_entropy = -tf.reduce_sum(y * tf.log(y_pred + 1e-10), reduction_indices=1)
cost = tf.reduce_mean(cross_entropy)

#加入優化演算法:隨機梯度下降演算法
train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost)

3.構建訓練迭代過程

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    
    #以下為訓練迭代,迭代100輪
    for epoch in range(100):
        total_loss = 0.
        for i in range(len(X_train)):
            feed = {X: [X_train[i]], y: [y_train[i]]}
            #通過session.run介面觸發執行
            _, loss = sess.run([train_op, cost], feed_dict=feed)
            total_loss += loss
        print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
    print('Training complete!')
    
    #評估準確率
    pred = sess.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)

4.執行訓練

執行訓練的每個epoch結果如下:

Epoch: 0001, total loss=2978.986924756
Epoch: 0002, total loss=1233.613931798
Epoch: 0003, total loss=1433.674743123
Epoch: 0004, total loss=1425.632846644
Epoch: 0005, total loss=1413.414649527
Epoch: 0006, total loss=1401.179366778
Epoch: 0007, total loss=1389.302903898
Epoch: 0008, total loss=1377.886010977
.....
Epoch: 0099, total loss=1165.767331228
Epoch: 0100, total loss=1165.626431299
Training complete!
Accuracy on validation set: 0.687150836

通過以上執行結果可以看出100輪訓練取得的準確率為0.687150836,我將epoch改為1000次後再執行,結果如下:

Epoch: 0001, total loss=1869.781745049
Epoch: 0002, total loss=1208.829884079
Epoch: 0003, total loss=1131.160947576
Epoch: 0004, total loss=1136.071243536
Epoch: 0005, total loss=1069.703441266
Epoch: 0006, total loss=1072.349545262
Epoch: 0007, total loss=1069.528637791
Epoch: 0008, total loss=1069.168335461
......
Epoch: 0999, total loss=970.790128045
Epoch: 1000, total loss=965.400083950
Training complete!
Accuracy on validation set: 0.770949721

由以上訓練的epoch次數不同而最終準確率的不同,可以感受到訓練次數對準確率的影響。

5.儲存和載入模型引數

變數的儲存和讀取時通過tf.train.Saver類來完成的,Saver物件的save()方法用於儲存,restore()方法用於讀取。這裡將變數儲存在save目錄下modle.ckpt中。

# 存檔入口
saver = tf.train.Saver()

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    
    #以下為訓練迭代,迭代100輪
    for epoch in range(100):
        total_loss = 0.
        for i in range(len(X_train)):
            feed = {X: [X_train[i]], y: [y_train[i]]}
            #通過session.run介面觸發執行
            _, loss = sess.run([train_op, cost], feed_dict=feed)
            total_loss += loss
        print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
    print('Training complete!')
    
    #評估準確率
    pred = sess.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)
    #持久化儲存變數
    save_path = saver.save(sess, "save/model.ckpt")

6.使用模型對測試資料進行預測

Titanic問題是一個沒有獎金的比賽專案,那麼,訓練出的模型就需要在給出的測試資料上來進行預測,並將預測結果一.cvs檔案的形式上傳kaggle網站。

#讀入測試資料集並完成預處理, 
testdata = pd.read_csv('data/test.csv')
testdata = testdata.fillna(0)

testdata['Sex'] = testdata['Sex'].apply(lambda s: 1 if s== 'male' else 0)
X_test = testdata[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]

with tf.Session() as sess2:
    tf.global_variables_initializer().run()
    #載入模型存檔
    saver.restore(sess2, save_path)
    #正向傳播計算
    predictions = np.argmax(sess2.run(y_pred, feed_dict={X:X_test}), 1)

    #構建提交結果的資料結構,並將結果儲存為csv檔案
    submission = pd.DataFrame({
        "PassengerId": testdata["PassengerId"],
        "Survived": predictions
    })
    #將預測資料寫入titanic_submissioin.csv檔案中
    submission.to_csv("titanic_submission.csv", index=False)