網上有不少關於sklearn的學習教程,大部分都是簡單的講清楚某一方面,其實最好的教程就是官方文檔。html
官方文檔地址:https://scikit-learn.org/stable/node
(但是官方文檔很是詳細,同時許多人對官方文檔的理解和結構上都不能很好地把握,我也打算好好學習sklearn,這多是機器學習的神器),下面先簡單介紹一下sklearn。git
自2007年發佈以來,scikit-learn已經成爲Python重要的機器學習庫了,scikit-learn簡稱sklearn,支持包括分類,迴歸,降維和聚類四大機器學習算法。還包括了特徵提取,數據處理和模型評估者三大模塊。算法
sklearn是Scipy的擴展,創建在Numpy和matplolib庫的基礎上。利用這幾大模塊的優點,能夠大大的提升機器學習的效率。數組
sklearn擁有着完善的文檔,上手容易,具備着豐富的API,在學術界頗受歡迎。sklearn已經封裝了大量的機器學習算法,包括LIBSVM和LIBINEAR。同時sklearn內置了大量數據集,節省了獲取和整理數據集的時間。網絡
定義:針對經驗E和一系列的任務T和必定表現的衡量P,若是隨着經驗E的積累,針對定義好的任務T能夠提升表現P,就說明機器具備學習能力。app
由圖中,能夠看到庫的算法主要有四類:分類,迴歸,聚類,降維。其中:dom
這個流程圖表明:藍色圓圈是判斷條件,綠色方框是能夠選擇的算法,咱們能夠根據本身的數據特徵和任務目標去找一條本身的操做路線。機器學習
sklearn中包含衆多數據預處理和特徵工程相關的模塊,雖然剛接觸sklearn時,你們都會爲其中包含的各類算法的廣度深度所震驚,但其實sklearn六大板塊中有兩塊都是關於數據預處理和特徵工程的,兩個板塊互相交互,爲建模以前的所有工程打下基礎。ide
傳統的機器學習任務從開始到建模的通常流程就是:獲取數據——》數據預處理——》訓練模型——》模型評估——》預測,分類。本次咱們將根據傳統機器學習的流程,看看在每一步流程中都有哪些經常使用的函數以及他們的用法是怎麼樣的。那麼首先先看一個簡單的例子:
鳶尾花識別是一個經典的機器學習分類問題,它的數據樣本中包括了4個特徵變量,1個類別變量,樣本總數爲150。
它的目標是爲了根據花萼長度(sepal length)、花萼寬度(sepal width)、花瓣長度(petal length)、花瓣寬度(petal width)這四個特徵來識別出鳶尾花屬於山鳶尾(iris-setosa)、變色鳶尾(iris-versicolor)和維吉尼亞鳶尾(iris-virginica)中的哪種。
# 引入數據集,sklearn包含衆多數據集 from sklearn import datasets # 將數據分爲測試集和訓練集 from sklearn.model_selection import train_test_split # 利用鄰近點方式訓練數據 from sklearn.neighbors import KNeighborsClassifier # 引入數據,本次導入鳶尾花數據,iris數據包含4個特徵變量 iris = datasets.load_iris() # 特徵變量 iris_X = iris.data # print(iris_X) print('特徵變量的長度',len(iris_X)) # 目標值 iris_y = iris.target print('鳶尾花的目標值',iris_y) # 利用train_test_split進行訓練集和測試機進行分開,test_size佔30% X_train,X_test,y_train,y_test=train_test_split(iris_X,iris_y,test_size=0.3) # 咱們看到訓練數據的特徵值分爲3類 # print(y_train) ''' [1 1 0 2 0 0 0 2 2 2 1 0 2 0 2 1 0 1 0 2 0 1 0 0 2 1 2 0 0 1 0 0 1 0 0 0 0 2 2 2 1 1 1 2 0 2 0 1 1 1 1 2 2 1 2 2 2 0 2 2 2 0 1 0 1 0 0 1 2 2 2 1 1 1 2 0 0 1 0 2 1 2 0 1 2 2 2 1 2 1 0 0 1 0 0 1 1 1 0 2 1 1 0 2 2] ''' # 訓練數據 # 引入訓練方法 knn = KNeighborsClassifier() # 進行填充測試數據進行訓練 knn.fit(X_train,y_train) params = knn.get_params() print(params) ''' {'algorithm': 'auto', 'leaf_size': 30, 'metric': 'minkowski', 'metric_params': None, 'n_jobs': None, 'n_neighbors': 5, 'p': 2, 'weights': 'uniform'} ''' score = knn.score(X_test,y_test) print("預測得分爲:%s"%score) ''' 預測得分爲:0.9555555555555556 [1 2 1 1 2 2 1 0 0 0 0 1 2 0 1 0 2 0 0 0 2 2 0 2 2 2 2 1 2 2 2 1 2 2 1 2 0 2 1 2 1 1 0 2 1] [1 2 1 1 2 2 1 0 0 0 0 1 2 0 1 0 2 0 0 0 1 2 0 2 2 2 2 1 1 2 2 1 2 2 1 2 0 2 1 2 1 1 0 2 1] ''' # 預測數據,預測特徵值 print(knn.predict(X_test)) ''' [0 2 2 2 2 0 0 0 0 2 2 0 2 0 2 1 2 0 2 1 0 2 1 0 1 2 2 0 2 1 0 2 1 1 2 0 2 1 2 0 2 1 0 1 2] ''' # 打印真實特徵值 print(y_test) ''' [1 2 2 2 2 1 1 1 1 2 1 1 1 1 2 1 1 0 2 1 1 1 0 2 0 2 0 0 2 0 2 0 2 0 2 2 0 2 2 0 1 0 2 0 0] '''
下面,咱們開始一步步介紹、
sklearn中包含了大量的優質的數據集,在咱們學習機器學習的過程當中,咱們可使用這些數據集實現出不一樣的模型,從而提升你動手實踐能力,同時這個過程也能夠加深對理論知識的理解和把握。除了引入數據以外,咱們還能夠經過load_sample_images()來引入圖片。
首先,要使用sklearn中的數據集,必須導入datasets模塊。
from sklearn import datasets
下面兩個圖中包含了大部分sklearn中的數據集,調用方式也圖中給出,
這裏咱們使用iris的數據來舉個例子,表示導出數據集:
iris = datasets.load_iris() # 導入數據集 X = iris.data # 得到其特徵向量 y = iris.target # 得到樣本label
手寫數字數據集包含1797個0-9的手寫數字數據,每一個數據由8 * 8 大小的矩陣構成,矩陣中值的範圍是0-16,表明顏色的深度。
使用sklearn.datasets.load_digits便可加載相關數據集。
from sklearn.datasets import load_digits digits = load_digits() print(digits.data.shape) print(digits.target.shape) print(digits.images.shape) ''' (1797, 64) (1797,) (1797, 8, 8) '''
展現以下:
import matplotlib.pyplot as plt from sklearn.datasets import load_digits digits = load_digits() plt.matshow(digits.images[0]) plt.show()
咱們除了可使用sklearn自帶的數據集,還能夠本身去建立訓練樣本,
具體用法能夠參考: https://scikit-learn.org/stable/datasets/
下面咱們拿分類問題的樣本生成器舉例子:
from sklearn.datasets.samples_generator import make_classification X, y = make_classification(n_samples=6, n_features=5, n_informative=2, n_redundant=2, n_classes=2, n_clusters_per_class=2, scale=1.0, random_state=20) # n_samples:指定樣本數 # n_features:指定特徵數 # n_classes:指定幾分類 # random_state:隨機種子,使得隨機狀可重
測試以下:
>>> for x_,y_ in zip(X,y): print(y_,end=': ') print(x_) 0: [-0.6600737 -0.0558978 0.82286793 1.1003977 -0.93493796] 1: [ 0.4113583 0.06249216 -0.90760075 -1.41296696 2.059838 ] 1: [ 1.52452016 -0.01867812 0.20900899 1.34422289 -1.61299022] 0: [-1.25725859 0.02347952 -0.28764782 -1.32091378 -0.88549315] 0: [-3.28323172 0.03899168 -0.43251277 -2.86249859 -1.10457948] 1: [ 1.68841011 0.06754955 -1.02805579 -0.83132182 0.93286635]
scikit中的make_blobs方法常被用來生成聚類算法的測試數據,直觀地說,make_blobs會根據用戶指定的特徵數量,中心點數量,範圍等來生成幾類數據,這些數據可用於測試聚類算法的效果。
sklearn.datasets.make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)[source]
輸入:
返回值:
from sklearn.datasets import make_blobs from matplotlib import pyplot data,label = make_blobs(n_samples=100,n_features=2,centers=5) # 繪製樣本顯示 pyplot.scatter(data[:,0],data[:,1],c=label) pyplot.show()
結果:
import matplotlib.pylab as plt from sklearn.datasets import make_blobs # 每一個樣本有幾個屬性或者特徵 n_features = 2 data,target = make_blobs(n_samples=100,n_features=2,centers=3,cluster_std=[1.0,2.0,3.0]) # 在2D圖中繪製樣本,每一個樣本顏色不一樣 plt.scatter(data[:,0],data[:,1],c=target) plt.show()
一般用於分類算法
sklearn.datasets.make_classification(n_samples=100, n_features=20, n_informative=2, n_redundant=2,n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None,flip_y=0.01, class_sep=1.0, hypercube=True,shift=0.0, scale=1.0, shuffle=True, random_state=None)
輸入:
n_features :特徵個數= n_informative() + n_redundant + n_repeated
n_informative:多信息特徵的個數
n_redundant:冗餘信息,informative特徵的隨機線性組合
n_repeated :重複信息,隨機提取n_informative和n_redundant 特徵
n_classes:分類類別
n_clusters_per_class :某一個類別是由幾個cluster構成的
sklearn.datasets.make_gaussian_quantiles(mean=None, cov=1.0, n_samples=100, n_features=2, n_classes=3,shuffle=True, random_state=None)
利用高斯分位點區分不一樣數據
sklearn.datasets.make_hastie_10_2(n_samples=12000, random_state=None)
利用Hastie算法,生成二分類數據
import matplotlib.pyplot as plt from sklearn.datasets import make_classification from sklearn.datasets import make_blobs from sklearn.datasets import make_gaussian_quantiles from sklearn.datasets import make_hastie_10_2 plt.figure(figsize=(8, 8)) plt.subplots_adjust(bottom=.05, top=.9, left=.05, right=.95) plt.subplot(421) plt.title("One informative feature, one cluster per class", fontsize='small') X1, Y1 = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=1, n_clusters_per_class=1) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.subplot(422) plt.title("Two informative features, one cluster per class", fontsize='small') X1, Y1 = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=2, n_clusters_per_class=1) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.subplot(423) plt.title("Two informative features, two clusters per class", fontsize='small') X2, Y2 = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=2) plt.scatter(X2[:, 0], X2[:, 1], marker='o', c=Y2) plt.subplot(424) plt.title("Multi-class, two informative features, one cluster", fontsize='small') X1, Y1 = make_classification(n_samples=1000,n_features=2, n_redundant=0, n_informative=2, n_clusters_per_class=1, n_classes=3) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.subplot(425) plt.title("Three blobs", fontsize='small') X1, Y1 = make_blobs(n_samples=1000,n_features=2, centers=3) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.subplot(426) plt.title("Gaussian divided into four quantiles", fontsize='small') X1, Y1 = make_gaussian_quantiles(n_samples=1000,n_features=2, n_classes=4) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.subplot(427) plt.title("hastie data ", fontsize='small') X1, Y1 = make_hastie_10_2(n_samples=1000) plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1) plt.show()
結果:
生成環線數據
sklearn.datasets.make_circles(n_samples=100, shuffle=True, noise=None, random_state=None, factor=0.8)
factor:外環和內環的尺度因子<1
sklearn.datasets.make_moons(n_samples=100, shuffle=True, noise=None, random_state=None)
生成半環圖
from sklearn.datasets import make_circles from sklearn.datasets import make_moons import matplotlib.pyplot as plt import numpy as np fig=plt.figure(1) x1,y1=make_circles(n_samples=1000,factor=0.5,noise=0.1) plt.subplot(121) plt.title('make_circles function example') plt.scatter(x1[:,0],x1[:,1],marker='o',c=y1) plt.subplot(122) x1,y1=make_moons(n_samples=1000,noise=0.1) plt.title('make_moons function example') plt.scatter(x1[:,0],x1[:,1],marker='o',c=y1) plt.show()
結果:
數據預處理階段是機器學習中不可缺乏的一環,它會使得數據更加有效的被模型或者評估器識別。下面咱們來看一下sklearn中有哪些平時咱們經常使用的函數:
from sklearn import preprocessing
爲了使得訓練數據的標準化規則與測試數據的標準化規則同步,preprocessing中提供了不少的Scaler:
StandardScaler
MaxAbsScaler
MinMaxScaler
RobustScaler
Normalizer
對應的有直接的函數使用:scale(),maxabs_scale(),minmax_scale(),robust_scale(),normaizer()
sklearn.preprocessing.scale(X)
標準化:在機器學習中,咱們可能要處理不一樣種類的資料,例如,音訊和圖片上的像素值,這些資料多是高緯度的,資料標準化後會使得每一個特徵中的數值平均變爲0(將每一個特徵的值都減掉原始資料中該特徵的平均),標準差變爲1,這個方法被普遍的使用在許多機器學習算法中(例如:支持向量機,邏輯迴歸和類神經網絡)。
StandardScaler計算訓練集的平均值和標準差,以便測試數據及使用相同的變換。
變換後各維特徵有0均值,單位方差,也叫z-score規範化(零均值規範化),計算方式是將特徵值減去均值,除以標準差。
fit
用於計算訓練數據的均值和方差,後面就會用均值和方差來轉換訓練數據
fit_transform
不只計算訓練數據的均值和方差,還會基於計算出來的均值和方差來轉換訓練數據,從而把數據轉化成標準的正態分佈。
transform
很顯然,它只是進行轉換,只是把訓練數據轉換成標準的正態分佈。(通常會把train和test集放在一塊兒作標準化,或者在train集上作標準化後,用一樣的標準化器去標準化test集,此時可使用scaler)。
data = [[0, 0], [0, 0], [1, 1], [1, 1]] # 1. 基於mean和std的標準化 scaler = preprocessing.StandardScaler().fit(train_data) scaler.transform(train_data) scaler.transform(test_data)
通常來講先使用fit:
scaler = preocessing.StandardScaler().fit(X)
這一步能夠計算獲得scaler,scaler裏面存的有計算出來的均值和方差。
再使用transform
scaler.transform(X)
這一步再用scaler中的均值和方差來轉換X,使X標準化。
最後,在預測的時候,也要對數據作一樣的標準化處理,即也要用上面的scaler中的均值和方差來對預測時候的特徵進行標準化。
注意:測試數據和預測數據的標準化的方式要和訓練數據標準化的方式同樣,必須使用同一個scaler來進行transform
最小最大規範化對原始數據進行線性變換,變換到[0,1]區間(也能夠是其餘固定最小最大值的區間)。
# 2. 將每一個特徵值歸一化到一個固定範圍 scaler = preprocessing.MinMaxScaler(feature_range=(0, 1)).fit(train_data) scaler.transform(train_data) scaler.transform(test_data) #feature_range: 定義歸一化範圍,注用()括起來
當你想要計算兩個樣本的類似度時必不可少的一個操做,就是正則化。其思想是:首先求出樣本的p範數,而後該樣本的全部元素都要除以該範數,這樣最終使得每一個樣本的範數都是1。規範化(Normalization)是將不一樣變化範圍的值映射到相同的固定範圍,常見的是[0,1],也成爲歸一化。
以下例子,將每一個樣本變換成unit norm。
>>> X = [[ 1., -1., 2.], ... [ 2., 0., 0.], ... [ 0., 1., -1.]] >>> X_normalized = preprocessing.normalize(X, norm='l2') >>> X_normalized array([[ 0.40..., -0.40..., 0.81...], [ 1. ..., 0. ..., 0. ...], [ 0. ..., 0.70..., -0.70...]])
咱們能夠發現對於每個樣本都有0.4^2+0.4^2+0.81^2=1。這就是L2 norm,變換後每一個樣本的各維特徵的平方和爲1.相似的,L1 norm則是變換後每一個樣本的各維特徵的絕對值之和爲1.還有max norm,則是將每一個樣本的各維特徵除以該樣本各維特徵的最大值,
在度量樣本之間類似性時,若是使用的是二次型kernel,則須要作Normalization。
one-hot編碼是一種對離散特徵值的編碼方式,在LR模型中經常使用到,用於給線性模型增長非線性能力。
data = [[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]] encoder = preprocessing.OneHotEncoder().fit(data) enc.transform(data).toarray()
給定閾值,將特徵轉換爲0/1.
binarizer = sklearn.preprocessing.Binarizer(threshold=1.1) binarizer.transform(X)
有時候特徵時類別型的,而一些算法的輸入必須是數值型,此時須要對其編碼,
enc = preprocessing.OneHotEncoder() enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]]) enc.transform([[0, 1, 3]]).toarray() #array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])
上面這個例子,第一維特徵有兩種值0和1,用兩位去編碼。第二維用三位,第三維用四位。
le = sklearn.preprocessing.LabelEncoder() le.fit([1, 2, 2, 6]) le.transform([1, 1, 2, 6]) #array([0, 0, 1, 2]) #非數值型轉化爲數值型 le.fit(["paris", "paris", "tokyo", "amsterdam"]) le.transform(["tokyo", "tokyo", "paris"]) #array([2, 2, 1])
在獲得訓練數據集時,一般咱們常常會把訓練數據進一步拆分紅訓練集和驗證集,這樣有助於咱們模型參數的選取。
train_test_split是交叉驗證中經常使用的函數,功能是從樣本中隨機的按比例選取train data和testdata,形式爲:
X_train,X_test, y_train, y_test = cross_validation.train_test_split(train_data,train_target,test_size=0.4, random_state=0)
# 做用:將數據集劃分爲 訓練集和測試集 # 格式:train_test_split(*arrays, **options) from sklearn.mode_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) """ 參數 --- arrays:樣本數組,包含特徵向量和標籤 test_size: float-得到多大比重的測試樣本 (默認:0.25) int - 得到多少個測試樣本 train_size: 同test_size random_state: int - 隨機種子(種子固定,實驗可復現) shuffle - 是否在分割以前對數據進行洗牌(默認True) 返回 --- 分割後的列表,長度=2*len(arrays), (train-test split) """
導入模塊
from sklearn.cross_validation import cross_val_score
則會報錯,代碼以下:
from sklearn.cross_validation import cross_val_score ModuleNotFoundError: No module named 'sklearn.cross_validation'
解決方法:
from sklearn.model_selection import cross_val_score
在這一步咱們首先要分析本身數據的類型,明白本身要用什麼模型來作,而後咱們就能夠在sklearn中定義模型了,sklearn爲全部模型提供了很是類似的接口,這樣使得咱們能夠更加快速的熟悉全部模型的用法,在這以前,咱們先來看看模型的經常使用屬性和功能。
# 擬合模型 model.fit(X_train, y_train) # 模型預測 model.predict(X_test) # 得到這個模型的參數 model.get_params() # 爲模型進行打分 model.score(data_X, data_y) # 線性迴歸:R square; 分類問題: acc
from sklearn.linear_model import LinearRegression # 定義線性迴歸模型 model = LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1) """ 參數 --- fit_intercept:是否計算截距。False-模型沒有截距 normalize: 當fit_intercept設置爲False時,該參數將被忽略。 若是爲真, 則迴歸前的迴歸係數X將經過減去平均值併除以l2-範數而歸一化。 n_jobs:指定線程數 """
from sklearn.linear_model import LogisticRegression # 定義邏輯迴歸模型 model = LogisticRegression(penalty=’l2’, dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver=’liblinear’, max_iter=100, multi_class=’ovr’, verbose=0, warm_start=False, n_jobs=1) """參數 --- penalty:使用指定正則化項(默認:l2) dual: n_samples > n_features取False(默認) C:正則化強度的反,值越小正則化強度越大 n_jobs: 指定線程數 random_state:隨機數生成器 fit_intercept: 是否須要常量 """
from sklearn import naive_bayes model = naive_bayes.GaussianNB() # 高斯貝葉斯 model = naive_bayes.MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None) model = naive_bayes.BernoulliNB(alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None) """ 文本分類問題經常使用MultinomialNB 參數 --- alpha:平滑參數 fit_prior:是否要學習類的先驗機率;false-使用統一的先驗機率 class_prior: 是否指定類的先驗機率;若指定則不能根據參數調整 binarize: 二值化的閾值,若爲None,則假設輸入由二進制向量組成 """
from sklearn import tree model = tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False) """參數 --- criterion :特徵選擇準則gini/entropy max_depth:樹的最大深度,None-儘可能下分 min_samples_split:分裂內部節點,所須要的最小樣本樹 min_samples_leaf:葉子節點所須要的最小樣本數 max_features: 尋找最優分割點時的最大特徵數 max_leaf_nodes:優先增加到最大葉子節點數 min_impurity_decrease:若是這種分離致使雜質的減小大於或等於這個值,則節點將被拆分。 """
from sklearn.svm import SVC model = SVC(C=1.0, kernel=’rbf’, gamma=’auto’) """參數 --- C:偏差項的懲罰參數C gamma: 核相關係數。浮點數,If gamma is ‘auto’ then 1/n_features will be used instead. """
from sklearn import neighbors #定義kNN分類模型 model = neighbors.KNeighborsClassifier(n_neighbors=5, n_jobs=1) # 分類 model = neighbors.KNeighborsRegressor(n_neighbors=5, n_jobs=1) # 迴歸 """參數 --- n_neighbors: 使用鄰居的數目 n_jobs:並行任務數 """
from sklearn.neural_network import MLPClassifier # 定義多層感知機分類算法 model = MLPClassifier(activation='relu', solver='adam', alpha=0.0001) """參數 --- hidden_layer_sizes: 元祖 activation:激活函數 solver :優化算法{‘lbfgs’, ‘sgd’, ‘adam’} alpha:L2懲罰(正則化項)參數。 """
評價指標針對不一樣的機器學習任務有不一樣的指標,同一任務也有不一樣側重點的評價指標。如下方法,sklearn中都在sklearn.metrics類下,務必記住那些指標適合分類,那些適合迴歸。
機器學習經常使用的評估指標請參考博文:Python機器學習筆記:經常使用評估指標的前世此生
交叉驗證cross_val_score的scoring參數
from sklearn.model_selection import cross_val_score cross_val_score(model, X, y=None, scoring=None, cv=None, n_jobs=1) """參數 --- model:擬合數據的模型 cv : k-fold scoring: 打分參數-‘accuracy’、‘f1’、‘precision’、‘recall’ 、‘roc_auc’、'neg_log_loss'等等 """
from sklearn.model_selection import cross_val_score
把某種意義下將原始數據(dataset)進行分組,一部分做爲訓練集(train set),另外一部分做爲驗證集(validation set or test set),首先用訓練集對分類器進行訓練,再利用驗證集來測試訓練獲得的模型(model),以此來做爲評價分類器的性能指標。
1,留出法(holdout cross validation)
在機器學習任務中,拿到數據後,咱們首先會將原始數據集分爲三部分:訓練集,驗證集和測試集。
訓練集用於訓練模型,驗證集用於模型的參數選擇配置,測試集對於模型來講是未知數據,用於評估模型的泛化能力。
這個方法操做簡單,只須要隨機將原始數據分爲三組便可。
不過若是隻作一次分割,它對訓練集,驗證集和測試機的樣本比例,還有分割後數據的分佈是否和原始數據集的分佈相同等因素比較敏感,不一樣的劃分會獲得不一樣的最優模型,,並且分紅三個集合後,用於訓練的數據更少了。因而又了2.k折交叉驗證(k-fold cross validation).
下面例子,一共有150條數據:
>>> import numpy as np >>> from sklearn.model_selection import train_test_split >>> from sklearn import datasets >>> from sklearn import svm >>> iris = datasets.load_iris() >>> iris.data.shape, iris.target.shape ((150, 4), (150,))
用train_test_split來隨機劃分數據集,其中40%用於測試集,有60條數據,60%爲訓練集,有90條數據:
>>> X_train, X_test, y_train, y_test = train_test_split( ... iris.data, iris.target, test_size=0.4, random_state=0) >>> X_train.shape, y_train.shape ((90, 4), (90,)) >>> X_test.shape, y_test.shape ((60, 4), (60,))
用train來訓練,用test來評價模型的分數。
>>> clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train) >>> clf.score(X_test, y_test) 0.96...
2,2. k 折交叉驗證(k-fold cross validation)
K折交叉驗證經過對k個不一樣分組訓練的結果進行平均來減小方差,所以模型的性能對數據的劃分就不那麼敏感。
K通常取10,數據量小的是,k能夠設大一點,這樣訓練集佔總體比例就比較大,不過同時訓練的模型個數也增多。數據量大的時候,k能夠設置小一點。當k=m的時候,即樣本總數,出現了留一法。
舉例,這裏直接調用了cross_val_score,這裏用了5折交叉驗證
>>> from sklearn.model_selection import cross_val_score >>> clf = svm.SVC(kernel='linear', C=1) >>> scores = cross_val_score(clf, iris.data, iris.target, cv=5) >>> scores array([ 0.96..., 1. ..., 0.96..., 0.96..., 1. ])
獲得最後平均分數爲0.98,以及它的95%置信區間:
>>> print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) Accuracy: 0.98 (+/- 0.03)
咱們能夠直接看一下K-Fold是怎麼樣劃分數據的:X有四個數據,把它分紅2折,結構中最後一個集合是測試集,前面的是訓練集,每一行爲1折:
>>> import numpy as np >>> from sklearn.model_selection import KFold >>> X = ["a", "b", "c", "d"] >>> kf = KFold(n_splits=2) >>> for train, test in kf.split(X): ... print("%s %s" % (train, test)) [2 3] [0 1] [0 1] [2 3]
一樣的數據X,咱們來看LeaveOneOut後是什麼樣子,那就是把它分紅4折,結果中最後一個集合是測試集,只有一個元素,前面的是訓練集,每一行爲1折:
>>> from sklearn.model_selection import LeaveOneOut >>> X = [1, 2, 3, 4] >>> loo = LeaveOneOut() >>> for train, test in loo.split(X): ... print("%s %s" % (train, test)) [1 2 3] [0] [0 2 3] [1] [0 1 3] [2] [0 1 2] [3]
3,留一法(Leave one out cross validation)
每次的測試集都只有一個樣本,要進行m次訓練和預測,這個方法用於訓練的數據只比總體數據集少一個樣本,所以最接近原始樣本的分佈。可是訓練複雜度增長了,由於模型的數量與原始數據樣本數量相同。通常在數據缺乏時使用。
此外:
4,Bootstrapping
經過自助採樣法,即在含有 m 個樣本的數據集中,每次隨機挑選一個樣本,再放回到數據集中,再隨機挑選一個樣本,這樣有放回地進行抽樣 m 次,組成了新的數據集做爲訓練集。
這裏會有重複屢次的樣本,也會有一次都沒有出現的樣本,原數據集中大概有 36.8% 的樣本不會出如今新組數據集中。
優勢是訓練集的樣本總數和原數據集同樣都是 m,而且仍有約 1/3 的數據不被訓練而能夠做爲測試集。
缺點是這樣產生的訓練集的數據分佈和原數據集的不同了,會引入估計誤差。
(此種方法不是很經常使用,除非數據量真的不多)
使用檢驗曲線,咱們能夠更加方便的改變模型參數,獲取模型表現。
from sklearn.model_selection import validation_curve train_score, test_score = validation_curve(model, X, y, param_name, param_range, cv=None, scoring=None, n_jobs=1) """參數 --- model:用於fit和predict的對象 X, y: 訓練集的特徵和標籤 param_name:將被改變的參數的名字 param_range: 參數的改變範圍 cv:k-fold 返回值 --- train_score: 訓練集得分(array) test_score: 驗證集得分(array) """
accuracy_score(y_test,y_pre) # 或者 model.score(x_test,y_test),大多模型都是有score方法的
print(classification_report(y_test,y_log_pre)) precision recall f1-score support 0 0.87 0.94 0.90 105 1 0.91 0.79 0.85 73 avg / total 0.88 0.88 0.88 178
>>> from sklearn.metrics import confusion_matrix >>> y_true = [2, 0, 2, 2, 0, 1] >>> y_pred = [0, 0, 2, 2, 0, 2] >>> confusion_matrix(y_true, y_pred) array([[2, 0, 0], [0, 0, 1], [1, 0, 2]])
這三個不只適合二分類,也適合多分類。只須要指出參數average=‘micro’/‘macro’/'weighted’ macro:計算二分類metrics的均值,爲每一個類給出相同權重的分值。 當小類很重要時會出問題,由於該macro-averging方法是對性能的平均。 另外一方面,該方法假設全部分類都是同樣重要的,所以macro-averaging 方法會對小類的性能影響很大 micro: 給出了每一個樣本類以及它對整個metrics的貢獻的pair(sample- weight),而非對整個類的metrics求和,它會每一個類的metrics上的權重及 因子進行求和,來計算整個份額。Micro-averaging方法在多標籤(multilabel) 問題中設置,包含多分類,此時,大類將被忽略 weighted: 對於不均衡數量的類來講,計算二分類metrics的平均, 經過在每一個類的score上進行加權實現
最後,咱們能夠將咱們訓練好的model保存到本地,或者放到線上供用戶使用,那麼如何保存訓練好的model呢?主要有下面兩種方式:
import pickle # 保存模型 with open('model.pickle', 'wb') as f: pickle.dump(model, f) # 讀取模型 with open('model.pickle', 'rb') as f: model = pickle.load(f) model.predict(X_test)
from sklearn.externals import joblib # 保存模型 joblib.dump(model, 'model.pickle') #載入模型 model = joblib.load('model.pickle')
1,模型的score方法:最簡單的模型評估方法就是調用模型本身的方法:
# 預測 y_predict = knnClf.predict(x_test) print("score on the testdata:",knnClf.score(x_test,y_test))
2,sklearn的指標函數:庫提供的一些計算方法,經常使用的有classification_report方法
3,sklearn也支持本身開發評價方法。
模型評價的目的:經過模型評價,咱們知道當前訓練模型的好壞,泛化能力如何?從而知道是否能夠應用在解決問題上,若是不行,那又是那些出了問題?
在分類問題中,咱們一般經過對訓練集進行triain_test_split,劃分出train 和test兩部分,其中train用來訓練模型,test用來評估模型,模型經過fit方法從train數據集中學習,而後調用score方法在test集上進行評估,打分;從分數上咱們知道模型當前的訓練水平如何。
from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression import matplotlib.pyplot as plt cancer = load_breast_cancer() X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0) logreg = LogisticRegression().fit(X_train,y_train) print("Test set score:{:.2f}".format(logreg.score(X_test,y_test)))
結果:
Test set score:0.96
然而這這方式只進行了一次劃分,數據結果具備偶然性,若是在某次劃分中,訓練集裏全是容易學習的數據,測試集裏全是複雜的數據,這樣的就會致使最終的結果不盡人意。
針對上面經過train_test_split劃分,從而進行模型評估方式存在的弊端,提出Cross Validation交叉驗證。
Cross Validation:進行屢次train_test_split劃分;每次劃分時,在不一樣的數據集上進行訓練,測試評估,從而獲得一個評價結果;若是是5折交叉驗證,意思就是在原始數據集上,進行五次劃分,每次劃分進行一次訓練,評估,最後獲得5次劃分後的評估結果,通常在這幾回評估結果上取平均獲得最後的評分,k-folf cross-validation ,其中K通常取5或10。
代碼:
from sklearn.model_selection import cross_val_score from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression import warnings warnings.filterwarnings('ignore') cancer = load_breast_cancer() X_train, X_test, y_train, y_test = train_test_split( cancer.data , cancer.target, random_state=0 ) logreg = LogisticRegression() # CV 默認是3折交叉驗證,能夠修改cv=5,變爲5折交叉驗證 scores = cross_val_score(logreg,cancer.data , cancer.target) print("Cross validation scores:{}".format(scores)) print("Mean cross validation score:{:2f}".format(scores.mean()))
結果:
Cross validation scores:[0.93684211 0.96842105 0.94179894] Mean cross validation score:0.949021
這種簡答的交叉驗證方式,從上面的圖片能夠看出來,每次劃分時對數據進行均分,設想一下,會不會存在一種狀況:數據集有5類,抽取出來的也正好是按照類別劃分的5類,也就是說第一折全是0類,第二折全是1類,等等;這樣的結果就會致使,模型訓練時。沒有學習到測試集中數據的特色,從而致使模型得分很低,甚至爲0,爲避免這種狀況,又出現了其餘的各類交叉驗證方式。
分層交叉驗證(Stratified k-fold cross validation):首先它屬於交叉驗證類型,分層的意思是說在每一折中都保持着原始數據中各個類別的比例關係,好比說:原始數據有3類,比例爲1:2:1,採用3折分層交叉驗證,那麼劃分的3折中,每一折中的數據類別保持着1:2:1的比例,這樣的驗證結果更加可信。
一般狀況下,能夠設置cv參數來控制幾折,可是咱們但願對其劃分等加以控制,因此出現了KFold,KFold控制劃分折,能夠控制劃分折的數目,是否打亂順序等,能夠賦值給cv,用來控制劃分。
代碼:
from sklearn.datasets import load_iris from sklearn.model_selection import StratifiedKFold ,cross_val_score from sklearn.linear_model import LogisticRegression import warnings warnings.filterwarnings('ignore') iris_data = load_iris() logreg = LogisticRegression() strKFold = StratifiedKFold(n_splits=3,shuffle=False,random_state=0) scores = cross_val_score(logreg,iris_data.data,iris_data.target,cv=strKFold) print("straitified cross validation scores:{}".format(scores)) print("Mean score of straitified cross validation:{:.2f}".format(scores.mean()))
結果:
straitified cross validation scores:[0.96078431 0.92156863 0.95833333] Mean score of straitified cross validation:0.95
留一法Leave-one-out Cross-validation:是一種特殊的交叉驗證方式。顧名思義,若是樣本容量爲n,則k=n,進行n折交叉驗證,每次留下一個樣本進行驗證。主要針對小樣本數據。
代碼:
from sklearn.datasets import load_iris from sklearn.model_selection import LeaveOneOut , cross_val_score from sklearn.linear_model import LogisticRegression import warnings warnings.filterwarnings('ignore') iris = load_iris() logreg = LogisticRegression() loout = LeaveOneOut() scores = cross_val_score(logreg,iris.data,iris.target,cv=loout) print("leave-one-out cross validation scores:{}".format(scores)) print("Mean score of leave-one-out cross validation:{:.2f}".format(scores.mean()))
結果:
leave-one-out cross validation scores:[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] Mean score of leave-one-out cross validation:0.95
控制更加靈活,能夠控制劃分迭代次數,每次劃分測試集和訓練集的比例(也就說:能夠存在機再也不訓練集也再也不測試集的狀況)
代碼:
from sklearn.datasets import load_iris from sklearn.model_selection import ShuffleSplit,cross_val_score from sklearn.linear_model import LogisticRegression import warnings warnings.filterwarnings('ignore') iris = load_iris() # 迭代八次 shufsp1 = ShuffleSplit(train_size=0.5,test_size=0.4,n_splits=8) logreg = LogisticRegression() scores = cross_val_score(logreg,iris.data,iris.target,cv=shufsp1) print("shuffle split cross validation scores:\n{}".format(scores)) print("Mean score of shuffle split cross validation:{:.2f}".format(scores.mean()))
結果:
shuffle split cross validation scores: [0.95 1. 0.86666667 0.95 0.88333333 0.88333333 0.85 0.9 ] Mean score of shuffle split cross validation:0.91
參考文獻:http://www.cnblogs.com/lianyingteng/p/7811126.html
https://www.cnblogs.com/magle/p/5638409.html
https://blog.csdn.net/u014248127/article/details/78885180
https://www.cnblogs.com/ysugyl/p/8707887.html