用scikit-learn估計值分類主要是為數據挖掘搭建通用的框架。有了這個框架之後,增加了演算法的泛化性,減少了數據挖掘的複雜性。 用scikit-learn估計值分類有這三個方面: 1. 估計器(estimator):用於分類、聚類和回歸分析。 2. 轉換器(transformer):用於數據的預 ...
用scikit-learn估計值分類主要是為數據挖掘搭建通用的框架。有了這個框架之後,增加了演算法的泛化性,減少了數據挖掘的複雜性。
用scikit-learn估計值分類有這三個方面:
1. 估計器(estimator):用於分類、聚類和回歸分析。
2. 轉換器(transformer):用於數據的預處理和數據的轉換。
3. 流水線(pipeline):組合數據挖掘流程,便於再次使用。
近鄰(kNN,k-NearestNeighbor)分類演算法是標準數據挖掘分類技術中最為直觀的一種。為了對新個體進行分類,它查找訓練集,找到了與新個體最相似的那些個體,看看這些個體大多屬於哪個類別,
就把新個體分到哪個類別。近鄰演算法幾乎可以對任何數據進行分類,但是要計算數據集中每兩個個體之間的距離,計算量很大。同時還有一個問題是在特征取離散值的數據集上表現很差。
距離是一個很關鍵的問題。歐式距離(兩個點之間直線距離)、曼哈頓距離(兩個特征在標準坐標系中絕對軸距之和)、餘弦距離(特征向量夾角的餘弦值)。
接下來我們利用一個叫電離層的數據集(http://archive.ics.uci.edu/ml/machine-learning-databases/ionosphere/)來分析近鄰演算法的運用。在這個網站里點擊ionosphere.data,之後複製這個數據,保存在本地。然後,我們來進行近鄰演算法的實現吧!
import csv import numpy as np # 創建兩個數組分別存放特征值和類別 x = np.zeros((351, 34), dtype="float") y = np.zeros((351, ), dtype="bool") ''' with open("ionosphere.data", 'r') as input_file: reader = csv.reader(input_file) ''' input_file = open('ionosphere.data', 'r') reader = csv.reader(input_file) # 遍歷文件中每一行數據,每一行數據相當於一個個體,用枚舉函數來獲取每一行的索引值,更新數據集x。 for i, row in enumerate(reader): data = [float(datum) for datum in row[:-1]] x[i] = data y[i] = row[-1] == "g" # 建立測試集和訓練集。 from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=14) # print "There are {0} samples in training dataset".format(x_train.shape[0]) # print "There are {0} samples in testing dataset".format(x_test.shape[0]) # print "Each sample has {0} features".format(x_train.shape[1]) # 然後導入K近鄰分類器這個類,併為其初始化一個實例。 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 accuracy is {0:.1f}%".format(accuracy) # The accuracy is 86.4% # 正確率很高,但是僅僅是使用預設的參數,在某些具體的情況下是不能通用的,所以,要學著根據實驗的實際情況,儘可能選用合適的參數值,爭取達到最佳的效果。 # 我們通常用訓練集訓練演算法,然後在測試集上評估效果。當測試集很簡單,我們就會認為演算法表現很出色。反之,我們可能會認為演算法很糟糕。其實,只是憑一次的測試或一次的訓練,是很難真正決定一個演算法的好壞。所以,此時我們就要用到交叉檢驗了(將數據分割成很多部分,多次測試)。 ''' 交叉檢驗: 1.將整個大數據集分成幾個部分 2.對於每一部分執行以下操作: 將其中一部分作為當前測試集 用剩餘部分去訓練演算法 在當前測試集上測試演算法 3.記錄每一次得分及平均得分 4.在上述過程中,每條數據只能在測試集中出現一次,以減少運氣成分。 ''' # 導入cross_val_score交叉檢驗方式 from sklearn.model_selection import cross_val_score scores = cross_val_score(estimator, x, y, scoring="accuracy") average_accuracy = np.mean(scores) * 100 print "The average accuracy is {0:.1f}%".format(average_accuracy) # The average accuracy is 82.3% # 設置參數。參數設置對於一個演算法很重要,靈活的設置參數能大大提高演算法的泛化能力,所以,選取好的參數值跟數據集的特征息息相關。 # 在近鄰演算法中,最重要的參數(n_neighbors)是選取多少個近鄰作為預測依據。它過大過小會造成不同的分類結果。 # 下麵我們測試n_neighbors的值,比如1到20,可以重覆進行多次實驗,觀察不同參數所帶來的結果之間的差異。 from collections import defaultdict avg_scores = [] all_scores = defaultdict(list) for n_neighbors in xrange(1,21): estimator_ = KNeighborsClassifier(n_neighbors=n_neighbors) scores = cross_val_score(estimator_, x, y, scoring="accuracy") avg_scores.append(np.mean(scores)) all_scores[n_neighbors].append(scores) # 為了更直觀的觀察差異,我們可以用圖來表示。 from matplotlib import pyplot as plt parameter_values = list(range(1,21)) #plt.plot(parameter_values, avg_scores, "-o") #plt.show() plt.figure(figsize=(32,20)) plt.plot(parameter_values, avg_scores, '-o', linewidth=5, markersize=24) plt.axis([0, max(parameter_values), 0, 1.0]) # plt.show() # 可以看出隨著近鄰數的增加,正確率不斷下降。 # 對數據預處理 ''' 對於不同特征的取值範圍千差萬別,常見的解決方法是對不同的特征進行規範化,使它們的特征值落在相同的值域或從屬於某幾個確定的類別。 ''' # 選擇最具區分度的特征、創建新特征等都屬於預處理的範疇。 # 預處理示例 x_broken = np.array(x) # 對數據的第三個特征的值除以10 x_broken[:,::2] /= 10 # print x_broken # 再來計算正確率 original_scores = cross_val_score(estimator, x, y, scoring='accuracy') print "The original average accuracy for is {0:.1f}%".format(np.mean(original_scores) * 100) # The original average accuracy for is 82.3% broken_scores = cross_val_score(estimator, x_broken, y, scoring="accuracy") print "The broken average accuracy for is {0:.1f}%".format(np.mean(broken_scores) * 100) # The broken average accuracy for is 71.5% # 這次跌到71.5%。如果,把特征值轉變到0到1之間就能解決這個問題。將特征值規範化,使用minmaxscaler類。 from sklearn.preprocessing import MinMaxScaler # 不需要單獨進行訓練,直接調用fit_transform()函數,即可完成訓練和轉換。 # x_transformed = MinMaxScaler().fit_transform(x) # 接下來將前面的broken數據拿來測試 x_transformed = MinMaxScaler().fit_transform(x_broken) transformed_scores = cross_val_score(estimator, x_transformed, y, scoring="accuracy") print "The average accuracy for is {0:.1f}%".format(np.mean(transformed_scores) * 100) # The average accuracy for is 82.3% # 正確率再次升到82.3%說明將特征值規範化有利於減少異常值對近鄰演算法的影響。 # 流水線 # 實現一個數據挖掘流水線,能大大提高效率。它就好比一個框架,能夠有效的將轉換器和估計器結合。 from sklearn.pipeline import Pipeline # 流水線的核心是元素為元組的列表。第一個元組規範特征取值範圍,第二個元組實現預測功能。 scaling_pipeline = Pipeline([("scale", MinMaxScaler()), ("predict", KNeighborsClassifier())]) scores_1 = cross_val_score(scaling_pipeline, x_broken, y, scoring="accuracy") print "The pipeline scored_1 an average accuracy for is {0:.1f}%".format(np.mean(scores_1) * 100) # The pipeline scored_1 an average accuracy for is 82.3% # 運行結果與之前的一樣,說明設置流水線很有用,因為它能確保代碼的複雜程度不至於超出掌控範圍。 # 我們再將數據規範化應用到原始數據集上,看看能不能使準確率上升,以說明數據集規範化能提升沒有異常值的數據。 scores_2 = cross_val_score(scaling_pipeline, x, y, scoring="accuracy") print "The pipeline scored_2 an average accuracy for is {0:.1f}%".format(np.mean(scores_2) * 100) # The pipeline scored_2 an average accuracy for is 82.3% # 這個結果說明,數據規範化只能將含有異常值的數據集的準確率提高。