Python機器學習筆記:sklearn庫的學習

  網上有不少關於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內置了大量數據集,節省了獲取和整理數據集的時間。網絡

一,sklearn官方文檔的內容和結構

1.1 sklearn官方文檔的內容

  定義:針對經驗E和一系列的任務T和必定表現的衡量P,若是隨着經驗E的積累,針對定義好的任務T能夠提升表現P,就說明機器具備學習能力。app

1.2 sklearn官方文檔結構

  由圖中,能夠看到庫的算法主要有四類:分類,迴歸,聚類,降維。其中:dom

  • 經常使用的迴歸:線性、決策樹、SVM、KNN ;集成迴歸:隨機森林、Adaboost、GradientBoosting、Bagging、ExtraTrees
  • 經常使用的分類:線性、決策樹、SVM、KNN,樸素貝葉斯;集成分類:隨機森林、Adaboost、GradientBoosting、Bagging、ExtraTrees
  • 經常使用聚類:k均值(K-means)、層次聚類(Hierarchical clustering)、DBSCAN
  • 經常使用降維:LinearDiscriminantAnalysis、PCA

  這個流程圖表明:藍色圓圈是判斷條件,綠色方框是能夠選擇的算法,咱們能夠根據本身的數據特徵和任務目標去找一條本身的操做路線。機器學習

  sklearn中包含衆多數據預處理和特徵工程相關的模塊,雖然剛接觸sklearn時,你們都會爲其中包含的各類算法的廣度深度所震驚,但其實sklearn六大板塊中有兩塊都是關於數據預處理和特徵工程的,兩個板塊互相交互,爲建模以前的所有工程打下基礎。ide

  

  • 模塊preprocessing:幾乎包含數據預處理的全部內容
  • 模塊Impute:填補缺失值專用
  • 模塊feature_selection:包含特徵選擇的各類方法的實踐
  • 模塊decomposition:包含降維算法

 二,sklearn的快速使用

  傳統的機器學習任務從開始到建模的通常流程就是:獲取數據——》數據預處理——》訓練模型——》模型評估——》預測,分類。本次咱們將根據傳統機器學習的流程,看看在每一步流程中都有哪些經常使用的函數以及他們的用法是怎麼樣的。那麼首先先看一個簡單的例子:

  鳶尾花識別是一個經典的機器學習分類問題,它的數據樣本中包括了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]

'''

  

  下面,咱們開始一步步介紹、

1,獲取數據

1.1 導入sklearn數據集

  sklearn中包含了大量的優質的數據集,在咱們學習機器學習的過程當中,咱們可使用這些數據集實現出不一樣的模型,從而提升你動手實踐能力,同時這個過程也能夠加深對理論知識的理解和把握。除了引入數據以外,咱們還能夠經過load_sample_images()來引入圖片。

  首先,要使用sklearn中的數據集,必須導入datasets模塊。

from sklearn import datasets

  下面兩個圖中包含了大部分sklearn中的數據集,調用方式也圖中給出,

 

這裏咱們使用iris的數據來舉個例子,表示導出數據集:

iris = datasets.load_iris() # 導入數據集
X = iris.data # 得到其特徵向量
y = iris.target # 得到樣本label

 

1.1.1  手寫數字數據集

  手寫數字數據集包含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()

 

 

1.2 建立數據集

  咱們除了可使用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]

 

1.2.1  用sklearn.datasets.make_blobs來生成數據

  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]

  輸入:

  • n_samples表示產生多少個數據
  • n_features表示數據是幾維
  • centers表示數據點中心,能夠輸入int數字,表明有多少箇中心,也能夠輸入幾個座標(fixed center locations)
  • cluster_std表示分佈的標準差

  返回值:

  • X,[n_samples, n_features]形狀的數組,表明產生的樣本
  • y,[n_samples]形狀的數組,表明每一個點的標籤(類別)

 例子(生成三類數據用於聚類(100個樣本,每一個樣本2個特徵)):

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()

  結果:

 爲每一個類別設置不一樣的方差,只須要在上述代碼中加入cluster_std參數便可:

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()

  

 

1.2.2  用sklearn.datasets.make_classification來生成數據

  一般用於分類算法

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構成的

1.2.3  用sklearn.datasets.make_gaussian和make_hastie_10_2來生成數據

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()

  結果:

1.2.4  用sklearn.datasets.make_circles和make_moons來生成數據

   生成環線數據

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()

  結果:

 

2,數據預處理

   數據預處理階段是機器學習中不可缺乏的一環,它會使得數據更加有效的被模型或者評估器識別。下面咱們來看一下sklearn中有哪些平時咱們經常使用的函數:

from sklearn import preprocessing

  爲了使得訓練數據的標準化規則與測試數據的標準化規則同步,preprocessing中提供了不少的Scaler:

  • StandardScaler
  • MaxAbsScaler
  • MinMaxScaler
  • RobustScaler
  • Normalizer
  • 等其餘預處理操做

  對應的有直接的函數使用:scale(),maxabs_scale(),minmax_scale(),robust_scale(),normaizer()

sklearn.preprocessing.scale(X)

 

2.1 數據標準化

  標準化:在機器學習中,咱們可能要處理不一樣種類的資料,例如,音訊和圖片上的像素值,這些資料多是高緯度的,資料標準化後會使得每一個特徵中的數值平均變爲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

2.2 最小-最大規範化

  最小最大規範化對原始數據進行線性變換,變換到[0,1]區間(也能夠是其餘固定最小最大值的區間)。

# 2. 將每一個特徵值歸一化到一個固定範圍
scaler = preprocessing.MinMaxScaler(feature_range=(0, 1)).fit(train_data)
scaler.transform(train_data)
scaler.transform(test_data)
#feature_range: 定義歸一化範圍,注用()括起來

  

2.3 正則化(normalize)

   當你想要計算兩個樣本的類似度時必不可少的一個操做,就是正則化。其思想是:首先求出樣本的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。

 

2.4 one-hot編碼

  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()

  

2.5 特徵二值化(Binarization)

  給定閾值,將特徵轉換爲0/1.

binarizer = sklearn.preprocessing.Binarizer(threshold=1.1)

binarizer.transform(X)

  

2.6 類別特徵編碼

  有時候特徵時類別型的,而一些算法的輸入必須是數值型,此時須要對其編碼,

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,用兩位去編碼。第二維用三位,第三維用四位。

2.7 標籤編碼(Label encoding)

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])

  

3,數據集拆分

  在獲得訓練數據集時,一般咱們常常會把訓練數據進一步拆分紅訓練集和驗證集,這樣有助於咱們模型參數的選取。

  train_test_split是交叉驗證中經常使用的函數,功能是從樣本中隨機的按比例選取train datatestdata,形式爲:

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_data:所要劃分的樣本特徵集
  • train_target:所要劃分的樣本結果
  • test_size:樣本佔比,若是是整數的話就是樣本的數量
  • random_state:是隨機數的種子。
  • 隨機數種子:其實就是該組隨機數的編號,在須要重複試驗的時候,保證獲得一組同樣的隨機數。好比你每次都填1其餘參數同樣的狀況下你獲得的隨機數組是同樣的。但填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

  

4,定義模型

  在這一步咱們首先要分析本身數據的類型,明白本身要用什麼模型來作,而後咱們就能夠在sklearn中定義模型了,sklearn爲全部模型提供了很是類似的接口,這樣使得咱們能夠更加快速的熟悉全部模型的用法,在這以前,咱們先來看看模型的經常使用屬性和功能。

# 擬合模型
model.fit(X_train, y_train)
# 模型預測
model.predict(X_test)

# 得到這個模型的參數
model.get_params()
# 爲模型進行打分
model.score(data_X, data_y) # 線性迴歸:R square; 分類問題: acc

  

4.1 線性迴歸

 

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:指定線程數
"""

  

4.2 邏輯迴歸LR

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: 是否須要常量
"""

  

4.3 樸素貝葉斯算法NB(Naive Bayes)

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,則假設輸入由二進制向量組成
"""

  

 4.4 決策樹DT

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:若是這種分離致使雜質的減小大於或等於這個值,則節點將被拆分。
"""

  

4.5 支持向量機SVM

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.
"""

  

4.6 k近鄰算法KNN

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:並行任務數
"""

  

4.7 多層感知器(神經網絡)

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懲罰(正則化項)參數。
"""

 

5,模型評估與選擇

  評價指標針對不一樣的機器學習任務有不一樣的指標,同一任務也有不一樣側重點的評價指標。如下方法,sklearn中都在sklearn.metrics類下,務必記住那些指標適合分類,那些適合迴歸。

   機器學習經常使用的評估指標請參考博文:Python機器學習筆記:經常使用評估指標的前世此生

5.1 交叉驗證

交叉驗證cross_val_score的scoring參數

  • 分類:accuracy(準確率)、f一、f1_micro、f1_macro(這兩個用於多分類的f1_score)、precision(精確度)、recall(召回率)、roc_auc
  • 迴歸:neg_mean_squared_error(MSE、均方偏差)、r2
  • 聚類:adjusted_rand_score、completeness_score等 

 

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'等等
"""

 

(補充):交叉驗證的學習

  1,導入k折交叉驗證模塊

from sklearn.model_selection import cross_val_score

  2,交叉驗證的思想

  把某種意義下將原始數據(dataset)進行分組,一部分做爲訓練集(train set),另外一部分做爲驗證集(validation set or test set),首先用訓練集對分類器進行訓練,再利用驗證集來測試訓練獲得的模型(model),以此來做爲評價分類器的性能指標。

  3,爲何使用交叉驗證法

  • 交叉驗證用於評估模型的預測性能,尤爲是訓練好的模型在新數據上的表現,能夠在必定程序熵減小過擬合。
  • 交叉驗證還能夠從有限的數據中獲取儘量多的有效信息

  4,主要有哪些方法

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 份。
  • 第二步,每一次挑選其中 1 份做爲測試集,剩餘 k-1 份做爲訓練集用於模型訓練。
  • 第三步,重複第二步 k 次,這樣每一個子集都有一次機會做爲測試集,其他機會做爲訓練集。
  • 在每一個訓練集上訓練後獲得一個模型,
  • 用這個模型在相應的測試集上測試,計算並保存模型的評估指標,
  • 第四步,計算 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次訓練和預測,這個方法用於訓練的數據只比總體數據集少一個樣本,所以最接近原始樣本的分佈。可是訓練複雜度增長了,由於模型的數量與原始數據樣本數量相同。通常在數據缺乏時使用。

此外:

  • 屢次 k 折交叉驗證再求均值,例如:10 次 10 折交叉驗證,以求更精確一點。
  • 劃分時有多種方法,例如對非平衡數據能夠用分層採樣,就是在每一份子集中都保持和原始數據集相同的類別比例。
  • 模型訓練過程的全部步驟,包括模型選擇,特徵選擇等都是在單個摺疊 fold 中獨立執行的。

4,Bootstrapping

  經過自助採樣法,即在含有 m 個樣本的數據集中,每次隨機挑選一個樣本,再放回到數據集中,再隨機挑選一個樣本,這樣有放回地進行抽樣 m 次,組成了新的數據集做爲訓練集。

  這裏會有重複屢次的樣本,也會有一次都沒有出現的樣本,原數據集中大概有 36.8% 的樣本不會出如今新組數據集中。

  優勢是訓練集的樣本總數和原數據集同樣都是 m,而且仍有約 1/3 的數據不被訓練而能夠做爲測試集。 
  缺點是這樣產生的訓練集的數據分佈和原數據集的不同了,會引入估計誤差。 
  (此種方法不是很經常使用,除非數據量真的不多)

 

5.2 檢驗曲線

  使用檢驗曲線,咱們能夠更加方便的改變模型參數,獲取模型表現。

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)
"""

  

5.3 分類模型

  • accuracy_score(準確率得分)是模型分類正確的數據除以樣本總數 【模型的score方法算的也是準確率】
accuracy_score(y_test,y_pre)
# 或者 model.score(x_test,y_test),大多模型都是有score方法的

  

  • classification_report中的各項得分的avg/total 是每一分類佔總數的比例加權算出來的
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

  

  • confusion_matrix(混淆矩陣),用來評估分類的準確性
>>> 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]])

  

  • precision_score(精確度)、recall_score(召回率)、f1_score(後者由前兩個推導出的)
這三個不只適合二分類,也適合多分類。只須要指出參數average=‘micro’/‘macro’/'weighted’

    macro:計算二分類metrics的均值,爲每一個類給出相同權重的分值。
當小類很重要時會出問題,由於該macro-averging方法是對性能的平均。
另外一方面,該方法假設全部分類都是同樣重要的,所以macro-averaging
方法會對小類的性能影響很大

    micro: 給出了每一個樣本類以及它對整個metrics的貢獻的pair(sample-
weight),而非對整個類的metrics求和,它會每一個類的metrics上的權重及
因子進行求和,來計算整個份額。Micro-averaging方法在多標籤(multilabel)
問題中設置,包含多分類,此時,大類將被忽略

    weighted: 對於不均衡數量的類來講,計算二分類metrics的平均,
經過在每一個類的score上進行加權實現
  • roc_curve(ROC曲線,用於二分類)

 

6 保存模型

  最後,咱們能夠將咱們訓練好的model保存到本地,或者放到線上供用戶使用,那麼如何保存訓練好的model呢?主要有下面兩種方式:

6.1 保存爲pickle文件

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)

  

6.2 sklearn自帶方法joblib

from sklearn.externals import joblib

# 保存模型
joblib.dump(model, 'model.pickle')

#載入模型
model = joblib.load('model.pickle')

  

7,模型評分

  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也支持本身開發評價方法。

 

8,幾種交叉驗證(cross validation)方式的比較

  模型評價的目的:經過模型評價,咱們知道當前訓練模型的好壞,泛化能力如何?從而知道是否能夠應用在解決問題上,若是不行,那又是那些出了問題?

train_test_split

  在分類問題中,咱們一般經過對訓練集進行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

  然而這這方式只進行了一次劃分,數據結果具備偶然性,若是在某次劃分中,訓練集裏全是容易學習的數據,測試集裏全是複雜的數據,這樣的就會致使最終的結果不盡人意。

Standard Cross Validation

  針對上面經過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

交叉驗證的優勢:

  • 原始採用的train_test_split方法,數據劃分具備偶然性;交叉驗證經過屢次劃分,大大下降了這種由一次隨機劃分帶來的偶然性,同時經過屢次劃分,屢次訓練,模型也能遇到各類各樣的數據,從而提升其泛化能力
  • 與原始的train_test_split相比,對數據的使用效率更高,train_test_split,默認訓練集,測試集比例爲3:1,而對交叉驗證來講,若是是5折交叉驗證,訓練集比測試集爲4:1;10折交叉驗證訓練集比測試集爲9:1.數據量越大,模型準確率越高!

交叉驗證的缺點:

這種簡答的交叉驗證方式,從上面的圖片能夠看出來,每次劃分時對數據進行均分,設想一下,會不會存在一種狀況:數據集有5類,抽取出來的也正好是按照類別劃分的5類,也就是說第一折全是0類,第二折全是1類,等等;這樣的結果就會致使,模型訓練時。沒有學習到測試集中數據的特色,從而致使模型得分很低,甚至爲0,爲避免這種狀況,又出現了其餘的各類交叉驗證方式。

Stratifid k-fold cross validation

  分層交叉驗證(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 留一法

  留一法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

  

Shuffle-split cross-validation

  控制更加靈活,能夠控制劃分迭代次數,每次劃分測試集和訓練集的比例(也就說:能夠存在機再也不訓練集也再也不測試集的狀況)

代碼:

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

相關文章
相關標籤/搜索