1. 程式人生 > >資料分析06sklearn資料集及K近鄰演算法(轉)

資料分析06sklearn資料集及K近鄰演算法(轉)

機器學習應用程式的步驟

(1)收集資料

我們可以使用很多方法收集樣本護具,如:

公司自有資料

製作網路爬蟲從網站上抽取資料、

第三方購買的資料

合作機構提供的資料

從RSS反饋或者API中得到資訊、裝置傳送過來的實測資料。

(2)準備輸入資料

得到資料之後,還必須確保資料格式符合要求。

(3)分析輸入資料

這一步的主要作用是確保資料集中沒有垃圾資料。如果是使用信任的資料來源,那麼可以直接跳過這個步驟

(4)訓練演算法

機器學習演算法從這一步才真正開始學習。如果使用無監督學習演算法,由於不存在目標變數值,故而也不需要訓練演算法,所有與演算法相關的內容在第(5)步

(5)測試演算法

這一步將實際使用第(4)步機器學習得到的知識資訊。當然在這也需要評估結果的準確率,然後根據需要重新訓練你的演算法

(6)使用演算法

轉化為應用程式,執行實際任務。以檢驗上述步驟是否可以在實際環境中正常工作。如果碰到新的資料問題,同樣需要重複執行上述的步驟

一、sklearn資料集

1、sklearn中的練習資料集

1.1、datasets.load_()

獲取小規模資料集,資料包含在datasets裡

#小資料集 
#波士頓房價資料集        load_boston       迴歸            資料量:50613 
#鳶尾花資料集           load_iris         分類            資料量:1504 
#糖尿病資料集 load_diabetes 迴歸 資料量: 4210 #手寫數字資料集 load_digits 分類 資料量:562064 .......... datasets.load_boston([return_X_y]) 載入並返回波士頓房價資料集(迴歸)。 datasets.load_breast_cancer([return_X_y])載入並返回乳腺癌威斯康星資料集(分類)。 datasets.load_diabetes([return_X_y])載入並返回糖尿病資料集(迴歸)。 datasets.
load_digits([n_class,return_X_y]) 載入並返回數字資料集(分類)。 datasets.load_files(container_path [...])載入帶有類別的文字檔案作為子資料夾名稱。 datasets.load_iris([return_X_y]) 載入並返回虹膜資料集(分類)。 datasets.load_linnerud([return_X_y]) 載入並返回linnerud資料集(多元迴歸)。 datasets.load_sample_image(IMAGE_NAME) 載入單個樣本影象的numpy陣列 datasets.load_sample_images() 載入樣本影象以進行影象處理。 datasets.load_svmlight_file(f [,n_features,...])將svmlight / libsvm格式的資料集載入到稀疏CSR矩陣中 datasets.load_svmlight_files(檔案[...]) 以SVMlight格式從多個檔案載入資料集 datasets.load_wine([return_X_y]) 載入並返回葡萄酒資料集(分類)。

1.2datasets.fetch_()

獲取大規模資料集,需要從網路上下載,函式的第一個引數是data_home,表示資料集下載的目錄,預設是 ~/scikit_learn_data/,要修改預設目錄,可以修改環境變數SCIKIT_LEARN_DATA

資料集目錄可以通過datasets.get_data_home()獲取,clear_data_home(data_home=None)刪除所有下載資料

#大資料集 
#Olivetti 臉部影象資料集       fetch_olivetti_faces      降維            
#新聞分類資料集                fetch_20newsgroups        分類
#帶標籤的人臉資料集             fetch_lfw_people          分類;降維 -
#加州房價資料					fetch_california_housing    迴歸
........

1.3datasets.make_()

2、sklearn中資料集的屬性

load*和 fetch 函式返回的資料型別是 datasets.base.Bunch,本質上是一個 dict,它的鍵值對可用通過物件的屬性方式訪問。主要包含以下屬性:*

  • data:特徵資料陣列,是 n_samples ,n_features 的二維 numpy.ndarray 陣列
  • target:標籤陣列,是 n_samples 的一維 numpy.ndarray 陣列
  • DESCR:資料描述
  • feature_names:特徵名
  • target_names:標籤名

3、獲取小資料集

def get_data1():
    #資料集獲取(糖尿病資料集)  #迴歸資料
    li = load_diabetes()
    #獲取特徵資料
    print(li.data)
    #獲取目標值
    print(li.target)
    #獲取描述資訊
    print(li.DESCR)
    
    
 def get_data2():
    #資料集獲取(糖尿病資料集)  #分類資料
    li = load_iris()
    #獲取特徵資料
    print(li.data)
    #獲取目標值
    print(li.target)
    #獲取描述資訊
    print(li.DESCR)
    

4、獲取大資料集

def get_news():
    # 獲取分類資料(新聞)
    news = fetch_20newsgroups(subset='all')
    print(news.DESCR)
    print(len(news.data))
    
#可選引數:

#subset: 'train'或者'test','all',可選,選擇要載入的資料集:訓練集的“訓練”,測試集的“測試”,兩者的“全部”,具有洗牌順序

#data_home: 可選,預設值:無,指定資料集的下載和快取資料夾。如果沒有,所有scikit學習資料都儲存在'〜/ scikit_learn_data'子資料夾中

#categories: 無或字串或Unicode的集合,如果沒有(預設),載入所有類別。如果不是無,要載入的類別名稱列表(忽略其他類別)

#shuffle: 是否對資料進行洗牌

#random_state: numpy隨機數生成器或種子整數

#download_if_missing: 可選,預設為True,如果False,如果資料不在本地可用而不是嘗試從源站點下載資料,則引發IOError

5、獲取本地生成資料

參考連結:資料科學學習手札21)sklearn.datasets常用功能詳解

1、生成本地分類資料:
  • sklearn.datasets.make_classification
  • make_multilabel_classification
主要引數
"""
生成用於分類的資料集

:param n_samples:int,optional(default = 100),樣本數量

:param n_features:int,可選(預設= 20),特徵總數

:param n_classes:int,可選(default = 2),類(或標籤)的分類問題的數量

:param random_state:int,RandomState例項或無,可選(預設=無)

返回值
:return :X,特徵資料集;y,目標分類值
"""

案列

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_classification
# X1為樣本特徵,Y1為樣本類別輸出, 共400個樣本,每個樣本2個特徵,輸出有3個類別,沒有冗餘特徵,每個類別一個簇
X1, Y1 = make_classification(n_samples=400, n_features=2, n_redundant=0,
                             n_clusters_per_class=1, n_classes=3)
plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)
plt.show()

分類資料

2、生成本地迴歸模型資料:
  • sklearn.datasets.make_regression
  """
  生成用於迴歸的資料集

  :param n_samples:int,optional(default = 100),樣本數量

  :param  n_features:int,optional(default = 100),特徵數量

  :param  coef:boolean,optional(default = False),如果為True,則返回底層線性模型的係數

  :param random_state:隨機數生成器使用的種子;
  
  :return :X,特徵資料集;y,目標值
  """
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_regression
# X為樣本特徵,y為樣本輸出, coef為迴歸係數(Y/X),共1000個樣本,每個樣本1個特徵(特徵過多時需要降維處理)
X, y, coef =make_regression(n_samples=1000, n_features=1,noise=10, coef=True)
# 畫圖
plt.scatter(X, y,  color='black')
plt.plot(X, X*coef, color='blue',
         linewidth=3)

plt.xticks(())
plt.yticks(())

plt.show()

迴歸模型資料

3、生成本地聚類模型資料
  • sklearn.datasets.make_blobs
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
# X為樣本特徵,Y為樣本簇類別, 共1000個樣本,每個樣本2個特徵,共3個簇,簇中心在[-1,-1], [1,1], [2,2], 簇方差分別為[0.4, 0.5, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [1,1], [2,2]], cluster_std=[0.4, 0.5, 0.2])
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
plt.show()

生成本地聚類模型資料

4、 生成本地分組多維正態分佈的資料
  • sklearn.datasets.make_gaussian_quantiles
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import make_gaussian_quantiles
#生成2維正態分佈,生成的資料按分位數分成3組,1000個樣本,2個樣本特徵均值為1和2,協方差係數為2
X1, Y1 = make_gaussian_quantiles(n_samples=1000, n_features=2, n_classes=3, mean=[1,2],cov=2)
plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

6、資料分割

from sklearn.datasets import load_boston

def split_data():
    '''資料集分割'''
    #獲取(波士頓資料集)
   	li = load_bosto()
    #對資料進行分割
    result = train_test_split(li.data,li.target,test_size=0.25)
    # result接收的是一個元祖(訓練集,目標值,測試集,目標值)
    x_tran,x_target,y_tran,y_target = result
    print('訓練集資料',x_tran)
    print('訓練集目標值', x_tran)

二、有監督學習和無監督學習

演算法是核心,資料和計算是基礎。

  • 監督學習
    • 分類 k-近鄰演算法、決策樹、貝葉斯、邏輯迴歸(LR)、支援向量機(SVM)
    • 迴歸 線性迴歸、嶺迴歸
  • 無監督學習
    • 聚類 k-means

1、監督學習(supervised learning)

從給定的訓練資料集中學習出一個函式(模型引數),當新的資料到來時,可以根據這個函式預測結果。監督學習的訓練集要求包括輸入輸出,也可以說是特徵和目標。訓練集中的目標是由人標註的。監督學習就是最常見的分類(注意和聚類區分)問題,通過已有的訓練樣本(即已知資料及其對應的輸出)去訓練得到一個最優模型(這個模型屬於某個函式的集合,最優表示某個評價準則下是最佳的),再利用這個模型將所有的輸入對映為相應的輸出,對輸出進行簡單的判斷從而實現分類的目的。也就具有了對未知資料分類的能力。監督學習的目標往往是讓計算機去學習我們已經建立好的分類系統(模型)。

監督學習是訓練神經網路和決策樹的常見技術。這兩種技術高度依賴事先確定的分類系統給出的資訊,對於神經網路,分類系統利用資訊判斷網路的錯誤,然後不斷調整網路引數。對於決策樹,分類系統用它來判斷哪些屬性提供了最多的資訊。
常見的有監督學習演算法:迴歸分析和統計分類。最典型的演算法是KNN和SVM

2、無監督學習(unsupervised learning)

輸入資料沒有被標記,也沒有確定的結果。樣本資料類別未知,需要根據樣本間的相似性對樣本集進行分類(聚類,clustering)試圖使類內差距最小化,類間差距最大化。通俗點將就是實際應用中,不少情況下無法預先知道樣本的標籤,也就是說沒有訓練樣本對應的類別,因而只能從原先沒有樣本標籤的樣本集開始學習分類器設計。

非監督學習目標不是告訴計算機怎麼做,而是讓它(計算機)自己去學習怎樣做事情。非監督學習有兩種思路。第一種思路是在指導Agent時不為其指定明確分類,而是在成功時,採用某種形式的激勵制度。需要注意的是,這類訓練通常會置於決策問題的框架裡,因為它的目標不是為了產生一個分類系統,而是做出最大回報的決定,這種思路很好的概括了現實世界,agent可以對正確的行為做出激勵,而對錯誤行為做出懲罰。

無監督學習的方法分為兩大類:

(1) 一類為基於概率密度函式估計的直接方法:指設法找到各類別在特徵空間的分佈引數,再進行分類。

(2) 另一類是稱為基於樣本間相似性度量的簡潔聚類方法:其原理是設法定出不同類別的核心或初始核心,然後依據樣本與核心之間的相似性度量將樣本聚整合不同的類別。

利用聚類結果,可以提取資料集中隱藏資訊,對未來資料進行分類和預測。應用於資料探勘,模式識別,影象處理等。

PCA和很多deep learning演算法都屬於無監督學習。 

兩者的不同點

  1. 有監督學習方法必須要有訓練集與測試樣本。在訓練集中找規律,而對測試樣本使用這種規律。而非監督學習沒有訓練集,只有一組資料,在該組資料集內尋找規律。

  2. 有監督學習的方法就是識別事物,識別的結果表現在給待識別資料加上了標籤。因此訓練樣本集必須由帶標籤的樣本組成。而非監督學習方法只有要分析的資料集的本身,預先沒有什麼標籤。如果發現數據集呈現某種聚集性,則可按自然的聚集性分類,但不予以某種預先分類標籤對上號為目的。

  3. 非監督學習方法在尋找資料集中的規律性,這種規律性並不一定要達到劃分資料集的目的,也就是說不一定要“分類”。

這一點是比有監督學習方法的用途要廣。 譬如分析一堆資料的主分量,或分析資料集有什麼特點都可以歸於非監督學習方法的範疇。

  1. 用非監督學習方法分析資料集的主分量與用K-L變換計算資料集的主分量又有區別。後者從方法上講不是學習方法。因此用K-L變換找主分量不屬於無監督學習方法,即方法上不是。而通過學習逐漸找到規律性這體現了學習方法這一點。在人工神經元網路中尋找主分量的方法屬於無監督學習方法。

三、sklearn分類演算法之k-近鄰

k-近鄰演算法採用測量不同特徵值之間的距離來進行分類

優點:精度高、對異常值不敏感、無資料輸入假定

缺點:計算複雜度高、空間複雜度高

使用資料範圍:數值型和標稱型

1、k-近鄰法簡介

k近鄰法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一種基本分類與迴歸方法。它的工作原理是:存在一個樣本資料集合,也稱作為訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本集中每一個數據與所屬分類的對應關係。輸入沒有標籤的新資料後,將新的資料的每個特徵與樣本集中資料對應的特徵進行比較,然後演算法提取樣本最相似資料(最近鄰)的分類標籤。一般來說,我們只選擇樣本資料集中前k個最相似的資料,這就是k-近鄰演算法中k的出處,通常k是不大於20的整數。最後,選擇k個最相似資料中出現次數最多的分類,作為新資料的分類。

舉個簡單的例子,我們可以使用k-近鄰演算法分類一個電影是愛情片還是動作片。

機器學習實戰教程(一):K-近鄰(KNN)演算法(史詩級乾貨長文)

表1.1 每部電影的打鬥鏡頭數、接吻鏡頭數以及電影型別

表1.1 就是我們已有的資料集合,也就是訓練樣本集。這個資料集有兩個特徵,即打鬥鏡頭數和接吻鏡頭數。除此之外,我們也知道每個電影的所屬型別,即分類標籤。用肉眼粗略地觀察,接吻鏡頭多的,是愛情片。打鬥鏡頭多的,是動作片。以我們多年的看片經驗,這個分類還算合理。如果現在給我一部電影,你告訴我這個電影打鬥鏡頭數和接吻鏡頭數。不告訴我這個電影型別,我可以根據你給我的資訊進行判斷,這個電影是屬於愛情片還是動作片。而k-近鄰演算法也可以像我們人一樣做到這一點,不同的地方在於,我們的經驗更"牛逼",而k-近鄰演算法是靠已有的資料。比如,你告訴我這個電影打鬥鏡頭數為2,接吻鏡頭數為102,我的經驗會告訴你這個是愛情片,k-近鄰演算法也會告訴你這個是愛情片。你又告訴我另一個電影打鬥鏡頭數為49,接吻鏡頭數為51,我"邪惡"的經驗可能會告訴你,這有可能是個"愛情動作片",畫面太美,我不敢想象。 (如果說,你不知道"愛情動作片"是什麼?請評論留言與我聯絡,我需要你這樣像我一樣純潔的朋友。) 但是k-近鄰演算法不會告訴你這些,因為在它的眼裡,電影型別只有愛情片和動作片,它會提取樣本集中特徵最相似資料(最鄰近)的分類標籤,得到的結果可能是愛情片,也可能是動作片,但絕不會是"愛情動作片"。當然,這些取決於資料集的大小以及最近鄰的判斷標準等因素。

2、sklearn.neighbors.

sklearn.neighbors.KNeighborsClassifier

sklearn.neighbors提供監督的基於鄰居的學習方法的功能,

sklearn.neighbors.KNeighborsClassifier是一個最近鄰居分類器。那麼KNeighborsClassifier是一個類,我們看一下例項化時候的引數

1、引數
 '''
  :引數:
  -n_neighbors:int,可選(預設= 5),k_neighbors查詢預設使用的鄰居數
  -algorithm:{'auto','ball_tree','kd_tree','brute'},可選用於計算最近鄰居的演算法:
  -'ball_tree'將會使用 BallTree,
  -'kd_tree'將使用 KDTree,“野獸”將使用強力搜尋。
  -'auto'將嘗試根據傳遞給fit方法的值來決定最合適的演算法。
  -n_jobs:int,可選(預設= 1),用於鄰居搜尋的並行作業數。如果-1
'''
2、方法

fit(X, y)

使用X作為訓練資料擬合模型,y作為X的類別值。X,y為陣列或者矩陣

import numpy as np
from sklearn.neighbors import KNeighborsClassifier

neigh = KNeighborsClassifier(n_neighbors=3)
X = np.array([[1,1],[1,1.1],[0,0],[0,0.1]])
y = np.array([1,1,0,0])
neigh.fit(X,y)

kneighbors(X=None, n_neighbors=None, return_distance=True)

找到指定點集X的n_neighbors個鄰居,return_distance為False的話,不返回距離

neigh.kneighbors(np.array([[1.1,1.1]]),return_distance= False)

neigh.kneighbors(np.array([[1.1,1.1]]),return_distance= False,an_neighbors=2)

predict(X)

預測提供的資料的類標籤

neigh.predict(np.array([[0.1,0.1],[1.1,1.1]]))

predict_proba(X)

返回測試資料X屬於某一類別的概率估計

neigh.predict_proba(np.array([[1.1,1.1]]))

3、GridSearchCV

sklearn裡面的GridSearchCV用於系統地遍歷多種引數組合,通過交叉驗證確定最佳效果引數。

​ 它存在的意義就是自動調參,只要把引數輸進去,就能給出最優化的結果和引數。但是這個方法適合於小資料集,一旦資料的量級上去了,很難得出結果。這個時候就是需要動腦筋了。資料量比較大的時候可以使用一個快速調優的方法——座標下降。它其實是一種貪心演算法:拿當前對模型影響最大的引數調優,直到最優化;再拿下一個影響最大的引數調優,如此下去,直到所有的引數調整完畢。這個方法的缺點就是可能會調到區域性最優而不是全域性最優,但是省時間省力,巨大的優勢面前,還是試一試吧,後續可以再拿bagging再優化。

classsklearn.model_selection.GridSearchCV(estimator,
                                          param_grid, 
                                          scoring=None, 
                                          fit_params=None,
                                          n_jobs=1,
                                          iid=True,
                                          refit=True,
                                          cv=None, 
                                          verbose=0, 
                                          pre_dispatch='2*n_jobs',
                                          error_score='raise',
                                          return_train_score=True)
1、常用引數
estimator:所使用的分類器,如estimator=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features='sqrt',random_state=10), 並且傳入除需要確定最佳的引數之外的其他引數。每一個分類器都需要一個scoring引數,或者score方法。

param_grid:值為字典或者列表,即需要最優化的引數的取值,
param_grid =param_test1,
param_test1 = {'n_estimators':range(10,71,10)}。

scoring :準確度評價標準,預設None,這時需要使用score函式;或者如scoring='roc_auc',根據所選模型不同,評價準則不同。字串(函式名),或是可呼叫物件,需要其函式簽名形如:scorer(estimator, X, y);如果是None,則使用estimator的誤差估計函式。

cv :交叉驗證引數,預設None,使用三折交叉驗證。指定fold數量,預設為3,也可以是yield訓練/測試資料的生成器。

refit :預設為True,程式將會以交叉驗證訓練集得到的最佳引數,重新對所有可用的訓練集與開發集進行,作為最終用於效能評估的最佳模型引數。即在搜尋引數結束後,用最佳引數結果再次fit一遍全部資料集。

iid:預設True,True時,預設為各個樣本fold概率分佈一致,誤差估計為所有樣本之和,而非各個fold的平均。

verbose:日誌冗長度,int:冗長度,0:不輸出訓練過程,1:偶爾輸出,>1:對每個子模型都輸出。

n_jobs: 並行數,int:個數,-1:跟CPU核數一致, 1:預設值。

pre_dispatch:指定總共分發的並行任務數。當n_jobs大於1時,資料將在每個執行點進行復制,這可能導致OOM,而設定pre_dispatch引數,則可以預先劃分總共的job數量,使資料最多被複制pre_dispatch次

2、進行預測的常用方法和屬性
grid.fit():執行網格搜尋

grid_scores_:給出不同引數情況下的評價結果

best_params_:描述了已取得最佳結果的引數的組合

score(x_test, y_test):在測試集上準確率

best_score_ :在交叉驗證當中最好的結果

gs.best_estimator_ :選擇最好的模型是:

gs.cv_results_  :每個超引數每次交叉驗證的結果
3、案列一
from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split

from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

from sklearn.model_selection import GridSearchCV

def knniris():
    """
    鳶尾花分類
    :return: None
    """

    # 資料集獲取和分割
    lr = load_iris()

    x_train, x_test, y_train, y_test = train_test_split(lr.data, lr.target, test_size=0.25)
	'''
	如需列印可進行降維處理
	'''
    # 進行標準化
    std = StandardScaler()

    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # estimator流程
    knn = KNeighborsClassifier()

    # 通過網格搜尋,n_neighbors為引數列表
    param = {"n_neighbors": [3, 5, 7]}

    gs = GridSearchCV(knn, param_grid=param, cv=10)

    # 建立模型
    gs.fit(x_train,y_train)

    # 預測準確率
    print("在測試集上準確率:", gs.score(x_test, y_test))

    print("在交叉驗證當中最好的結果:", gs.best_score_)

    print("選擇最好的模型是:", gs.best_estimator_)

    print("每個超引數每次交叉驗證的結果:", gs.cv_results_)


knniris()

結果:

在測試集上準確率: 1.0
在交叉驗證當中最好的結果: 0.9375
選擇最好的模型是: KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')
每個超引數每次交叉驗證的結果: {'mean_fit_time': array([0.00135021, 0.00095284, 0.00100255]), 'std_fit_time': array([0.00059321, 0.0002651 , 0.00022308]), 'mean_score_time': array([0.00220425, 0.001596  , 0.00164721]), 'std_score_time': array([0.00074352, 0.00037176, 0.0002317 ]), 'param_n_neighbors': masked_array(data=[3, 5, 7],
             mask=[False, False, False],
       fill_value='?',
            dtype=object), 'params': [{'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 7}], 'split0_test_score': array([0.91666667, 0.83333333, 0.83333333]), 'split1_test_score': array([0.91666667, 1.        , 1.        ]), 'split2_test_score': array([1., 1., 1.]), 'split3_test_score': array([0.83333333, 0.91666667, 0.91666667]), 'split4_test_score': array([0.83333333, 0.91666667, 0.91666667]), 'split5_test_score': array([0.91666667, 1.        , 0.91666667]), 'split6_test_score': array([1.        , 1.        , 0.90909091]), 'split7_test_score': array