1. 程式人生 > >2. 用scikit-learn估計器分類

2. 用scikit-learn估計器分類

# -*- coding: utf-8 -*-
"""
Created on Sat Sep 22 09:43:28 2018

@author: asus
"""
#2 用scikit-learn估計器分類
#估計器(Estimator):用於分類、聚類和迴歸分析
#轉換器(Transformer):用於資料預處理和資料轉換
#流水線(Pipeline):組合資料探勘流程,便於再次使用。

#2.1 scikit-learn估計器
#主要引數
#fit():訓練演算法,設定內部引數。該函式接收訓練集及其類別兩個引數。
#predict():引數為測試集。預測測試集類別,並返回一個包含測試集各條資料類別的陣列。

#scikit-learn提供了大量估計器,其中有支援向量機(SVM)、隨機森林、神經網路等。

#2.1.1 近鄰演算法
#計算量大,在特徵取離散值的資料集上表現很差。

#常用的距離度量,歐氏距離,曼哈頓距離,餘弦距離。

#即將用到的資料集叫作電離層,這些資料是由高頻天線收集的。最後一列,'g'好,'b'壞,為數
#據的好壞,即是否提供了有價值的資訊。

import numpy as np
import csv

data_filename = "E:/books/Python資料探勘入門與實踐/ionosphere.data"
#建立NumPy陣列x和y存放資料集。資料大小已知,共有351行34列。
x = np.zeros((351, 34), dtype='float')
y = np.zeros((351,), dtype='bool')
with open(data_filename, 'r') as input_file:
    reader = csv.reader(input_file)
    #遍歷檔案中的每一行資料。用列舉函式獲得每行的索引號
    for i, row in enumerate(reader):
        #獲取每一個個體的前34個值,將其轉化為浮點型,儲存到X中
        data = [float(datum) for datum in row[:-1]]
        x[i] = data
        #獲得每個個體最後一個表示類別的值,把字母轉化為數字,如果類別為‘g’,值為1,
        #否則為0
        y[i] = row[-1] == 'g'

#2.1.4 努力實現流程標準化

#建立訓練集和測試集
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_train訓練集,x_test測試集。y_train,y_test分別為以上兩個資料集的類別資訊。

#匯入K近鄰分類器這個類,併為其初始化一個例項。預設選擇5個近鄰作為分類依據。
from sklearn.neighbors import KNeighborsClassifier
estimator = KNeighborsClassifier()
#估計器建立好後,接下來就要用訓練資料進行訓練。K近鄰估計器分析訓練集中的資料,比較待分
#類的新資料點和訓練集中的資料,找到新資料點的近鄰。
estimator.fit(x_train, y_train)
#接著,用測試集測試演算法,評估它在測試集上的表現
y_predicted = estimator.predict(x_test)
accuracy = np.mean(y_test == y_predicted) * 100
print("The test accuracy is {:.1f}%".format(accuracy))

#2.1.5 執行演算法
#交叉檢驗
from sklearn.cross_validation import cross_val_score
scores = cross_val_score(estimator, x, y, scoring='accuracy')
average_accuracy = np.mean(scores) * 100
print("The test accuracy is {:.1f}%".format(average_accuracy))

#2.1.6 設定引數
#n_neighbors,選取多少個近鄰作為預測依據。

#測試1到20的n_neighbors
avg_scores = []
all_scores = []
parameter_values = list(range(1, 21))
for n_neighbors in parameter_values:
    estimator = KNeighborsClassifier(n_neighbors=n_neighbors)
    scores = cross_val_score(estimator, x, y, scoring='accuracy')
    #把不同n_neighbors值的得分和平均儲存起來,留作分析用
    avg_scores.append(np.mean(scores))
    all_scores.append(scores)
%matplotlib inline
from matplotlib import pyplot as plt
plt.plot(parameter_values, avg_scores, '-o')

#2.2 流水線在預處理中的應用
#轉換器(Transformer),它接受原始資料集,返回轉換後的資料集。

#2.2.1 預處理案例
#講解需要,先對資料集做些破壞
x_broken = np.array(x) #建立一個副本
x_broken[:,::2] /= 10  #每隔一行,就把第二行的特徵除以10
#數值範圍變了,再次計算正確率
estimator = KNeighborsClassifier()
#原始資料集的正確率
original_scores = cross_val_score(estimator, x, y, scoring='accuracy')
print("The test accuracy is {:.1f}%".format(np.mean(original_scores) * 100))
#副本的正確率
broken_scores = cross_val_score(estimator, x_broken, y, scoring='accuracy')
print("The test accuracy is {:.1f}%".format(np.mean(broken_scores) * 100))

#2.2.2 標準預處理
from sklearn.preprocessing import MinMaxScaler
#規範化,標準化,最小值用0代替,最大值用1代替,其餘值介於兩者之間
x_transformed = MinMaxScaler().fit_transform(x)

#其他規範化方法
#為使每條資料各特徵值的和為1,使用sklearn.preprocessing.Normalizer
#為使各特徵的均值為0,方差為1,使用sklearn.preprocessing.StandardScaler,常用作規範
#化的基準
#為將數值型特徵的二值化,使用sklearn.preprocessing.Binarizer,大於閾值的為1,反之為0

#2.2.3 組裝起來
x_transformed = MinMaxScaler().fit_transform(x_broken)
estimator = KNeighborsClassifier()
transformed_scores = cross_val_score(estimator, x_transformed, y,
                                     scoring='accuracy')
print("The test accuracy is {:.1f}%".format(np.mean(transformed_scores) * 100))
#正確率又再次升回來了
#異常值會影響近鄰演算法,不同演算法對值域大小的敏感度不同

#2.3 流水線
#流水線把這些步驟儲存到資料探勘的工作流中。之後你就可以用它們讀入資料,做各種必要的處
#理,然後給出預測結果。
from sklearn.pipeline import Pipeline
#流水線的輸入為一連串的資料探勘步驟,其中最後一步必須是估計器,前幾步是轉換器。
#每一部都用元組(‘名稱’,步驟)表示。
scaling_pipeline = Pipeline([('scale', MinMaxScaler()),
                             ('predict', KNeighborsClassifier())])
#流水線的核心是元素為元組的列表。第一個元組規範特徵取值範圍,第二個元組實現預測功能。
scores = cross_val_score(scaling_pipeline, x_broken, y, scoring='accuracy')
print("The pipeline scored an average accuracy for is {0:.1f}%".
      format(np.mean(scores) * 100))