1. 程式人生 > >python資料探勘與入門實踐(2.1)用sciket-learn估計器分類

python資料探勘與入門實踐(2.1)用sciket-learn估計器分類

書中主要是用sciket-learn的近鄰演算法進行估計器分類。

準備工作:

         目標  ; -建立分類器,自動判別資料的好壞;

         資料集 :來自http://archive.ics.uci.edu/ml/machine-learning-databases/ionosphere/的資料ionosphere.data和ionosphere.names。將其儲存到使用者主目錄下的Data資料夾中;

          g/b  ; 這條資料屬於好/ 壞的一類

一、.載入資料集

%matplotlib  inline#將matplotlib的圖表直接鑲嵌在notebook中
import os
home_folder=os.path.expanduser("~")#當不知道Data資料夾具體所在的主目錄的時候,用os模組的這條程式碼輸出主目錄所在位置
print(home_folder)

程式碼結果為   C:\Users\Administrator

接著用Data資料夾路徑、資料集所在的資料夾名稱和資料集名稱組合成資料集檔案的完整路徑:data_folder:是Data資料夾中Ionosphere資料夾的路徑;ionosphere.data是資料集名稱。

data_folder = os.path.join(home_folder, "Data", "Ionosphere")
data_filename = os.path.join(data_folder, "ionosphere.data")
print(data_filename)#data_filename就是資料集檔案ionosphere.data的完整路徑

程式碼結果為:
C:\Users\Administrator\Data\Ionosphere\ionosphere.data

建立Numpy陣列X和y存放資料集。由於資料集大小已知,共有351行35列,我們建立的陣列X存放所有的數值資料,而判定的結果資料則放在陣列y中。故X共有351行,34列資料,而y有351行,1列資料。

import csv#匯入csv模組
import numpy as np

X = np.zeros((351, 34), dtype='float')
#建立一個shape屬性為(351,34),元素都為0的二維陣列,存放351條數值資料,每條數值資料共有34個,資料型別為浮點型
y = np.zeros((351,), dtype='bool')
#建立一個shape屬性為(351,)的一維陣列,其形式為[0. 0. ....0.],其中每個資料對應X中的每條資料的判定結果,原始資料集中用‘g'或者’b'來表示,這裡換成布林值型別

with open(data_filename, 'r') as input_file:
      reader = csv.reader(input_file)#用csv模組來匯入資料及檔案,並建立csv閱讀器物件
      for i, row in enumerate(reader):#遍歷檔案中的每一行資料
           data = [float(datum) for datum in row[:-1]]#將每一條資料中最後一個數據前面的34個值強制轉換成float型別
 # Set the appropriate row in our dataset
           X[i] = data#將每個索引i對應的轉換後的data資料賦值給陣列X中相應的每一行
 # 1 if the class is 'g', 0 otherwise
           y[i] = row[-1] == 'g'#將每一行最後的資料複製給陣列y,當row[-1]=='g'時,y[i]為'g',否則為False


我的程式碼在with open() as這一步總是出錯,所以我臨時換成用open來開啟檔案

datafile=open('/Users/Administrator/Desktop/ionosphere.data','r')
#剩下的步驟都一樣
reader = csv.reader(datafile)
for i, row in enumerate(reader):
     data = [float(datum) for datum in row[:-1]]
     X[i] = data
     y[i] = row[-1] == 'g'


這次沒有報錯

相關知識點:
1.with open()和open
http://ludaming.com/posts/Python/python-open-file.html 這個部落格講得很清楚
2.
for i,row in enumerate(reader)

enumerate函式用於遍歷序列中的元素及其下標:

eg1.

seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
    print (i, seq[i])

0 one
1 two
2 three

eg2.

seq = ['one', 'two', 'three']
for i, element in enumerate(seq,start=1):
    print (i,seq[i])
1 two
2 three

eg3.

for i,j in enumerate('abc'):
    print((i,j))

(0, 'a')
(1, 'b')
(2, 'c')

eg4.

import numpy as np
a=np.array( [ (1,2,3,4), (5,6,7,8),(9,10,11,12) ] )
for i, element in enumerate(a):
    print (i,element)
0 [1 2 3 4]
1 [5 6 7 8]
2 [ 9 10 11 12]

二、努力實現流程標準化

sciket-learn估計器由兩大函式組成:fit()和 predict()
用fit方法在訓練集上完成模型的建立,用predict方法在測試集上評估效果
首先,建立訓練集和測試集,平時常用from sklearn.cross_validation import train_test_split匯入並執行train_test_split函式:
train_test_split是交叉驗證中常用的函式,功能是從樣本中隨機地按比例選取train data資料和test data測試資料,構成訓練集和測試集,其形式為X_train, X_test, y_train, y_test = train_test_split(train_data, train_target, test_size=0.4,random_state=0)
引數解釋:train_data : 所要劃分的樣本特徵集;
          train_target : 所要劃分的樣本結果;
          test_size:樣本佔比,如果是整數,就是測試樣本的數量,即X_test裡的樣本數量;test_size值不同的情況下,得到的訓練集和測試集的樣本數量也不同,test_size為小於1的小數時,值越小,X_train的樣本數越多,X_test的樣本數越少;
          random_state :隨機數的種子;
          隨機數種子:其實就是該組隨機數的編號,在需要重複試驗的時候,保證得到一組一樣的隨機數,比如每次都填1,在其他引數一樣的情況下得到的隨機陣列是一樣的;但是填0或者不填,每次都會不一樣。隨機數的產生取決於種子,隨機數和種子之間得分關係遵從以下規則:種子不同,隨機數不同;種子相同,即使例項不同,隨機數也相同。

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=14)#所要劃分的樣本特徵集為X,所要劃分的樣本結果為y,由於沒有test_size引數,樣本全部進行劃分
print("There are {} samples in the training dataset".format(X_train.shape[0]))
print("There are {} samples in the testing dataset".format(X_test.shape[0]))
print("Each sample has {} features".format(X_train.shape[1]))
There are 263 samples in the training dataset
There are 88 samples in the testing dataset
Each sample has 34 features

最後用三個列印語句打印出訓練集的樣本數、測試集的樣本數和每個樣本的特徵值個數。匯入K近鄰分類器(KNN)這個類,併為其初始化一個例項。該演算法預設選擇5個近鄰作為分類依據;估計器建立好後,用訓練資料進行訓練。K近鄰分類器分析訓練集中的資料,比較待分類的新資料點和訓練集中的資料,找到新資料點的近鄰。

from sklearn.neighbors import KNeighborsClassifier
#匯入KNN分類樹的類KNeighborsClassifier;在scikit-learn 中,與近鄰法這一大類相關的類庫都在sklearn.neighbors包之中。
estimator = KNeighborsClassifier() #建立估計器
estimator.fit(X_train, y_train)#用訓練資料進行訓練
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')

接著,用測試集測試演算法,評估它在測試集上的表現。
y_predicted = estimator.predict(X_test)#對測試集X_test測試,88個測試樣本的評估結果True或者False
accuracy = np.mean(y_test == y_predicted) * 100#accuracy為精確度,比較測試集的測試結果和估計結果,
print("The accuracy is {0:.1f}%".format(accuracy))

The accuracy is 86.4%


相關知識:
np.mean():求矩陣的均值
在sklearn中,np.mean(answer == y[test])的說明

eg1.

answer=[1, 0, 1, 1, 1, 1]  
y=[0, 0, 0, 0, 0, 1]  
print(answer==y)  
結果:  False  

eg2.

answer=np.array([1, 0, 1, 1, 1, 1])  
 y=np.array([0, 0, 0, 0, 0, 1])  
 print(answer==y)  
 結果:  
 [False  True False False False  True] 

eg3.

answer=np.array([1, 0, 1, 1, 1, 1])  
 y=np.array([0, 0, 0, 0, 0, 1])  
 print(np.mean(answer == y[test])) 
結果:  0.333333333333 

說明:
       1、 answer == y表示兩個陣列中的值相同時,輸出True;否則輸出False
       2、 eg3 對 eg2 中結果取平均值,其中True=1,False=0;

三、執行演算法

在前面的演算法中,我們把資料集分為訓練集和測試集,用訓練集訓練演算法,在測試集上評估效果。如果只進行一次性測試,極有可能出現以下問題:若是碰巧走運,測試集很簡單,我們就會覺得演算法表現不錯;反之,則會懷疑演算法很糟糕,此時極有可能把一個其實很不錯的演算法給拋棄了。
交叉檢驗(Cross-Validation): 有時亦稱迴圈估計, 是一種統計學上將資料樣本切割成較小子集的實用方法。於是可以先在一個子集上做分析, 而其它子集則用來做後續對此分析的確認及驗證。 一開始的子集被稱為訓練集。而其它的子集則被稱為驗證集或測試集。WIKI
交叉驗證對於人工智慧,機器學習,模式識別,分類器等研究都具有很強的指導與驗證意義。
基本思想是把在某種意義下將原始資料(dataset)進行分組,一部分做為訓練集(train set),另一部分做為驗證集(validation set or test set),首先用訓練集對分類器進行訓練,在利用驗證集來測試訓練得到的模型(model),以此來做為評價分類器的效能指標.


.