目標
本文的目標是解釋一個可用於構建基本LSTM模型的簡單代碼。我不會討論和分析結果。這只是爲了讓您開始編寫代碼。
設置環境
我將在本文中使用python編寫LSTM代碼。環境設置如下:
我建議您下載pycharm IDE並通過IDE將Tensorflow和所有其他庫下載到您的項目中。您可以按照以下步驟設置環境。
- 下載PyCharm IDE
- 創建一個項目
- 將Tensorflow,NumPy,SciPy,scikit-learn和Pandas下載到您的項目中。
- 在項目中創建一個新的python文件
如果您想手動創建環境,下面列出的是python和Tensorflow的兼容版本以及您需要遵循本文的所有其他庫。
注意:不要使用與提到的不同版本的python,因爲它可能與給定的Tensorflow版本不兼容。下載scikit-learn時,首先下載NumPy和SciPy軟件包。
- Python: 3.6.5
- Tensorflow: 1.9.0
- scikit-learn: 0.19.1
- Pip: 10.0.1
- NumPy: 1.14.3
- Pandas: 0.23.0
- SciPy: 1.1.0
我們到底下載了什麼?
- Tensorflow:這是一個機器學習框架。
- Pandas:這是一個有助於分析和輕鬆完成數據準備的庫。
- scikit-learn:這是一個機器學習庫,它具有各種機器學習算法,並且還執行必要的輔助函數。
- NumPy:這是一個可以在多維數組和矩陣上執行高級數學函數的庫。
- SciPy:這是一個用於科學計算和技術計算的庫。
- Pip:這是一個Python的包管理系統,可以安裝和管理用Python編寫的軟件包。
數據?
對於本文,我們將使用在kaggle上發佈的信用卡欺詐數據集。我們將使用此數據集來訓練我們的LSTM模型,以便對交易是欺詐性交易還是正常交易進行分類。
您可以在此處(https://www.kaggle.com/mlg-ulb/creditcardfraud/version/2)獲取數據集表單的csv文件。下載後,將其放入項目中以方便使用。如果您可以在開始使用數據之前瀏覽數據並閱讀並理解每列數據所代表的內容,將會很有幫助。
注意:如果您在機器學習算法(如“隨機森林分類器”)上測試,此數據集將提供更好的分數,但我們可以使用此數據集作爲構建LSTM模型的起點。此外,您應該記住,此數據集具有非常高的類不平衡。
-
Python代碼
首先,讓我們導入所需Python庫。
-
import tensorflow as tf import pandas as pd import numpy as np from tensorflow.contrib import rnn from sklearn.model_selection import train_test_split from sklearn.metrics import f1_score, accuracy_score, recall_score, precision_score
現在,我們必須將所有數據加載到我們的程序中。我們可以使用Pandas來做到這一點
-
data = pd.read_csv('creditcard.csv', skiprows=[0], header=None)
上面的Python代碼將加載來自csv文件的所有數據,從而省略帶有標題的行,因此加載的數據現在看起來像這樣:
-
前5行數據
-
接下來,我們將加載的數據分成標籤和特徵。
- features = data.iloc[:, 1:30]
- labels = data.iloc[:, -1]
如果您瀏覽了信用卡數據,您會注意到其中有31列。第1行代碼將數據從第1列(第0列)加載到第30列,作爲“特徵”。
如kaggle所述,最後一列是指定交易是否存在欺詐行的列。因此,在第二行代碼中,我們將最後一列中的數據作爲標籤加載。
注意:我們正在排除第0列,因爲它只提供有關交易順序的信息,並沒有爲我們的訓練增加實際價值。我們可以根據數據的發生順序來保留數據的順序。
我們現在擁有標籤和特徵,我們需要將這些標籤和特徵劃分爲訓練集和測試集。我們可以使用scikit-learn的'train test split function'。
-
X_train,X_test,y_train,y_test = train_test_split(features, labels, test_size=0.2, shuffle=False, random_state=42)
此功能自動將特徵和標籤分爲測試和訓練集。“X_train”和“X_test”是特徵的訓練和測試集,“y_test”和“y_train”是標籤的訓練和測試集。參數“test_size”指定測試集應該是整個數據集的20%。“shuffle”參數指定在將數據拆分爲測試和訓練集之前是否應該對數據進行混洗。這裏我們將其設置爲false以保留事務的發生順序。我們使用“random_state”參數,以便每次運行此函數時獲得相同的輸出。
-
我們現在要指定我們的超參數
-
epochs = 8 n_classes = 1 n_units = 200 n_features = 29 batch_size = 35
- epochs:epochs對應於我們將通過模型運行數據集的迭代次數。
- n_classes:這對應於我們爲此分類所做的類的數量。在我們的例子中,我們有一個二元分類,如果它是正常的事務我們分配0,如果它是欺詐性事務則分配1。在一個非常基礎的層面,如果我們採用一列,我們可以非常容易地表示0和1的欺詐和正常交易。因此,我們可以將類的數量設爲1。
- n_units:這對應於LSTM隱藏狀態的大小(c和h)。
- n_features:如名稱所指定,這表示數據集中的特徵數。
- batch_size:這是指您要輸入模型的每批數據的大小。每批次將進行一次反向傳播。
- 接下來,我們將爲我們將要提供給機器學習模型的批數據定義place-holders。
xplaceholder= tf.placeholder('float',[None,n_features]) yplaceholder = tf.placeholder('float')
'xplaceholder'佔位符包含一批特徵數據,'yplaceholder'包含相應批次的標籤數據。'xplaceholder'的shape 已被指定爲(<batch_size>,n_features),因爲“None”值允許長度靈活到插入佔位符的長度,但是fed矩陣應該具有代碼中指定的相同數量的特徵。由於沒有爲'yplaceholder'明確指定shape,它將是一個向量,但它的長度將取決於送入佔位符的內容。在我們的例子中,y將是一個長度爲batch_size的向量。
我們已完成大部分準備工作,因此,我們現在將設計,訓練和測試我們的LSTM模型
def recurrent_neural_network_model(): layer ={ 'weights': tf.Variable(tf.random_normal([n_units, n_classes])),'bias': tf.Variable(tf.random_normal([n_classes]))} x = tf.split(xplaceholder, n_features, 1) print(x) lstm_cell = rnn.BasicLSTMCell(n_units) outputs, states = rnn.static_rnn(lstm_cell, x, dtype=tf.float32) output = tf.matmul(outputs[-1], layer['weights']) + layer['bias'] return output
讓我們理解代碼。我將首先解釋'recurrent_neural_network_model()'函數內部的代碼正在做什麼,逐行解釋Python代碼如下:
- 在這一行中,我們手動定義權重和偏差的shapes。我們分別使用shape[rnn_size,n_classes]和[n_classes]的隨機值賦予TensorFlow變量'weight'和'bias'。
- 現在我們將數據作爲序列分配給'x'。爲此,我們將特徵批處理沿着它的垂直維度(維度:1)分成29個切片,這是一個二維張量。每個切片是作爲LSTM層的輸入給出的序列的元素。(序列的一個元素的形狀將是:(<batch_size>,1))
- 然後我們正在創建LSTM層。該函數實例化所有門的變量。
- 'outputs'變量包含每個時間步長的LSTM層的所有輸出,'state'包含兩個隱藏狀態(h和c)的最後狀態的值。
- 這裏我們只使用'outputs [-1]'獲取LSTM層的最後一個輸出,並將它與先前定義的權重矩陣相乘,並將偏差值添加到它。結果值是前向傳播的logit值。
- 最後,我們將logit值返回給調用函數'train_neural_network()'。
def train_neural_network(): #1 logit = recurrent_neural_network_model() logit = tf.reshape(logit, [-1]) #3 cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logit, labels=yplaceholder)) optimizer = tf.train.AdamOptimizer().minimize(cost) with tf.Session() as sess: #6 tf.global_variables_initializer().run() tf.local_variables_initializer().run() #7 for epoch in range(epochs): epoch_loss = 0 #8 i = 0 for i in range(int(len(X_train) / batch_size)): #10 #11 start = i end = i + batch_size #13 batch_x = np.array(X_train[start:end]) batch_y = np.array(y_train[start:end]) #15 _, c = sess.run([optimizer, cost], feed_dict={xplaceholder: batch_x, yplaceholder: batch_y}) epoch_loss += c i += batch_size #18 print('Epoch', epoch, 'completed out of', epochs, 'loss:', epoch_loss) pred = tf.round(tf.nn.sigmoid(logit)).eval({xplaceholder: np.array(X_test), yplaceholder: np.array(y_test)}) #20 f1 = f1_score(np.array(y_test), pred, average='macro') accuracy=accuracy_score(np.array(y_test), pred) recall = recall_score(y_true=np.array(y_test), y_pred= pred) precision = precision_score(y_true=np.array(y_test), y_pred=pred) #24 print("F1 Score:", f1) print("Accuracy Score:",accuracy) print("Recall:", recall) print("Precision:", precision) train_neural_network()
現在讓我們瞭解'train_neural_network()'函數中的代碼是做什麼的,逐行解釋Python代碼如下:
- 1.這裏我們將接收的logit值分配給變量。logit值是激活的倒數。
- 2.然後我們將矩陣重reshaping 爲一個向量,因爲當將它提供給損失函數時,標籤的shape和logits 應該相等。
- 3.我們在這裏定義了損失函數。使用“sigmoid_cross_entropy_with_logits”函數是因爲我們正在進行二元分類。如果這是一個多類分類,我們應該使用像'softmax_cross_entropy_with_logits'這樣的損失函數。
- 4.我們使用“AdamOptimizer()”優化器,因爲它具有相當好的性能。
-
直到這一點,我們討論的所有代碼都不在Tensorflow會話中。從這裏開始,所有討論的代碼都將在TensorFlow會話中。
在調用“train_neural_network()”以啓動程序之後,Tensorflow會話的起點將是執行開始的位置。
我們正在初始化到目前爲止我們已聲明的所有全局變量。
- 6.然後我們正在初始化項目中的所有局部變量。
- 7.在這裏,我們定義一個循環,直到滿足我們定義的迭代次數(epoch)。
- 8.在每個epoch開始時將epoch loss重置爲0。
- 9.定義變量以在將數據拆分爲批次時跟蹤開始和結束計算
- 10.在這裏,我們再次定義一個循環,直到batches 達到計算閾值爲止。
- 11.和12.我們使用'start'和'end'變量來跟蹤數據在每次迭代中的分割位置。
- 13.和14.在每次迭代中,將分別爲“batch_x”和“batch_y”變量分配一批特徵和標籤。
- 15.在這一行中,我們告訴Tensorflow運行必要的子圖來計算優化器和成本,方法是將'batch_x'和'batch_y'變量中的值提供給前面提到的佔位符。結果,將計算優化器的值和成本,並分別分配給“throw-away”變量和“c”變量。
- 16.當前批處理的損失將添加到“epoch_loss”變量中。
- 17.此行有助於遍歷每批數據(特徵和標籤)。
- 18.打印那個epoch的總損失
-
到目前爲止我們討論的是模型的訓練方面。訓練將持續到epochs數達到閾值。
接下來的幾行代碼用於測試模型。
注意:理想情況下,我們將數據集劃分爲3組,即訓練,驗證和測試。我們將保留測試集並使用驗證集來查看模型的性能並更改超參數以實現更好的性能。當我們認爲模型已經足夠改進時,我們只會採用測試集來了解模型的表現。對於本文,我們只使用了兩套訓練集和測試集來保持簡單。
- 19.這是我們將測試數據集提供給模型並告訴Tensorflow運行計算logit所需的子圖的地方。然後我們通過sigmoid激活傳遞logit值來獲得預測。四捨五入該值以刪除預測值的小數位。
- 20.我們在這裏計算F1得分。F1 Score是Precision和Recall的加權平均值。您可以從這裏閱讀更多相關信息。
- 21.然後我們計算準確度分數。
- 22.這次召回正在計算中。召回是正確預測的陽性觀察與所有陽性觀察的比率。
- 23.我們也在計算精度。精確度是正確預測的陽性觀察值與總預測陽性觀察值的比率。
- 24.至27.打印出所有計算得分。
-
所以,我們終於完成了代碼。
我希望本文能幫助您瞭解使用Tensorflow構建基本LSTM的過程。請注意,此模型是一個非常基本的版本,是構建和改進的良好起點。