從零開始使用TensorFlow創建簡單的邏輯迴歸模型

TensorFlow 是一個基於 python 的機器學習框架。在 Coursera 上學習了邏輯迴歸的課程內容後,想把在 MATLAB 中實現了的內容用 TensorFlow 從新實現一遍,當作學習 Python 和框架的敲門磚。python

目標讀者

知道邏輯迴歸是什麼,懂一點 Python,據說過 TensorFlowwindows

數據集

來自 Coursera 上 Andrew 的機器學習課程中的ex2data1.txt,根據學生的兩次考試成績判斷該學生是否會被錄取。數組

環境

Python 2.7 - 3.xsession

pandas, matplotlib, numpyapp

安裝 TensorFlow

在本身的電腦上安裝 TensorFlow 框架,安裝方法過程不贅述,CPU 版相對更容易一點,GPU 版須要 CUDA 支持,各位看官看狀況安裝就好。框架

開始

建立一個文件夾(好比就叫作tensorflow),在文件夾中建立一個 Python 文件main.py,並將數據集文件放到這個文件夾下:機器學習

建立目錄結構

數據形式:函數

數據截圖

前兩列分別爲兩次考試成績(x1, x2),最後一列爲是否被錄取(y),1表明被錄取,0則反之。學習

在源文件main.py中,咱們首先引入須要的包:優化

import pandas as pd                # 用於讀取數據文件
import tensorflow as tf
import matplotlib.pyplot as plt    # 用於畫圖
import numpy as np                 # 用於後續計算

pandas是一個數據處理相關的包,能夠對數據集進行讀取和其餘各類操做;matplotlib能夠用來把咱們的數據集繪成圖表展現出來。

接着咱們將數據集文件讀入程序,用於後面的訓練:

# 讀取數據文件
df = pd.read_csv("ex2data1.txt", header=None)
train_data = df.values

pandas函數read_csv能夠將 csv(comma-separated values)文件中的數據讀入df變量,經過df.values將 DataFrame 轉化爲二維數組:

有了數據以後,咱們須要將特徵(x1, x2)和標籤(y)分別放到兩個變量中,以便在訓練中代入公式:

# 分離特徵和標籤,並獲取數據維數
train_X = train_data[:, :-1]
train_y = train_data[:, -1:]
feature_num = len(train_X[0])
sample_num = len(train_X)
print("Size of train_X: {}x{}".format(sample_num, feature_num))
print("Size of train_y: {}x{}".format(len(train_y), len(train_y[0])))

能夠看到,咱們的數據集中有100條樣例,每條樣例的特徵數量爲2。

TensorFlow 模型設計

在邏輯迴歸中,咱們使用的預測函數(Hypothesis)爲:

$$
h_θ(x) = sigmoid(XW + b)
$$

其中,sigmoid是一個激活函數,在這裏表示學生被錄取的機率:

$$
P(y = 1 | x, \theta)
$$

這個函數的形狀請自行百度

Wb 是咱們接下來的學習目標,W 爲權值矩陣(Weights),b 爲偏置量(Bias,體如今圖像上又叫截距)。

咱們使用的損失函數爲:

$$
J(θ) = -\frac{1}{m} \left[ \sum_{i=1}^m y^{(i)}\log(h_\theta(x^{(i)})) + (1 - y^{(i)})\log(1 - h_\theta(x^{(i)})) \right]
$$

因爲咱們的數據集只有兩個特徵,所以不用擔憂過擬合,因此損失函數裏的正規化項就不要了?。

首先咱們用 TensorFlow 定義兩個變量用來存放咱們的訓練用數據:

# 數據集
X = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)

這裏的X和y不是通常的變量,而是一個 placeholder(佔位符),意味着這兩個變量的值是未指定的,直到你開始訓練模型時才須要將給定的數據賦值給變量。

接着咱們再定義出咱們要訓練的 Wb

# 訓練目標
W = tf.Variable(tf.zeros([feature_num, 1]))
b = tf.Variable([-.9])

這裏他們的類型爲 Variable(變量),意味着這兩個變量將在訓練迭代的過程當中不斷地變化,最終取得咱們指望的值。能夠看到,咱們將 W 的初始值設爲了 feature_num 維的0向量,將 b 初始值設爲了 -0.9(隨便設的,不要介意?)

接下來咱們要用 TensorFlow 的方式將損失函數表達出來:

db = tf.matmul(X, tf.reshape(W, [-1, 1])) + b
hyp = tf.sigmoid(db)

cost0 = y * tf.log(hyp)
cost1 = (1 - y) * tf.log(1 - hyp)
cost = (cost0 + cost1) / -sample_num
loss = tf.reduce_sum(cost)

能夠看到,我表達損失函數是分三步進行的:先分別將求和內的兩部分表示出來,再將它們加和並和外面的常數m進行運算,最後對這個向量進行求和,便獲得了損失函數的值。

接下來,咱們要定義使用的優化方法:

optimizer = tf.train.GradientDescentOptimizer(0.001)
train = optimizer.minimize(loss)

其中,第一步是選取優化器,這裏咱們選擇梯度降低方法;第二步是優化目標,從函數名字顧名思義,咱們的優化目標是使得損失函數的值最小化。

注意:此處的學習率(0.001)應當儘量小,不然可能會出現損失計算中出現 log(0)的問題。

訓練

上面的工做作完以後,咱們就能夠開始訓練咱們的模型了。

在 TensorFlow 中,首先要將以前定義的Variable初始化:

init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

在這裏,咱們看到出現了一個tf.Session(),顧名思義是會話,即任務執行的主體。咱們上面定義了一堆東西,只是一個模型爲了獲得結果而須要的執行步驟和框架,一個相似流程圖的東西,光有流程圖還不夠,咱們須要一個主體來實際地運行它,這就是Session的做用。

----------特別提示----------

若是你是使用 GPU 版 TensorFlow 的話,而且你想在顯卡高佔用率的狀況下(好比玩遊戲)訓練模型,那你要注意在初始化 Session 的時候爲其分配固定數量的顯存,不然可能會在開始訓練的時候直接報錯退出:

2017-06-27 20:39:21.955486: E c:\tf_jenkins\home\workspace\release-win\m\windows-gpu\py\35\tensorflow\stream_executor\cuda\cuda_blas.cc:365] failed to create cublas handle: CUBLAS_STATUS_ALLOC_FAILED
Traceback (most recent call last):
  File "C:\Users\DYZ\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\client\session.py", line 1139, in _do_call
    return fn(*args)
  File "C:\Users\DYZ\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\client\session.py", line 1121, in _run_fn
    status, run_metadata)
  File "C:\Users\DYZ\Anaconda3\envs\tensorflow\lib\contextlib.py", line 66, in __exit__
    next(self.gen)
  File "C:\Users\DYZ\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\errors_impl.py", line 466, in raise_exception_on_not_ok_status
    pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.InternalError: Blas GEMV launch failed:  m=2, n=100
         [[Node: MatMul = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false, _device="/job:localhost/replica:0/task:0/gpu:0"](_arg_Placeholder_0_0/_3, Reshape)]]

這時你須要用下面的方法建立 Session

gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))

這裏的0.333就是佔你總顯存的份額。

----------End 特別提示----------

下面就是用咱們的數據集來對模型進行訓練了:

feed_dict = {X: train_X, y: train_y}

for step in range(1000000):
    sess.run(train, {X: train_X, y: train_y})
    if step % 100 == 0:
        print(step, sess.run(W).flatten(), sess.run(b).flatten())

首先講要傳入的數據存放到一個變量中,在訓練模型時傳入 sess.run();咱們進行 10000 次訓練,每隔 100
次輸出一次當前的目標參數 W, b

到這裏,訓練代碼的部分就完成了,你可使用你本身的 python 命令來運行了。若是你嚴格按照上面的代碼作了,不出現錯誤,你如今應該能夠看到控制檯裏已經開始不斷輸出訓練狀態了:

訓練過程

圖形化表示結果

當訓練結束後,你能夠獲得一個 W,和一個 b,這樣咱們能夠將數據集和擬合的結果經過圖表直觀地展示出來。

就在寫做的過程當中,我用上面的代碼訓練出了一個結果:

訓練結果

咱們將其直接寫入代碼,即:

w = [0.12888144, 0.12310864]
b = -15.47322273

下面咱們先將數據集表示在圖表上(x1爲橫軸,x2爲縱軸):

x1 = train_data[:, 0]
x2 = train_data[:, 1]
y = train_data[:, -1:]

for x1p, x2p, yp in zip(x1, x2, y):
    if yp == 0:
        plt.scatter(x1p, x2p, marker='x', c='r')
    else:
        plt.scatter(x1p, x2p, marker='o', c='g')

其中,咱們用 紅色的x 表明 沒有被錄取,用 綠色的o 表明 被錄取

其次咱們將訓練得出的決策邊界 XW + b = 0 表示到圖表上:

# 根據參數獲得直線
x = np.linspace(20, 100, 10)
y = []
for i in x:
    y.append((i * -w[1] - b) / w[0])
    
plt.plot(x, y)
plt.show()

此時,若是你的代碼沒錯的話,再次運行,你將獲得以下結果:

擬合結果

能夠看到,咱們經過訓練得出的參數劃出一條直線,很是合適地將兩種不一樣的數據樣例區分開來。

到此,一個完整的簡單的邏輯迴歸模型就實現完畢了,但願經過這篇文章,能讓各位看官對在 TensorFlow 中機器學習模型的實現有一個初步的瞭解。本人也在初步學習當中,若有不當之處歡迎在評論區拍磚,在實現以上代碼的過程當中若是遇到什麼問題也請在評論區隨意開火。

相關文章
相關標籤/搜索