資料分析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演算法都屬於無監督學習。
兩者的不同點
-
有監督學習方法必須要有訓練集與測試樣本。在訓練集中找規律,而對測試樣本使用這種規律。而非監督學習沒有訓練集,只有一組資料,在該組資料集內尋找規律。
-
有監督學習的方法就是識別事物,識別的結果表現在給待識別資料加上了標籤。因此訓練樣本集必須由帶標籤的樣本組成。而非監督學習方法只有要分析的資料集的本身,預先沒有什麼標籤。如果發現數據集呈現某種聚集性,則可按自然的聚集性分類,但不予以某種預先分類標籤對上號為目的。
-
非監督學習方法在尋找資料集中的規律性,這種規律性並不一定要達到劃分資料集的目的,也就是說不一定要“分類”。
這一點是比有監督學習方法的用途要廣。 譬如分析一堆資料的主分量,或分析資料集有什麼特點都可以歸於非監督學習方法的範疇。
- 用非監督學習方法分析資料集的主分量與用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-近鄰演算法分類一個電影是愛情片還是動作片。
表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