分類問題屬於機器學習問題的類別,其中給定一組特徵,任務是預測離散值。分類問題的一些常見示例是,預測腫瘤是否爲癌症,或者學生是否可能經過考試。在本文中,鑑於銀行客戶的某些特徵,咱們將預測客戶在6個月後是否可能離開銀行。客戶離開組織的現象也稱爲客戶流失。所以,咱們的任務是根據各類客戶特徵預測客戶流失。python
$ pip install pytorch
讓咱們將所需的庫和數據集導入到咱們的Python應用程序中:web
import torch import torch.nn as nn import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline
咱們可使用pandas
庫的read_csv()
方法來導入包含咱們的數據集的CSV文件。數組
dataset = pd.read_csv(r'E:Datasetscustomer_data.csv')
讓咱們輸出數據集 :網絡
dataset.shape
輸出:python爬蟲
(10000, 14)
輸出顯示該數據集具備1萬條記錄和14列。咱們可使用head()
數據框的方法來輸出數據集的前五行。機器學習
dataset.head()
輸出:函數
您能夠在咱們的數據集中看到14列。根據前13列,咱們的任務是預測第14列的值,即Exited
。性能
讓咱們對數據集進行一些探索性數據分析。咱們將首先預測6個月後實際離開銀行並使用餅圖進行可視化的客戶比例。讓咱們首先增長圖形的默認繪圖大小:學習
fig_size = plt.rcParams["figure.figsize"] fig_size[0] = 10 fig_size[1] = 8 plt.rcParams["figure.figsize"] = fig_size
如下腳本繪製該Exited
列的餅圖。測試
dataset.Exited.value_counts().plot(kind='pie', autopct='%1.0f%%', colors=['skyblue', 'orange'], explode=(0.05, 0.05))
輸出:
輸出顯示,在咱們的數據集中,有20%的客戶離開了銀行。這裏1表明客戶離開銀行的狀況,0表明客戶沒有離開銀行的狀況。讓咱們繪製數據集中全部地理位置的客戶數量:
輸出顯示,幾乎一半的客戶來自法國,而西班牙和德國的客戶比例分別爲25%。
如今,讓咱們繪製來自每一個惟一地理位置的客戶數量以及客戶流失信息。咱們可使用庫中的countplot()
函數seaborn
來執行此操做。
輸出顯示,儘管法國客戶總數是西班牙和德國客戶總數的兩倍,但法國和德國客戶離開銀行的客戶比例是相同的。一樣,德國和西班牙客戶的總數相同,可是離開銀行的德國客戶數量是西班牙客戶的兩倍,這代表德國客戶在6個月後離開銀行的可能性更大。
在訓練PyTorch模型以前,咱們須要預處理數據。若是查看數據集,您將看到它具備兩種類型的列:數值列和分類列。數字列包含數字信息。CreditScore
,Balance
,Age
等。相似地,Geography
和Gender
是分類列,由於它們含有分類信息,如客戶的位置和性別。有幾列能夠視爲數字列和類別列。例如,該HasCrCard
列的值能夠爲1或0。可是,那HasCrCard
列包含有關客戶是否擁有信用卡的信息。
讓咱們再次輸出數據集中的全部列,並找出哪些列能夠視爲數字列,哪些列應該視爲類別列。columns
數據框的屬性顯示全部列名稱:
Index(['RowNumber', 'CustomerId', 'Surname', 'CreditScore', 'Geography', 'Gender', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard', 'IsActiveMember', 'EstimatedSalary', 'Exited'], dtype='object')
從咱們的數據列,咱們將不使用的RowNumber
,CustomerId
以及Surname
列,由於這些列的值是徹底隨機的,並與輸出無關。例如,客戶的姓氏對客戶是否離開銀行沒有影響。其中列的其他部分,Geography
,Gender
,HasCrCard
,和IsActiveMember
列能夠被視爲類別列。讓咱們建立這些列的列表: 除該列外,其他全部列都可視爲數字列。
numerical_columns = ['CreditScore', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'EstimatedSalary']
最後,輸出(Exited
列中的值)存儲在outputs
變量中。
咱們已經建立了分類,數字和輸出列的列表。可是,目前,分類列的類型不是分類的。您可使用如下腳本檢查數據集中全部列的類型:
輸出:
RowNumber int64 CustomerId int64 Surname object CreditScore int64 Geography object Gender object Age int64 Tenure int64 Balance float64 NumOfProducts int64 HasCrCard int64 IsActiveMember int64 EstimatedSalary float64 Exited int64 dtype: object
您能夠看到Geography
和Gender
列的類型是object,HasCrCard
和IsActive
列的類型是int64。咱們須要將分類列的類型轉換爲category
。咱們可使用astype()
函數來作到這一點,
如今,若是再次繪製數據集中各列的類型,您將看到如下結果:
輸出量
RowNumber int64 CustomerId int64 Surname object CreditScore int64 Geography category Gender category Age int64 Tenure int64 Balance float64 NumOfProducts int64 HasCrCard category IsActiveMember category EstimatedSalary float64 Exited int64 dtype: object
如今讓咱們查看Geography
列中的全部類別:
Index(['France', 'Germany', 'Spain'], dtype='object')
當您將列的數據類型更改成類別時,該列中的每一個類別都會分配一個惟一的代碼。例如,讓咱們繪製列的前五行,Geography
並輸出前五行的代碼值:
輸出:
0 France 1 Spain 2 France 3 France 4 Spain Name: Geography, dtype: category Categories (3, object): [France, Germany, Spain]
如下腳本在該列的前五行中繪製了值的代碼Geography
:
輸出:
0 0 1 2 2 0 3 0 4 2 dtype: int8
輸出顯示法國已編碼爲0,西班牙已編碼爲2。
將分類列與數字列分開的基本目的是,能夠將數字列中的值直接輸入到神經網絡中。可是,必須首先將類別列的值轉換爲數字類型。分類列中的值的編碼部分地解決了分類列的數值轉換的任務。
因爲咱們將使用PyTorch進行模型訓練,所以須要將分類列和數值列轉換爲張量。首先讓咱們將分類列轉換爲張量。在PyTorch中,能夠經過numpy數組建立張量。咱們將首先將四個分類列中的數據轉換爲numpy數組,而後將全部列水平堆疊,如如下腳本所示:
geo = dataset['Geography'].cat.codes.values ...
上面的腳本輸出分類列中前十條記錄。輸出以下:輸出:
array([[0, 0, 1, 1], [2, 0, 0, 1], [0, 0, 1, 0], [0, 0, 0, 0], [2, 0, 1, 1], [2, 1, 1, 0], [0, 1, 1, 1], [1, 0, 1, 0], [0, 1, 0, 1], [0, 1, 1, 1]], dtype=int8)
如今要從上述numpy數組建立張量,您只需將數組傳遞給模塊的tensor
類torch
。
輸出:
tensor([[0, 0, 1, 1], [2, 0, 0, 1], [0, 0, 1, 0], [0, 0, 0, 0], [2, 0, 1, 1], [2, 1, 1, 0], [0, 1, 1, 1], [1, 0, 1, 0], [0, 1, 0, 1], [0, 1, 1, 1]])
在輸出中,您能夠看到類別數據的numpy數組如今已轉換爲tensor
對象。一樣,咱們能夠將數值列轉換爲張量:
numerical_data = np.stack([dataset[col].values for col in numerical_columns], 1) ...
輸出:
tensor([[6.1900e+02, 4.2000e+01, 2.0000e+00, 0.0000e+00, 1.0000e+00, 1.0135e+05], [6.0800e+02, 4.1000e+01, 1.0000e+00, 8.3808e+04, 1.0000e+00, 1.1254e+05], [5.0200e+02, 4.2000e+01, 8.0000e+00, 1.5966e+05, 3.0000e+00, 1.1393e+05], [6.9900e+02, 3.9000e+01, 1.0000e+00, 0.0000e+00, 2.0000e+00, 9.3827e+04], [8.5000e+02, 4.3000e+01, 2.0000e+00, 1.2551e+05, 1.0000e+00, 7.9084e+04]])
在輸出中,您能夠看到前五行,其中包含咱們數據集中六個數字列的值。最後一步是將輸出的numpy數組轉換爲tensor
對象。輸出:
tensor([1, 0, 1, 0, 0])
如今,讓咱們繪製分類數據,數值數據和相應輸出的形狀: 輸出:
torch.Size([10000, 4]) torch.Size([10000, 6]) torch.Size([10000])
在訓練模型以前,有一個很是重要的步驟。咱們將分類列轉換爲數值,其中惟一值由單個整數表示。例如,在該Geography
列中,咱們看到法國用0表示,德國用1表示。咱們可使用這些值來訓練咱們的模型。可是,更好的方法是以N維向量的形式表示分類列中的值,而不是單個整數。
咱們須要爲全部分類列定義矢量大小。關於維數沒有嚴格的規定。定義列的嵌入大小的一個好的經驗法則是將列中惟一值的數量除以2(但不超過50)。例如,對於該Geography
列,惟一值的數量爲3。該Geography
列的相應嵌入大小將爲3/2 = 1.5 = 2(四捨五入)。如下腳本建立一個元組,其中包含全部類別列的惟一值數量和維度大小:
categorical_column_sizes = [len(dataset[column].cat.categories) for column in categorical_columns] ...
輸出:
[(3, 2), (2, 1), (2, 1), (2, 1)]
使用訓練數據對監督型深度學習模型(例如咱們在本文中開發的模型)進行訓練,並在測試數據集上評估模型的性能。所以,咱們須要將數據集分爲訓練集和測試集,如如下腳本所示:
total_records = 10000 ....
咱們的數據集中有1萬條記錄,其中80%的記錄(即8000條記錄)將用於訓練模型,而其他20%的記錄將用於評估模型的性能。注意,在上面的腳本中,分類和數字數據以及輸出已分爲訓練集和測試集。爲了驗證咱們已正確地將數據分爲訓練和測試集:
print(len(categorical_train_data)) print(len(numerical_train_data)) print(len(train_outputs)) print(len(categorical_test_data)) print(len(numerical_test_data)) print(len(test_outputs))
輸出:
8000 8000 8000 2000 2000 2000
咱們將數據分爲訓練集和測試集,如今是時候定義訓練模型了。爲此,咱們能夠定義一個名爲的類Model
,該類將用於訓練模型。看下面的腳本:
class Model(nn.Module): def __init__(self, embedding_size, num_numerical_cols, output_size, layers, p=0.4): super().__init__() self.all_embeddings = nn.ModuleList([nn.Embedding(ni, nf) for ni, nf in embedding_size]) self.embedding_dropout = nn.Dropout(p) self.batch_norm_num = nn.BatchNorm1d(num_numerical_cols) return x
接下來,要查找輸入層的大小,將類別列和數字列的數量加在一塊兒並存儲在input_size
變量中。以後,for
循環迭代,並將相應的層添加到all_layers
列表中。添加的層是:
Linear
:用於計算輸入和權重矩陣之間的點積ReLu
:用做激活函數BatchNorm1d
:用於對數字列應用批量歸一化Dropout
:用於避免過擬合在後for
循環中,輸出層被附加到的層的列表。因爲咱們但願神經網絡中的全部層都按順序執行,所以將層列表傳遞給nn.Sequential
該類。
接下來,在該forward
方法中,將類別列和數字列都做爲輸入傳遞。類別列的嵌入在如下幾行中進行。
`embeddings = []
...`
數字列的批量歸一化可經過如下腳本應用:
x_numerical = self.batch_norm_num(x_numerical)
最後,將嵌入的分類列x
和數字列x_numerical
鏈接在一塊兒,並傳遞給sequence layers
。
要訓練模型,首先咱們必須建立Model
在上一節中定義的類的對象。
您能夠看到咱們傳遞了分類列的嵌入大小,數字列的數量,輸出大小(在咱們的例子中爲2)以及隱藏層中的神經元。您能夠看到咱們有三個分別具備200、100和50個神經元的隱藏層。
讓咱們輸出模型並查看:
print(model)
輸出:
Model( (all_embeddings): ModuleList( ... ) )
您能夠看到,在第一線性層中,in_features
變量的值爲11,由於咱們有6個數字列,而且類別列的嵌入維數之和爲5,所以6 + 5 = 11。out_features
的值爲2,由於咱們只有2個可能的輸出。
在實際訓練模型以前,咱們須要定義損失函數和將用於訓練模型的優化器。如下腳本定義了損失函數和優化器:
loss_function = nn.CrossEntropyLoss()
如今,咱們訓練模型。如下腳本訓練模型:
epochs = 300 aggregated_losses = [] for i in range(epochs): print(f'epoch: {i:3} loss: {single_loss.item():10.10f}')
神經元元數設置爲300,這意味着要訓練模型,完整的數據集將使用300次。for
爲每次迭代期間循環的執行方式,損失是使用損耗函數來計算。每次迭代過程當中的損失將添加到aggregated_loss
列表中。
上面腳本的輸出以下:
`epoch: 1 loss: 0.71847951
epoch: 26 loss: 0.57145703
epoch: 51 loss: 0.48110831
epoch: 76 loss: 0.42529839
epoch: 101 loss: 0.39972275
epoch: 126 loss: 0.37837571
epoch: 151 loss: 0.37133673
epoch: 176 loss: 0.36773482
epoch: 201 loss: 0.36305946
epoch: 226 loss: 0.36079505
epoch: 251 loss: 0.35350436
epoch: 276 loss: 0.35540250
epoch: 300 loss: 0.3465710580`
如下腳本繪製了各個時期的損失函數:
`plt.plot(range(epochs), aggregated_losses)
plt.ylabel('Loss')
plt.xlabel('epoch');`
輸出:
輸出顯示,最初損失函數迅速下降。在250個步長以後,損失幾乎沒有減小。
最後一步是對測試數據進行預測。爲此,咱們只須要將categorical_test_data
和numerical_test_data
傳遞給model
該類。而後能夠將返回的值與實際測試輸出值進行比較。如下腳本對測試類進行預測,並輸出測試數據的交叉熵損失。
with torch.no_grad(): ...
輸出:
Loss: 0.36855841
測試集上的損失爲0.3685,比訓練集上得到的0.3465略多,這代表咱們的模型有些過擬合。因爲咱們指定輸出層將包含2個神經元,所以每一個預測將包含2個值。例如,前5個預測值以下所示:
print(y_val[:5])
輸出:
tensor([[ 1.2045, -1.3857], [ 1.3911, -1.5957], [ 1.2781, -1.3598], [ 0.6261, -0.5429], [ 2.5430, -1.9991]])
這種預測的思想是,若是實際輸出爲0,則索引0處的值應大於索引1處的值,反之亦然。咱們可使用如下腳本檢索列表中最大值的索引:
y_val = np.argmax(y_val, axis=1)
輸出:如今讓咱們再次輸出y_val
列表的前五個值:
print(y_val[:5])
輸出:
tensor([0, 0, 0, 0, 0])
因爲在最初預測的輸出列表中,對於前五個記錄,零索引處的值大於第一索引處的值,所以能夠在已處理輸出的前五行中看到0。
最後,咱們可使用從sklearn.metrics
模塊confusion_matrix
,accuracy_score
以及classification_report
類找到了準確度,精密度和召回值,混淆矩陣。
`from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
print(confusion_matrix(test_outputs,y_val))
print(classification_report(test_outputs,y_val))
print(accuracy_score(test_outputs, y_val))`
輸出:
`[[1527 83]
[ 224 166]]
precision recall f1-score support 0 0.87 0.95 0.91 1610 1 0.67 0.43 0.52 390
micro avg 0.85 0.85 0.85 2000
macro avg 0.77 0.69 0.71 2000
weighted avg 0.83 0.85 0.83 2000
0.8465`
輸出結果代表,咱們的模型達到了84.65%的精度,考慮到咱們隨機選擇神經網絡模型的全部參數這一事實,這很是使人印象深入。我建議您嘗試更改模型參數,例如訓練/測試比例,隱藏層的數量和大小等,以查看是否能夠得到更好的結果。
PyTorch是Facebook開發的經常使用深度學習庫,可用於各類任務,例如分類,迴歸和聚類。本文介紹瞭如何使用PyTorch庫對錶格數據進行分類。
最受歡迎的看法
3.r語言文本挖掘tf-idf主題建模,情感分析n-gram建模研究
4.python主題建模可視化lda和t-sne交互式可視化