owned this note
owned this note
Published
Linked with GitHub
---
tags: Python
---
# Sklearn 菜單
|導覽|Supervised監督學習|Unsupervised非監督學習|
|---|---|---|
|Discrete離散|Classification分類|Clustering分群|
|Continuous連續|Regression回歸|Dimensionality Reduction降維|
1. 前置處理(訓練驗證分割、降維讓資料更好建模)
2. 建立模型(呼叫Class如常用的KNN、決策樹)
3. 訓練模型(最佳化Class中的參數)
4. 預測結果(代入測試資料輸入)
5. 評估模型(計算誤差)
### 載入資料集
|模組來源|sklearn.datasets|
|-|-|
|鳶尾花(分類)|load_iris()|
|波士頓房價(回歸)|load_boston()|
|肥胖因素(分類)|load_diabetes()|
### 羅吉特模型
我們想藉由許多變數算出P~w,b~(C~1~|x),並且藉此機率來進行分類,而對於離散的二元變數來說,他們的因素常常不是線性關係的,可能超過一個臨界值就有明顯的差異,所以使用sigmoid函數來取代線性函數做為機率分配函數σ(z)
```
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
answer = logreg.fit(X,y)
coef = answer.params #係數
print(answer.summary()) #詳情
y_predict = logreg.predict(X) #進行預測
logreg.predict_proba(X) #預測可能機率
```
```
#顯示模型預測準度
from sklearn import metrics
print(metrics.accuracy_score(y,y_predict))
```
### 隨機梯度下降法(Stochastic Gradient Research)
梯度下降法是根據微分與學習幅度不斷迭代去一步步的找出最佳解,而SGD則是利用統計變異數區間收斂的特性,每次從訓練集中隨機抽取部分樣本來更新參數,讓訓練過程變得更快
```
from sklearn.linear_model import SGDClassifier
clf = SGDClassfier(lost='hinge', penalty='12')
clf.fit(X,y)
coef = clf.coef_
intercept = clf.intercept_
```
### KNN模型
依據歐式距離以k個附近的點作為參考,比較該類別的數量多寡來分類,對異常值不敏感,但當計算量大時會相當耗時
```
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X,y)
y_predict = knn.predict(X)
```
### 支援向量機
在線性可分的情況下,在兩者資料點之間,建構一個超平面(hyperplane)使其與資料點的最小距離達到最大化,然而在大多數的情況下都是線性不可分的,這時就得動用到了核技巧(kernel trick),將資料透過核函數對映到更高的維度,便能神奇的能夠使用超平面進行分割
[影片介紹](https://www.youtube.com/watch?v=Y6RRHw9uN9o)
```
linear 線性
poly 多項式(Polynomial)
rbf 徑向基函數(Radial basis function)
sigmoid 邏輯函數
C 懲罰函數,預設為1
gamma 每筆資料的影響力
```
```
from sklearn.svm import SVC, SVR
# SVC 分類器 SVR 回歸
clf = SVC(kernel='linear', C=1)
clf.fit(X,y)
y_predict = clf.predict(X)
```
### 決策樹模型
依據資料差異特性左右子樹分支,並藉由階層關係達到更細密的分類,資訊增益、吉尼係數或卡方統計量是用來決定分類特徵的指標,以係數最大的項目(代表偏差最大)進行節點的分類
```
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
clf = DecisionTreeClassifier()
clf = clf.fit(X,y)
y_predict = clf.predict(X)
clf.predict_proba(X)
clf.importances_
```
```
參數
max_depth: 最大深度,越深越容易過度擬和
max_features: 在分節點的時候,最多考慮多少個特徵
min_samples_split: 分枝所需最少資料數
min_samples_leaf: 每個節點的最少資料數
```
### 單純貝氏
利用統計條件機率,取得機率最高者
假設我們想透過天氣、溫度、濕度、風速判斷一個人會不會出門,可以利用在特定的條件下出門的機率進行分類,比如說在晴天、高溫、低濕度、弱風的條件下會不會出門的機率為
會出門:p(晴天|會出門)p(高溫|會出門)p(低濕度|會出門)p(弱風|會出門)=0.087
不會出門:p(晴天|不出門)p(高溫|不出門)p(低濕度|不出門)p(弱風|不出門)=0.006
```
from sklearnn.naive_bayes import GaussianNB
gnb = GaussianNB()
gnb.fit(X,y)
gnb.predict(X)
```
### Ensemble---讓分類器合體
1. Bagging(Bootstrap Aggregating)
將資料分成N個子集,進行訓練並且求出各自的方程式,接著在測試的時候對這些方程式取平均與投票篩選來找出更好的分類方式,當模型很複雜、又容易過度擬和的時候,這時該考慮看看使用bagging囉
2. Boosting
首先找到一個新訓練集使得原先的分類器完全不準,其方法為透過原先的分類結果重新分配得分高低,將分類答對的得分除以d~1~、答錯的得分乘以d~1~,使得原先的分類器表現降至最低,這時就可以從數學式中導出d~1~=sqrt((1-ε~1~)/ε~1~)、α~1~=ln(d~1~)=這個弱分類器的權重,最後結合多個弱分類器形成一個組織,哪些弱分類器講話比較大聲(權重總和最大)就用聽他們說的去分類
神奇的現象: 雖然在訓練的時候錯誤率很快的就降到最低,但不斷的訓練還是會降低在測試集上的錯誤率
### 隨機森林
決策樹只要深度夠深,很容易就可以達到零誤差的程度,但也因此也很容易出現過度擬和的情況,於是有了結合決策樹與bagging的演算法
```
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(n_estimators=10)
```
### Adaboost(Adaptive Boosting)
```
from sklearn.ensemble import AdaBoostClassifier, GradientBoostingRegressor
clf = AdaboostClassifier(n_estimators=100, learning_rate=0.1, loss='ls')
```
### Gradient Boosting
Boosting結合gradient descent,用微分迭代的方式進行參數更新
```
from sklearn.ensemble import GradientBoostingClassfier
clf = GradientBoostingClassfier()
```
### 類神經網路
李宏毅老師:簡單來講就是將一堆logistic model接在一起
需要進行大量矩陣運算,依靠SGD等方法進行權重更新,可以產出高維非線性的函數,因此在高維度的資料來源表現會明顯優於其他演算法
```
Multilayer Perceptron 多層感知器
from sklearn.neural_network import MLPClassifier
clf = MLPClassifier()
```
### 多元線性回歸
線性回歸假設
1. 線性關係
2. 常態性
3. 誤差項的獨立性
4. 誤差項的變異數相等
```
#使用statsmodels做多元線性較適合統計學家
import statsmodels.api as sm
const_x = sm.add_constant(X)
est = sm.OLS(y, const_x).fit()
est.params #係數
est.tvalues #檢定統計量
est.pvalues #p-value
est.summary() #詳情
```
```
from sklearn import linear_model
reg = linear_model.LinearRegression()
est = reg.fit(X,y)
reg.coef_ #係數
reg.intercept_ #常數
reg.score(X, y) #R-square
est.summary() #詳情
predict_y = reg.predict(test_X)
```
### 正規化L1回歸、L2回歸
```
reg = linear_model.Ridge(alpha=.5)
reg = linear_model.Lasso(alpha=.1)
```
### 回歸誤差計算
|縮寫|全名|實作|
|-|-|-|
|MSE|mean square error||
|RMSE|root mean square error||
|MAE|mean absolute error||
|MAPE|mean absolute percentage error||
### 製作資料集
```
from sklearn import datasets
#同心圓
noisy_circles = datasets.make_circles(n_samples=n_samples, factor=.5,noise=.05)
#弧線
noisy_moons = datasets.make_moons(n_samples=n_samples, noise=.05)
#散亂的圓點
varied = datasets.make_blobs(n_samples=n_samples,
cluster_std=[1.0, 2.5, 0.5],
random_state=random_state)
#各向異性的圓點
X, y = datasets.make_blobs(n_samples=n_samples, random_state=170)
aniso = (np.dot(X, [[0.6, -0.6], [-0.4, 0.8]]), y)
#集中的圓點
blobs = datasets.make_blobs(n_samples=n_samples, random_state=8)
```
從前至今發明了這麼多的分類演算法,但最終卻只會選出一個最佳的方法,該如何使用sklearn去評估以及篩選這些模型呢?
### 網格搜尋
將任何可選的參數加到一個字典內,以排列組合的方式進行所有測試
```
from sklearn.grid_search import GridSearchCV
param_grid = {模型參數集}
grid = GridSearchCV(knn, param_grid, cv=10, scoring='accuracy')
#cv = 10,交叉驗證cross validation十次
print(grid.grid_scores_[0].parameters) #各項集的引用參數
print(grid.grid_scores_[0].cv_validation_scores) #各項集的準確度
print(grid.grid_scores_[0].mean_validation_score) #各項集的平均準確度
print(grid.best_score_) #最佳準確度
print(grid.best_params_) #最佳引用參數
print(grid.best_estimator_) #最佳分類器
```
### 二元分類模型評估方法
|ROC空間|真實為 陽性|真實為 陰性|
|---|---|---|
|預測為 陽性|True Positive|False Positive|
|預測為 陰性|False Negative|True Negative|
```python
from sklearn.metrics import confusion_matrix
[[TP,FP],[FN,TN]] = confusion_matrix(y_test, y_predict)
#預測準確度
(TP+TN)/float(TP+TN+FP+FN) #等同於
metrics.accuracy_score(y_test,y_predict)
#預測錯誤率
(FP+FN)/float(TP+TN+FP+FN) #等同於
1-metrics.accuracy_score(y_test,y_predict)
#真陽性率(敏感度) p(預測與真實皆為1|真實為1)
TP/float(TP+FN) #等同於
metrics.recall_score(y_test,y_predict)
#偽陽性率
FP/float(TN+FP)
#特異性
TN/float(TN+FP)
#準確性 p(預測與真實皆為1|預測為1)
TP/float(TP+FP) #等同於
metrics.precision_score(y_test,y_predict)
```
### Reciever Operating Characteristic Curve(ROC曲線)
Area Under the Curve(AUC曲線下面積)
```
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred_prob)
metrics.roc_auc_score(y_test, y_predict)
```
### 交叉驗證 Cross-validated AUC
將同一個資料集切成多個不同的測試、訓練集,並且把這些資料一一代入模型並且觀察結果
```
from sklearn.cross_validation import cross_val_score
cross_val_score(logreg,X,y,cv=10,scoring='roc_auc').mean()
```
### KMeans 模型
```
#經典演算法
from sklearn import KMeans
kmeans = KMeans(n_cluster=3,random_state=2)
kmeans.fit(df[['x_col','y_col']])
kmeans.labels_
kmeans.cluster_centers_
```
### K-Spectral-Clustering 模型
```
#在空間上表現較kmeans好
spectral = cluster.SpectralClustering(
n_clusters=params['n_clusters'], eigen_solver='arpack',
affinity="nearest_neighbors")
```
### DBSCAN 模型
```
#Density-based spatial clustering of applications with noise
#以密度為本,將附近的點分成一組
dbscan = cluster.DBSCAN(eps=params['eps'])
```
在做多變量資料分析的時候,使用統計特徵或是疊代排序,將與目標比較不相關的特徵排除並留下最相近的特徵,以增加判斷的準確度
### PCA(MDS)
Principal Components Analysis主成分分析,找到方向使原始資料的變異最大化,並且將其投射至一個維度較小的子空間,同時能夠保留大多數資訊,其步驟如下
1. 從共變異數(需先正規化)或相關數矩陣獲得特徵向量eigenvector與特徵值eigenvalue
2. 將特徵值由大到小排列,並選擇k個最大的特徵值
3. 從k個特徵值中建立一個投射矩陣W
4. 將原始資料透過投射矩陣W獲得一個子空間Y
```
import numpy as np
from sklearn.datasets import load_iris
iris = load_iris()
correlation_matrix = np.corrcoef(iris.data.T)
eigenvalues, eigenvectors = np.linalg.eig(correlation_matrix)
correlation_matrix
[[ 1. -0.10936925 0.87175416 0.81795363]
[-0.10936925 1. -0.4205161 -0.35654409]
[ 0.87175416 -0.4205161 1. 0.9627571 ]
[ 0.81795363 -0.35654409 0.9627571 1. ]]
eigenvectors
[[ 0.52237162 -0.37231836 -0.72101681 0.26199559]
[-0.26335492 -0.92555649 0.24203288 -0.12413481]
[ 0.58125401 -0.02109478 0.14089226 -0.80115427]
[ 0.56561105 -0.06541577 0.6338014 0.52354627]]
eigenvalues
[ 2.91081808 0.92122093 0.14735328 0.02060771]
```
```
from sklearn.decomposition import PCA
pca = PCA(n_components=3) #子空間維度等於3
pca.fit(x)
x_reduced = pca.fit_transform(x)
pca.components_ #等於3
pca.explained_variance_ratio_ #等於特徵值
pca.singular_values_ #奇異數分解,等於特徵向量
```
### 訓練集、測試集
分割訓練集、測試集,在沒有大樣本的情況下,建議採用80-20或70-30的比例分割
```
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = \
train_test_split(X, y, test_size=0.2, random_state=4)
```
分層分割並產生多個測試訓練集(KFold)
|||||||
| ------ | ---- | ----- | ----- | ----- | ----- |
|資料集1 | Test | Train | Train | Train | Train |
|資料集2 | | Test | | | |
|資料集3 | | | Test | | |
|資料集4 | | | | Test | |
|資料集5 | | | | | Test |
```
from sklearn.cross_validation import KFold
kf = KFold(25, n_folds=5, shuffle=False)
```
### 正規化 StandardScaler
為了提升運算的效率,通常會將數值的範圍定在[0,1]之間或是[-1,1]之間,而正規化的處理方式為先取出最大和最小值,將最大值定為1、最小值定為0,而其他的數值則依據在這兩者之間的比例轉為浮點數,運算方式為scaled_number = (number-min)/(max-min)
```
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler() #設定物件參數
scaled_data = scaler.transform(data) #轉換資料
```
### 編碼 LabelEncoder
將離散的資料轉成重新編碼成整數數列
['winner','chicken','dinner'] -> [0,1,2]
```
from sklearn.preprocessing import LabelEncoder
le = LabelEnoder()
le.fit(ndarray) #使用fit將資料重新編碼
le.classes_ #查看原始的資料
labeled_data = le.transform(data) #使用transform將資料重新編碼
data = le.inverse_transform(labeled_data) #把資料轉回來
```
也可以使用pandas做一樣的事情
```
df.col.astype('category').cat.codes
```
### 編碼 OneHotEncoder
將離散的資料類別轉換成[0,1]虛擬變數,方能餵給分類模型使用
['winner','chicken','dinner'] -> [[1,0,0],[0,1,0],[0,0,1]]
```
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
enc.fit(data)
enc.n_values_ #總類數量
enc.feature_indices_ #原始種類
enc.transform(ndarray).toarray() #使用transform將資料重新編碼
```
### 文字探勘
依據出現次數建立成一個字典,並將原有的資料向量化
```
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
x_train_counts = vect.fit_transform(x_text)
```
依據出現次數處理有一個問題,當文章的長度越長,單字出現次數也容易較高,這對文長較短的文章來說不公平,因為這兩個文章可能表達的概念是一樣的,可是向量化後的特徵卻有差異,所以使用出現次數除以文章長度的方法(term frequency)重新分配向量
Term Frequency times Inverse Document Frequency(tf-idf)
```
from sklearn.feature_extraction.text import TfidfTransformer
tfidf = TfidfTransformer()
x_train_tfidf = tfidf.fit(X_train_counts)
```
word2vec